sp_c32.c 1.9 MB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860228612286222863228642286522866228672286822869228702287122872228732287422875228762287722878228792288022881228822288322884228852288622887228882288922890228912289222893228942289522896228972289822899229002290122902229032290422905229062290722908229092291022911229122291322914229152291622917229182291922920229212292222923229242292522926229272292822929229302293122932229332293422935229362293722938229392294022941229422294322944229452294622947229482294922950229512295222953229542295522956229572295822959229602296122962229632296422965229662296722968229692297022971229722297322974229752297622977229782297922980229812298222983229842298522986229872298822989229902299122992229932299422995229962299722998229992300023001230022300323004230052300623007230082300923010230112301223013230142301523016230172301823019230202302123022230232302423025230262302723028230292303023031230322303323034230352303623037230382303923040230412304223043230442304523046230472304823049230502305123052230532305423055230562305723058230592306023061230622306323064230652306623067230682306923070230712307223073230742307523076230772307823079230802308123082230832308423085230862308723088230892309023091230922309323094230952309623097230982309923100231012310223103231042310523106231072310823109231102311123112231132311423115231162311723118231192312023121231222312323124231252312623127231282312923130231312313223133231342313523136231372313823139231402314123142231432314423145231462314723148231492315023151231522315323154231552315623157231582315923160231612316223163231642316523166231672316823169231702317123172231732317423175231762317723178231792318023181231822318323184231852318623187231882318923190231912319223193231942319523196231972319823199232002320123202232032320423205232062320723208232092321023211232122321323214232152321623217232182321923220232212322223223232242322523226232272322823229232302323123232232332323423235232362323723238232392324023241232422324323244232452324623247232482324923250232512325223253232542325523256232572325823259232602326123262232632326423265232662326723268232692327023271232722327323274232752327623277232782327923280232812328223283232842328523286232872328823289232902329123292232932329423295232962329723298232992330023301233022330323304233052330623307233082330923310233112331223313233142331523316233172331823319233202332123322233232332423325233262332723328233292333023331233322333323334233352333623337233382333923340233412334223343233442334523346233472334823349233502335123352233532335423355233562335723358233592336023361233622336323364233652336623367233682336923370233712337223373233742337523376233772337823379233802338123382233832338423385233862338723388233892339023391233922339323394233952339623397233982339923400234012340223403234042340523406234072340823409234102341123412234132341423415234162341723418234192342023421234222342323424234252342623427234282342923430234312343223433234342343523436234372343823439234402344123442234432344423445234462344723448234492345023451234522345323454234552345623457234582345923460234612346223463234642346523466234672346823469234702347123472234732347423475234762347723478234792348023481234822348323484234852348623487234882348923490234912349223493234942349523496234972349823499235002350123502235032350423505235062350723508235092351023511235122351323514235152351623517235182351923520235212352223523235242352523526235272352823529235302353123532235332353423535235362353723538235392354023541235422354323544235452354623547235482354923550235512355223553235542355523556235572355823559235602356123562235632356423565235662356723568235692357023571235722357323574235752357623577235782357923580235812358223583235842358523586235872358823589235902359123592235932359423595235962359723598235992360023601236022360323604236052360623607236082360923610236112361223613236142361523616236172361823619236202362123622236232362423625236262362723628236292363023631236322363323634236352363623637236382363923640236412364223643236442364523646236472364823649236502365123652236532365423655236562365723658236592366023661236622366323664236652366623667236682366923670236712367223673236742367523676236772367823679236802368123682236832368423685236862368723688236892369023691236922369323694236952369623697236982369923700237012370223703237042370523706237072370823709237102371123712237132371423715237162371723718237192372023721237222372323724237252372623727237282372923730237312373223733237342373523736237372373823739237402374123742237432374423745237462374723748237492375023751237522375323754237552375623757237582375923760237612376223763237642376523766237672376823769237702377123772237732377423775237762377723778237792378023781237822378323784237852378623787237882378923790237912379223793237942379523796237972379823799238002380123802238032380423805238062380723808238092381023811238122381323814238152381623817238182381923820238212382223823238242382523826238272382823829238302383123832238332383423835238362383723838238392384023841238422384323844238452384623847238482384923850238512385223853238542385523856238572385823859238602386123862238632386423865238662386723868238692387023871238722387323874238752387623877238782387923880238812388223883238842388523886238872388823889238902389123892238932389423895238962389723898238992390023901239022390323904239052390623907239082390923910239112391223913239142391523916239172391823919239202392123922239232392423925239262392723928239292393023931239322393323934239352393623937239382393923940239412394223943239442394523946239472394823949239502395123952239532395423955239562395723958239592396023961239622396323964239652396623967239682396923970239712397223973239742397523976239772397823979239802398123982239832398423985239862398723988239892399023991239922399323994239952399623997239982399924000240012400224003240042400524006240072400824009240102401124012240132401424015240162401724018240192402024021240222402324024240252402624027240282402924030240312403224033240342403524036240372403824039240402404124042240432404424045240462404724048240492405024051240522405324054240552405624057240582405924060240612406224063240642406524066240672406824069240702407124072240732407424075240762407724078240792408024081240822408324084240852408624087240882408924090240912409224093240942409524096240972409824099241002410124102241032410424105241062410724108241092411024111241122411324114241152411624117241182411924120241212412224123241242412524126241272412824129241302413124132241332413424135241362413724138241392414024141241422414324144241452414624147241482414924150241512415224153241542415524156241572415824159241602416124162241632416424165241662416724168241692417024171241722417324174241752417624177241782417924180241812418224183241842418524186241872418824189241902419124192241932419424195241962419724198241992420024201242022420324204242052420624207242082420924210242112421224213242142421524216242172421824219242202422124222242232422424225242262422724228242292423024231242322423324234242352423624237242382423924240242412424224243242442424524246242472424824249242502425124252242532425424255242562425724258242592426024261242622426324264242652426624267242682426924270242712427224273242742427524276242772427824279242802428124282242832428424285242862428724288242892429024291242922429324294242952429624297242982429924300243012430224303243042430524306243072430824309243102431124312243132431424315243162431724318243192432024321243222432324324243252432624327243282432924330243312433224333243342433524336243372433824339243402434124342243432434424345243462434724348243492435024351243522435324354243552435624357243582435924360243612436224363243642436524366243672436824369243702437124372243732437424375243762437724378243792438024381243822438324384243852438624387243882438924390243912439224393243942439524396243972439824399244002440124402244032440424405244062440724408244092441024411244122441324414244152441624417244182441924420244212442224423244242442524426244272442824429244302443124432244332443424435244362443724438244392444024441244422444324444244452444624447244482444924450244512445224453244542445524456244572445824459244602446124462244632446424465244662446724468244692447024471244722447324474244752447624477244782447924480244812448224483244842448524486244872448824489244902449124492244932449424495244962449724498244992450024501245022450324504245052450624507245082450924510245112451224513245142451524516245172451824519245202452124522245232452424525245262452724528245292453024531245322453324534245352453624537245382453924540245412454224543245442454524546245472454824549245502455124552245532455424555245562455724558245592456024561245622456324564245652456624567245682456924570245712457224573245742457524576245772457824579245802458124582245832458424585245862458724588245892459024591245922459324594245952459624597245982459924600246012460224603246042460524606246072460824609246102461124612246132461424615246162461724618246192462024621246222462324624246252462624627246282462924630246312463224633246342463524636246372463824639246402464124642246432464424645246462464724648246492465024651246522465324654246552465624657246582465924660246612466224663246642466524666246672466824669246702467124672246732467424675246762467724678246792468024681246822468324684246852468624687246882468924690246912469224693246942469524696246972469824699247002470124702247032470424705247062470724708247092471024711247122471324714247152471624717247182471924720247212472224723247242472524726247272472824729247302473124732247332473424735247362473724738247392474024741247422474324744247452474624747247482474924750247512475224753247542475524756247572475824759247602476124762247632476424765247662476724768247692477024771247722477324774247752477624777247782477924780247812478224783247842478524786247872478824789247902479124792247932479424795247962479724798247992480024801248022480324804248052480624807248082480924810248112481224813248142481524816248172481824819248202482124822248232482424825248262482724828248292483024831248322483324834248352483624837248382483924840248412484224843248442484524846248472484824849248502485124852248532485424855248562485724858248592486024861248622486324864248652486624867248682486924870248712487224873248742487524876248772487824879248802488124882248832488424885248862488724888248892489024891248922489324894248952489624897248982489924900249012490224903249042490524906249072490824909249102491124912249132491424915249162491724918249192492024921249222492324924249252492624927249282492924930249312493224933249342493524936249372493824939249402494124942249432494424945249462494724948249492495024951249522495324954249552495624957249582495924960249612496224963249642496524966249672496824969249702497124972249732497424975249762497724978249792498024981249822498324984249852498624987249882498924990249912499224993249942499524996249972499824999250002500125002250032500425005250062500725008250092501025011250122501325014250152501625017250182501925020250212502225023250242502525026250272502825029250302503125032250332503425035250362503725038250392504025041250422504325044250452504625047250482504925050250512505225053250542505525056250572505825059250602506125062250632506425065250662506725068250692507025071250722507325074250752507625077250782507925080250812508225083250842508525086250872508825089250902509125092250932509425095250962509725098250992510025101251022510325104251052510625107251082510925110251112511225113251142511525116251172511825119251202512125122251232512425125251262512725128251292513025131251322513325134251352513625137251382513925140251412514225143251442514525146251472514825149251502515125152251532515425155251562515725158251592516025161251622516325164251652516625167251682516925170251712517225173251742517525176251772517825179251802518125182251832518425185251862518725188251892519025191251922519325194251952519625197251982519925200252012520225203252042520525206252072520825209252102521125212252132521425215252162521725218252192522025221252222522325224252252522625227252282522925230252312523225233252342523525236252372523825239252402524125242252432524425245252462524725248252492525025251252522525325254252552525625257252582525925260252612526225263252642526525266252672526825269252702527125272252732527425275252762527725278252792528025281252822528325284252852528625287252882528925290252912529225293252942529525296252972529825299253002530125302253032530425305253062530725308253092531025311253122531325314253152531625317253182531925320253212532225323253242532525326253272532825329253302533125332253332533425335253362533725338253392534025341253422534325344253452534625347253482534925350253512535225353253542535525356253572535825359253602536125362253632536425365253662536725368253692537025371253722537325374253752537625377253782537925380253812538225383253842538525386253872538825389253902539125392253932539425395253962539725398253992540025401254022540325404254052540625407254082540925410254112541225413254142541525416254172541825419254202542125422254232542425425254262542725428254292543025431254322543325434254352543625437254382543925440254412544225443254442544525446254472544825449254502545125452254532545425455254562545725458254592546025461254622546325464254652546625467254682546925470254712547225473254742547525476254772547825479254802548125482254832548425485254862548725488254892549025491254922549325494254952549625497254982549925500255012550225503255042550525506255072550825509255102551125512255132551425515255162551725518255192552025521255222552325524255252552625527255282552925530255312553225533255342553525536255372553825539255402554125542255432554425545255462554725548255492555025551255522555325554255552555625557255582555925560255612556225563255642556525566255672556825569255702557125572255732557425575255762557725578255792558025581255822558325584255852558625587255882558925590255912559225593255942559525596255972559825599256002560125602256032560425605256062560725608256092561025611256122561325614256152561625617256182561925620256212562225623256242562525626256272562825629256302563125632256332563425635256362563725638256392564025641256422564325644256452564625647256482564925650256512565225653256542565525656256572565825659256602566125662256632566425665256662566725668256692567025671256722567325674256752567625677256782567925680256812568225683256842568525686256872568825689256902569125692256932569425695256962569725698256992570025701257022570325704257052570625707257082570925710257112571225713257142571525716257172571825719257202572125722257232572425725257262572725728257292573025731257322573325734257352573625737257382573925740257412574225743257442574525746257472574825749257502575125752257532575425755257562575725758257592576025761257622576325764257652576625767257682576925770257712577225773257742577525776257772577825779257802578125782257832578425785257862578725788257892579025791257922579325794257952579625797257982579925800258012580225803258042580525806258072580825809258102581125812258132581425815258162581725818258192582025821258222582325824258252582625827258282582925830258312583225833258342583525836258372583825839258402584125842258432584425845258462584725848258492585025851258522585325854258552585625857258582585925860258612586225863258642586525866258672586825869258702587125872258732587425875258762587725878258792588025881258822588325884258852588625887258882588925890258912589225893258942589525896258972589825899259002590125902259032590425905259062590725908259092591025911259122591325914259152591625917259182591925920259212592225923259242592525926259272592825929259302593125932259332593425935259362593725938259392594025941259422594325944259452594625947259482594925950259512595225953259542595525956259572595825959259602596125962259632596425965259662596725968259692597025971259722597325974259752597625977259782597925980259812598225983259842598525986259872598825989259902599125992259932599425995259962599725998259992600026001260022600326004260052600626007260082600926010260112601226013260142601526016260172601826019260202602126022260232602426025260262602726028260292603026031260322603326034260352603626037260382603926040260412604226043260442604526046260472604826049260502605126052260532605426055260562605726058260592606026061260622606326064260652606626067260682606926070260712607226073260742607526076260772607826079260802608126082260832608426085260862608726088260892609026091260922609326094260952609626097260982609926100261012610226103261042610526106261072610826109261102611126112261132611426115261162611726118261192612026121261222612326124261252612626127261282612926130261312613226133261342613526136261372613826139261402614126142261432614426145261462614726148261492615026151261522615326154261552615626157261582615926160261612616226163261642616526166261672616826169261702617126172261732617426175261762617726178261792618026181261822618326184261852618626187261882618926190261912619226193261942619526196261972619826199262002620126202262032620426205262062620726208262092621026211262122621326214262152621626217262182621926220262212622226223262242622526226262272622826229262302623126232262332623426235262362623726238262392624026241262422624326244262452624626247262482624926250262512625226253262542625526256262572625826259262602626126262262632626426265262662626726268262692627026271262722627326274262752627626277262782627926280262812628226283262842628526286262872628826289262902629126292262932629426295262962629726298262992630026301263022630326304263052630626307263082630926310263112631226313263142631526316263172631826319263202632126322263232632426325263262632726328263292633026331263322633326334263352633626337263382633926340263412634226343263442634526346263472634826349263502635126352263532635426355263562635726358263592636026361263622636326364263652636626367263682636926370263712637226373263742637526376263772637826379263802638126382263832638426385263862638726388263892639026391263922639326394263952639626397263982639926400264012640226403264042640526406264072640826409264102641126412264132641426415264162641726418264192642026421264222642326424264252642626427264282642926430264312643226433264342643526436264372643826439264402644126442264432644426445264462644726448264492645026451264522645326454264552645626457264582645926460264612646226463264642646526466264672646826469264702647126472264732647426475264762647726478264792648026481264822648326484264852648626487264882648926490264912649226493264942649526496264972649826499265002650126502265032650426505265062650726508265092651026511265122651326514265152651626517265182651926520265212652226523265242652526526265272652826529265302653126532265332653426535265362653726538265392654026541265422654326544265452654626547265482654926550265512655226553265542655526556265572655826559265602656126562265632656426565265662656726568265692657026571265722657326574265752657626577265782657926580265812658226583265842658526586265872658826589265902659126592265932659426595265962659726598265992660026601266022660326604266052660626607266082660926610266112661226613266142661526616266172661826619266202662126622266232662426625266262662726628266292663026631266322663326634266352663626637266382663926640266412664226643266442664526646266472664826649266502665126652266532665426655266562665726658266592666026661266622666326664266652666626667266682666926670266712667226673266742667526676266772667826679266802668126682266832668426685266862668726688266892669026691266922669326694266952669626697266982669926700267012670226703267042670526706267072670826709267102671126712267132671426715267162671726718267192672026721267222672326724267252672626727267282672926730267312673226733267342673526736267372673826739267402674126742267432674426745267462674726748267492675026751267522675326754267552675626757267582675926760267612676226763267642676526766267672676826769267702677126772267732677426775267762677726778267792678026781267822678326784267852678626787267882678926790267912679226793267942679526796267972679826799268002680126802268032680426805268062680726808268092681026811268122681326814268152681626817268182681926820268212682226823268242682526826268272682826829268302683126832268332683426835268362683726838268392684026841268422684326844268452684626847268482684926850268512685226853268542685526856268572685826859268602686126862268632686426865268662686726868268692687026871268722687326874268752687626877268782687926880268812688226883268842688526886268872688826889268902689126892268932689426895268962689726898268992690026901269022690326904269052690626907269082690926910269112691226913269142691526916269172691826919269202692126922269232692426925269262692726928269292693026931269322693326934269352693626937269382693926940269412694226943269442694526946269472694826949269502695126952269532695426955269562695726958269592696026961269622696326964269652696626967269682696926970269712697226973269742697526976269772697826979269802698126982269832698426985269862698726988269892699026991269922699326994269952699626997269982699927000270012700227003270042700527006270072700827009270102701127012270132701427015270162701727018270192702027021270222702327024270252702627027270282702927030270312703227033270342703527036270372703827039270402704127042270432704427045270462704727048270492705027051270522705327054270552705627057270582705927060270612706227063270642706527066270672706827069270702707127072270732707427075270762707727078270792708027081270822708327084270852708627087270882708927090270912709227093270942709527096270972709827099271002710127102271032710427105271062710727108271092711027111271122711327114271152711627117271182711927120271212712227123271242712527126271272712827129271302713127132271332713427135271362713727138271392714027141271422714327144271452714627147271482714927150271512715227153271542715527156271572715827159271602716127162271632716427165271662716727168271692717027171271722717327174271752717627177271782717927180271812718227183271842718527186271872718827189271902719127192271932719427195271962719727198271992720027201272022720327204272052720627207272082720927210272112721227213272142721527216272172721827219272202722127222272232722427225272262722727228272292723027231272322723327234272352723627237272382723927240272412724227243272442724527246272472724827249272502725127252272532725427255272562725727258272592726027261272622726327264272652726627267272682726927270272712727227273272742727527276272772727827279272802728127282272832728427285272862728727288272892729027291272922729327294272952729627297272982729927300273012730227303273042730527306273072730827309273102731127312273132731427315273162731727318273192732027321273222732327324273252732627327273282732927330273312733227333273342733527336273372733827339273402734127342273432734427345273462734727348273492735027351273522735327354273552735627357273582735927360273612736227363273642736527366273672736827369273702737127372273732737427375273762737727378273792738027381273822738327384273852738627387273882738927390273912739227393273942739527396273972739827399274002740127402274032740427405274062740727408274092741027411274122741327414274152741627417274182741927420274212742227423274242742527426274272742827429274302743127432274332743427435274362743727438274392744027441274422744327444274452744627447274482744927450274512745227453274542745527456274572745827459274602746127462274632746427465274662746727468274692747027471274722747327474274752747627477274782747927480274812748227483274842748527486274872748827489274902749127492274932749427495274962749727498274992750027501275022750327504275052750627507275082750927510275112751227513275142751527516275172751827519275202752127522275232752427525275262752727528275292753027531275322753327534275352753627537275382753927540275412754227543275442754527546275472754827549275502755127552275532755427555275562755727558275592756027561275622756327564275652756627567275682756927570275712757227573275742757527576275772757827579275802758127582275832758427585275862758727588275892759027591275922759327594275952759627597275982759927600276012760227603276042760527606276072760827609276102761127612276132761427615276162761727618276192762027621276222762327624276252762627627276282762927630276312763227633276342763527636276372763827639276402764127642276432764427645276462764727648276492765027651276522765327654276552765627657276582765927660276612766227663276642766527666276672766827669276702767127672276732767427675276762767727678276792768027681276822768327684276852768627687276882768927690276912769227693276942769527696276972769827699277002770127702277032770427705277062770727708277092771027711277122771327714277152771627717277182771927720277212772227723277242772527726277272772827729277302773127732277332773427735277362773727738277392774027741277422774327744277452774627747277482774927750277512775227753277542775527756277572775827759277602776127762277632776427765277662776727768277692777027771277722777327774277752777627777277782777927780277812778227783277842778527786277872778827789277902779127792277932779427795277962779727798277992780027801278022780327804278052780627807278082780927810278112781227813278142781527816278172781827819278202782127822278232782427825278262782727828278292783027831278322783327834278352783627837278382783927840278412784227843278442784527846278472784827849278502785127852278532785427855278562785727858278592786027861278622786327864278652786627867278682786927870278712787227873278742787527876278772787827879278802788127882278832788427885278862788727888278892789027891278922789327894278952789627897278982789927900279012790227903279042790527906279072790827909279102791127912279132791427915279162791727918279192792027921279222792327924279252792627927279282792927930279312793227933279342793527936279372793827939279402794127942279432794427945279462794727948279492795027951279522795327954279552795627957279582795927960279612796227963279642796527966279672796827969279702797127972279732797427975279762797727978279792798027981279822798327984279852798627987279882798927990279912799227993279942799527996279972799827999280002800128002280032800428005280062800728008280092801028011280122801328014280152801628017280182801928020280212802228023280242802528026280272802828029280302803128032280332803428035280362803728038280392804028041280422804328044280452804628047280482804928050280512805228053280542805528056280572805828059280602806128062280632806428065280662806728068280692807028071280722807328074280752807628077280782807928080280812808228083280842808528086280872808828089280902809128092280932809428095280962809728098280992810028101281022810328104281052810628107281082810928110281112811228113281142811528116281172811828119281202812128122281232812428125281262812728128281292813028131281322813328134281352813628137281382813928140281412814228143281442814528146281472814828149281502815128152281532815428155281562815728158281592816028161281622816328164281652816628167281682816928170281712817228173281742817528176281772817828179281802818128182281832818428185281862818728188281892819028191281922819328194281952819628197281982819928200282012820228203282042820528206282072820828209282102821128212282132821428215282162821728218282192822028221282222822328224282252822628227282282822928230282312823228233282342823528236282372823828239282402824128242282432824428245282462824728248282492825028251282522825328254282552825628257282582825928260282612826228263282642826528266282672826828269282702827128272282732827428275282762827728278282792828028281282822828328284282852828628287282882828928290282912829228293282942829528296282972829828299283002830128302283032830428305283062830728308283092831028311283122831328314283152831628317283182831928320283212832228323283242832528326283272832828329283302833128332283332833428335283362833728338283392834028341283422834328344283452834628347283482834928350283512835228353283542835528356283572835828359283602836128362283632836428365283662836728368283692837028371283722837328374283752837628377283782837928380283812838228383283842838528386283872838828389283902839128392283932839428395283962839728398283992840028401284022840328404284052840628407284082840928410284112841228413284142841528416284172841828419284202842128422284232842428425284262842728428284292843028431284322843328434284352843628437284382843928440284412844228443284442844528446284472844828449284502845128452284532845428455284562845728458284592846028461284622846328464284652846628467284682846928470284712847228473284742847528476284772847828479284802848128482284832848428485284862848728488284892849028491284922849328494284952849628497284982849928500285012850228503285042850528506285072850828509285102851128512285132851428515285162851728518285192852028521285222852328524285252852628527285282852928530285312853228533285342853528536285372853828539285402854128542285432854428545285462854728548285492855028551285522855328554285552855628557285582855928560285612856228563285642856528566285672856828569285702857128572285732857428575285762857728578285792858028581285822858328584285852858628587285882858928590285912859228593285942859528596285972859828599286002860128602286032860428605286062860728608286092861028611286122861328614286152861628617286182861928620286212862228623286242862528626286272862828629286302863128632286332863428635286362863728638286392864028641286422864328644286452864628647286482864928650286512865228653286542865528656286572865828659286602866128662286632866428665286662866728668286692867028671286722867328674286752867628677286782867928680286812868228683286842868528686286872868828689286902869128692286932869428695286962869728698286992870028701287022870328704287052870628707287082870928710287112871228713287142871528716287172871828719287202872128722287232872428725287262872728728287292873028731287322873328734287352873628737287382873928740287412874228743287442874528746287472874828749287502875128752287532875428755287562875728758287592876028761287622876328764287652876628767287682876928770287712877228773287742877528776287772877828779287802878128782287832878428785287862878728788287892879028791287922879328794287952879628797287982879928800288012880228803288042880528806288072880828809288102881128812288132881428815288162881728818288192882028821288222882328824288252882628827288282882928830288312883228833288342883528836288372883828839288402884128842288432884428845288462884728848288492885028851288522885328854288552885628857288582885928860288612886228863288642886528866288672886828869288702887128872288732887428875288762887728878288792888028881288822888328884288852888628887288882888928890288912889228893288942889528896288972889828899289002890128902289032890428905289062890728908289092891028911289122891328914289152891628917289182891928920289212892228923289242892528926289272892828929289302893128932289332893428935289362893728938289392894028941289422894328944289452894628947289482894928950289512895228953289542895528956289572895828959289602896128962289632896428965289662896728968289692897028971289722897328974289752897628977289782897928980289812898228983289842898528986289872898828989289902899128992289932899428995289962899728998289992900029001290022900329004290052900629007290082900929010290112901229013290142901529016290172901829019290202902129022290232902429025290262902729028290292903029031290322903329034290352903629037290382903929040290412904229043290442904529046290472904829049290502905129052290532905429055290562905729058290592906029061290622906329064290652906629067290682906929070290712907229073290742907529076290772907829079290802908129082290832908429085290862908729088290892909029091290922909329094290952909629097290982909929100291012910229103291042910529106291072910829109291102911129112291132911429115291162911729118291192912029121291222912329124291252912629127291282912929130291312913229133291342913529136291372913829139291402914129142291432914429145291462914729148291492915029151291522915329154291552915629157291582915929160291612916229163291642916529166291672916829169291702917129172291732917429175291762917729178291792918029181291822918329184291852918629187291882918929190291912919229193291942919529196291972919829199292002920129202292032920429205292062920729208292092921029211292122921329214292152921629217292182921929220292212922229223292242922529226292272922829229292302923129232292332923429235292362923729238292392924029241292422924329244292452924629247292482924929250292512925229253292542925529256292572925829259292602926129262292632926429265292662926729268292692927029271292722927329274292752927629277292782927929280292812928229283292842928529286292872928829289292902929129292292932929429295292962929729298292992930029301293022930329304293052930629307293082930929310293112931229313293142931529316293172931829319293202932129322293232932429325293262932729328293292933029331293322933329334293352933629337293382933929340293412934229343293442934529346293472934829349293502935129352293532935429355293562935729358293592936029361293622936329364293652936629367293682936929370293712937229373293742937529376293772937829379293802938129382293832938429385293862938729388293892939029391293922939329394293952939629397293982939929400294012940229403294042940529406294072940829409294102941129412294132941429415294162941729418294192942029421294222942329424294252942629427294282942929430294312943229433294342943529436294372943829439294402944129442294432944429445294462944729448294492945029451294522945329454294552945629457294582945929460294612946229463294642946529466294672946829469294702947129472294732947429475294762947729478294792948029481294822948329484294852948629487294882948929490294912949229493294942949529496294972949829499295002950129502295032950429505295062950729508295092951029511295122951329514295152951629517295182951929520295212952229523295242952529526295272952829529295302953129532295332953429535295362953729538295392954029541295422954329544295452954629547295482954929550295512955229553295542955529556295572955829559295602956129562295632956429565295662956729568295692957029571295722957329574295752957629577295782957929580295812958229583295842958529586295872958829589295902959129592295932959429595295962959729598295992960029601296022960329604296052960629607296082960929610296112961229613296142961529616296172961829619296202962129622296232962429625296262962729628296292963029631296322963329634296352963629637296382963929640296412964229643296442964529646296472964829649296502965129652296532965429655296562965729658296592966029661296622966329664296652966629667296682966929670296712967229673296742967529676296772967829679296802968129682296832968429685296862968729688296892969029691296922969329694296952969629697296982969929700297012970229703297042970529706297072970829709297102971129712297132971429715297162971729718297192972029721297222972329724297252972629727297282972929730297312973229733297342973529736297372973829739297402974129742297432974429745297462974729748297492975029751297522975329754297552975629757297582975929760297612976229763297642976529766297672976829769297702977129772297732977429775297762977729778297792978029781297822978329784297852978629787297882978929790297912979229793297942979529796297972979829799298002980129802298032980429805298062980729808298092981029811298122981329814298152981629817298182981929820298212982229823298242982529826298272982829829298302983129832298332983429835298362983729838298392984029841298422984329844298452984629847298482984929850298512985229853298542985529856298572985829859298602986129862298632986429865298662986729868298692987029871298722987329874298752987629877298782987929880298812988229883298842988529886298872988829889298902989129892298932989429895298962989729898298992990029901299022990329904299052990629907299082990929910299112991229913299142991529916299172991829919299202992129922299232992429925299262992729928299292993029931299322993329934299352993629937299382993929940299412994229943299442994529946299472994829949299502995129952299532995429955299562995729958299592996029961299622996329964299652996629967299682996929970299712997229973299742997529976299772997829979299802998129982299832998429985299862998729988299892999029991299922999329994299952999629997299982999930000300013000230003300043000530006300073000830009300103001130012300133001430015300163001730018300193002030021300223002330024300253002630027300283002930030300313003230033300343003530036300373003830039300403004130042300433004430045300463004730048300493005030051300523005330054300553005630057300583005930060300613006230063300643006530066300673006830069300703007130072300733007430075300763007730078300793008030081300823008330084300853008630087300883008930090300913009230093300943009530096300973009830099301003010130102301033010430105301063010730108301093011030111301123011330114301153011630117301183011930120301213012230123301243012530126301273012830129301303013130132301333013430135301363013730138301393014030141301423014330144301453014630147301483014930150301513015230153301543015530156301573015830159301603016130162301633016430165301663016730168301693017030171301723017330174301753017630177301783017930180301813018230183301843018530186301873018830189301903019130192301933019430195301963019730198301993020030201302023020330204302053020630207302083020930210302113021230213302143021530216302173021830219302203022130222302233022430225302263022730228302293023030231302323023330234302353023630237302383023930240302413024230243302443024530246302473024830249302503025130252302533025430255302563025730258302593026030261302623026330264302653026630267302683026930270302713027230273302743027530276302773027830279302803028130282302833028430285302863028730288302893029030291302923029330294302953029630297302983029930300303013030230303303043030530306303073030830309303103031130312303133031430315303163031730318303193032030321303223032330324303253032630327303283032930330303313033230333303343033530336303373033830339303403034130342303433034430345303463034730348303493035030351303523035330354303553035630357303583035930360303613036230363303643036530366303673036830369303703037130372303733037430375303763037730378303793038030381303823038330384303853038630387303883038930390303913039230393303943039530396303973039830399304003040130402304033040430405304063040730408304093041030411304123041330414304153041630417304183041930420304213042230423304243042530426304273042830429304303043130432304333043430435304363043730438304393044030441304423044330444304453044630447304483044930450304513045230453304543045530456304573045830459304603046130462304633046430465304663046730468304693047030471304723047330474304753047630477304783047930480304813048230483304843048530486304873048830489304903049130492304933049430495304963049730498304993050030501305023050330504305053050630507305083050930510305113051230513305143051530516305173051830519305203052130522305233052430525305263052730528305293053030531305323053330534305353053630537305383053930540305413054230543305443054530546305473054830549305503055130552305533055430555305563055730558305593056030561305623056330564305653056630567305683056930570305713057230573305743057530576305773057830579305803058130582305833058430585305863058730588305893059030591305923059330594305953059630597305983059930600306013060230603306043060530606306073060830609306103061130612306133061430615306163061730618306193062030621306223062330624306253062630627306283062930630306313063230633306343063530636306373063830639306403064130642306433064430645306463064730648306493065030651306523065330654306553065630657306583065930660306613066230663306643066530666306673066830669306703067130672306733067430675306763067730678306793068030681306823068330684306853068630687306883068930690306913069230693306943069530696306973069830699307003070130702307033070430705307063070730708307093071030711307123071330714307153071630717307183071930720307213072230723307243072530726307273072830729307303073130732307333073430735307363073730738307393074030741307423074330744307453074630747307483074930750307513075230753307543075530756307573075830759307603076130762307633076430765307663076730768307693077030771307723077330774307753077630777307783077930780307813078230783307843078530786307873078830789307903079130792307933079430795307963079730798307993080030801308023080330804308053080630807308083080930810308113081230813308143081530816308173081830819308203082130822308233082430825308263082730828308293083030831308323083330834308353083630837308383083930840308413084230843308443084530846308473084830849308503085130852308533085430855308563085730858308593086030861308623086330864308653086630867308683086930870308713087230873308743087530876308773087830879308803088130882308833088430885308863088730888308893089030891308923089330894308953089630897308983089930900309013090230903309043090530906309073090830909309103091130912309133091430915309163091730918309193092030921309223092330924309253092630927309283092930930309313093230933309343093530936309373093830939309403094130942309433094430945309463094730948309493095030951309523095330954309553095630957309583095930960309613096230963309643096530966309673096830969309703097130972309733097430975309763097730978309793098030981309823098330984309853098630987309883098930990309913099230993309943099530996309973099830999310003100131002310033100431005310063100731008310093101031011310123101331014310153101631017310183101931020310213102231023310243102531026310273102831029310303103131032310333103431035310363103731038310393104031041310423104331044310453104631047310483104931050310513105231053310543105531056310573105831059310603106131062310633106431065310663106731068310693107031071310723107331074310753107631077310783107931080310813108231083310843108531086310873108831089310903109131092310933109431095310963109731098310993110031101311023110331104311053110631107311083110931110311113111231113311143111531116311173111831119311203112131122311233112431125311263112731128311293113031131311323113331134311353113631137311383113931140311413114231143311443114531146311473114831149311503115131152311533115431155311563115731158311593116031161311623116331164311653116631167311683116931170311713117231173311743117531176311773117831179311803118131182311833118431185311863118731188311893119031191311923119331194311953119631197311983119931200312013120231203312043120531206312073120831209312103121131212312133121431215312163121731218312193122031221312223122331224312253122631227312283122931230312313123231233312343123531236312373123831239312403124131242312433124431245312463124731248312493125031251312523125331254312553125631257312583125931260312613126231263312643126531266312673126831269312703127131272312733127431275312763127731278312793128031281312823128331284312853128631287312883128931290312913129231293312943129531296312973129831299313003130131302313033130431305313063130731308313093131031311313123131331314313153131631317313183131931320313213132231323313243132531326313273132831329313303133131332313333133431335313363133731338313393134031341313423134331344313453134631347313483134931350313513135231353313543135531356313573135831359313603136131362313633136431365313663136731368313693137031371313723137331374313753137631377313783137931380313813138231383313843138531386313873138831389313903139131392313933139431395313963139731398313993140031401314023140331404314053140631407314083140931410314113141231413314143141531416314173141831419314203142131422314233142431425314263142731428314293143031431314323143331434314353143631437314383143931440314413144231443314443144531446314473144831449314503145131452314533145431455314563145731458314593146031461314623146331464314653146631467314683146931470314713147231473314743147531476314773147831479314803148131482314833148431485314863148731488314893149031491314923149331494314953149631497314983149931500315013150231503315043150531506315073150831509315103151131512315133151431515315163151731518315193152031521315223152331524315253152631527315283152931530315313153231533315343153531536315373153831539315403154131542315433154431545315463154731548315493155031551315523155331554315553155631557315583155931560315613156231563315643156531566315673156831569315703157131572315733157431575315763157731578315793158031581315823158331584315853158631587315883158931590315913159231593315943159531596315973159831599316003160131602316033160431605316063160731608316093161031611316123161331614316153161631617316183161931620316213162231623316243162531626316273162831629316303163131632316333163431635316363163731638316393164031641316423164331644316453164631647316483164931650316513165231653316543165531656316573165831659316603166131662316633166431665316663166731668316693167031671316723167331674316753167631677316783167931680316813168231683316843168531686316873168831689316903169131692316933169431695316963169731698316993170031701317023170331704317053170631707317083170931710317113171231713317143171531716317173171831719317203172131722317233172431725317263172731728317293173031731317323173331734317353173631737317383173931740317413174231743317443174531746317473174831749317503175131752317533175431755317563175731758317593176031761317623176331764317653176631767317683176931770317713177231773317743177531776317773177831779317803178131782317833178431785317863178731788317893179031791317923179331794317953179631797317983179931800318013180231803318043180531806318073180831809318103181131812318133181431815318163181731818318193182031821318223182331824318253182631827318283182931830318313183231833318343183531836318373183831839318403184131842318433184431845318463184731848318493185031851318523185331854318553185631857318583185931860318613186231863318643186531866318673186831869318703187131872318733187431875318763187731878318793188031881318823188331884318853188631887318883188931890318913189231893318943189531896318973189831899319003190131902319033190431905319063190731908319093191031911319123191331914319153191631917319183191931920319213192231923319243192531926319273192831929319303193131932319333193431935319363193731938319393194031941319423194331944319453194631947319483194931950319513195231953319543195531956319573195831959319603196131962319633196431965319663196731968319693197031971319723197331974319753197631977319783197931980319813198231983319843198531986319873198831989319903199131992319933199431995319963199731998319993200032001320023200332004320053200632007320083200932010320113201232013320143201532016320173201832019320203202132022320233202432025320263202732028320293203032031320323203332034320353203632037320383203932040320413204232043320443204532046320473204832049320503205132052320533205432055320563205732058320593206032061320623206332064320653206632067320683206932070320713207232073320743207532076320773207832079320803208132082320833208432085320863208732088320893209032091320923209332094320953209632097320983209932100321013210232103321043210532106321073210832109321103211132112321133211432115321163211732118321193212032121321223212332124321253212632127321283212932130321313213232133321343213532136321373213832139321403214132142321433214432145321463214732148321493215032151321523215332154321553215632157321583215932160321613216232163321643216532166321673216832169321703217132172321733217432175321763217732178321793218032181321823218332184321853218632187321883218932190321913219232193321943219532196321973219832199322003220132202322033220432205322063220732208322093221032211322123221332214322153221632217322183221932220322213222232223322243222532226322273222832229322303223132232322333223432235322363223732238322393224032241322423224332244322453224632247322483224932250322513225232253322543225532256322573225832259322603226132262322633226432265322663226732268322693227032271322723227332274322753227632277322783227932280322813228232283322843228532286322873228832289322903229132292322933229432295322963229732298322993230032301323023230332304323053230632307323083230932310323113231232313323143231532316323173231832319323203232132322323233232432325323263232732328323293233032331323323233332334323353233632337323383233932340323413234232343323443234532346323473234832349323503235132352323533235432355323563235732358323593236032361323623236332364323653236632367323683236932370323713237232373323743237532376323773237832379323803238132382323833238432385323863238732388323893239032391323923239332394323953239632397323983239932400324013240232403324043240532406324073240832409324103241132412324133241432415324163241732418324193242032421324223242332424324253242632427324283242932430324313243232433324343243532436324373243832439324403244132442324433244432445324463244732448324493245032451324523245332454324553245632457324583245932460324613246232463324643246532466324673246832469324703247132472324733247432475324763247732478324793248032481324823248332484324853248632487324883248932490324913249232493324943249532496324973249832499325003250132502325033250432505325063250732508325093251032511325123251332514325153251632517325183251932520325213252232523325243252532526325273252832529325303253132532325333253432535325363253732538325393254032541325423254332544325453254632547325483254932550325513255232553325543255532556325573255832559325603256132562325633256432565325663256732568325693257032571325723257332574325753257632577325783257932580325813258232583325843258532586325873258832589325903259132592325933259432595325963259732598325993260032601326023260332604326053260632607326083260932610326113261232613326143261532616326173261832619326203262132622326233262432625326263262732628326293263032631326323263332634326353263632637326383263932640326413264232643326443264532646326473264832649326503265132652326533265432655326563265732658326593266032661326623266332664326653266632667326683266932670326713267232673326743267532676326773267832679326803268132682326833268432685326863268732688326893269032691326923269332694326953269632697326983269932700327013270232703327043270532706327073270832709327103271132712327133271432715327163271732718327193272032721327223272332724327253272632727327283272932730327313273232733327343273532736327373273832739327403274132742327433274432745327463274732748327493275032751327523275332754327553275632757327583275932760327613276232763327643276532766327673276832769327703277132772327733277432775327763277732778327793278032781327823278332784327853278632787327883278932790327913279232793327943279532796327973279832799328003280132802328033280432805328063280732808328093281032811328123281332814328153281632817328183281932820328213282232823328243282532826328273282832829328303283132832328333283432835328363283732838328393284032841328423284332844328453284632847328483284932850328513285232853328543285532856328573285832859328603286132862328633286432865328663286732868328693287032871328723287332874328753287632877328783287932880328813288232883328843288532886328873288832889328903289132892328933289432895328963289732898328993290032901329023290332904329053290632907329083290932910329113291232913329143291532916329173291832919329203292132922329233292432925329263292732928329293293032931329323293332934329353293632937329383293932940329413294232943329443294532946329473294832949329503295132952329533295432955329563295732958329593296032961329623296332964329653296632967329683296932970329713297232973329743297532976329773297832979329803298132982329833298432985329863298732988329893299032991329923299332994329953299632997329983299933000330013300233003330043300533006330073300833009330103301133012330133301433015330163301733018330193302033021330223302333024330253302633027330283302933030330313303233033330343303533036330373303833039330403304133042330433304433045330463304733048330493305033051330523305333054330553305633057330583305933060330613306233063330643306533066330673306833069330703307133072330733307433075330763307733078330793308033081330823308333084330853308633087330883308933090330913309233093330943309533096330973309833099331003310133102331033310433105331063310733108331093311033111331123311333114331153311633117331183311933120331213312233123331243312533126331273312833129331303313133132331333313433135331363313733138331393314033141331423314333144331453314633147331483314933150331513315233153331543315533156331573315833159331603316133162331633316433165331663316733168331693317033171331723317333174331753317633177331783317933180331813318233183331843318533186331873318833189331903319133192331933319433195331963319733198331993320033201332023320333204332053320633207332083320933210332113321233213332143321533216332173321833219332203322133222332233322433225332263322733228332293323033231332323323333234332353323633237332383323933240332413324233243332443324533246332473324833249332503325133252332533325433255332563325733258332593326033261332623326333264332653326633267332683326933270332713327233273332743327533276332773327833279332803328133282332833328433285332863328733288332893329033291332923329333294332953329633297332983329933300333013330233303333043330533306333073330833309333103331133312333133331433315333163331733318333193332033321333223332333324333253332633327333283332933330333313333233333333343333533336333373333833339333403334133342333433334433345333463334733348333493335033351333523335333354333553335633357333583335933360333613336233363333643336533366333673336833369333703337133372333733337433375333763337733378333793338033381333823338333384333853338633387333883338933390333913339233393333943339533396333973339833399334003340133402334033340433405334063340733408334093341033411334123341333414334153341633417334183341933420334213342233423334243342533426334273342833429334303343133432334333343433435334363343733438334393344033441334423344333444334453344633447334483344933450334513345233453334543345533456334573345833459334603346133462334633346433465334663346733468334693347033471334723347333474334753347633477334783347933480334813348233483334843348533486334873348833489334903349133492334933349433495334963349733498334993350033501335023350333504335053350633507335083350933510335113351233513335143351533516335173351833519335203352133522335233352433525335263352733528335293353033531335323353333534335353353633537335383353933540335413354233543335443354533546335473354833549335503355133552335533355433555335563355733558335593356033561335623356333564335653356633567335683356933570335713357233573335743357533576335773357833579335803358133582335833358433585335863358733588335893359033591335923359333594335953359633597335983359933600336013360233603336043360533606336073360833609336103361133612336133361433615336163361733618336193362033621336223362333624336253362633627336283362933630336313363233633336343363533636336373363833639336403364133642336433364433645336463364733648336493365033651336523365333654336553365633657336583365933660336613366233663336643366533666336673366833669336703367133672336733367433675336763367733678336793368033681336823368333684336853368633687336883368933690336913369233693336943369533696336973369833699337003370133702337033370433705337063370733708337093371033711337123371333714337153371633717337183371933720337213372233723337243372533726337273372833729337303373133732337333373433735337363373733738337393374033741337423374333744337453374633747337483374933750337513375233753337543375533756337573375833759337603376133762337633376433765337663376733768337693377033771337723377333774337753377633777337783377933780337813378233783337843378533786337873378833789337903379133792337933379433795337963379733798337993380033801338023380333804338053380633807338083380933810338113381233813338143381533816338173381833819338203382133822338233382433825338263382733828338293383033831338323383333834338353383633837338383383933840338413384233843338443384533846338473384833849338503385133852338533385433855338563385733858338593386033861338623386333864338653386633867338683386933870338713387233873338743387533876338773387833879338803388133882338833388433885338863388733888338893389033891338923389333894338953389633897338983389933900339013390233903339043390533906339073390833909339103391133912339133391433915339163391733918339193392033921339223392333924339253392633927339283392933930339313393233933339343393533936339373393833939339403394133942339433394433945339463394733948339493395033951339523395333954339553395633957339583395933960339613396233963339643396533966339673396833969339703397133972339733397433975339763397733978339793398033981339823398333984339853398633987339883398933990339913399233993339943399533996339973399833999340003400134002340033400434005340063400734008340093401034011340123401334014340153401634017340183401934020340213402234023340243402534026340273402834029340303403134032340333403434035340363403734038340393404034041340423404334044340453404634047340483404934050340513405234053340543405534056340573405834059340603406134062340633406434065340663406734068340693407034071340723407334074340753407634077340783407934080340813408234083340843408534086340873408834089340903409134092340933409434095340963409734098340993410034101341023410334104341053410634107341083410934110341113411234113341143411534116341173411834119341203412134122341233412434125341263412734128341293413034131341323413334134341353413634137341383413934140341413414234143341443414534146341473414834149341503415134152341533415434155341563415734158341593416034161341623416334164341653416634167341683416934170341713417234173341743417534176341773417834179341803418134182341833418434185341863418734188341893419034191341923419334194341953419634197341983419934200342013420234203342043420534206342073420834209342103421134212342133421434215342163421734218342193422034221342223422334224342253422634227342283422934230342313423234233342343423534236342373423834239342403424134242342433424434245342463424734248342493425034251342523425334254342553425634257342583425934260342613426234263342643426534266342673426834269342703427134272342733427434275342763427734278342793428034281342823428334284342853428634287342883428934290342913429234293342943429534296342973429834299343003430134302343033430434305343063430734308343093431034311343123431334314343153431634317343183431934320343213432234323343243432534326343273432834329343303433134332343333433434335343363433734338343393434034341343423434334344343453434634347343483434934350343513435234353343543435534356343573435834359343603436134362343633436434365343663436734368343693437034371343723437334374343753437634377343783437934380343813438234383343843438534386343873438834389343903439134392343933439434395343963439734398343993440034401344023440334404344053440634407344083440934410344113441234413344143441534416344173441834419344203442134422344233442434425344263442734428344293443034431344323443334434344353443634437344383443934440344413444234443344443444534446344473444834449344503445134452344533445434455344563445734458344593446034461344623446334464344653446634467344683446934470344713447234473344743447534476344773447834479344803448134482344833448434485344863448734488344893449034491344923449334494344953449634497344983449934500345013450234503345043450534506345073450834509345103451134512345133451434515345163451734518345193452034521345223452334524345253452634527345283452934530345313453234533345343453534536345373453834539345403454134542345433454434545345463454734548345493455034551345523455334554345553455634557345583455934560345613456234563345643456534566345673456834569345703457134572345733457434575345763457734578345793458034581345823458334584345853458634587345883458934590345913459234593345943459534596345973459834599346003460134602346033460434605346063460734608346093461034611346123461334614346153461634617346183461934620346213462234623346243462534626346273462834629346303463134632346333463434635346363463734638346393464034641346423464334644346453464634647346483464934650346513465234653346543465534656346573465834659346603466134662346633466434665346663466734668346693467034671346723467334674346753467634677346783467934680346813468234683346843468534686346873468834689346903469134692346933469434695346963469734698346993470034701347023470334704347053470634707347083470934710347113471234713347143471534716347173471834719347203472134722347233472434725347263472734728347293473034731347323473334734347353473634737347383473934740347413474234743347443474534746347473474834749347503475134752347533475434755347563475734758347593476034761347623476334764347653476634767347683476934770347713477234773347743477534776347773477834779347803478134782347833478434785347863478734788347893479034791347923479334794347953479634797347983479934800348013480234803348043480534806348073480834809348103481134812348133481434815348163481734818348193482034821348223482334824348253482634827348283482934830348313483234833348343483534836348373483834839348403484134842348433484434845348463484734848348493485034851348523485334854348553485634857348583485934860348613486234863348643486534866348673486834869348703487134872348733487434875348763487734878348793488034881348823488334884348853488634887348883488934890348913489234893348943489534896348973489834899349003490134902349033490434905349063490734908349093491034911349123491334914349153491634917349183491934920349213492234923349243492534926349273492834929349303493134932349333493434935349363493734938349393494034941349423494334944349453494634947349483494934950349513495234953349543495534956349573495834959349603496134962349633496434965349663496734968349693497034971349723497334974349753497634977349783497934980349813498234983349843498534986349873498834989349903499134992349933499434995349963499734998349993500035001350023500335004350053500635007350083500935010350113501235013350143501535016350173501835019350203502135022350233502435025350263502735028350293503035031350323503335034350353503635037350383503935040350413504235043350443504535046350473504835049350503505135052350533505435055350563505735058350593506035061350623506335064350653506635067350683506935070350713507235073350743507535076350773507835079350803508135082350833508435085350863508735088350893509035091350923509335094350953509635097350983509935100351013510235103351043510535106351073510835109351103511135112351133511435115351163511735118351193512035121351223512335124351253512635127351283512935130351313513235133351343513535136351373513835139351403514135142351433514435145351463514735148351493515035151351523515335154351553515635157351583515935160351613516235163351643516535166351673516835169351703517135172351733517435175351763517735178351793518035181351823518335184351853518635187351883518935190351913519235193351943519535196351973519835199352003520135202352033520435205352063520735208352093521035211352123521335214352153521635217352183521935220352213522235223352243522535226352273522835229352303523135232352333523435235352363523735238352393524035241352423524335244352453524635247352483524935250352513525235253352543525535256352573525835259352603526135262352633526435265352663526735268352693527035271352723527335274352753527635277352783527935280352813528235283352843528535286352873528835289352903529135292352933529435295352963529735298352993530035301353023530335304353053530635307353083530935310353113531235313353143531535316353173531835319353203532135322353233532435325353263532735328353293533035331353323533335334353353533635337353383533935340353413534235343353443534535346353473534835349353503535135352353533535435355353563535735358353593536035361353623536335364353653536635367353683536935370353713537235373353743537535376353773537835379353803538135382353833538435385353863538735388353893539035391353923539335394353953539635397353983539935400354013540235403354043540535406354073540835409354103541135412354133541435415354163541735418354193542035421354223542335424354253542635427354283542935430354313543235433354343543535436354373543835439354403544135442354433544435445354463544735448354493545035451354523545335454354553545635457354583545935460354613546235463354643546535466354673546835469354703547135472354733547435475354763547735478354793548035481354823548335484354853548635487354883548935490354913549235493354943549535496354973549835499355003550135502355033550435505355063550735508355093551035511355123551335514355153551635517355183551935520355213552235523355243552535526355273552835529355303553135532355333553435535355363553735538355393554035541355423554335544355453554635547355483554935550355513555235553355543555535556355573555835559355603556135562355633556435565355663556735568355693557035571355723557335574355753557635577355783557935580355813558235583355843558535586355873558835589355903559135592355933559435595355963559735598355993560035601356023560335604356053560635607356083560935610356113561235613356143561535616356173561835619356203562135622356233562435625356263562735628356293563035631356323563335634356353563635637356383563935640356413564235643356443564535646356473564835649356503565135652356533565435655356563565735658356593566035661356623566335664356653566635667356683566935670356713567235673356743567535676356773567835679356803568135682356833568435685356863568735688356893569035691356923569335694356953569635697356983569935700357013570235703357043570535706357073570835709357103571135712357133571435715357163571735718357193572035721357223572335724357253572635727357283572935730357313573235733357343573535736357373573835739357403574135742357433574435745357463574735748357493575035751357523575335754357553575635757357583575935760357613576235763357643576535766357673576835769357703577135772357733577435775357763577735778357793578035781357823578335784357853578635787357883578935790357913579235793357943579535796357973579835799358003580135802358033580435805358063580735808358093581035811358123581335814358153581635817358183581935820358213582235823358243582535826358273582835829358303583135832358333583435835358363583735838358393584035841358423584335844358453584635847358483584935850358513585235853358543585535856358573585835859358603586135862358633586435865358663586735868358693587035871358723587335874358753587635877358783587935880358813588235883358843588535886358873588835889358903589135892358933589435895358963589735898358993590035901359023590335904359053590635907359083590935910359113591235913359143591535916359173591835919359203592135922359233592435925359263592735928359293593035931359323593335934359353593635937359383593935940359413594235943359443594535946359473594835949359503595135952359533595435955359563595735958359593596035961359623596335964359653596635967359683596935970359713597235973359743597535976359773597835979359803598135982359833598435985359863598735988359893599035991359923599335994359953599635997359983599936000360013600236003360043600536006360073600836009360103601136012360133601436015360163601736018360193602036021360223602336024360253602636027360283602936030360313603236033360343603536036360373603836039360403604136042360433604436045360463604736048360493605036051360523605336054360553605636057360583605936060360613606236063360643606536066360673606836069360703607136072360733607436075360763607736078360793608036081360823608336084360853608636087360883608936090360913609236093360943609536096360973609836099361003610136102361033610436105361063610736108361093611036111361123611336114361153611636117361183611936120361213612236123361243612536126361273612836129361303613136132361333613436135361363613736138361393614036141361423614336144361453614636147361483614936150361513615236153361543615536156361573615836159361603616136162361633616436165361663616736168361693617036171361723617336174361753617636177361783617936180361813618236183361843618536186361873618836189361903619136192361933619436195361963619736198361993620036201362023620336204362053620636207362083620936210362113621236213362143621536216362173621836219362203622136222362233622436225362263622736228362293623036231362323623336234362353623636237362383623936240362413624236243362443624536246362473624836249362503625136252362533625436255362563625736258362593626036261362623626336264362653626636267362683626936270362713627236273362743627536276362773627836279362803628136282362833628436285362863628736288362893629036291362923629336294362953629636297362983629936300363013630236303363043630536306363073630836309363103631136312363133631436315363163631736318363193632036321363223632336324363253632636327363283632936330363313633236333363343633536336363373633836339363403634136342363433634436345363463634736348363493635036351363523635336354363553635636357363583635936360363613636236363363643636536366363673636836369363703637136372363733637436375363763637736378363793638036381363823638336384363853638636387363883638936390363913639236393363943639536396363973639836399364003640136402364033640436405364063640736408364093641036411364123641336414364153641636417364183641936420364213642236423364243642536426364273642836429364303643136432364333643436435364363643736438364393644036441364423644336444364453644636447364483644936450364513645236453364543645536456364573645836459364603646136462364633646436465364663646736468364693647036471364723647336474364753647636477364783647936480364813648236483364843648536486364873648836489364903649136492364933649436495364963649736498364993650036501365023650336504365053650636507365083650936510365113651236513365143651536516365173651836519365203652136522365233652436525365263652736528365293653036531365323653336534365353653636537365383653936540365413654236543365443654536546365473654836549365503655136552365533655436555365563655736558365593656036561365623656336564365653656636567365683656936570365713657236573365743657536576365773657836579365803658136582365833658436585365863658736588365893659036591365923659336594365953659636597365983659936600366013660236603366043660536606366073660836609366103661136612366133661436615366163661736618366193662036621366223662336624366253662636627366283662936630366313663236633366343663536636366373663836639366403664136642366433664436645366463664736648366493665036651366523665336654366553665636657366583665936660366613666236663366643666536666366673666836669366703667136672366733667436675366763667736678366793668036681366823668336684366853668636687366883668936690366913669236693366943669536696366973669836699367003670136702367033670436705367063670736708367093671036711367123671336714367153671636717367183671936720367213672236723367243672536726367273672836729367303673136732367333673436735367363673736738367393674036741367423674336744367453674636747367483674936750367513675236753367543675536756367573675836759367603676136762367633676436765367663676736768367693677036771367723677336774367753677636777367783677936780367813678236783367843678536786367873678836789367903679136792367933679436795367963679736798367993680036801368023680336804368053680636807368083680936810368113681236813368143681536816368173681836819368203682136822368233682436825368263682736828368293683036831368323683336834368353683636837368383683936840368413684236843368443684536846368473684836849368503685136852368533685436855368563685736858368593686036861368623686336864368653686636867368683686936870368713687236873368743687536876368773687836879368803688136882368833688436885368863688736888368893689036891368923689336894368953689636897368983689936900369013690236903369043690536906369073690836909369103691136912369133691436915369163691736918369193692036921369223692336924369253692636927369283692936930369313693236933369343693536936369373693836939369403694136942369433694436945369463694736948369493695036951369523695336954369553695636957369583695936960369613696236963369643696536966369673696836969369703697136972369733697436975369763697736978369793698036981369823698336984369853698636987369883698936990369913699236993369943699536996369973699836999370003700137002370033700437005370063700737008370093701037011370123701337014370153701637017370183701937020370213702237023370243702537026370273702837029370303703137032370333703437035370363703737038370393704037041370423704337044370453704637047370483704937050370513705237053370543705537056370573705837059370603706137062370633706437065370663706737068370693707037071370723707337074370753707637077370783707937080370813708237083370843708537086370873708837089370903709137092370933709437095370963709737098370993710037101371023710337104371053710637107371083710937110371113711237113371143711537116371173711837119371203712137122371233712437125371263712737128371293713037131371323713337134371353713637137371383713937140371413714237143371443714537146371473714837149371503715137152371533715437155371563715737158371593716037161371623716337164371653716637167371683716937170371713717237173371743717537176371773717837179371803718137182371833718437185371863718737188371893719037191371923719337194371953719637197371983719937200372013720237203372043720537206372073720837209372103721137212372133721437215372163721737218372193722037221372223722337224372253722637227372283722937230372313723237233372343723537236372373723837239372403724137242372433724437245372463724737248372493725037251372523725337254372553725637257372583725937260372613726237263372643726537266372673726837269372703727137272372733727437275372763727737278372793728037281372823728337284372853728637287372883728937290372913729237293372943729537296372973729837299373003730137302373033730437305373063730737308373093731037311373123731337314373153731637317373183731937320373213732237323373243732537326373273732837329373303733137332373333733437335373363733737338373393734037341373423734337344373453734637347373483734937350373513735237353373543735537356373573735837359373603736137362373633736437365373663736737368373693737037371373723737337374373753737637377373783737937380373813738237383373843738537386373873738837389373903739137392373933739437395373963739737398373993740037401374023740337404374053740637407374083740937410374113741237413374143741537416374173741837419374203742137422374233742437425374263742737428374293743037431374323743337434374353743637437374383743937440374413744237443374443744537446374473744837449374503745137452374533745437455374563745737458374593746037461374623746337464374653746637467374683746937470374713747237473374743747537476374773747837479374803748137482374833748437485374863748737488374893749037491374923749337494374953749637497374983749937500375013750237503375043750537506375073750837509375103751137512375133751437515375163751737518375193752037521375223752337524375253752637527375283752937530375313753237533375343753537536375373753837539375403754137542375433754437545375463754737548375493755037551375523755337554375553755637557375583755937560375613756237563375643756537566375673756837569375703757137572375733757437575375763757737578375793758037581375823758337584375853758637587375883758937590375913759237593375943759537596375973759837599376003760137602376033760437605376063760737608376093761037611376123761337614376153761637617376183761937620376213762237623376243762537626376273762837629376303763137632376333763437635376363763737638376393764037641376423764337644376453764637647376483764937650376513765237653376543765537656376573765837659376603766137662376633766437665376663766737668376693767037671376723767337674376753767637677376783767937680376813768237683376843768537686376873768837689376903769137692376933769437695376963769737698376993770037701377023770337704377053770637707377083770937710377113771237713377143771537716377173771837719377203772137722377233772437725377263772737728377293773037731377323773337734377353773637737377383773937740377413774237743377443774537746377473774837749377503775137752377533775437755377563775737758377593776037761377623776337764377653776637767377683776937770377713777237773377743777537776377773777837779377803778137782377833778437785377863778737788377893779037791377923779337794377953779637797377983779937800378013780237803378043780537806378073780837809378103781137812378133781437815378163781737818378193782037821378223782337824378253782637827378283782937830378313783237833378343783537836378373783837839378403784137842378433784437845378463784737848378493785037851378523785337854378553785637857378583785937860378613786237863378643786537866378673786837869378703787137872378733787437875378763787737878378793788037881378823788337884378853788637887378883788937890378913789237893378943789537896378973789837899379003790137902379033790437905379063790737908379093791037911379123791337914379153791637917379183791937920379213792237923379243792537926379273792837929379303793137932379333793437935379363793737938379393794037941379423794337944379453794637947379483794937950379513795237953379543795537956379573795837959379603796137962379633796437965379663796737968379693797037971379723797337974379753797637977379783797937980379813798237983379843798537986379873798837989379903799137992379933799437995379963799737998379993800038001380023800338004380053800638007380083800938010380113801238013380143801538016380173801838019380203802138022380233802438025380263802738028380293803038031380323803338034380353803638037380383803938040380413804238043380443804538046380473804838049380503805138052380533805438055380563805738058380593806038061380623806338064380653806638067380683806938070380713807238073380743807538076380773807838079380803808138082380833808438085380863808738088380893809038091380923809338094380953809638097380983809938100381013810238103381043810538106381073810838109381103811138112381133811438115381163811738118381193812038121381223812338124381253812638127381283812938130381313813238133381343813538136381373813838139381403814138142381433814438145381463814738148381493815038151381523815338154381553815638157381583815938160381613816238163381643816538166381673816838169381703817138172381733817438175381763817738178381793818038181381823818338184381853818638187381883818938190381913819238193381943819538196381973819838199382003820138202382033820438205382063820738208382093821038211382123821338214382153821638217382183821938220382213822238223382243822538226382273822838229382303823138232382333823438235382363823738238382393824038241382423824338244382453824638247382483824938250382513825238253382543825538256382573825838259382603826138262382633826438265382663826738268382693827038271382723827338274382753827638277382783827938280382813828238283382843828538286382873828838289382903829138292382933829438295382963829738298382993830038301383023830338304383053830638307383083830938310383113831238313383143831538316383173831838319383203832138322383233832438325383263832738328383293833038331383323833338334383353833638337383383833938340383413834238343383443834538346383473834838349383503835138352383533835438355383563835738358383593836038361383623836338364383653836638367383683836938370383713837238373383743837538376383773837838379383803838138382383833838438385383863838738388383893839038391383923839338394383953839638397383983839938400384013840238403384043840538406384073840838409384103841138412384133841438415384163841738418384193842038421384223842338424384253842638427384283842938430384313843238433384343843538436384373843838439384403844138442384433844438445384463844738448384493845038451384523845338454384553845638457384583845938460384613846238463384643846538466384673846838469384703847138472384733847438475384763847738478384793848038481384823848338484384853848638487384883848938490384913849238493384943849538496384973849838499385003850138502385033850438505385063850738508385093851038511385123851338514385153851638517385183851938520385213852238523385243852538526385273852838529385303853138532385333853438535385363853738538385393854038541385423854338544385453854638547385483854938550385513855238553385543855538556385573855838559385603856138562385633856438565385663856738568385693857038571385723857338574385753857638577385783857938580385813858238583385843858538586385873858838589385903859138592385933859438595385963859738598385993860038601386023860338604386053860638607386083860938610386113861238613386143861538616386173861838619386203862138622386233862438625386263862738628386293863038631386323863338634386353863638637386383863938640386413864238643386443864538646386473864838649386503865138652386533865438655386563865738658386593866038661386623866338664386653866638667386683866938670386713867238673386743867538676386773867838679386803868138682386833868438685386863868738688386893869038691386923869338694386953869638697386983869938700387013870238703387043870538706387073870838709387103871138712387133871438715387163871738718387193872038721387223872338724387253872638727387283872938730387313873238733387343873538736387373873838739387403874138742387433874438745387463874738748387493875038751387523875338754387553875638757387583875938760387613876238763387643876538766387673876838769387703877138772387733877438775387763877738778387793878038781387823878338784387853878638787387883878938790387913879238793387943879538796387973879838799388003880138802388033880438805388063880738808388093881038811388123881338814388153881638817388183881938820388213882238823388243882538826388273882838829388303883138832388333883438835388363883738838388393884038841388423884338844388453884638847388483884938850388513885238853388543885538856388573885838859388603886138862388633886438865388663886738868388693887038871388723887338874388753887638877388783887938880388813888238883388843888538886388873888838889388903889138892388933889438895388963889738898388993890038901389023890338904389053890638907389083890938910389113891238913389143891538916389173891838919389203892138922389233892438925389263892738928389293893038931389323893338934389353893638937389383893938940389413894238943389443894538946389473894838949389503895138952389533895438955389563895738958389593896038961389623896338964389653896638967389683896938970389713897238973389743897538976389773897838979389803898138982389833898438985389863898738988389893899038991389923899338994389953899638997389983899939000390013900239003390043900539006390073900839009390103901139012390133901439015390163901739018390193902039021390223902339024390253902639027390283902939030390313903239033390343903539036390373903839039390403904139042390433904439045390463904739048390493905039051390523905339054390553905639057390583905939060390613906239063390643906539066390673906839069390703907139072390733907439075390763907739078390793908039081390823908339084390853908639087390883908939090390913909239093390943909539096390973909839099391003910139102391033910439105391063910739108391093911039111391123911339114391153911639117391183911939120391213912239123391243912539126391273912839129391303913139132391333913439135391363913739138391393914039141391423914339144391453914639147391483914939150391513915239153391543915539156391573915839159391603916139162391633916439165391663916739168391693917039171391723917339174391753917639177391783917939180391813918239183391843918539186391873918839189391903919139192391933919439195391963919739198391993920039201392023920339204392053920639207392083920939210392113921239213392143921539216392173921839219392203922139222392233922439225392263922739228392293923039231392323923339234392353923639237392383923939240392413924239243392443924539246392473924839249392503925139252392533925439255392563925739258392593926039261392623926339264392653926639267392683926939270392713927239273392743927539276392773927839279392803928139282392833928439285392863928739288392893929039291392923929339294392953929639297392983929939300393013930239303393043930539306393073930839309393103931139312393133931439315393163931739318393193932039321393223932339324393253932639327393283932939330393313933239333393343933539336393373933839339393403934139342393433934439345393463934739348393493935039351393523935339354393553935639357393583935939360393613936239363393643936539366393673936839369393703937139372393733937439375393763937739378393793938039381393823938339384393853938639387393883938939390393913939239393393943939539396393973939839399394003940139402394033940439405394063940739408394093941039411394123941339414394153941639417394183941939420394213942239423394243942539426394273942839429394303943139432394333943439435394363943739438394393944039441394423944339444394453944639447394483944939450394513945239453394543945539456394573945839459394603946139462394633946439465394663946739468394693947039471394723947339474394753947639477394783947939480394813948239483394843948539486394873948839489394903949139492394933949439495394963949739498394993950039501395023950339504395053950639507395083950939510395113951239513395143951539516395173951839519395203952139522395233952439525395263952739528395293953039531395323953339534395353953639537395383953939540395413954239543395443954539546395473954839549395503955139552395533955439555395563955739558395593956039561395623956339564395653956639567395683956939570395713957239573395743957539576395773957839579395803958139582395833958439585395863958739588395893959039591395923959339594395953959639597395983959939600396013960239603396043960539606396073960839609396103961139612396133961439615396163961739618396193962039621396223962339624396253962639627396283962939630396313963239633396343963539636396373963839639396403964139642396433964439645396463964739648396493965039651396523965339654396553965639657396583965939660396613966239663396643966539666396673966839669396703967139672396733967439675396763967739678396793968039681396823968339684396853968639687396883968939690396913969239693396943969539696396973969839699397003970139702397033970439705397063970739708397093971039711397123971339714397153971639717397183971939720397213972239723397243972539726397273972839729397303973139732397333973439735397363973739738397393974039741397423974339744397453974639747397483974939750397513975239753397543975539756397573975839759397603976139762397633976439765397663976739768397693977039771397723977339774397753977639777397783977939780397813978239783397843978539786397873978839789397903979139792397933979439795397963979739798397993980039801398023980339804398053980639807398083980939810398113981239813398143981539816398173981839819398203982139822398233982439825398263982739828398293983039831398323983339834398353983639837398383983939840398413984239843398443984539846398473984839849398503985139852398533985439855398563985739858398593986039861398623986339864398653986639867398683986939870398713987239873398743987539876398773987839879398803988139882398833988439885398863988739888398893989039891398923989339894398953989639897398983989939900399013990239903399043990539906399073990839909399103991139912399133991439915399163991739918399193992039921399223992339924399253992639927399283992939930399313993239933399343993539936399373993839939399403994139942399433994439945399463994739948399493995039951399523995339954399553995639957399583995939960399613996239963399643996539966399673996839969399703997139972399733997439975399763997739978399793998039981399823998339984399853998639987399883998939990399913999239993399943999539996399973999839999400004000140002400034000440005400064000740008400094001040011400124001340014400154001640017400184001940020400214002240023400244002540026400274002840029400304003140032400334003440035400364003740038400394004040041400424004340044400454004640047400484004940050400514005240053400544005540056400574005840059400604006140062400634006440065400664006740068400694007040071400724007340074400754007640077400784007940080400814008240083400844008540086400874008840089400904009140092400934009440095400964009740098400994010040101401024010340104401054010640107401084010940110401114011240113401144011540116401174011840119401204012140122401234012440125401264012740128401294013040131401324013340134401354013640137401384013940140401414014240143401444014540146401474014840149401504015140152401534015440155401564015740158401594016040161401624016340164401654016640167401684016940170401714017240173401744017540176401774017840179401804018140182401834018440185401864018740188401894019040191401924019340194401954019640197401984019940200402014020240203402044020540206402074020840209402104021140212402134021440215402164021740218402194022040221402224022340224402254022640227402284022940230402314023240233402344023540236402374023840239402404024140242402434024440245402464024740248402494025040251402524025340254402554025640257402584025940260402614026240263402644026540266402674026840269402704027140272402734027440275402764027740278402794028040281402824028340284402854028640287402884028940290402914029240293402944029540296402974029840299403004030140302403034030440305403064030740308403094031040311403124031340314403154031640317403184031940320403214032240323403244032540326403274032840329403304033140332403334033440335403364033740338403394034040341403424034340344403454034640347403484034940350403514035240353403544035540356403574035840359403604036140362403634036440365403664036740368403694037040371403724037340374403754037640377403784037940380403814038240383403844038540386403874038840389403904039140392403934039440395403964039740398403994040040401404024040340404404054040640407404084040940410404114041240413404144041540416404174041840419404204042140422404234042440425404264042740428404294043040431404324043340434404354043640437404384043940440404414044240443404444044540446404474044840449404504045140452404534045440455404564045740458404594046040461404624046340464404654046640467404684046940470404714047240473404744047540476404774047840479404804048140482404834048440485404864048740488404894049040491404924049340494404954049640497404984049940500405014050240503405044050540506405074050840509405104051140512405134051440515405164051740518405194052040521405224052340524405254052640527405284052940530405314053240533405344053540536405374053840539405404054140542405434054440545405464054740548405494055040551405524055340554405554055640557405584055940560405614056240563405644056540566405674056840569405704057140572405734057440575405764057740578405794058040581405824058340584405854058640587405884058940590405914059240593405944059540596405974059840599406004060140602406034060440605406064060740608406094061040611406124061340614406154061640617406184061940620406214062240623406244062540626406274062840629406304063140632406334063440635406364063740638406394064040641406424064340644406454064640647406484064940650406514065240653406544065540656406574065840659406604066140662406634066440665406664066740668406694067040671406724067340674406754067640677406784067940680406814068240683406844068540686406874068840689406904069140692406934069440695406964069740698406994070040701407024070340704407054070640707407084070940710407114071240713407144071540716407174071840719407204072140722407234072440725407264072740728407294073040731407324073340734407354073640737407384073940740407414074240743407444074540746407474074840749407504075140752407534075440755407564075740758407594076040761407624076340764407654076640767407684076940770407714077240773407744077540776407774077840779407804078140782407834078440785407864078740788407894079040791407924079340794407954079640797407984079940800408014080240803408044080540806408074080840809408104081140812408134081440815408164081740818408194082040821408224082340824408254082640827408284082940830408314083240833408344083540836408374083840839408404084140842408434084440845408464084740848408494085040851408524085340854408554085640857408584085940860408614086240863408644086540866408674086840869408704087140872408734087440875408764087740878408794088040881408824088340884408854088640887408884088940890408914089240893408944089540896408974089840899409004090140902409034090440905409064090740908409094091040911409124091340914409154091640917409184091940920409214092240923409244092540926409274092840929409304093140932409334093440935409364093740938409394094040941409424094340944409454094640947409484094940950409514095240953409544095540956409574095840959409604096140962409634096440965409664096740968409694097040971409724097340974409754097640977409784097940980409814098240983409844098540986409874098840989409904099140992409934099440995409964099740998409994100041001410024100341004410054100641007410084100941010410114101241013410144101541016410174101841019410204102141022410234102441025410264102741028410294103041031410324103341034410354103641037410384103941040410414104241043410444104541046410474104841049410504105141052410534105441055410564105741058410594106041061410624106341064410654106641067410684106941070410714107241073410744107541076410774107841079410804108141082410834108441085410864108741088410894109041091410924109341094410954109641097410984109941100411014110241103411044110541106411074110841109411104111141112411134111441115411164111741118411194112041121411224112341124411254112641127411284112941130411314113241133411344113541136411374113841139411404114141142411434114441145411464114741148411494115041151411524115341154411554115641157411584115941160411614116241163411644116541166411674116841169411704117141172411734117441175411764117741178411794118041181411824118341184411854118641187411884118941190411914119241193411944119541196411974119841199412004120141202412034120441205412064120741208412094121041211412124121341214412154121641217412184121941220412214122241223412244122541226412274122841229412304123141232412334123441235412364123741238412394124041241412424124341244412454124641247412484124941250412514125241253412544125541256412574125841259412604126141262412634126441265412664126741268412694127041271412724127341274412754127641277412784127941280412814128241283412844128541286412874128841289412904129141292412934129441295412964129741298412994130041301413024130341304413054130641307413084130941310413114131241313413144131541316413174131841319413204132141322413234132441325413264132741328413294133041331413324133341334413354133641337413384133941340413414134241343413444134541346413474134841349413504135141352413534135441355413564135741358413594136041361413624136341364413654136641367413684136941370413714137241373413744137541376413774137841379413804138141382413834138441385413864138741388413894139041391413924139341394413954139641397413984139941400414014140241403414044140541406414074140841409414104141141412414134141441415414164141741418414194142041421414224142341424414254142641427414284142941430414314143241433414344143541436414374143841439414404144141442414434144441445414464144741448414494145041451414524145341454414554145641457414584145941460414614146241463414644146541466414674146841469414704147141472414734147441475414764147741478414794148041481414824148341484414854148641487414884148941490414914149241493414944149541496414974149841499415004150141502415034150441505415064150741508415094151041511415124151341514415154151641517415184151941520415214152241523415244152541526415274152841529415304153141532415334153441535415364153741538415394154041541415424154341544415454154641547415484154941550415514155241553415544155541556415574155841559415604156141562415634156441565415664156741568415694157041571415724157341574415754157641577415784157941580415814158241583415844158541586415874158841589415904159141592415934159441595415964159741598415994160041601416024160341604416054160641607416084160941610416114161241613416144161541616416174161841619416204162141622416234162441625416264162741628416294163041631416324163341634416354163641637416384163941640416414164241643416444164541646416474164841649416504165141652416534165441655416564165741658416594166041661416624166341664416654166641667416684166941670416714167241673416744167541676416774167841679416804168141682416834168441685416864168741688416894169041691416924169341694416954169641697416984169941700417014170241703417044170541706417074170841709417104171141712417134171441715417164171741718417194172041721417224172341724417254172641727417284172941730417314173241733417344173541736417374173841739417404174141742417434174441745417464174741748417494175041751417524175341754417554175641757417584175941760417614176241763417644176541766417674176841769417704177141772417734177441775417764177741778417794178041781417824178341784417854178641787417884178941790417914179241793417944179541796417974179841799418004180141802418034180441805418064180741808418094181041811418124181341814418154181641817418184181941820418214182241823418244182541826418274182841829418304183141832418334183441835418364183741838418394184041841418424184341844418454184641847418484184941850418514185241853418544185541856418574185841859418604186141862418634186441865418664186741868418694187041871418724187341874418754187641877418784187941880418814188241883418844188541886418874188841889418904189141892418934189441895418964189741898418994190041901419024190341904419054190641907419084190941910419114191241913419144191541916419174191841919419204192141922419234192441925419264192741928419294193041931419324193341934419354193641937419384193941940419414194241943419444194541946419474194841949419504195141952419534195441955419564195741958419594196041961419624196341964419654196641967419684196941970419714197241973419744197541976419774197841979419804198141982419834198441985419864198741988419894199041991419924199341994419954199641997419984199942000420014200242003420044200542006420074200842009420104201142012420134201442015420164201742018420194202042021420224202342024420254202642027420284202942030420314203242033420344203542036420374203842039420404204142042420434204442045420464204742048420494205042051420524205342054420554205642057420584205942060420614206242063420644206542066420674206842069420704207142072420734207442075420764207742078420794208042081420824208342084420854208642087420884208942090420914209242093420944209542096420974209842099421004210142102421034210442105421064210742108421094211042111421124211342114421154211642117421184211942120421214212242123421244212542126421274212842129421304213142132421334213442135421364213742138421394214042141421424214342144421454214642147421484214942150421514215242153421544215542156421574215842159421604216142162421634216442165421664216742168421694217042171421724217342174421754217642177421784217942180421814218242183421844218542186421874218842189421904219142192421934219442195421964219742198421994220042201422024220342204422054220642207422084220942210422114221242213422144221542216422174221842219422204222142222422234222442225422264222742228422294223042231422324223342234422354223642237422384223942240422414224242243422444224542246422474224842249422504225142252422534225442255422564225742258422594226042261422624226342264422654226642267422684226942270422714227242273422744227542276422774227842279422804228142282422834228442285422864228742288422894229042291422924229342294422954229642297422984229942300423014230242303423044230542306423074230842309423104231142312423134231442315423164231742318423194232042321423224232342324423254232642327423284232942330423314233242333423344233542336423374233842339423404234142342423434234442345423464234742348423494235042351423524235342354423554235642357423584235942360423614236242363423644236542366423674236842369423704237142372423734237442375423764237742378423794238042381423824238342384423854238642387423884238942390423914239242393423944239542396423974239842399424004240142402424034240442405424064240742408424094241042411424124241342414424154241642417424184241942420424214242242423424244242542426424274242842429424304243142432424334243442435424364243742438424394244042441424424244342444424454244642447424484244942450424514245242453424544245542456424574245842459424604246142462424634246442465424664246742468424694247042471424724247342474424754247642477424784247942480424814248242483424844248542486424874248842489424904249142492424934249442495424964249742498424994250042501425024250342504425054250642507425084250942510425114251242513425144251542516425174251842519425204252142522425234252442525425264252742528425294253042531425324253342534425354253642537425384253942540425414254242543425444254542546425474254842549425504255142552425534255442555425564255742558425594256042561425624256342564425654256642567425684256942570425714257242573425744257542576425774257842579425804258142582425834258442585425864258742588425894259042591425924259342594425954259642597425984259942600426014260242603426044260542606426074260842609426104261142612426134261442615426164261742618426194262042621426224262342624426254262642627426284262942630426314263242633426344263542636426374263842639426404264142642426434264442645426464264742648426494265042651426524265342654426554265642657426584265942660426614266242663426644266542666426674266842669426704267142672426734267442675426764267742678426794268042681426824268342684426854268642687426884268942690426914269242693426944269542696426974269842699427004270142702427034270442705427064270742708427094271042711427124271342714427154271642717427184271942720427214272242723427244272542726427274272842729427304273142732427334273442735427364273742738427394274042741427424274342744427454274642747427484274942750427514275242753427544275542756427574275842759427604276142762427634276442765427664276742768427694277042771427724277342774427754277642777427784277942780427814278242783427844278542786427874278842789427904279142792427934279442795427964279742798427994280042801428024280342804428054280642807428084280942810428114281242813428144281542816428174281842819428204282142822428234282442825428264282742828428294283042831428324283342834428354283642837428384283942840428414284242843428444284542846428474284842849428504285142852428534285442855428564285742858428594286042861428624286342864428654286642867428684286942870428714287242873428744287542876428774287842879428804288142882428834288442885428864288742888428894289042891428924289342894428954289642897428984289942900429014290242903429044290542906429074290842909429104291142912429134291442915429164291742918429194292042921429224292342924429254292642927429284292942930429314293242933429344293542936429374293842939429404294142942429434294442945429464294742948429494295042951429524295342954429554295642957429584295942960429614296242963429644296542966429674296842969429704297142972429734297442975429764297742978429794298042981429824298342984429854298642987429884298942990429914299242993429944299542996429974299842999430004300143002430034300443005430064300743008430094301043011430124301343014430154301643017430184301943020430214302243023430244302543026430274302843029430304303143032430334303443035430364303743038430394304043041430424304343044430454304643047430484304943050430514305243053430544305543056430574305843059430604306143062430634306443065430664306743068430694307043071430724307343074430754307643077430784307943080430814308243083430844308543086430874308843089430904309143092430934309443095430964309743098430994310043101431024310343104431054310643107431084310943110431114311243113431144311543116431174311843119431204312143122431234312443125431264312743128431294313043131431324313343134431354313643137431384313943140431414314243143431444314543146431474314843149431504315143152431534315443155431564315743158431594316043161431624316343164431654316643167431684316943170431714317243173431744317543176431774317843179431804318143182431834318443185431864318743188431894319043191431924319343194431954319643197431984319943200432014320243203432044320543206432074320843209432104321143212432134321443215432164321743218432194322043221432224322343224432254322643227432284322943230432314323243233432344323543236432374323843239432404324143242432434324443245432464324743248432494325043251432524325343254432554325643257432584325943260432614326243263432644326543266432674326843269432704327143272432734327443275432764327743278432794328043281432824328343284432854328643287432884328943290432914329243293432944329543296432974329843299433004330143302433034330443305433064330743308433094331043311433124331343314433154331643317433184331943320433214332243323433244332543326433274332843329433304333143332433334333443335433364333743338433394334043341433424334343344433454334643347433484334943350433514335243353433544335543356433574335843359433604336143362433634336443365433664336743368433694337043371433724337343374433754337643377433784337943380433814338243383433844338543386433874338843389433904339143392433934339443395433964339743398433994340043401434024340343404434054340643407434084340943410434114341243413434144341543416434174341843419434204342143422434234342443425434264342743428434294343043431434324343343434434354343643437434384343943440434414344243443434444344543446434474344843449434504345143452434534345443455434564345743458434594346043461434624346343464434654346643467434684346943470434714347243473434744347543476434774347843479434804348143482434834348443485434864348743488434894349043491434924349343494434954349643497434984349943500435014350243503435044350543506435074350843509435104351143512435134351443515435164351743518435194352043521435224352343524435254352643527435284352943530435314353243533435344353543536435374353843539435404354143542435434354443545435464354743548435494355043551435524355343554435554355643557435584355943560435614356243563435644356543566435674356843569435704357143572435734357443575435764357743578435794358043581435824358343584435854358643587435884358943590435914359243593435944359543596435974359843599436004360143602436034360443605436064360743608436094361043611436124361343614436154361643617436184361943620436214362243623436244362543626436274362843629436304363143632436334363443635436364363743638436394364043641436424364343644436454364643647436484364943650436514365243653436544365543656436574365843659436604366143662436634366443665436664366743668436694367043671436724367343674436754367643677436784367943680436814368243683436844368543686436874368843689436904369143692436934369443695436964369743698436994370043701437024370343704437054370643707437084370943710437114371243713437144371543716437174371843719437204372143722437234372443725437264372743728437294373043731437324373343734437354373643737437384373943740437414374243743437444374543746437474374843749437504375143752437534375443755437564375743758437594376043761437624376343764437654376643767437684376943770437714377243773437744377543776437774377843779437804378143782437834378443785437864378743788437894379043791437924379343794437954379643797437984379943800438014380243803438044380543806438074380843809438104381143812438134381443815438164381743818438194382043821438224382343824438254382643827438284382943830438314383243833438344383543836438374383843839438404384143842438434384443845438464384743848438494385043851438524385343854438554385643857438584385943860438614386243863438644386543866438674386843869438704387143872438734387443875438764387743878438794388043881438824388343884438854388643887438884388943890438914389243893438944389543896438974389843899439004390143902439034390443905439064390743908439094391043911439124391343914439154391643917439184391943920439214392243923439244392543926439274392843929439304393143932439334393443935439364393743938439394394043941439424394343944439454394643947439484394943950439514395243953439544395543956439574395843959439604396143962439634396443965439664396743968439694397043971439724397343974439754397643977439784397943980439814398243983439844398543986439874398843989439904399143992439934399443995439964399743998439994400044001440024400344004440054400644007440084400944010440114401244013440144401544016440174401844019440204402144022440234402444025440264402744028440294403044031440324403344034440354403644037440384403944040440414404244043440444404544046440474404844049440504405144052440534405444055440564405744058440594406044061440624406344064440654406644067440684406944070440714407244073440744407544076440774407844079440804408144082440834408444085440864408744088440894409044091440924409344094440954409644097440984409944100441014410244103441044410544106441074410844109441104411144112441134411444115441164411744118441194412044121441224412344124441254412644127441284412944130441314413244133441344413544136441374413844139441404414144142441434414444145441464414744148441494415044151441524415344154441554415644157441584415944160441614416244163441644416544166441674416844169441704417144172441734417444175441764417744178441794418044181441824418344184441854418644187441884418944190441914419244193441944419544196441974419844199442004420144202442034420444205442064420744208442094421044211442124421344214442154421644217442184421944220442214422244223442244422544226442274422844229442304423144232442334423444235442364423744238442394424044241442424424344244442454424644247442484424944250442514425244253442544425544256442574425844259442604426144262442634426444265442664426744268442694427044271442724427344274442754427644277442784427944280442814428244283442844428544286442874428844289442904429144292442934429444295442964429744298442994430044301443024430344304443054430644307443084430944310443114431244313443144431544316443174431844319443204432144322443234432444325443264432744328443294433044331443324433344334443354433644337443384433944340443414434244343443444434544346443474434844349443504435144352443534435444355443564435744358443594436044361443624436344364443654436644367443684436944370443714437244373443744437544376443774437844379443804438144382443834438444385443864438744388443894439044391443924439344394443954439644397443984439944400444014440244403444044440544406444074440844409444104441144412444134441444415444164441744418444194442044421444224442344424444254442644427444284442944430444314443244433444344443544436444374443844439444404444144442444434444444445444464444744448444494445044451444524445344454444554445644457444584445944460444614446244463444644446544466444674446844469444704447144472444734447444475444764447744478444794448044481444824448344484444854448644487444884448944490444914449244493444944449544496444974449844499445004450144502445034450444505445064450744508445094451044511445124451344514445154451644517445184451944520445214452244523445244452544526445274452844529445304453144532445334453444535445364453744538445394454044541445424454344544445454454644547445484454944550445514455244553445544455544556445574455844559445604456144562445634456444565445664456744568445694457044571445724457344574445754457644577445784457944580445814458244583445844458544586445874458844589445904459144592445934459444595445964459744598445994460044601446024460344604446054460644607446084460944610446114461244613446144461544616446174461844619446204462144622446234462444625446264462744628446294463044631446324463344634446354463644637446384463944640446414464244643446444464544646446474464844649446504465144652446534465444655446564465744658446594466044661446624466344664446654466644667446684466944670446714467244673446744467544676446774467844679446804468144682446834468444685446864468744688446894469044691446924469344694446954469644697446984469944700447014470244703447044470544706447074470844709447104471144712447134471444715447164471744718447194472044721447224472344724447254472644727447284472944730447314473244733447344473544736447374473844739447404474144742447434474444745447464474744748447494475044751447524475344754447554475644757447584475944760447614476244763447644476544766447674476844769447704477144772447734477444775447764477744778447794478044781447824478344784447854478644787447884478944790447914479244793447944479544796447974479844799448004480144802448034480444805448064480744808448094481044811448124481344814448154481644817448184481944820448214482244823448244482544826448274482844829448304483144832448334483444835448364483744838448394484044841448424484344844448454484644847448484484944850448514485244853448544485544856448574485844859448604486144862448634486444865448664486744868448694487044871448724487344874448754487644877448784487944880448814488244883448844488544886448874488844889448904489144892448934489444895448964489744898448994490044901449024490344904449054490644907449084490944910449114491244913449144491544916449174491844919449204492144922449234492444925449264492744928449294493044931449324493344934449354493644937449384493944940449414494244943449444494544946449474494844949449504495144952449534495444955449564495744958449594496044961449624496344964449654496644967449684496944970449714497244973449744497544976449774497844979449804498144982449834498444985449864498744988449894499044991449924499344994449954499644997449984499945000450014500245003450044500545006450074500845009450104501145012450134501445015450164501745018450194502045021450224502345024450254502645027450284502945030450314503245033450344503545036450374503845039450404504145042450434504445045450464504745048450494505045051450524505345054450554505645057450584505945060450614506245063450644506545066450674506845069450704507145072450734507445075450764507745078450794508045081450824508345084450854508645087450884508945090450914509245093450944509545096450974509845099451004510145102451034510445105451064510745108451094511045111451124511345114451154511645117451184511945120451214512245123451244512545126451274512845129451304513145132451334513445135451364513745138451394514045141451424514345144451454514645147451484514945150451514515245153451544515545156451574515845159451604516145162451634516445165451664516745168451694517045171451724517345174451754517645177451784517945180451814518245183451844518545186451874518845189451904519145192451934519445195451964519745198451994520045201452024520345204452054520645207452084520945210452114521245213452144521545216452174521845219452204522145222452234522445225452264522745228452294523045231452324523345234452354523645237452384523945240452414524245243452444524545246452474524845249452504525145252452534525445255452564525745258452594526045261452624526345264452654526645267452684526945270452714527245273452744527545276452774527845279452804528145282452834528445285452864528745288452894529045291452924529345294452954529645297452984529945300453014530245303453044530545306453074530845309453104531145312453134531445315453164531745318453194532045321453224532345324453254532645327453284532945330453314533245333453344533545336453374533845339453404534145342453434534445345453464534745348453494535045351453524535345354453554535645357453584535945360453614536245363453644536545366453674536845369453704537145372453734537445375453764537745378453794538045381453824538345384453854538645387453884538945390453914539245393453944539545396453974539845399454004540145402454034540445405454064540745408454094541045411454124541345414454154541645417454184541945420454214542245423454244542545426454274542845429454304543145432454334543445435454364543745438454394544045441454424544345444454454544645447454484544945450454514545245453454544545545456454574545845459454604546145462454634546445465454664546745468454694547045471454724547345474454754547645477454784547945480454814548245483454844548545486454874548845489454904549145492454934549445495454964549745498454994550045501455024550345504455054550645507455084550945510455114551245513455144551545516455174551845519455204552145522455234552445525455264552745528455294553045531455324553345534455354553645537455384553945540455414554245543455444554545546455474554845549455504555145552455534555445555455564555745558455594556045561455624556345564455654556645567455684556945570455714557245573455744557545576455774557845579455804558145582455834558445585455864558745588455894559045591455924559345594455954559645597455984559945600456014560245603456044560545606456074560845609456104561145612456134561445615456164561745618456194562045621456224562345624456254562645627456284562945630456314563245633456344563545636456374563845639456404564145642456434564445645456464564745648456494565045651456524565345654456554565645657456584565945660456614566245663456644566545666456674566845669456704567145672456734567445675456764567745678456794568045681456824568345684456854568645687456884568945690456914569245693456944569545696456974569845699457004570145702457034570445705457064570745708457094571045711457124571345714457154571645717457184571945720457214572245723457244572545726457274572845729457304573145732457334573445735457364573745738457394574045741457424574345744457454574645747457484574945750457514575245753457544575545756457574575845759457604576145762457634576445765457664576745768457694577045771457724577345774457754577645777457784577945780457814578245783457844578545786457874578845789457904579145792457934579445795457964579745798457994580045801458024580345804458054580645807458084580945810458114581245813458144581545816458174581845819458204582145822458234582445825458264582745828458294583045831458324583345834458354583645837458384583945840458414584245843458444584545846458474584845849458504585145852458534585445855458564585745858458594586045861458624586345864458654586645867458684586945870458714587245873458744587545876458774587845879458804588145882458834588445885458864588745888458894589045891458924589345894458954589645897458984589945900459014590245903459044590545906459074590845909459104591145912459134591445915459164591745918459194592045921459224592345924459254592645927459284592945930459314593245933459344593545936459374593845939459404594145942459434594445945459464594745948459494595045951459524595345954459554595645957459584595945960459614596245963459644596545966459674596845969459704597145972459734597445975459764597745978459794598045981459824598345984459854598645987459884598945990459914599245993459944599545996459974599845999460004600146002460034600446005460064600746008460094601046011460124601346014460154601646017460184601946020460214602246023460244602546026460274602846029460304603146032460334603446035460364603746038460394604046041460424604346044460454604646047460484604946050460514605246053460544605546056460574605846059460604606146062460634606446065460664606746068460694607046071460724607346074460754607646077460784607946080460814608246083460844608546086460874608846089460904609146092460934609446095460964609746098460994610046101461024610346104461054610646107461084610946110461114611246113461144611546116461174611846119461204612146122461234612446125461264612746128461294613046131461324613346134461354613646137461384613946140461414614246143461444614546146461474614846149461504615146152461534615446155461564615746158461594616046161461624616346164461654616646167461684616946170461714617246173461744617546176461774617846179461804618146182461834618446185461864618746188461894619046191461924619346194461954619646197461984619946200462014620246203462044620546206462074620846209462104621146212462134621446215462164621746218462194622046221462224622346224462254622646227462284622946230462314623246233462344623546236462374623846239462404624146242462434624446245462464624746248462494625046251462524625346254462554625646257462584625946260462614626246263462644626546266462674626846269462704627146272462734627446275462764627746278462794628046281462824628346284462854628646287462884628946290462914629246293462944629546296462974629846299463004630146302463034630446305463064630746308463094631046311463124631346314463154631646317463184631946320463214632246323463244632546326463274632846329463304633146332463334633446335463364633746338463394634046341463424634346344463454634646347463484634946350463514635246353463544635546356463574635846359463604636146362463634636446365463664636746368463694637046371463724637346374463754637646377463784637946380463814638246383463844638546386463874638846389463904639146392463934639446395463964639746398463994640046401464024640346404464054640646407464084640946410464114641246413464144641546416464174641846419464204642146422464234642446425464264642746428464294643046431464324643346434464354643646437464384643946440464414644246443464444644546446464474644846449464504645146452464534645446455464564645746458464594646046461464624646346464464654646646467464684646946470464714647246473464744647546476464774647846479464804648146482464834648446485464864648746488464894649046491464924649346494464954649646497464984649946500465014650246503465044650546506465074650846509465104651146512465134651446515465164651746518465194652046521465224652346524465254652646527465284652946530465314653246533465344653546536465374653846539465404654146542465434654446545465464654746548465494655046551465524655346554465554655646557465584655946560465614656246563465644656546566465674656846569465704657146572465734657446575465764657746578465794658046581465824658346584465854658646587465884658946590465914659246593465944659546596465974659846599466004660146602466034660446605466064660746608466094661046611466124661346614466154661646617466184661946620466214662246623466244662546626466274662846629466304663146632466334663446635466364663746638466394664046641466424664346644466454664646647466484664946650466514665246653466544665546656466574665846659466604666146662466634666446665466664666746668466694667046671466724667346674466754667646677466784667946680466814668246683466844668546686466874668846689466904669146692466934669446695466964669746698466994670046701467024670346704467054670646707467084670946710467114671246713467144671546716467174671846719467204672146722467234672446725467264672746728467294673046731467324673346734467354673646737467384673946740467414674246743467444674546746467474674846749467504675146752467534675446755467564675746758467594676046761467624676346764467654676646767467684676946770467714677246773467744677546776467774677846779467804678146782467834678446785467864678746788467894679046791467924679346794467954679646797467984679946800468014680246803468044680546806468074680846809468104681146812468134681446815468164681746818468194682046821468224682346824468254682646827468284682946830468314683246833468344683546836468374683846839468404684146842468434684446845468464684746848468494685046851468524685346854468554685646857468584685946860468614686246863468644686546866468674686846869468704687146872468734687446875468764687746878468794688046881468824688346884468854688646887468884688946890468914689246893468944689546896468974689846899469004690146902469034690446905469064690746908469094691046911469124691346914469154691646917469184691946920469214692246923469244692546926469274692846929469304693146932469334693446935469364693746938469394694046941469424694346944469454694646947469484694946950469514695246953469544695546956469574695846959469604696146962469634696446965469664696746968469694697046971469724697346974469754697646977469784697946980469814698246983469844698546986469874698846989469904699146992469934699446995469964699746998469994700047001470024700347004470054700647007470084700947010470114701247013470144701547016470174701847019470204702147022470234702447025470264702747028470294703047031470324703347034470354703647037470384703947040470414704247043470444704547046470474704847049470504705147052470534705447055470564705747058470594706047061470624706347064470654706647067470684706947070470714707247073470744707547076470774707847079470804708147082470834708447085470864708747088470894709047091470924709347094470954709647097470984709947100471014710247103471044710547106471074710847109471104711147112471134711447115471164711747118471194712047121471224712347124471254712647127471284712947130471314713247133471344713547136471374713847139471404714147142471434714447145471464714747148471494715047151471524715347154471554715647157471584715947160471614716247163471644716547166471674716847169471704717147172471734717447175471764717747178471794718047181471824718347184471854718647187471884718947190471914719247193471944719547196471974719847199472004720147202472034720447205472064720747208472094721047211472124721347214472154721647217472184721947220472214722247223472244722547226472274722847229472304723147232472334723447235472364723747238472394724047241472424724347244472454724647247472484724947250472514725247253472544725547256472574725847259472604726147262472634726447265472664726747268472694727047271472724727347274472754727647277472784727947280472814728247283472844728547286472874728847289472904729147292472934729447295472964729747298472994730047301473024730347304473054730647307473084730947310473114731247313473144731547316473174731847319473204732147322473234732447325473264732747328473294733047331473324733347334473354733647337473384733947340473414734247343473444734547346473474734847349473504735147352473534735447355473564735747358473594736047361473624736347364473654736647367473684736947370473714737247373473744737547376473774737847379473804738147382473834738447385473864738747388473894739047391473924739347394473954739647397473984739947400474014740247403474044740547406474074740847409474104741147412474134741447415474164741747418474194742047421474224742347424474254742647427474284742947430474314743247433474344743547436474374743847439474404744147442474434744447445474464744747448474494745047451474524745347454474554745647457474584745947460474614746247463474644746547466474674746847469474704747147472474734747447475474764747747478474794748047481474824748347484474854748647487474884748947490474914749247493474944749547496474974749847499475004750147502475034750447505475064750747508475094751047511475124751347514475154751647517475184751947520475214752247523475244752547526475274752847529475304753147532475334753447535475364753747538475394754047541475424754347544475454754647547475484754947550475514755247553475544755547556475574755847559475604756147562475634756447565475664756747568475694757047571475724757347574475754757647577475784757947580475814758247583475844758547586475874758847589475904759147592475934759447595475964759747598475994760047601476024760347604476054760647607476084760947610476114761247613476144761547616476174761847619476204762147622476234762447625476264762747628476294763047631476324763347634476354763647637476384763947640476414764247643476444764547646476474764847649476504765147652476534765447655476564765747658476594766047661476624766347664476654766647667476684766947670476714767247673476744767547676476774767847679476804768147682476834768447685476864768747688476894769047691476924769347694476954769647697476984769947700477014770247703477044770547706477074770847709477104771147712477134771447715477164771747718477194772047721477224772347724477254772647727477284772947730477314773247733477344773547736477374773847739477404774147742477434774447745477464774747748477494775047751477524775347754477554775647757477584775947760477614776247763477644776547766477674776847769477704777147772477734777447775477764777747778477794778047781477824778347784477854778647787477884778947790477914779247793477944779547796477974779847799478004780147802478034780447805478064780747808478094781047811478124781347814478154781647817478184781947820478214782247823478244782547826478274782847829478304783147832478334783447835478364783747838478394784047841478424784347844478454784647847478484784947850478514785247853478544785547856478574785847859478604786147862478634786447865478664786747868478694787047871478724787347874478754787647877478784787947880478814788247883478844788547886478874788847889478904789147892478934789447895478964789747898478994790047901479024790347904479054790647907479084790947910479114791247913479144791547916479174791847919479204792147922479234792447925479264792747928479294793047931479324793347934479354793647937479384793947940479414794247943479444794547946479474794847949479504795147952479534795447955479564795747958479594796047961479624796347964479654796647967479684796947970479714797247973479744797547976479774797847979479804798147982479834798447985479864798747988479894799047991479924799347994479954799647997479984799948000480014800248003480044800548006480074800848009480104801148012480134801448015480164801748018480194802048021480224802348024480254802648027480284802948030480314803248033480344803548036480374803848039480404804148042480434804448045480464804748048480494805048051480524805348054480554805648057480584805948060480614806248063480644806548066480674806848069480704807148072480734807448075480764807748078480794808048081480824808348084480854808648087480884808948090480914809248093480944809548096480974809848099481004810148102481034810448105481064810748108481094811048111481124811348114481154811648117481184811948120481214812248123481244812548126481274812848129481304813148132481334813448135481364813748138481394814048141481424814348144481454814648147481484814948150481514815248153481544815548156481574815848159481604816148162481634816448165481664816748168481694817048171481724817348174481754817648177481784817948180481814818248183481844818548186481874818848189481904819148192481934819448195481964819748198481994820048201482024820348204482054820648207482084820948210482114821248213482144821548216482174821848219482204822148222482234822448225482264822748228482294823048231482324823348234482354823648237482384823948240482414824248243482444824548246482474824848249482504825148252482534825448255482564825748258482594826048261482624826348264482654826648267482684826948270482714827248273482744827548276482774827848279482804828148282482834828448285482864828748288482894829048291482924829348294482954829648297482984829948300483014830248303483044830548306483074830848309483104831148312483134831448315483164831748318483194832048321483224832348324483254832648327483284832948330483314833248333483344833548336483374833848339483404834148342483434834448345483464834748348483494835048351483524835348354483554835648357483584835948360483614836248363483644836548366483674836848369483704837148372483734837448375483764837748378483794838048381483824838348384483854838648387483884838948390483914839248393483944839548396483974839848399484004840148402484034840448405484064840748408484094841048411484124841348414484154841648417484184841948420484214842248423484244842548426484274842848429484304843148432484334843448435484364843748438484394844048441484424844348444484454844648447484484844948450484514845248453484544845548456484574845848459484604846148462484634846448465484664846748468484694847048471484724847348474484754847648477484784847948480484814848248483484844848548486484874848848489484904849148492484934849448495484964849748498484994850048501485024850348504485054850648507485084850948510485114851248513485144851548516485174851848519485204852148522485234852448525485264852748528485294853048531485324853348534485354853648537485384853948540485414854248543485444854548546485474854848549485504855148552485534855448555485564855748558485594856048561485624856348564485654856648567485684856948570485714857248573485744857548576485774857848579485804858148582485834858448585485864858748588485894859048591485924859348594485954859648597485984859948600486014860248603486044860548606486074860848609486104861148612486134861448615486164861748618486194862048621486224862348624486254862648627486284862948630486314863248633486344863548636486374863848639486404864148642486434864448645486464864748648486494865048651486524865348654486554865648657486584865948660486614866248663486644866548666486674866848669486704867148672486734867448675486764867748678486794868048681486824868348684486854868648687486884868948690486914869248693486944869548696486974869848699487004870148702487034870448705487064870748708487094871048711487124871348714487154871648717487184871948720487214872248723487244872548726487274872848729487304873148732487334873448735487364873748738487394874048741487424874348744487454874648747487484874948750487514875248753487544875548756487574875848759487604876148762487634876448765487664876748768487694877048771487724877348774487754877648777487784877948780487814878248783487844878548786487874878848789487904879148792487934879448795487964879748798487994880048801488024880348804488054880648807488084880948810488114881248813488144881548816488174881848819488204882148822488234882448825488264882748828488294883048831488324883348834488354883648837488384883948840488414884248843488444884548846488474884848849488504885148852488534885448855488564885748858488594886048861488624886348864488654886648867488684886948870488714887248873488744887548876488774887848879488804888148882488834888448885488864888748888488894889048891488924889348894488954889648897488984889948900489014890248903489044890548906489074890848909489104891148912489134891448915489164891748918489194892048921489224892348924489254892648927489284892948930489314893248933489344893548936489374893848939489404894148942489434894448945489464894748948489494895048951489524895348954489554895648957489584895948960489614896248963489644896548966489674896848969489704897148972489734897448975489764897748978489794898048981489824898348984489854898648987489884898948990489914899248993489944899548996489974899848999490004900149002490034900449005490064900749008490094901049011490124901349014490154901649017490184901949020490214902249023490244902549026490274902849029490304903149032490334903449035490364903749038490394904049041490424904349044490454904649047490484904949050490514905249053490544905549056490574905849059490604906149062490634906449065490664906749068490694907049071490724907349074490754907649077490784907949080490814908249083490844908549086490874908849089490904909149092490934909449095490964909749098490994910049101491024910349104491054910649107491084910949110491114911249113491144911549116491174911849119491204912149122491234912449125491264912749128491294913049131491324913349134491354913649137491384913949140491414914249143491444914549146491474914849149491504915149152491534915449155491564915749158491594916049161491624916349164491654916649167491684916949170491714917249173491744917549176491774917849179491804918149182491834918449185491864918749188491894919049191491924919349194491954919649197491984919949200492014920249203492044920549206492074920849209492104921149212492134921449215492164921749218492194922049221492224922349224492254922649227492284922949230492314923249233492344923549236492374923849239492404924149242492434924449245492464924749248492494925049251492524925349254492554925649257492584925949260492614926249263492644926549266492674926849269492704927149272492734927449275492764927749278492794928049281492824928349284492854928649287492884928949290492914929249293492944929549296492974929849299493004930149302493034930449305493064930749308493094931049311493124931349314493154931649317493184931949320493214932249323493244932549326493274932849329493304933149332493334933449335493364933749338493394934049341493424934349344493454934649347493484934949350493514935249353493544935549356493574935849359493604936149362493634936449365493664936749368493694937049371493724937349374493754937649377493784937949380493814938249383493844938549386493874938849389493904939149392493934939449395493964939749398493994940049401494024940349404494054940649407494084940949410494114941249413494144941549416494174941849419494204942149422494234942449425494264942749428494294943049431494324943349434494354943649437494384943949440494414944249443494444944549446494474944849449494504945149452494534945449455494564945749458494594946049461494624946349464494654946649467494684946949470494714947249473494744947549476494774947849479494804948149482494834948449485494864948749488494894949049491494924949349494494954949649497494984949949500495014950249503495044950549506495074950849509495104951149512495134951449515495164951749518495194952049521495224952349524495254952649527495284952949530495314953249533495344953549536495374953849539495404954149542495434954449545495464954749548495494955049551495524955349554495554955649557495584955949560495614956249563495644956549566495674956849569495704957149572495734957449575495764957749578495794958049581495824958349584495854958649587495884958949590495914959249593495944959549596495974959849599496004960149602496034960449605496064960749608496094961049611496124961349614496154961649617496184961949620496214962249623496244962549626496274962849629496304963149632496334963449635496364963749638496394964049641496424964349644496454964649647496484964949650496514965249653496544965549656496574965849659496604966149662496634966449665496664966749668496694967049671496724967349674496754967649677496784967949680496814968249683496844968549686496874968849689496904969149692496934969449695496964969749698496994970049701497024970349704497054970649707497084970949710497114971249713497144971549716497174971849719497204972149722497234972449725497264972749728497294973049731497324973349734497354973649737497384973949740497414974249743497444974549746497474974849749497504975149752497534975449755497564975749758497594976049761497624976349764497654976649767497684976949770497714977249773497744977549776497774977849779497804978149782497834978449785497864978749788497894979049791497924979349794497954979649797497984979949800498014980249803498044980549806498074980849809498104981149812498134981449815498164981749818498194982049821498224982349824498254982649827498284982949830498314983249833498344983549836498374983849839498404984149842498434984449845498464984749848498494985049851498524985349854498554985649857498584985949860498614986249863498644986549866498674986849869498704987149872498734987449875498764987749878498794988049881498824988349884498854988649887498884988949890498914989249893498944989549896498974989849899499004990149902499034990449905499064990749908499094991049911499124991349914499154991649917499184991949920499214992249923499244992549926499274992849929499304993149932499334993449935499364993749938499394994049941499424994349944499454994649947499484994949950499514995249953499544995549956499574995849959499604996149962499634996449965499664996749968499694997049971499724997349974499754997649977499784997949980499814998249983499844998549986499874998849989499904999149992499934999449995499964999749998499995000050001500025000350004500055000650007500085000950010500115001250013500145001550016500175001850019500205002150022500235002450025500265002750028500295003050031500325003350034500355003650037500385003950040500415004250043500445004550046500475004850049500505005150052500535005450055500565005750058500595006050061500625006350064500655006650067500685006950070500715007250073500745007550076500775007850079500805008150082500835008450085500865008750088500895009050091500925009350094500955009650097500985009950100501015010250103501045010550106501075010850109501105011150112501135011450115501165011750118501195012050121501225012350124501255012650127501285012950130501315013250133501345013550136501375013850139501405014150142501435014450145501465014750148501495015050151501525015350154501555015650157501585015950160501615016250163501645016550166501675016850169501705017150172501735017450175501765017750178501795018050181501825018350184501855018650187501885018950190501915019250193501945019550196501975019850199502005020150202502035020450205502065020750208502095021050211502125021350214502155021650217502185021950220502215022250223502245022550226502275022850229502305023150232502335023450235502365023750238502395024050241502425024350244502455024650247502485024950250502515025250253502545025550256502575025850259502605026150262502635026450265502665026750268502695027050271502725027350274502755027650277502785027950280502815028250283502845028550286502875028850289502905029150292502935029450295502965029750298502995030050301503025030350304503055030650307503085030950310503115031250313503145031550316503175031850319503205032150322503235032450325503265032750328503295033050331503325033350334503355033650337503385033950340503415034250343503445034550346503475034850349503505035150352503535035450355503565035750358503595036050361503625036350364503655036650367503685036950370503715037250373503745037550376503775037850379503805038150382503835038450385503865038750388503895039050391503925039350394503955039650397503985039950400504015040250403504045040550406504075040850409504105041150412504135041450415504165041750418504195042050421504225042350424504255042650427504285042950430504315043250433504345043550436504375043850439504405044150442504435044450445504465044750448504495045050451504525045350454504555045650457504585045950460504615046250463504645046550466504675046850469504705047150472504735047450475504765047750478504795048050481504825048350484504855048650487504885048950490504915049250493504945049550496504975049850499505005050150502505035050450505505065050750508505095051050511505125051350514505155051650517505185051950520505215052250523505245052550526505275052850529505305053150532505335053450535505365053750538505395054050541505425054350544505455054650547505485054950550505515055250553505545055550556505575055850559505605056150562505635056450565505665056750568505695057050571505725057350574505755057650577505785057950580505815058250583505845058550586505875058850589505905059150592505935059450595505965059750598505995060050601506025060350604506055060650607506085060950610506115061250613506145061550616506175061850619506205062150622506235062450625506265062750628506295063050631506325063350634506355063650637506385063950640506415064250643506445064550646506475064850649506505065150652506535065450655506565065750658506595066050661506625066350664506655066650667506685066950670506715067250673506745067550676506775067850679506805068150682506835068450685506865068750688506895069050691506925069350694506955069650697506985069950700507015070250703507045070550706507075070850709507105071150712507135071450715507165071750718507195072050721507225072350724507255072650727507285072950730507315073250733507345073550736507375073850739507405074150742507435074450745507465074750748507495075050751507525075350754507555075650757507585075950760507615076250763507645076550766507675076850769507705077150772507735077450775507765077750778507795078050781507825078350784507855078650787507885078950790507915079250793507945079550796507975079850799508005080150802508035080450805508065080750808508095081050811508125081350814508155081650817508185081950820508215082250823508245082550826508275082850829508305083150832508335083450835508365083750838508395084050841508425084350844508455084650847508485084950850508515085250853508545085550856508575085850859508605086150862508635086450865508665086750868508695087050871508725087350874508755087650877508785087950880508815088250883508845088550886508875088850889508905089150892508935089450895508965089750898508995090050901509025090350904509055090650907509085090950910509115091250913509145091550916509175091850919509205092150922509235092450925509265092750928509295093050931509325093350934509355093650937509385093950940509415094250943509445094550946509475094850949509505095150952509535095450955509565095750958509595096050961509625096350964509655096650967509685096950970509715097250973509745097550976509775097850979509805098150982509835098450985509865098750988509895099050991509925099350994509955099650997509985099951000510015100251003510045100551006510075100851009510105101151012510135101451015510165101751018510195102051021510225102351024510255102651027510285102951030510315103251033510345103551036510375103851039510405104151042510435104451045510465104751048510495105051051510525105351054510555105651057510585105951060510615106251063510645106551066510675106851069510705107151072510735107451075510765107751078510795108051081510825108351084510855108651087510885108951090510915109251093510945109551096510975109851099511005110151102511035110451105511065110751108511095111051111511125111351114511155111651117511185111951120511215112251123511245112551126511275112851129511305113151132511335113451135511365113751138511395114051141511425114351144511455114651147511485114951150511515115251153511545115551156511575115851159511605116151162511635116451165511665116751168511695117051171511725117351174511755117651177511785117951180511815118251183511845118551186511875118851189511905119151192511935119451195511965119751198511995120051201512025120351204512055120651207512085120951210512115121251213512145121551216512175121851219512205122151222512235122451225512265122751228512295123051231512325123351234512355123651237512385123951240512415124251243512445124551246512475124851249512505125151252512535125451255512565125751258512595126051261512625126351264512655126651267512685126951270512715127251273512745127551276512775127851279512805128151282512835128451285512865128751288512895129051291512925129351294512955129651297512985129951300513015130251303513045130551306513075130851309513105131151312513135131451315513165131751318513195132051321513225132351324513255132651327513285132951330513315133251333513345133551336513375133851339513405134151342513435134451345513465134751348513495135051351513525135351354513555135651357513585135951360513615136251363513645136551366513675136851369513705137151372513735137451375513765137751378513795138051381513825138351384513855138651387513885138951390513915139251393513945139551396513975139851399514005140151402514035140451405514065140751408514095141051411514125141351414514155141651417514185141951420514215142251423514245142551426514275142851429514305143151432514335143451435514365143751438514395144051441514425144351444514455144651447514485144951450514515145251453514545145551456514575145851459514605146151462514635146451465514665146751468514695147051471514725147351474514755147651477514785147951480514815148251483514845148551486514875148851489514905149151492514935149451495514965149751498514995150051501515025150351504515055150651507515085150951510515115151251513515145151551516515175151851519515205152151522515235152451525515265152751528515295153051531515325153351534515355153651537515385153951540515415154251543515445154551546515475154851549515505155151552515535155451555515565155751558515595156051561515625156351564515655156651567515685156951570515715157251573515745157551576515775157851579515805158151582515835158451585515865158751588515895159051591515925159351594515955159651597515985159951600516015160251603516045160551606516075160851609516105161151612516135161451615516165161751618516195162051621516225162351624516255162651627516285162951630516315163251633516345163551636516375163851639516405164151642516435164451645516465164751648516495165051651516525165351654516555165651657516585165951660516615166251663516645166551666516675166851669516705167151672516735167451675516765167751678516795168051681516825168351684516855168651687516885168951690516915169251693516945169551696516975169851699517005170151702517035170451705517065170751708517095171051711517125171351714517155171651717517185171951720517215172251723517245172551726517275172851729517305173151732517335173451735517365173751738517395174051741517425174351744517455174651747517485174951750517515175251753517545175551756517575175851759517605176151762517635176451765517665176751768517695177051771517725177351774517755177651777517785177951780517815178251783517845178551786517875178851789517905179151792517935179451795517965179751798517995180051801518025180351804518055180651807518085180951810518115181251813518145181551816518175181851819518205182151822518235182451825518265182751828518295183051831518325183351834518355183651837518385183951840518415184251843518445184551846518475184851849518505185151852518535185451855518565185751858518595186051861518625186351864518655186651867518685186951870518715187251873518745187551876518775187851879518805188151882518835188451885518865188751888518895189051891518925189351894518955189651897518985189951900519015190251903519045190551906519075190851909519105191151912519135191451915519165191751918519195192051921519225192351924519255192651927519285192951930519315193251933519345193551936519375193851939519405194151942519435194451945519465194751948519495195051951519525195351954519555195651957519585195951960519615196251963519645196551966519675196851969519705197151972519735197451975519765197751978519795198051981519825198351984519855198651987519885198951990519915199251993519945199551996519975199851999520005200152002520035200452005520065200752008520095201052011520125201352014520155201652017520185201952020520215202252023520245202552026520275202852029520305203152032520335203452035520365203752038520395204052041520425204352044520455204652047520485204952050520515205252053520545205552056520575205852059520605206152062520635206452065520665206752068520695207052071520725207352074520755207652077520785207952080520815208252083520845208552086520875208852089520905209152092520935209452095520965209752098520995210052101521025210352104521055210652107521085210952110521115211252113521145211552116521175211852119521205212152122521235212452125521265212752128521295213052131521325213352134521355213652137521385213952140521415214252143521445214552146521475214852149521505215152152521535215452155521565215752158521595216052161521625216352164521655216652167521685216952170521715217252173521745217552176521775217852179521805218152182521835218452185521865218752188521895219052191521925219352194521955219652197521985219952200522015220252203522045220552206522075220852209522105221152212522135221452215522165221752218522195222052221522225222352224522255222652227522285222952230522315223252233522345223552236522375223852239522405224152242522435224452245522465224752248522495225052251522525225352254522555225652257522585225952260522615226252263522645226552266522675226852269522705227152272522735227452275522765227752278522795228052281522825228352284522855228652287522885228952290522915229252293522945229552296522975229852299523005230152302523035230452305523065230752308523095231052311523125231352314523155231652317523185231952320523215232252323523245232552326523275232852329523305233152332523335233452335523365233752338523395234052341523425234352344523455234652347523485234952350523515235252353523545235552356523575235852359523605236152362523635236452365523665236752368523695237052371523725237352374523755237652377523785237952380523815238252383523845238552386523875238852389523905239152392523935239452395523965239752398523995240052401524025240352404524055240652407524085240952410524115241252413524145241552416524175241852419524205242152422524235242452425524265242752428524295243052431524325243352434524355243652437524385243952440524415244252443524445244552446524475244852449524505245152452524535245452455524565245752458524595246052461524625246352464524655246652467524685246952470524715247252473524745247552476524775247852479524805248152482524835248452485524865248752488524895249052491524925249352494524955249652497524985249952500525015250252503525045250552506525075250852509525105251152512525135251452515525165251752518525195252052521525225252352524525255252652527525285252952530525315253252533525345253552536525375253852539525405254152542525435254452545525465254752548525495255052551525525255352554525555255652557525585255952560525615256252563525645256552566525675256852569525705257152572525735257452575525765257752578525795258052581525825258352584525855258652587525885258952590525915259252593525945259552596525975259852599526005260152602526035260452605526065260752608526095261052611526125261352614526155261652617526185261952620526215262252623526245262552626526275262852629526305263152632526335263452635526365263752638526395264052641526425264352644526455264652647526485264952650526515265252653526545265552656526575265852659526605266152662526635266452665526665266752668526695267052671526725267352674526755267652677526785267952680526815268252683526845268552686526875268852689526905269152692526935269452695526965269752698526995270052701527025270352704527055270652707527085270952710527115271252713527145271552716527175271852719527205272152722527235272452725527265272752728527295273052731527325273352734527355273652737527385273952740527415274252743527445274552746527475274852749527505275152752527535275452755527565275752758527595276052761527625276352764527655276652767527685276952770527715277252773527745277552776527775277852779527805278152782527835278452785527865278752788527895279052791527925279352794527955279652797527985279952800528015280252803528045280552806528075280852809528105281152812528135281452815528165281752818528195282052821528225282352824528255282652827528285282952830528315283252833528345283552836528375283852839528405284152842528435284452845528465284752848528495285052851528525285352854528555285652857528585285952860528615286252863528645286552866528675286852869528705287152872528735287452875528765287752878528795288052881528825288352884528855288652887528885288952890528915289252893528945289552896528975289852899529005290152902529035290452905529065290752908529095291052911529125291352914529155291652917529185291952920529215292252923529245292552926529275292852929529305293152932529335293452935529365293752938529395294052941529425294352944529455294652947529485294952950529515295252953529545295552956529575295852959529605296152962529635296452965529665296752968529695297052971529725297352974529755297652977529785297952980529815298252983529845298552986529875298852989529905299152992529935299452995529965299752998529995300053001530025300353004530055300653007530085300953010530115301253013530145301553016530175301853019530205302153022530235302453025530265302753028530295303053031530325303353034530355303653037530385303953040530415304253043530445304553046530475304853049530505305153052530535305453055530565305753058530595306053061530625306353064530655306653067530685306953070530715307253073530745307553076530775307853079530805308153082530835308453085530865308753088530895309053091530925309353094530955309653097530985309953100531015310253103531045310553106531075310853109531105311153112531135311453115531165311753118531195312053121531225312353124531255312653127531285312953130531315313253133531345313553136531375313853139531405314153142531435314453145531465314753148531495315053151531525315353154531555315653157531585315953160531615316253163531645316553166531675316853169531705317153172531735317453175531765317753178531795318053181531825318353184531855318653187531885318953190531915319253193531945319553196531975319853199532005320153202532035320453205532065320753208532095321053211532125321353214532155321653217532185321953220532215322253223532245322553226532275322853229532305323153232532335323453235532365323753238532395324053241532425324353244532455324653247532485324953250532515325253253532545325553256532575325853259532605326153262532635326453265532665326753268532695327053271532725327353274532755327653277532785327953280532815328253283532845328553286532875328853289532905329153292532935329453295532965329753298532995330053301533025330353304533055330653307533085330953310533115331253313533145331553316533175331853319533205332153322533235332453325533265332753328533295333053331533325333353334533355333653337533385333953340533415334253343533445334553346533475334853349533505335153352533535335453355533565335753358533595336053361533625336353364533655336653367533685336953370533715337253373533745337553376533775337853379533805338153382533835338453385533865338753388533895339053391533925339353394533955339653397533985339953400534015340253403534045340553406534075340853409534105341153412534135341453415534165341753418534195342053421534225342353424534255342653427534285342953430534315343253433534345343553436534375343853439534405344153442534435344453445534465344753448534495345053451534525345353454534555345653457534585345953460534615346253463534645346553466534675346853469534705347153472534735347453475534765347753478534795348053481534825348353484534855348653487534885348953490534915349253493534945349553496534975349853499535005350153502535035350453505535065350753508535095351053511535125351353514535155351653517535185351953520535215352253523535245352553526535275352853529535305353153532535335353453535535365353753538535395354053541535425354353544535455354653547535485354953550535515355253553535545355553556535575355853559535605356153562535635356453565535665356753568535695357053571535725357353574535755357653577535785357953580535815358253583535845358553586535875358853589535905359153592535935359453595535965359753598535995360053601536025360353604536055360653607536085360953610536115361253613536145361553616536175361853619536205362153622536235362453625536265362753628536295363053631536325363353634536355363653637536385363953640536415364253643536445364553646536475364853649536505365153652536535365453655536565365753658536595366053661536625366353664536655366653667536685366953670536715367253673536745367553676536775367853679536805368153682536835368453685536865368753688536895369053691536925369353694536955369653697536985369953700537015370253703537045370553706537075370853709537105371153712537135371453715537165371753718537195372053721537225372353724537255372653727537285372953730537315373253733537345373553736537375373853739537405374153742537435374453745537465374753748537495375053751537525375353754537555375653757537585375953760537615376253763537645376553766537675376853769537705377153772537735377453775537765377753778537795378053781537825378353784537855378653787537885378953790537915379253793537945379553796537975379853799538005380153802538035380453805538065380753808538095381053811538125381353814538155381653817538185381953820538215382253823538245382553826538275382853829538305383153832538335383453835538365383753838538395384053841538425384353844538455384653847538485384953850538515385253853538545385553856538575385853859538605386153862538635386453865538665386753868538695387053871538725387353874538755387653877538785387953880538815388253883538845388553886538875388853889538905389153892538935389453895538965389753898538995390053901539025390353904539055390653907539085390953910539115391253913539145391553916539175391853919539205392153922539235392453925539265392753928539295393053931539325393353934539355393653937539385393953940539415394253943539445394553946539475394853949539505395153952539535395453955539565395753958539595396053961539625396353964539655396653967539685396953970539715397253973539745397553976539775397853979539805398153982539835398453985539865398753988539895399053991539925399353994539955399653997539985399954000540015400254003540045400554006540075400854009540105401154012540135401454015540165401754018540195402054021540225402354024540255402654027540285402954030540315403254033540345403554036540375403854039540405404154042540435404454045540465404754048540495405054051540525405354054540555405654057540585405954060540615406254063540645406554066540675406854069540705407154072540735407454075540765407754078540795408054081540825408354084540855408654087540885408954090540915409254093540945409554096540975409854099541005410154102541035410454105541065410754108541095411054111541125411354114541155411654117541185411954120541215412254123541245412554126541275412854129541305413154132541335413454135541365413754138541395414054141541425414354144541455414654147541485414954150541515415254153541545415554156541575415854159541605416154162541635416454165541665416754168541695417054171541725417354174541755417654177541785417954180541815418254183541845418554186541875418854189541905419154192541935419454195541965419754198541995420054201542025420354204542055420654207542085420954210542115421254213542145421554216542175421854219542205422154222542235422454225542265422754228542295423054231542325423354234542355423654237542385423954240542415424254243542445424554246542475424854249542505425154252542535425454255542565425754258542595426054261542625426354264542655426654267542685426954270542715427254273542745427554276542775427854279542805428154282542835428454285542865428754288542895429054291542925429354294542955429654297542985429954300543015430254303543045430554306543075430854309543105431154312543135431454315543165431754318543195432054321543225432354324543255432654327543285432954330543315433254333543345433554336543375433854339
  1. /* sp.c
  2. *
  3. * Copyright (C) 2006-2022 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 SP_RSA_PRIVATE_EXP_D
  38. #define SP_RSA_PRIVATE_EXP_D
  39. #endif
  40. #ifndef WOLFSSL_SP_SMALL
  41. #define WOLFSSL_SP_SMALL
  42. #endif
  43. #endif
  44. #include <wolfssl/wolfcrypt/sp.h>
  45. #ifndef WOLFSSL_SP_ASM
  46. #if SP_WORD_SIZE == 32
  47. #define SP_PRINT_NUM(var, name, total, words, bits) \
  48. do { \
  49. int ii; \
  50. byte nb[(bits + 7) / 8]; \
  51. sp_digit _s[words]; \
  52. XMEMCPY(_s, var, sizeof(_s)); \
  53. sp_##total##_norm_##words(_s); \
  54. sp_##total##_to_bin_##words(_s, nb); \
  55. fprintf(stderr, name "=0x"); \
  56. for (ii=0; ii<(bits + 7) / 8; ii++) \
  57. fprintf(stderr, "%02x", nb[ii]); \
  58. fprintf(stderr, "\n"); \
  59. } while (0)
  60. #define SP_PRINT_VAL(var, name) \
  61. fprintf(stderr, name "=0x" SP_PRINT_FMT "\n", var)
  62. #define SP_PRINT_INT(var, name) \
  63. fprintf(stderr, name "=%d\n", var)
  64. #if (((!defined(WC_NO_CACHE_RESISTANT) && \
  65. (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH))) || \
  66. (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP))) && \
  67. !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || (defined(WOLFSSL_SP_SMALL) && \
  68. defined(WOLFSSL_HAVE_SP_ECC))
  69. /* Mask for address to obfuscate which of the two address will be used. */
  70. static const size_t addr_mask[2] = { 0, (size_t)-1 };
  71. #endif
  72. #if defined(WOLFSSL_SP_NONBLOCK) && (!defined(WOLFSSL_SP_NO_MALLOC) || !defined(WOLFSSL_SP_SMALL))
  73. #error SP non-blocking requires small and no-malloc (WOLFSSL_SP_SMALL and WOLFSSL_SP_NO_MALLOC)
  74. #endif
  75. #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
  76. #ifndef WOLFSSL_SP_NO_2048
  77. /* Read big endian unsigned byte array into r.
  78. *
  79. * r A single precision integer.
  80. * size Maximum number of bytes to convert
  81. * a Byte array.
  82. * n Number of bytes in array to read.
  83. */
  84. static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n)
  85. {
  86. int i;
  87. int j = 0;
  88. word32 s = 0;
  89. r[0] = 0;
  90. for (i = n-1; i >= 0; i--) {
  91. r[j] |= (((sp_digit)a[i]) << s);
  92. if (s >= 21U) {
  93. r[j] &= 0x1fffffff;
  94. s = 29U - s;
  95. if (j + 1 >= size) {
  96. break;
  97. }
  98. r[++j] = (sp_digit)a[i] >> s;
  99. s = 8U - s;
  100. }
  101. else {
  102. s += 8U;
  103. }
  104. }
  105. for (j++; j < size; j++) {
  106. r[j] = 0;
  107. }
  108. }
  109. /* Convert an mp_int to an array of sp_digit.
  110. *
  111. * r A single precision integer.
  112. * size Maximum number of bytes to convert
  113. * a A multi-precision integer.
  114. */
  115. static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
  116. {
  117. #if DIGIT_BIT == 29
  118. int j;
  119. XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
  120. for (j = a->used; j < size; j++) {
  121. r[j] = 0;
  122. }
  123. #elif DIGIT_BIT > 29
  124. int i;
  125. int j = 0;
  126. word32 s = 0;
  127. r[0] = 0;
  128. for (i = 0; i < a->used && j < size; i++) {
  129. r[j] |= ((sp_digit)a->dp[i] << s);
  130. r[j] &= 0x1fffffff;
  131. s = 29U - s;
  132. if (j + 1 >= size) {
  133. break;
  134. }
  135. /* lint allow cast of mismatch word32 and mp_digit */
  136. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  137. while ((s + 29U) <= (word32)DIGIT_BIT) {
  138. s += 29U;
  139. r[j] &= 0x1fffffff;
  140. if (j + 1 >= size) {
  141. break;
  142. }
  143. if (s < (word32)DIGIT_BIT) {
  144. /* lint allow cast of mismatch word32 and mp_digit */
  145. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  146. }
  147. else {
  148. r[++j] = (sp_digit)0;
  149. }
  150. }
  151. s = (word32)DIGIT_BIT - s;
  152. }
  153. for (j++; j < size; j++) {
  154. r[j] = 0;
  155. }
  156. #else
  157. int i;
  158. int j = 0;
  159. int s = 0;
  160. r[0] = 0;
  161. for (i = 0; i < a->used && j < size; i++) {
  162. r[j] |= ((sp_digit)a->dp[i]) << s;
  163. if (s + DIGIT_BIT >= 29) {
  164. r[j] &= 0x1fffffff;
  165. if (j + 1 >= size) {
  166. break;
  167. }
  168. s = 29 - s;
  169. if (s == DIGIT_BIT) {
  170. r[++j] = 0;
  171. s = 0;
  172. }
  173. else {
  174. r[++j] = a->dp[i] >> s;
  175. s = DIGIT_BIT - s;
  176. }
  177. }
  178. else {
  179. s += DIGIT_BIT;
  180. }
  181. }
  182. for (j++; j < size; j++) {
  183. r[j] = 0;
  184. }
  185. #endif
  186. }
  187. /* Write r as big endian to byte array.
  188. * Fixed length number of bytes written: 256
  189. *
  190. * r A single precision integer.
  191. * a Byte array.
  192. */
  193. static void sp_2048_to_bin_72(sp_digit* r, byte* a)
  194. {
  195. int i;
  196. int j;
  197. int s = 0;
  198. int b;
  199. for (i=0; i<71; i++) {
  200. r[i+1] += r[i] >> 29;
  201. r[i] &= 0x1fffffff;
  202. }
  203. j = 2055 / 8 - 1;
  204. a[j] = 0;
  205. for (i=0; i<72 && j>=0; i++) {
  206. b = 0;
  207. /* lint allow cast of mismatch sp_digit and int */
  208. a[j--] |= (byte)(r[i] << s); /*lint !e9033*/
  209. b += 8 - s;
  210. if (j < 0) {
  211. break;
  212. }
  213. while (b < 29) {
  214. a[j--] = (byte)(r[i] >> b);
  215. b += 8;
  216. if (j < 0) {
  217. break;
  218. }
  219. }
  220. s = 8 - (b - 29);
  221. if (j >= 0) {
  222. a[j] = 0;
  223. }
  224. if (s != 0) {
  225. j++;
  226. }
  227. }
  228. }
  229. #if (defined(WOLFSSL_HAVE_SP_RSA) && (!defined(WOLFSSL_RSA_PUBLIC_ONLY) || !defined(WOLFSSL_SP_SMALL))) || defined(WOLFSSL_HAVE_SP_DH)
  230. /* Normalize the values in each word to 29 bits.
  231. *
  232. * a Array of sp_digit to normalize.
  233. */
  234. static void sp_2048_norm_36(sp_digit* a)
  235. {
  236. #ifdef WOLFSSL_SP_SMALL
  237. int i;
  238. for (i = 0; i < 35; i++) {
  239. a[i+1] += a[i] >> 29;
  240. a[i] &= 0x1fffffff;
  241. }
  242. #else
  243. int i;
  244. for (i = 0; i < 32; i += 8) {
  245. a[i+1] += a[i+0] >> 29; a[i+0] &= 0x1fffffff;
  246. a[i+2] += a[i+1] >> 29; a[i+1] &= 0x1fffffff;
  247. a[i+3] += a[i+2] >> 29; a[i+2] &= 0x1fffffff;
  248. a[i+4] += a[i+3] >> 29; a[i+3] &= 0x1fffffff;
  249. a[i+5] += a[i+4] >> 29; a[i+4] &= 0x1fffffff;
  250. a[i+6] += a[i+5] >> 29; a[i+5] &= 0x1fffffff;
  251. a[i+7] += a[i+6] >> 29; a[i+6] &= 0x1fffffff;
  252. a[i+8] += a[i+7] >> 29; a[i+7] &= 0x1fffffff;
  253. }
  254. a[33] += a[32] >> 29; a[32] &= 0x1fffffff;
  255. a[34] += a[33] >> 29; a[33] &= 0x1fffffff;
  256. a[35] += a[34] >> 29; a[34] &= 0x1fffffff;
  257. #endif /* WOLFSSL_SP_SMALL */
  258. }
  259. #endif /* (WOLFSSL_HAVE_SP_RSA && (!WOLFSSL_RSA_PUBLIC_ONLY || !WOLFSSL_SP_SMALL)) || WOLFSSL_HAVE_SP_DH */
  260. /* Normalize the values in each word to 29 bits.
  261. *
  262. * a Array of sp_digit to normalize.
  263. */
  264. static void sp_2048_norm_72(sp_digit* a)
  265. {
  266. #ifdef WOLFSSL_SP_SMALL
  267. int i;
  268. for (i = 0; i < 71; i++) {
  269. a[i+1] += a[i] >> 29;
  270. a[i] &= 0x1fffffff;
  271. }
  272. #else
  273. int i;
  274. for (i = 0; i < 64; i += 8) {
  275. a[i+1] += a[i+0] >> 29; a[i+0] &= 0x1fffffff;
  276. a[i+2] += a[i+1] >> 29; a[i+1] &= 0x1fffffff;
  277. a[i+3] += a[i+2] >> 29; a[i+2] &= 0x1fffffff;
  278. a[i+4] += a[i+3] >> 29; a[i+3] &= 0x1fffffff;
  279. a[i+5] += a[i+4] >> 29; a[i+4] &= 0x1fffffff;
  280. a[i+6] += a[i+5] >> 29; a[i+5] &= 0x1fffffff;
  281. a[i+7] += a[i+6] >> 29; a[i+6] &= 0x1fffffff;
  282. a[i+8] += a[i+7] >> 29; a[i+7] &= 0x1fffffff;
  283. }
  284. a[65] += a[64] >> 29; a[64] &= 0x1fffffff;
  285. a[66] += a[65] >> 29; a[65] &= 0x1fffffff;
  286. a[67] += a[66] >> 29; a[66] &= 0x1fffffff;
  287. a[68] += a[67] >> 29; a[67] &= 0x1fffffff;
  288. a[69] += a[68] >> 29; a[68] &= 0x1fffffff;
  289. a[70] += a[69] >> 29; a[69] &= 0x1fffffff;
  290. a[71] += a[70] >> 29; a[70] &= 0x1fffffff;
  291. #endif /* WOLFSSL_SP_SMALL */
  292. }
  293. #ifndef WOLFSSL_SP_SMALL
  294. /* Multiply a and b into r. (r = a * b)
  295. *
  296. * r A single precision integer.
  297. * a A single precision integer.
  298. * b A single precision integer.
  299. */
  300. SP_NOINLINE static void sp_2048_mul_12(sp_digit* r, const sp_digit* a,
  301. const sp_digit* b)
  302. {
  303. sp_uint64 t0 = ((sp_uint64)a[ 0]) * b[ 0];
  304. sp_uint64 t1 = ((sp_uint64)a[ 0]) * b[ 1]
  305. + ((sp_uint64)a[ 1]) * b[ 0];
  306. sp_uint64 t2 = ((sp_uint64)a[ 0]) * b[ 2]
  307. + ((sp_uint64)a[ 1]) * b[ 1]
  308. + ((sp_uint64)a[ 2]) * b[ 0];
  309. sp_uint64 t3 = ((sp_uint64)a[ 0]) * b[ 3]
  310. + ((sp_uint64)a[ 1]) * b[ 2]
  311. + ((sp_uint64)a[ 2]) * b[ 1]
  312. + ((sp_uint64)a[ 3]) * b[ 0];
  313. sp_uint64 t4 = ((sp_uint64)a[ 0]) * b[ 4]
  314. + ((sp_uint64)a[ 1]) * b[ 3]
  315. + ((sp_uint64)a[ 2]) * b[ 2]
  316. + ((sp_uint64)a[ 3]) * b[ 1]
  317. + ((sp_uint64)a[ 4]) * b[ 0];
  318. sp_uint64 t5 = ((sp_uint64)a[ 0]) * b[ 5]
  319. + ((sp_uint64)a[ 1]) * b[ 4]
  320. + ((sp_uint64)a[ 2]) * b[ 3]
  321. + ((sp_uint64)a[ 3]) * b[ 2]
  322. + ((sp_uint64)a[ 4]) * b[ 1]
  323. + ((sp_uint64)a[ 5]) * b[ 0];
  324. sp_uint64 t6 = ((sp_uint64)a[ 0]) * b[ 6]
  325. + ((sp_uint64)a[ 1]) * b[ 5]
  326. + ((sp_uint64)a[ 2]) * b[ 4]
  327. + ((sp_uint64)a[ 3]) * b[ 3]
  328. + ((sp_uint64)a[ 4]) * b[ 2]
  329. + ((sp_uint64)a[ 5]) * b[ 1]
  330. + ((sp_uint64)a[ 6]) * b[ 0];
  331. sp_uint64 t7 = ((sp_uint64)a[ 0]) * b[ 7]
  332. + ((sp_uint64)a[ 1]) * b[ 6]
  333. + ((sp_uint64)a[ 2]) * b[ 5]
  334. + ((sp_uint64)a[ 3]) * b[ 4]
  335. + ((sp_uint64)a[ 4]) * b[ 3]
  336. + ((sp_uint64)a[ 5]) * b[ 2]
  337. + ((sp_uint64)a[ 6]) * b[ 1]
  338. + ((sp_uint64)a[ 7]) * b[ 0];
  339. sp_uint64 t8 = ((sp_uint64)a[ 0]) * b[ 8]
  340. + ((sp_uint64)a[ 1]) * b[ 7]
  341. + ((sp_uint64)a[ 2]) * b[ 6]
  342. + ((sp_uint64)a[ 3]) * b[ 5]
  343. + ((sp_uint64)a[ 4]) * b[ 4]
  344. + ((sp_uint64)a[ 5]) * b[ 3]
  345. + ((sp_uint64)a[ 6]) * b[ 2]
  346. + ((sp_uint64)a[ 7]) * b[ 1]
  347. + ((sp_uint64)a[ 8]) * b[ 0];
  348. sp_uint64 t9 = ((sp_uint64)a[ 0]) * b[ 9]
  349. + ((sp_uint64)a[ 1]) * b[ 8]
  350. + ((sp_uint64)a[ 2]) * b[ 7]
  351. + ((sp_uint64)a[ 3]) * b[ 6]
  352. + ((sp_uint64)a[ 4]) * b[ 5]
  353. + ((sp_uint64)a[ 5]) * b[ 4]
  354. + ((sp_uint64)a[ 6]) * b[ 3]
  355. + ((sp_uint64)a[ 7]) * b[ 2]
  356. + ((sp_uint64)a[ 8]) * b[ 1]
  357. + ((sp_uint64)a[ 9]) * b[ 0];
  358. sp_uint64 t10 = ((sp_uint64)a[ 0]) * b[10]
  359. + ((sp_uint64)a[ 1]) * b[ 9]
  360. + ((sp_uint64)a[ 2]) * b[ 8]
  361. + ((sp_uint64)a[ 3]) * b[ 7]
  362. + ((sp_uint64)a[ 4]) * b[ 6]
  363. + ((sp_uint64)a[ 5]) * b[ 5]
  364. + ((sp_uint64)a[ 6]) * b[ 4]
  365. + ((sp_uint64)a[ 7]) * b[ 3]
  366. + ((sp_uint64)a[ 8]) * b[ 2]
  367. + ((sp_uint64)a[ 9]) * b[ 1]
  368. + ((sp_uint64)a[10]) * b[ 0];
  369. sp_uint64 t11 = ((sp_uint64)a[ 0]) * b[11]
  370. + ((sp_uint64)a[ 1]) * b[10]
  371. + ((sp_uint64)a[ 2]) * b[ 9]
  372. + ((sp_uint64)a[ 3]) * b[ 8]
  373. + ((sp_uint64)a[ 4]) * b[ 7]
  374. + ((sp_uint64)a[ 5]) * b[ 6]
  375. + ((sp_uint64)a[ 6]) * b[ 5]
  376. + ((sp_uint64)a[ 7]) * b[ 4]
  377. + ((sp_uint64)a[ 8]) * b[ 3]
  378. + ((sp_uint64)a[ 9]) * b[ 2]
  379. + ((sp_uint64)a[10]) * b[ 1]
  380. + ((sp_uint64)a[11]) * b[ 0];
  381. sp_uint64 t12 = ((sp_uint64)a[ 1]) * b[11]
  382. + ((sp_uint64)a[ 2]) * b[10]
  383. + ((sp_uint64)a[ 3]) * b[ 9]
  384. + ((sp_uint64)a[ 4]) * b[ 8]
  385. + ((sp_uint64)a[ 5]) * b[ 7]
  386. + ((sp_uint64)a[ 6]) * b[ 6]
  387. + ((sp_uint64)a[ 7]) * b[ 5]
  388. + ((sp_uint64)a[ 8]) * b[ 4]
  389. + ((sp_uint64)a[ 9]) * b[ 3]
  390. + ((sp_uint64)a[10]) * b[ 2]
  391. + ((sp_uint64)a[11]) * b[ 1];
  392. sp_uint64 t13 = ((sp_uint64)a[ 2]) * b[11]
  393. + ((sp_uint64)a[ 3]) * b[10]
  394. + ((sp_uint64)a[ 4]) * b[ 9]
  395. + ((sp_uint64)a[ 5]) * b[ 8]
  396. + ((sp_uint64)a[ 6]) * b[ 7]
  397. + ((sp_uint64)a[ 7]) * b[ 6]
  398. + ((sp_uint64)a[ 8]) * b[ 5]
  399. + ((sp_uint64)a[ 9]) * b[ 4]
  400. + ((sp_uint64)a[10]) * b[ 3]
  401. + ((sp_uint64)a[11]) * b[ 2];
  402. sp_uint64 t14 = ((sp_uint64)a[ 3]) * b[11]
  403. + ((sp_uint64)a[ 4]) * b[10]
  404. + ((sp_uint64)a[ 5]) * b[ 9]
  405. + ((sp_uint64)a[ 6]) * b[ 8]
  406. + ((sp_uint64)a[ 7]) * b[ 7]
  407. + ((sp_uint64)a[ 8]) * b[ 6]
  408. + ((sp_uint64)a[ 9]) * b[ 5]
  409. + ((sp_uint64)a[10]) * b[ 4]
  410. + ((sp_uint64)a[11]) * b[ 3];
  411. sp_uint64 t15 = ((sp_uint64)a[ 4]) * b[11]
  412. + ((sp_uint64)a[ 5]) * b[10]
  413. + ((sp_uint64)a[ 6]) * b[ 9]
  414. + ((sp_uint64)a[ 7]) * b[ 8]
  415. + ((sp_uint64)a[ 8]) * b[ 7]
  416. + ((sp_uint64)a[ 9]) * b[ 6]
  417. + ((sp_uint64)a[10]) * b[ 5]
  418. + ((sp_uint64)a[11]) * b[ 4];
  419. sp_uint64 t16 = ((sp_uint64)a[ 5]) * b[11]
  420. + ((sp_uint64)a[ 6]) * b[10]
  421. + ((sp_uint64)a[ 7]) * b[ 9]
  422. + ((sp_uint64)a[ 8]) * b[ 8]
  423. + ((sp_uint64)a[ 9]) * b[ 7]
  424. + ((sp_uint64)a[10]) * b[ 6]
  425. + ((sp_uint64)a[11]) * b[ 5];
  426. sp_uint64 t17 = ((sp_uint64)a[ 6]) * b[11]
  427. + ((sp_uint64)a[ 7]) * b[10]
  428. + ((sp_uint64)a[ 8]) * b[ 9]
  429. + ((sp_uint64)a[ 9]) * b[ 8]
  430. + ((sp_uint64)a[10]) * b[ 7]
  431. + ((sp_uint64)a[11]) * b[ 6];
  432. sp_uint64 t18 = ((sp_uint64)a[ 7]) * b[11]
  433. + ((sp_uint64)a[ 8]) * b[10]
  434. + ((sp_uint64)a[ 9]) * b[ 9]
  435. + ((sp_uint64)a[10]) * b[ 8]
  436. + ((sp_uint64)a[11]) * b[ 7];
  437. sp_uint64 t19 = ((sp_uint64)a[ 8]) * b[11]
  438. + ((sp_uint64)a[ 9]) * b[10]
  439. + ((sp_uint64)a[10]) * b[ 9]
  440. + ((sp_uint64)a[11]) * b[ 8];
  441. sp_uint64 t20 = ((sp_uint64)a[ 9]) * b[11]
  442. + ((sp_uint64)a[10]) * b[10]
  443. + ((sp_uint64)a[11]) * b[ 9];
  444. sp_uint64 t21 = ((sp_uint64)a[10]) * b[11]
  445. + ((sp_uint64)a[11]) * b[10];
  446. sp_uint64 t22 = ((sp_uint64)a[11]) * b[11];
  447. t1 += t0 >> 29; r[ 0] = t0 & 0x1fffffff;
  448. t2 += t1 >> 29; r[ 1] = t1 & 0x1fffffff;
  449. t3 += t2 >> 29; r[ 2] = t2 & 0x1fffffff;
  450. t4 += t3 >> 29; r[ 3] = t3 & 0x1fffffff;
  451. t5 += t4 >> 29; r[ 4] = t4 & 0x1fffffff;
  452. t6 += t5 >> 29; r[ 5] = t5 & 0x1fffffff;
  453. t7 += t6 >> 29; r[ 6] = t6 & 0x1fffffff;
  454. t8 += t7 >> 29; r[ 7] = t7 & 0x1fffffff;
  455. t9 += t8 >> 29; r[ 8] = t8 & 0x1fffffff;
  456. t10 += t9 >> 29; r[ 9] = t9 & 0x1fffffff;
  457. t11 += t10 >> 29; r[10] = t10 & 0x1fffffff;
  458. t12 += t11 >> 29; r[11] = t11 & 0x1fffffff;
  459. t13 += t12 >> 29; r[12] = t12 & 0x1fffffff;
  460. t14 += t13 >> 29; r[13] = t13 & 0x1fffffff;
  461. t15 += t14 >> 29; r[14] = t14 & 0x1fffffff;
  462. t16 += t15 >> 29; r[15] = t15 & 0x1fffffff;
  463. t17 += t16 >> 29; r[16] = t16 & 0x1fffffff;
  464. t18 += t17 >> 29; r[17] = t17 & 0x1fffffff;
  465. t19 += t18 >> 29; r[18] = t18 & 0x1fffffff;
  466. t20 += t19 >> 29; r[19] = t19 & 0x1fffffff;
  467. t21 += t20 >> 29; r[20] = t20 & 0x1fffffff;
  468. t22 += t21 >> 29; r[21] = t21 & 0x1fffffff;
  469. r[23] = (sp_digit)(t22 >> 29);
  470. r[22] = t22 & 0x1fffffff;
  471. }
  472. /* Add b to a into r. (r = a + b)
  473. *
  474. * r A single precision integer.
  475. * a A single precision integer.
  476. * b A single precision integer.
  477. */
  478. SP_NOINLINE static int sp_2048_add_12(sp_digit* r, const sp_digit* a,
  479. const sp_digit* b)
  480. {
  481. r[ 0] = a[ 0] + b[ 0];
  482. r[ 1] = a[ 1] + b[ 1];
  483. r[ 2] = a[ 2] + b[ 2];
  484. r[ 3] = a[ 3] + b[ 3];
  485. r[ 4] = a[ 4] + b[ 4];
  486. r[ 5] = a[ 5] + b[ 5];
  487. r[ 6] = a[ 6] + b[ 6];
  488. r[ 7] = a[ 7] + b[ 7];
  489. r[ 8] = a[ 8] + b[ 8];
  490. r[ 9] = a[ 9] + b[ 9];
  491. r[10] = a[10] + b[10];
  492. r[11] = a[11] + b[11];
  493. return 0;
  494. }
  495. /* Sub b from a into r. (r = a - b)
  496. *
  497. * r A single precision integer.
  498. * a A single precision integer.
  499. * b A single precision integer.
  500. */
  501. SP_NOINLINE static int sp_2048_sub_24(sp_digit* r, const sp_digit* a,
  502. const sp_digit* b)
  503. {
  504. int i;
  505. for (i = 0; i < 24; i += 8) {
  506. r[i + 0] = a[i + 0] - b[i + 0];
  507. r[i + 1] = a[i + 1] - b[i + 1];
  508. r[i + 2] = a[i + 2] - b[i + 2];
  509. r[i + 3] = a[i + 3] - b[i + 3];
  510. r[i + 4] = a[i + 4] - b[i + 4];
  511. r[i + 5] = a[i + 5] - b[i + 5];
  512. r[i + 6] = a[i + 6] - b[i + 6];
  513. r[i + 7] = a[i + 7] - b[i + 7];
  514. }
  515. return 0;
  516. }
  517. /* Add b to a into r. (r = a + b)
  518. *
  519. * r A single precision integer.
  520. * a A single precision integer.
  521. * b A single precision integer.
  522. */
  523. SP_NOINLINE static int sp_2048_add_24(sp_digit* r, const sp_digit* a,
  524. const sp_digit* b)
  525. {
  526. int i;
  527. for (i = 0; i < 24; i += 8) {
  528. r[i + 0] = a[i + 0] + b[i + 0];
  529. r[i + 1] = a[i + 1] + b[i + 1];
  530. r[i + 2] = a[i + 2] + b[i + 2];
  531. r[i + 3] = a[i + 3] + b[i + 3];
  532. r[i + 4] = a[i + 4] + b[i + 4];
  533. r[i + 5] = a[i + 5] + b[i + 5];
  534. r[i + 6] = a[i + 6] + b[i + 6];
  535. r[i + 7] = a[i + 7] + b[i + 7];
  536. }
  537. return 0;
  538. }
  539. /* Normalize the values in each word to 29 bits.
  540. *
  541. * a Array of sp_digit to normalize.
  542. */
  543. static void sp_2048_norm_12(sp_digit* a)
  544. {
  545. #ifdef WOLFSSL_SP_SMALL
  546. int i;
  547. for (i = 0; i < 11; i++) {
  548. a[i+1] += a[i] >> 29;
  549. a[i] &= 0x1fffffff;
  550. }
  551. #else
  552. a[1] += a[0] >> 29; a[0] &= 0x1fffffff;
  553. a[2] += a[1] >> 29; a[1] &= 0x1fffffff;
  554. a[3] += a[2] >> 29; a[2] &= 0x1fffffff;
  555. a[4] += a[3] >> 29; a[3] &= 0x1fffffff;
  556. a[5] += a[4] >> 29; a[4] &= 0x1fffffff;
  557. a[6] += a[5] >> 29; a[5] &= 0x1fffffff;
  558. a[7] += a[6] >> 29; a[6] &= 0x1fffffff;
  559. a[8] += a[7] >> 29; a[7] &= 0x1fffffff;
  560. a[9] += a[8] >> 29; a[8] &= 0x1fffffff;
  561. a[10] += a[9] >> 29; a[9] &= 0x1fffffff;
  562. a[11] += a[10] >> 29; a[10] &= 0x1fffffff;
  563. #endif /* WOLFSSL_SP_SMALL */
  564. }
  565. /* Normalize the values in each word to 29 bits.
  566. *
  567. * a Array of sp_digit to normalize.
  568. */
  569. static void sp_2048_norm_24(sp_digit* a)
  570. {
  571. #ifdef WOLFSSL_SP_SMALL
  572. int i;
  573. for (i = 0; i < 23; i++) {
  574. a[i+1] += a[i] >> 29;
  575. a[i] &= 0x1fffffff;
  576. }
  577. #else
  578. int i;
  579. for (i = 0; i < 16; i += 8) {
  580. a[i+1] += a[i+0] >> 29; a[i+0] &= 0x1fffffff;
  581. a[i+2] += a[i+1] >> 29; a[i+1] &= 0x1fffffff;
  582. a[i+3] += a[i+2] >> 29; a[i+2] &= 0x1fffffff;
  583. a[i+4] += a[i+3] >> 29; a[i+3] &= 0x1fffffff;
  584. a[i+5] += a[i+4] >> 29; a[i+4] &= 0x1fffffff;
  585. a[i+6] += a[i+5] >> 29; a[i+5] &= 0x1fffffff;
  586. a[i+7] += a[i+6] >> 29; a[i+6] &= 0x1fffffff;
  587. a[i+8] += a[i+7] >> 29; a[i+7] &= 0x1fffffff;
  588. }
  589. a[17] += a[16] >> 29; a[16] &= 0x1fffffff;
  590. a[18] += a[17] >> 29; a[17] &= 0x1fffffff;
  591. a[19] += a[18] >> 29; a[18] &= 0x1fffffff;
  592. a[20] += a[19] >> 29; a[19] &= 0x1fffffff;
  593. a[21] += a[20] >> 29; a[20] &= 0x1fffffff;
  594. a[22] += a[21] >> 29; a[21] &= 0x1fffffff;
  595. a[23] += a[22] >> 29; a[22] &= 0x1fffffff;
  596. #endif /* WOLFSSL_SP_SMALL */
  597. }
  598. /* Multiply a and b into r. (r = a * b)
  599. *
  600. * r A single precision integer.
  601. * a A single precision integer.
  602. * b A single precision integer.
  603. */
  604. SP_NOINLINE static void sp_2048_mul_36(sp_digit* r, const sp_digit* a,
  605. const sp_digit* b)
  606. {
  607. sp_digit p0[24];
  608. sp_digit p1[24];
  609. sp_digit p2[24];
  610. sp_digit p3[24];
  611. sp_digit p4[24];
  612. sp_digit p5[24];
  613. sp_digit t0[24];
  614. sp_digit t1[24];
  615. sp_digit t2[24];
  616. sp_digit a0[12];
  617. sp_digit a1[12];
  618. sp_digit a2[12];
  619. sp_digit b0[12];
  620. sp_digit b1[12];
  621. sp_digit b2[12];
  622. (void)sp_2048_add_12(a0, a, &a[12]);
  623. sp_2048_norm_12(a0);
  624. (void)sp_2048_add_12(b0, b, &b[12]);
  625. sp_2048_norm_12(b0);
  626. (void)sp_2048_add_12(a1, &a[12], &a[24]);
  627. sp_2048_norm_12(a1);
  628. (void)sp_2048_add_12(b1, &b[12], &b[24]);
  629. sp_2048_norm_12(b1);
  630. (void)sp_2048_add_12(a2, a0, &a[24]);
  631. sp_2048_norm_12(a1);
  632. (void)sp_2048_add_12(b2, b0, &b[24]);
  633. sp_2048_norm_12(b2);
  634. sp_2048_mul_12(p0, a, b);
  635. sp_2048_mul_12(p2, &a[12], &b[12]);
  636. sp_2048_mul_12(p4, &a[24], &b[24]);
  637. sp_2048_mul_12(p1, a0, b0);
  638. sp_2048_mul_12(p3, a1, b1);
  639. sp_2048_mul_12(p5, a2, b2);
  640. XMEMSET(r, 0, sizeof(*r)*2U*36U);
  641. (void)sp_2048_sub_24(t0, p3, p2);
  642. (void)sp_2048_sub_24(t1, p1, p2);
  643. (void)sp_2048_sub_24(t2, p5, t0);
  644. (void)sp_2048_sub_24(t2, t2, t1);
  645. sp_2048_norm_24(t2);
  646. (void)sp_2048_sub_24(t0, t0, p4);
  647. sp_2048_norm_24(t0);
  648. (void)sp_2048_sub_24(t1, t1, p0);
  649. sp_2048_norm_24(t1);
  650. (void)sp_2048_add_24(r, r, p0);
  651. (void)sp_2048_add_24(&r[12], &r[12], t1);
  652. (void)sp_2048_add_24(&r[24], &r[24], t2);
  653. (void)sp_2048_add_24(&r[36], &r[36], t0);
  654. (void)sp_2048_add_24(&r[48], &r[48], p4);
  655. sp_2048_norm_72(r);
  656. }
  657. /* Add b to a into r. (r = a + b)
  658. *
  659. * r A single precision integer.
  660. * a A single precision integer.
  661. * b A single precision integer.
  662. */
  663. SP_NOINLINE static int sp_2048_add_36(sp_digit* r, const sp_digit* a,
  664. const sp_digit* b)
  665. {
  666. int i;
  667. for (i = 0; i < 32; i += 8) {
  668. r[i + 0] = a[i + 0] + b[i + 0];
  669. r[i + 1] = a[i + 1] + b[i + 1];
  670. r[i + 2] = a[i + 2] + b[i + 2];
  671. r[i + 3] = a[i + 3] + b[i + 3];
  672. r[i + 4] = a[i + 4] + b[i + 4];
  673. r[i + 5] = a[i + 5] + b[i + 5];
  674. r[i + 6] = a[i + 6] + b[i + 6];
  675. r[i + 7] = a[i + 7] + b[i + 7];
  676. }
  677. r[32] = a[32] + b[32];
  678. r[33] = a[33] + b[33];
  679. r[34] = a[34] + b[34];
  680. r[35] = a[35] + b[35];
  681. return 0;
  682. }
  683. /* Add b to a into r. (r = a + b)
  684. *
  685. * r A single precision integer.
  686. * a A single precision integer.
  687. * b A single precision integer.
  688. */
  689. SP_NOINLINE static int sp_2048_add_72(sp_digit* r, const sp_digit* a,
  690. const sp_digit* b)
  691. {
  692. int i;
  693. for (i = 0; i < 72; i += 8) {
  694. r[i + 0] = a[i + 0] + b[i + 0];
  695. r[i + 1] = a[i + 1] + b[i + 1];
  696. r[i + 2] = a[i + 2] + b[i + 2];
  697. r[i + 3] = a[i + 3] + b[i + 3];
  698. r[i + 4] = a[i + 4] + b[i + 4];
  699. r[i + 5] = a[i + 5] + b[i + 5];
  700. r[i + 6] = a[i + 6] + b[i + 6];
  701. r[i + 7] = a[i + 7] + b[i + 7];
  702. }
  703. return 0;
  704. }
  705. /* Sub b from a into r. (r = a - b)
  706. *
  707. * r A single precision integer.
  708. * a A single precision integer.
  709. * b A single precision integer.
  710. */
  711. SP_NOINLINE static int sp_2048_sub_72(sp_digit* r, const sp_digit* a,
  712. const sp_digit* b)
  713. {
  714. int i;
  715. for (i = 0; i < 72; i += 8) {
  716. r[i + 0] = a[i + 0] - b[i + 0];
  717. r[i + 1] = a[i + 1] - b[i + 1];
  718. r[i + 2] = a[i + 2] - b[i + 2];
  719. r[i + 3] = a[i + 3] - b[i + 3];
  720. r[i + 4] = a[i + 4] - b[i + 4];
  721. r[i + 5] = a[i + 5] - b[i + 5];
  722. r[i + 6] = a[i + 6] - b[i + 6];
  723. r[i + 7] = a[i + 7] - b[i + 7];
  724. }
  725. return 0;
  726. }
  727. /* Normalize the values in each word to 29 bits.
  728. *
  729. * a Array of sp_digit to normalize.
  730. */
  731. static void sp_2048_norm_144(sp_digit* a)
  732. {
  733. #ifdef WOLFSSL_SP_SMALL
  734. int i;
  735. for (i = 0; i < 143; i++) {
  736. a[i+1] += a[i] >> 29;
  737. a[i] &= 0x1fffffff;
  738. }
  739. #else
  740. int i;
  741. for (i = 0; i < 136; i += 8) {
  742. a[i+1] += a[i+0] >> 29; a[i+0] &= 0x1fffffff;
  743. a[i+2] += a[i+1] >> 29; a[i+1] &= 0x1fffffff;
  744. a[i+3] += a[i+2] >> 29; a[i+2] &= 0x1fffffff;
  745. a[i+4] += a[i+3] >> 29; a[i+3] &= 0x1fffffff;
  746. a[i+5] += a[i+4] >> 29; a[i+4] &= 0x1fffffff;
  747. a[i+6] += a[i+5] >> 29; a[i+5] &= 0x1fffffff;
  748. a[i+7] += a[i+6] >> 29; a[i+6] &= 0x1fffffff;
  749. a[i+8] += a[i+7] >> 29; a[i+7] &= 0x1fffffff;
  750. }
  751. a[137] += a[136] >> 29; a[136] &= 0x1fffffff;
  752. a[138] += a[137] >> 29; a[137] &= 0x1fffffff;
  753. a[139] += a[138] >> 29; a[138] &= 0x1fffffff;
  754. a[140] += a[139] >> 29; a[139] &= 0x1fffffff;
  755. a[141] += a[140] >> 29; a[140] &= 0x1fffffff;
  756. a[142] += a[141] >> 29; a[141] &= 0x1fffffff;
  757. a[143] += a[142] >> 29; a[142] &= 0x1fffffff;
  758. #endif /* WOLFSSL_SP_SMALL */
  759. }
  760. /* Multiply a and b into r. (r = a * b)
  761. *
  762. * r A single precision integer.
  763. * a A single precision integer.
  764. * b A single precision integer.
  765. */
  766. SP_NOINLINE static void sp_2048_mul_72(sp_digit* r, const sp_digit* a,
  767. const sp_digit* b)
  768. {
  769. sp_digit* z0 = r;
  770. sp_digit z1[72];
  771. sp_digit* a1 = z1;
  772. sp_digit b1[36];
  773. sp_digit* z2 = r + 72;
  774. (void)sp_2048_add_36(a1, a, &a[36]);
  775. sp_2048_norm_36(a1);
  776. (void)sp_2048_add_36(b1, b, &b[36]);
  777. sp_2048_norm_36(b1);
  778. sp_2048_mul_36(z2, &a[36], &b[36]);
  779. sp_2048_mul_36(z0, a, b);
  780. sp_2048_mul_36(z1, a1, b1);
  781. (void)sp_2048_sub_72(z1, z1, z2);
  782. (void)sp_2048_sub_72(z1, z1, z0);
  783. (void)sp_2048_add_72(r + 36, r + 36, z1);
  784. sp_2048_norm_144(r);
  785. }
  786. /* Square a and put result in r. (r = a * a)
  787. *
  788. * r A single precision integer.
  789. * a A single precision integer.
  790. */
  791. SP_NOINLINE static void sp_2048_sqr_12(sp_digit* r, const sp_digit* a)
  792. {
  793. sp_uint64 t0 = ((sp_uint64)a[ 0]) * a[ 0];
  794. sp_uint64 t1 = (((sp_uint64)a[ 0]) * a[ 1]) * 2;
  795. sp_uint64 t2 = (((sp_uint64)a[ 0]) * a[ 2]) * 2
  796. + ((sp_uint64)a[ 1]) * a[ 1];
  797. sp_uint64 t3 = (((sp_uint64)a[ 0]) * a[ 3]
  798. + ((sp_uint64)a[ 1]) * a[ 2]) * 2;
  799. sp_uint64 t4 = (((sp_uint64)a[ 0]) * a[ 4]
  800. + ((sp_uint64)a[ 1]) * a[ 3]) * 2
  801. + ((sp_uint64)a[ 2]) * a[ 2];
  802. sp_uint64 t5 = (((sp_uint64)a[ 0]) * a[ 5]
  803. + ((sp_uint64)a[ 1]) * a[ 4]
  804. + ((sp_uint64)a[ 2]) * a[ 3]) * 2;
  805. sp_uint64 t6 = (((sp_uint64)a[ 0]) * a[ 6]
  806. + ((sp_uint64)a[ 1]) * a[ 5]
  807. + ((sp_uint64)a[ 2]) * a[ 4]) * 2
  808. + ((sp_uint64)a[ 3]) * a[ 3];
  809. sp_uint64 t7 = (((sp_uint64)a[ 0]) * a[ 7]
  810. + ((sp_uint64)a[ 1]) * a[ 6]
  811. + ((sp_uint64)a[ 2]) * a[ 5]
  812. + ((sp_uint64)a[ 3]) * a[ 4]) * 2;
  813. sp_uint64 t8 = (((sp_uint64)a[ 0]) * a[ 8]
  814. + ((sp_uint64)a[ 1]) * a[ 7]
  815. + ((sp_uint64)a[ 2]) * a[ 6]
  816. + ((sp_uint64)a[ 3]) * a[ 5]) * 2
  817. + ((sp_uint64)a[ 4]) * a[ 4];
  818. sp_uint64 t9 = (((sp_uint64)a[ 0]) * a[ 9]
  819. + ((sp_uint64)a[ 1]) * a[ 8]
  820. + ((sp_uint64)a[ 2]) * a[ 7]
  821. + ((sp_uint64)a[ 3]) * a[ 6]
  822. + ((sp_uint64)a[ 4]) * a[ 5]) * 2;
  823. sp_uint64 t10 = (((sp_uint64)a[ 0]) * a[10]
  824. + ((sp_uint64)a[ 1]) * a[ 9]
  825. + ((sp_uint64)a[ 2]) * a[ 8]
  826. + ((sp_uint64)a[ 3]) * a[ 7]
  827. + ((sp_uint64)a[ 4]) * a[ 6]) * 2
  828. + ((sp_uint64)a[ 5]) * a[ 5];
  829. sp_uint64 t11 = (((sp_uint64)a[ 0]) * a[11]
  830. + ((sp_uint64)a[ 1]) * a[10]
  831. + ((sp_uint64)a[ 2]) * a[ 9]
  832. + ((sp_uint64)a[ 3]) * a[ 8]
  833. + ((sp_uint64)a[ 4]) * a[ 7]
  834. + ((sp_uint64)a[ 5]) * a[ 6]) * 2;
  835. sp_uint64 t12 = (((sp_uint64)a[ 1]) * a[11]
  836. + ((sp_uint64)a[ 2]) * a[10]
  837. + ((sp_uint64)a[ 3]) * a[ 9]
  838. + ((sp_uint64)a[ 4]) * a[ 8]
  839. + ((sp_uint64)a[ 5]) * a[ 7]) * 2
  840. + ((sp_uint64)a[ 6]) * a[ 6];
  841. sp_uint64 t13 = (((sp_uint64)a[ 2]) * a[11]
  842. + ((sp_uint64)a[ 3]) * a[10]
  843. + ((sp_uint64)a[ 4]) * a[ 9]
  844. + ((sp_uint64)a[ 5]) * a[ 8]
  845. + ((sp_uint64)a[ 6]) * a[ 7]) * 2;
  846. sp_uint64 t14 = (((sp_uint64)a[ 3]) * a[11]
  847. + ((sp_uint64)a[ 4]) * a[10]
  848. + ((sp_uint64)a[ 5]) * a[ 9]
  849. + ((sp_uint64)a[ 6]) * a[ 8]) * 2
  850. + ((sp_uint64)a[ 7]) * a[ 7];
  851. sp_uint64 t15 = (((sp_uint64)a[ 4]) * a[11]
  852. + ((sp_uint64)a[ 5]) * a[10]
  853. + ((sp_uint64)a[ 6]) * a[ 9]
  854. + ((sp_uint64)a[ 7]) * a[ 8]) * 2;
  855. sp_uint64 t16 = (((sp_uint64)a[ 5]) * a[11]
  856. + ((sp_uint64)a[ 6]) * a[10]
  857. + ((sp_uint64)a[ 7]) * a[ 9]) * 2
  858. + ((sp_uint64)a[ 8]) * a[ 8];
  859. sp_uint64 t17 = (((sp_uint64)a[ 6]) * a[11]
  860. + ((sp_uint64)a[ 7]) * a[10]
  861. + ((sp_uint64)a[ 8]) * a[ 9]) * 2;
  862. sp_uint64 t18 = (((sp_uint64)a[ 7]) * a[11]
  863. + ((sp_uint64)a[ 8]) * a[10]) * 2
  864. + ((sp_uint64)a[ 9]) * a[ 9];
  865. sp_uint64 t19 = (((sp_uint64)a[ 8]) * a[11]
  866. + ((sp_uint64)a[ 9]) * a[10]) * 2;
  867. sp_uint64 t20 = (((sp_uint64)a[ 9]) * a[11]) * 2
  868. + ((sp_uint64)a[10]) * a[10];
  869. sp_uint64 t21 = (((sp_uint64)a[10]) * a[11]) * 2;
  870. sp_uint64 t22 = ((sp_uint64)a[11]) * a[11];
  871. t1 += t0 >> 29; r[ 0] = t0 & 0x1fffffff;
  872. t2 += t1 >> 29; r[ 1] = t1 & 0x1fffffff;
  873. t3 += t2 >> 29; r[ 2] = t2 & 0x1fffffff;
  874. t4 += t3 >> 29; r[ 3] = t3 & 0x1fffffff;
  875. t5 += t4 >> 29; r[ 4] = t4 & 0x1fffffff;
  876. t6 += t5 >> 29; r[ 5] = t5 & 0x1fffffff;
  877. t7 += t6 >> 29; r[ 6] = t6 & 0x1fffffff;
  878. t8 += t7 >> 29; r[ 7] = t7 & 0x1fffffff;
  879. t9 += t8 >> 29; r[ 8] = t8 & 0x1fffffff;
  880. t10 += t9 >> 29; r[ 9] = t9 & 0x1fffffff;
  881. t11 += t10 >> 29; r[10] = t10 & 0x1fffffff;
  882. t12 += t11 >> 29; r[11] = t11 & 0x1fffffff;
  883. t13 += t12 >> 29; r[12] = t12 & 0x1fffffff;
  884. t14 += t13 >> 29; r[13] = t13 & 0x1fffffff;
  885. t15 += t14 >> 29; r[14] = t14 & 0x1fffffff;
  886. t16 += t15 >> 29; r[15] = t15 & 0x1fffffff;
  887. t17 += t16 >> 29; r[16] = t16 & 0x1fffffff;
  888. t18 += t17 >> 29; r[17] = t17 & 0x1fffffff;
  889. t19 += t18 >> 29; r[18] = t18 & 0x1fffffff;
  890. t20 += t19 >> 29; r[19] = t19 & 0x1fffffff;
  891. t21 += t20 >> 29; r[20] = t20 & 0x1fffffff;
  892. t22 += t21 >> 29; r[21] = t21 & 0x1fffffff;
  893. r[23] = (sp_digit)(t22 >> 29);
  894. r[22] = t22 & 0x1fffffff;
  895. }
  896. /* Square a into r. (r = a * a)
  897. *
  898. * r A single precision integer.
  899. * a A single precision integer.
  900. */
  901. SP_NOINLINE static void sp_2048_sqr_36(sp_digit* r, const sp_digit* a)
  902. {
  903. sp_digit p0[24];
  904. sp_digit p1[24];
  905. sp_digit p2[24];
  906. sp_digit p3[24];
  907. sp_digit p4[24];
  908. sp_digit p5[24];
  909. sp_digit t0[24];
  910. sp_digit t1[24];
  911. sp_digit t2[24];
  912. sp_digit a0[12];
  913. sp_digit a1[12];
  914. sp_digit a2[12];
  915. (void)sp_2048_add_12(a0, a, &a[12]);
  916. sp_2048_norm_12(a0);
  917. (void)sp_2048_add_12(a1, &a[12], &a[24]);
  918. sp_2048_norm_12(a1);
  919. (void)sp_2048_add_12(a2, a0, &a[24]);
  920. sp_2048_norm_12(a2);
  921. sp_2048_sqr_12(p0, a);
  922. sp_2048_sqr_12(p2, &a[12]);
  923. sp_2048_sqr_12(p4, &a[24]);
  924. sp_2048_sqr_12(p1, a0);
  925. sp_2048_sqr_12(p3, a1);
  926. sp_2048_sqr_12(p5, a2);
  927. XMEMSET(r, 0, sizeof(*r)*2U*36U);
  928. (void)sp_2048_sub_24(t0, p3, p2);
  929. (void)sp_2048_sub_24(t1, p1, p2);
  930. (void)sp_2048_sub_24(t2, p5, t0);
  931. (void)sp_2048_sub_24(t2, t2, t1);
  932. sp_2048_norm_24(t2);
  933. (void)sp_2048_sub_24(t0, t0, p4);
  934. sp_2048_norm_24(t0);
  935. (void)sp_2048_sub_24(t1, t1, p0);
  936. sp_2048_norm_24(t1);
  937. (void)sp_2048_add_24(r, r, p0);
  938. (void)sp_2048_add_24(&r[12], &r[12], t1);
  939. (void)sp_2048_add_24(&r[24], &r[24], t2);
  940. (void)sp_2048_add_24(&r[36], &r[36], t0);
  941. (void)sp_2048_add_24(&r[48], &r[48], p4);
  942. sp_2048_norm_72(r);
  943. }
  944. /* Square a and put result in r. (r = a * a)
  945. *
  946. * r A single precision integer.
  947. * a A single precision integer.
  948. */
  949. SP_NOINLINE static void sp_2048_sqr_72(sp_digit* r, const sp_digit* a)
  950. {
  951. sp_digit* z0 = r;
  952. sp_digit z1[72];
  953. sp_digit* a1 = z1;
  954. sp_digit* z2 = r + 72;
  955. (void)sp_2048_add_36(a1, a, &a[36]);
  956. sp_2048_norm_36(a1);
  957. sp_2048_sqr_36(z2, &a[36]);
  958. sp_2048_sqr_36(z0, a);
  959. sp_2048_sqr_36(z1, a1);
  960. (void)sp_2048_sub_72(z1, z1, z2);
  961. (void)sp_2048_sub_72(z1, z1, z0);
  962. (void)sp_2048_add_72(r + 36, r + 36, z1);
  963. sp_2048_norm_144(r);
  964. }
  965. #endif /* !WOLFSSL_SP_SMALL */
  966. #ifdef WOLFSSL_SP_SMALL
  967. /* Add b to a into r. (r = a + b)
  968. *
  969. * r A single precision integer.
  970. * a A single precision integer.
  971. * b A single precision integer.
  972. */
  973. SP_NOINLINE static int sp_2048_add_72(sp_digit* r, const sp_digit* a,
  974. const sp_digit* b)
  975. {
  976. int i;
  977. for (i = 0; i < 72; i++) {
  978. r[i] = a[i] + b[i];
  979. }
  980. return 0;
  981. }
  982. #endif /* WOLFSSL_SP_SMALL */
  983. #ifdef WOLFSSL_SP_SMALL
  984. /* Sub b from a into r. (r = a - b)
  985. *
  986. * r A single precision integer.
  987. * a A single precision integer.
  988. * b A single precision integer.
  989. */
  990. SP_NOINLINE static int sp_2048_sub_72(sp_digit* r, const sp_digit* a,
  991. const sp_digit* b)
  992. {
  993. int i;
  994. for (i = 0; i < 72; i++) {
  995. r[i] = a[i] - b[i];
  996. }
  997. return 0;
  998. }
  999. #endif /* WOLFSSL_SP_SMALL */
  1000. #ifdef WOLFSSL_SP_SMALL
  1001. /* Multiply a and b into r. (r = a * b)
  1002. *
  1003. * r A single precision integer.
  1004. * a A single precision integer.
  1005. * b A single precision integer.
  1006. */
  1007. SP_NOINLINE static void sp_2048_mul_72(sp_digit* r, const sp_digit* a,
  1008. const sp_digit* b)
  1009. {
  1010. int i;
  1011. int imax;
  1012. int k;
  1013. sp_uint64 c;
  1014. sp_uint64 lo;
  1015. c = ((sp_uint64)a[71]) * b[71];
  1016. r[143] = (sp_digit)(c >> 29);
  1017. c &= 0x1fffffff;
  1018. for (k = 141; k >= 0; k--) {
  1019. if (k >= 72) {
  1020. i = k - 71;
  1021. imax = 71;
  1022. }
  1023. else {
  1024. i = 0;
  1025. imax = k;
  1026. }
  1027. if (imax - i > 15) {
  1028. int imaxlo;
  1029. lo = 0;
  1030. for (imaxlo = i; imaxlo <= imax; imaxlo += 15) {
  1031. for (; i <= imax && i < imaxlo + 15; i++) {
  1032. lo += ((sp_uint64)a[i]) * b[k - i];
  1033. }
  1034. c += lo >> 29;
  1035. lo &= 0x1fffffff;
  1036. }
  1037. r[k + 2] += (sp_digit)(c >> 29);
  1038. r[k + 1] = (sp_digit)(c & 0x1fffffff);
  1039. c = lo & 0x1fffffff;
  1040. }
  1041. else {
  1042. lo = 0;
  1043. for (; i <= imax; i++) {
  1044. lo += ((sp_uint64)a[i]) * b[k - i];
  1045. }
  1046. c += lo >> 29;
  1047. r[k + 2] += (sp_digit)(c >> 29);
  1048. r[k + 1] = (sp_digit)(c & 0x1fffffff);
  1049. c = lo & 0x1fffffff;
  1050. }
  1051. }
  1052. r[0] = (sp_digit)c;
  1053. }
  1054. /* Square a and put result in r. (r = a * a)
  1055. *
  1056. * r A single precision integer.
  1057. * a A single precision integer.
  1058. */
  1059. SP_NOINLINE static void sp_2048_sqr_72(sp_digit* r, const sp_digit* a)
  1060. {
  1061. int i;
  1062. int imax;
  1063. int k;
  1064. sp_uint64 c;
  1065. sp_uint64 t;
  1066. c = ((sp_uint64)a[71]) * a[71];
  1067. r[143] = (sp_digit)(c >> 29);
  1068. c = (c & 0x1fffffff) << 29;
  1069. for (k = 141; k >= 0; k--) {
  1070. i = (k + 1) / 2;
  1071. if ((k & 1) == 0) {
  1072. c += ((sp_uint64)a[i]) * a[i];
  1073. i++;
  1074. }
  1075. if (k < 71) {
  1076. imax = k;
  1077. }
  1078. else {
  1079. imax = 71;
  1080. }
  1081. if (imax - i >= 14) {
  1082. int imaxlo;
  1083. sp_uint64 hi;
  1084. hi = c >> 29;
  1085. c &= 0x1fffffff;
  1086. for (imaxlo = i; imaxlo <= imax; imaxlo += 14) {
  1087. t = 0;
  1088. for (; i <= imax && i < imaxlo + 14; i++) {
  1089. t += ((sp_uint64)a[i]) * a[k - i];
  1090. }
  1091. c += t * 2;
  1092. hi += c >> 29;
  1093. c &= 0x1fffffff;
  1094. }
  1095. r[k + 2] += (sp_digit)(hi >> 29);
  1096. r[k + 1] = (sp_digit)(hi & 0x1fffffff);
  1097. c <<= 29;
  1098. }
  1099. else
  1100. {
  1101. t = 0;
  1102. for (; i <= imax; i++) {
  1103. t += ((sp_uint64)a[i]) * a[k - i];
  1104. }
  1105. c += t * 2;
  1106. r[k + 2] += (sp_digit) (c >> 58);
  1107. r[k + 1] = (sp_digit)((c >> 29) & 0x1fffffff);
  1108. c = (c & 0x1fffffff) << 29;
  1109. }
  1110. }
  1111. r[0] = (sp_digit)(c >> 29);
  1112. }
  1113. #endif /* WOLFSSL_SP_SMALL */
  1114. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  1115. #ifdef WOLFSSL_SP_SMALL
  1116. /* Add b to a into r. (r = a + b)
  1117. *
  1118. * r A single precision integer.
  1119. * a A single precision integer.
  1120. * b A single precision integer.
  1121. */
  1122. SP_NOINLINE static int sp_2048_add_36(sp_digit* r, const sp_digit* a,
  1123. const sp_digit* b)
  1124. {
  1125. int i;
  1126. for (i = 0; i < 36; i++) {
  1127. r[i] = a[i] + b[i];
  1128. }
  1129. return 0;
  1130. }
  1131. #endif /* WOLFSSL_SP_SMALL */
  1132. #ifdef WOLFSSL_SP_SMALL
  1133. /* Sub b from a into r. (r = a - b)
  1134. *
  1135. * r A single precision integer.
  1136. * a A single precision integer.
  1137. * b A single precision integer.
  1138. */
  1139. SP_NOINLINE static int sp_2048_sub_36(sp_digit* r, const sp_digit* a,
  1140. const sp_digit* b)
  1141. {
  1142. int i;
  1143. for (i = 0; i < 36; i++) {
  1144. r[i] = a[i] - b[i];
  1145. }
  1146. return 0;
  1147. }
  1148. #else
  1149. /* Sub b from a into r. (r = a - b)
  1150. *
  1151. * r A single precision integer.
  1152. * a A single precision integer.
  1153. * b A single precision integer.
  1154. */
  1155. SP_NOINLINE static int sp_2048_sub_36(sp_digit* r, const sp_digit* a,
  1156. const sp_digit* b)
  1157. {
  1158. int i;
  1159. for (i = 0; i < 32; i += 8) {
  1160. r[i + 0] = a[i + 0] - b[i + 0];
  1161. r[i + 1] = a[i + 1] - b[i + 1];
  1162. r[i + 2] = a[i + 2] - b[i + 2];
  1163. r[i + 3] = a[i + 3] - b[i + 3];
  1164. r[i + 4] = a[i + 4] - b[i + 4];
  1165. r[i + 5] = a[i + 5] - b[i + 5];
  1166. r[i + 6] = a[i + 6] - b[i + 6];
  1167. r[i + 7] = a[i + 7] - b[i + 7];
  1168. }
  1169. r[32] = a[32] - b[32];
  1170. r[33] = a[33] - b[33];
  1171. r[34] = a[34] - b[34];
  1172. r[35] = a[35] - b[35];
  1173. return 0;
  1174. }
  1175. #endif /* WOLFSSL_SP_SMALL */
  1176. #ifdef WOLFSSL_SP_SMALL
  1177. /* Multiply a and b into r. (r = a * b)
  1178. *
  1179. * r A single precision integer.
  1180. * a A single precision integer.
  1181. * b A single precision integer.
  1182. */
  1183. SP_NOINLINE static void sp_2048_mul_36(sp_digit* r, const sp_digit* a,
  1184. const sp_digit* b)
  1185. {
  1186. int i;
  1187. int imax;
  1188. int k;
  1189. sp_uint64 c;
  1190. sp_uint64 lo;
  1191. c = ((sp_uint64)a[35]) * b[35];
  1192. r[71] = (sp_digit)(c >> 29);
  1193. c &= 0x1fffffff;
  1194. for (k = 69; k >= 0; k--) {
  1195. if (k >= 36) {
  1196. i = k - 35;
  1197. imax = 35;
  1198. }
  1199. else {
  1200. i = 0;
  1201. imax = k;
  1202. }
  1203. if (imax - i > 15) {
  1204. int imaxlo;
  1205. lo = 0;
  1206. for (imaxlo = i; imaxlo <= imax; imaxlo += 15) {
  1207. for (; i <= imax && i < imaxlo + 15; i++) {
  1208. lo += ((sp_uint64)a[i]) * b[k - i];
  1209. }
  1210. c += lo >> 29;
  1211. lo &= 0x1fffffff;
  1212. }
  1213. r[k + 2] += (sp_digit)(c >> 29);
  1214. r[k + 1] = (sp_digit)(c & 0x1fffffff);
  1215. c = lo & 0x1fffffff;
  1216. }
  1217. else {
  1218. lo = 0;
  1219. for (; i <= imax; i++) {
  1220. lo += ((sp_uint64)a[i]) * b[k - i];
  1221. }
  1222. c += lo >> 29;
  1223. r[k + 2] += (sp_digit)(c >> 29);
  1224. r[k + 1] = (sp_digit)(c & 0x1fffffff);
  1225. c = lo & 0x1fffffff;
  1226. }
  1227. }
  1228. r[0] = (sp_digit)c;
  1229. }
  1230. /* Square a and put result in r. (r = a * a)
  1231. *
  1232. * r A single precision integer.
  1233. * a A single precision integer.
  1234. */
  1235. SP_NOINLINE static void sp_2048_sqr_36(sp_digit* r, const sp_digit* a)
  1236. {
  1237. int i;
  1238. int imax;
  1239. int k;
  1240. sp_uint64 c;
  1241. sp_uint64 t;
  1242. c = ((sp_uint64)a[35]) * a[35];
  1243. r[71] = (sp_digit)(c >> 29);
  1244. c = (c & 0x1fffffff) << 29;
  1245. for (k = 69; k >= 0; k--) {
  1246. i = (k + 1) / 2;
  1247. if ((k & 1) == 0) {
  1248. c += ((sp_uint64)a[i]) * a[i];
  1249. i++;
  1250. }
  1251. if (k < 35) {
  1252. imax = k;
  1253. }
  1254. else {
  1255. imax = 35;
  1256. }
  1257. if (imax - i >= 14) {
  1258. int imaxlo;
  1259. sp_uint64 hi;
  1260. hi = c >> 29;
  1261. c &= 0x1fffffff;
  1262. for (imaxlo = i; imaxlo <= imax; imaxlo += 14) {
  1263. t = 0;
  1264. for (; i <= imax && i < imaxlo + 14; i++) {
  1265. t += ((sp_uint64)a[i]) * a[k - i];
  1266. }
  1267. c += t * 2;
  1268. hi += c >> 29;
  1269. c &= 0x1fffffff;
  1270. }
  1271. r[k + 2] += (sp_digit)(hi >> 29);
  1272. r[k + 1] = (sp_digit)(hi & 0x1fffffff);
  1273. c <<= 29;
  1274. }
  1275. else
  1276. {
  1277. t = 0;
  1278. for (; i <= imax; i++) {
  1279. t += ((sp_uint64)a[i]) * a[k - i];
  1280. }
  1281. c += t * 2;
  1282. r[k + 2] += (sp_digit) (c >> 58);
  1283. r[k + 1] = (sp_digit)((c >> 29) & 0x1fffffff);
  1284. c = (c & 0x1fffffff) << 29;
  1285. }
  1286. }
  1287. r[0] = (sp_digit)(c >> 29);
  1288. }
  1289. #endif /* WOLFSSL_SP_SMALL */
  1290. #endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
  1291. /* Caclulate the bottom digit of -1/a mod 2^n.
  1292. *
  1293. * a A single precision number.
  1294. * rho Bottom word of inverse.
  1295. */
  1296. static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho)
  1297. {
  1298. sp_digit x;
  1299. sp_digit b;
  1300. b = a[0];
  1301. x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
  1302. x *= 2 - b * x; /* here x*a==1 mod 2**8 */
  1303. x *= 2 - b * x; /* here x*a==1 mod 2**16 */
  1304. x *= 2 - b * x; /* here x*a==1 mod 2**32 */
  1305. x &= 0x1fffffff;
  1306. /* rho = -1/m mod b */
  1307. *rho = ((sp_digit)1 << 29) - x;
  1308. }
  1309. /* Multiply a by scalar b into r. (r = a * b)
  1310. *
  1311. * r A single precision integer.
  1312. * a A single precision integer.
  1313. * b A scalar.
  1314. */
  1315. SP_NOINLINE static void sp_2048_mul_d_72(sp_digit* r, const sp_digit* a,
  1316. sp_digit b)
  1317. {
  1318. #ifdef WOLFSSL_SP_SMALL
  1319. sp_int64 tb = b;
  1320. sp_int64 t = 0;
  1321. int i;
  1322. for (i = 0; i < 72; i++) {
  1323. t += tb * a[i];
  1324. r[i] = (sp_digit)(t & 0x1fffffff);
  1325. t >>= 29;
  1326. }
  1327. r[72] = (sp_digit)t;
  1328. #else
  1329. sp_int64 tb = b;
  1330. sp_int64 t = 0;
  1331. sp_digit t2;
  1332. sp_int64 p[4];
  1333. int i;
  1334. for (i = 0; i < 72; i += 4) {
  1335. p[0] = tb * a[i + 0];
  1336. p[1] = tb * a[i + 1];
  1337. p[2] = tb * a[i + 2];
  1338. p[3] = tb * a[i + 3];
  1339. t += p[0];
  1340. t2 = (sp_digit)(t & 0x1fffffff);
  1341. t >>= 29;
  1342. r[i + 0] = (sp_digit)t2;
  1343. t += p[1];
  1344. t2 = (sp_digit)(t & 0x1fffffff);
  1345. t >>= 29;
  1346. r[i + 1] = (sp_digit)t2;
  1347. t += p[2];
  1348. t2 = (sp_digit)(t & 0x1fffffff);
  1349. t >>= 29;
  1350. r[i + 2] = (sp_digit)t2;
  1351. t += p[3];
  1352. t2 = (sp_digit)(t & 0x1fffffff);
  1353. t >>= 29;
  1354. r[i + 3] = (sp_digit)t2;
  1355. }
  1356. r[72] = (sp_digit)(t & 0x1fffffff);
  1357. #endif /* WOLFSSL_SP_SMALL */
  1358. }
  1359. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  1360. /* r = 2^n mod m where n is the number of bits to reduce by.
  1361. * Given m must be 2048 bits, just need to subtract.
  1362. *
  1363. * r A single precision number.
  1364. * m A single precision number.
  1365. */
  1366. static void sp_2048_mont_norm_36(sp_digit* r, const sp_digit* m)
  1367. {
  1368. /* Set r = 2^n - 1. */
  1369. #ifdef WOLFSSL_SP_SMALL
  1370. int i;
  1371. for (i=0; i<35; i++) {
  1372. r[i] = 0x1fffffff;
  1373. }
  1374. #else
  1375. int i;
  1376. for (i = 0; i < 32; i += 8) {
  1377. r[i + 0] = 0x1fffffff;
  1378. r[i + 1] = 0x1fffffff;
  1379. r[i + 2] = 0x1fffffff;
  1380. r[i + 3] = 0x1fffffff;
  1381. r[i + 4] = 0x1fffffff;
  1382. r[i + 5] = 0x1fffffff;
  1383. r[i + 6] = 0x1fffffff;
  1384. r[i + 7] = 0x1fffffff;
  1385. }
  1386. r[32] = 0x1fffffff;
  1387. r[33] = 0x1fffffff;
  1388. r[34] = 0x1fffffff;
  1389. #endif /* WOLFSSL_SP_SMALL */
  1390. r[35] = 0x1ffL;
  1391. /* r = (2^n - 1) mod n */
  1392. (void)sp_2048_sub_36(r, r, m);
  1393. /* Add one so r = 2^n mod m */
  1394. r[0] += 1;
  1395. }
  1396. /* Compare a with b in constant time.
  1397. *
  1398. * a A single precision integer.
  1399. * b A single precision integer.
  1400. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  1401. * respectively.
  1402. */
  1403. static sp_digit sp_2048_cmp_36(const sp_digit* a, const sp_digit* b)
  1404. {
  1405. sp_digit r = 0;
  1406. #ifdef WOLFSSL_SP_SMALL
  1407. int i;
  1408. for (i=35; i>=0; i--) {
  1409. r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 28);
  1410. }
  1411. #else
  1412. int i;
  1413. r |= (a[35] - b[35]) & (0 - (sp_digit)1);
  1414. r |= (a[34] - b[34]) & ~(((sp_digit)0 - r) >> 28);
  1415. r |= (a[33] - b[33]) & ~(((sp_digit)0 - r) >> 28);
  1416. r |= (a[32] - b[32]) & ~(((sp_digit)0 - r) >> 28);
  1417. for (i = 24; i >= 0; i -= 8) {
  1418. r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 28);
  1419. r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 28);
  1420. r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 28);
  1421. r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 28);
  1422. r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 28);
  1423. r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 28);
  1424. r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 28);
  1425. r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 28);
  1426. }
  1427. #endif /* WOLFSSL_SP_SMALL */
  1428. return r;
  1429. }
  1430. /* Conditionally subtract b from a using the mask m.
  1431. * m is -1 to subtract and 0 when not.
  1432. *
  1433. * r A single precision number representing condition subtract result.
  1434. * a A single precision number to subtract from.
  1435. * b A single precision number to subtract.
  1436. * m Mask value to apply.
  1437. */
  1438. static void sp_2048_cond_sub_36(sp_digit* r, const sp_digit* a,
  1439. const sp_digit* b, const sp_digit m)
  1440. {
  1441. #ifdef WOLFSSL_SP_SMALL
  1442. int i;
  1443. for (i = 0; i < 36; i++) {
  1444. r[i] = a[i] - (b[i] & m);
  1445. }
  1446. #else
  1447. int i;
  1448. for (i = 0; i < 32; i += 8) {
  1449. r[i + 0] = a[i + 0] - (b[i + 0] & m);
  1450. r[i + 1] = a[i + 1] - (b[i + 1] & m);
  1451. r[i + 2] = a[i + 2] - (b[i + 2] & m);
  1452. r[i + 3] = a[i + 3] - (b[i + 3] & m);
  1453. r[i + 4] = a[i + 4] - (b[i + 4] & m);
  1454. r[i + 5] = a[i + 5] - (b[i + 5] & m);
  1455. r[i + 6] = a[i + 6] - (b[i + 6] & m);
  1456. r[i + 7] = a[i + 7] - (b[i + 7] & m);
  1457. }
  1458. r[32] = a[32] - (b[32] & m);
  1459. r[33] = a[33] - (b[33] & m);
  1460. r[34] = a[34] - (b[34] & m);
  1461. r[35] = a[35] - (b[35] & m);
  1462. #endif /* WOLFSSL_SP_SMALL */
  1463. }
  1464. /* Mul a by scalar b and add into r. (r += a * b)
  1465. *
  1466. * r A single precision integer.
  1467. * a A single precision integer.
  1468. * b A scalar.
  1469. */
  1470. SP_NOINLINE static void sp_2048_mul_add_36(sp_digit* r, const sp_digit* a,
  1471. const sp_digit b)
  1472. {
  1473. #ifndef WOLFSSL_SP_LARGE_CODE
  1474. sp_int64 tb = b;
  1475. sp_int64 t = 0;
  1476. int i;
  1477. for (i = 0; i < 36; i++) {
  1478. t += r[i];
  1479. t += tb * a[i];
  1480. r[i] = ((sp_digit)t) & 0x1fffffff;
  1481. t >>= 29;
  1482. }
  1483. r[36] += (sp_digit)t;
  1484. #else
  1485. #ifdef WOLFSSL_SP_SMALL
  1486. sp_int64 tb = b;
  1487. sp_int64 t[4];
  1488. int i;
  1489. t[0] = 0;
  1490. for (i = 0; i < 32; i += 4) {
  1491. t[0] += (tb * a[i+0]) + r[i+0];
  1492. t[1] = (tb * a[i+1]) + r[i+1];
  1493. t[2] = (tb * a[i+2]) + r[i+2];
  1494. t[3] = (tb * a[i+3]) + r[i+3];
  1495. r[i+0] = t[0] & 0x1fffffff;
  1496. t[1] += t[0] >> 29;
  1497. r[i+1] = t[1] & 0x1fffffff;
  1498. t[2] += t[1] >> 29;
  1499. r[i+2] = t[2] & 0x1fffffff;
  1500. t[3] += t[2] >> 29;
  1501. r[i+3] = t[3] & 0x1fffffff;
  1502. t[0] = t[3] >> 29;
  1503. }
  1504. t[0] += (tb * a[32]) + r[32];
  1505. t[1] = (tb * a[33]) + r[33];
  1506. t[2] = (tb * a[34]) + r[34];
  1507. t[3] = (tb * a[35]) + r[35];
  1508. r[32] = t[0] & 0x1fffffff;
  1509. t[1] += t[0] >> 29;
  1510. r[33] = t[1] & 0x1fffffff;
  1511. t[2] += t[1] >> 29;
  1512. r[34] = t[2] & 0x1fffffff;
  1513. t[3] += t[2] >> 29;
  1514. r[35] = t[3] & 0x1fffffff;
  1515. r[36] += (sp_digit)(t[3] >> 29);
  1516. #else
  1517. sp_int64 tb = b;
  1518. sp_int64 t[8];
  1519. int i;
  1520. t[0] = 0;
  1521. for (i = 0; i < 32; i += 8) {
  1522. t[0] += (tb * a[i+0]) + r[i+0];
  1523. t[1] = (tb * a[i+1]) + r[i+1];
  1524. t[2] = (tb * a[i+2]) + r[i+2];
  1525. t[3] = (tb * a[i+3]) + r[i+3];
  1526. t[4] = (tb * a[i+4]) + r[i+4];
  1527. t[5] = (tb * a[i+5]) + r[i+5];
  1528. t[6] = (tb * a[i+6]) + r[i+6];
  1529. t[7] = (tb * a[i+7]) + r[i+7];
  1530. r[i+0] = t[0] & 0x1fffffff;
  1531. t[1] += t[0] >> 29;
  1532. r[i+1] = t[1] & 0x1fffffff;
  1533. t[2] += t[1] >> 29;
  1534. r[i+2] = t[2] & 0x1fffffff;
  1535. t[3] += t[2] >> 29;
  1536. r[i+3] = t[3] & 0x1fffffff;
  1537. t[4] += t[3] >> 29;
  1538. r[i+4] = t[4] & 0x1fffffff;
  1539. t[5] += t[4] >> 29;
  1540. r[i+5] = t[5] & 0x1fffffff;
  1541. t[6] += t[5] >> 29;
  1542. r[i+6] = t[6] & 0x1fffffff;
  1543. t[7] += t[6] >> 29;
  1544. r[i+7] = t[7] & 0x1fffffff;
  1545. t[0] = t[7] >> 29;
  1546. }
  1547. t[0] += (tb * a[32]) + r[32];
  1548. t[1] = (tb * a[33]) + r[33];
  1549. t[2] = (tb * a[34]) + r[34];
  1550. t[3] = (tb * a[35]) + r[35];
  1551. r[32] = t[0] & 0x1fffffff;
  1552. t[1] += t[0] >> 29;
  1553. r[33] = t[1] & 0x1fffffff;
  1554. t[2] += t[1] >> 29;
  1555. r[34] = t[2] & 0x1fffffff;
  1556. t[3] += t[2] >> 29;
  1557. r[35] = t[3] & 0x1fffffff;
  1558. r[36] += (sp_digit)(t[3] >> 29);
  1559. #endif /* WOLFSSL_SP_SMALL */
  1560. #endif /* !WOLFSSL_SP_LARGE_CODE */
  1561. }
  1562. /* Shift the result in the high 1024 bits down to the bottom.
  1563. *
  1564. * r A single precision number.
  1565. * a A single precision number.
  1566. */
  1567. static void sp_2048_mont_shift_36(sp_digit* r, const sp_digit* a)
  1568. {
  1569. #ifdef WOLFSSL_SP_SMALL
  1570. int i;
  1571. sp_int64 n = a[35] >> 9;
  1572. n += ((sp_int64)a[36]) << 20;
  1573. for (i = 0; i < 35; i++) {
  1574. r[i] = n & 0x1fffffff;
  1575. n >>= 29;
  1576. n += ((sp_int64)a[37 + i]) << 20;
  1577. }
  1578. r[35] = (sp_digit)n;
  1579. #else
  1580. int i;
  1581. sp_int64 n = a[35] >> 9;
  1582. n += ((sp_int64)a[36]) << 20;
  1583. for (i = 0; i < 32; i += 8) {
  1584. r[i + 0] = n & 0x1fffffff;
  1585. n >>= 29; n += ((sp_int64)a[i + 37]) << 20;
  1586. r[i + 1] = n & 0x1fffffff;
  1587. n >>= 29; n += ((sp_int64)a[i + 38]) << 20;
  1588. r[i + 2] = n & 0x1fffffff;
  1589. n >>= 29; n += ((sp_int64)a[i + 39]) << 20;
  1590. r[i + 3] = n & 0x1fffffff;
  1591. n >>= 29; n += ((sp_int64)a[i + 40]) << 20;
  1592. r[i + 4] = n & 0x1fffffff;
  1593. n >>= 29; n += ((sp_int64)a[i + 41]) << 20;
  1594. r[i + 5] = n & 0x1fffffff;
  1595. n >>= 29; n += ((sp_int64)a[i + 42]) << 20;
  1596. r[i + 6] = n & 0x1fffffff;
  1597. n >>= 29; n += ((sp_int64)a[i + 43]) << 20;
  1598. r[i + 7] = n & 0x1fffffff;
  1599. n >>= 29; n += ((sp_int64)a[i + 44]) << 20;
  1600. }
  1601. r[32] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[69]) << 20;
  1602. r[33] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[70]) << 20;
  1603. r[34] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[71]) << 20;
  1604. r[35] = (sp_digit)n;
  1605. #endif /* WOLFSSL_SP_SMALL */
  1606. XMEMSET(&r[36], 0, sizeof(*r) * 36U);
  1607. }
  1608. /* Reduce the number back to 2048 bits using Montgomery reduction.
  1609. *
  1610. * a A single precision number to reduce in place.
  1611. * m The single precision number representing the modulus.
  1612. * mp The digit representing the negative inverse of m mod 2^n.
  1613. */
  1614. static void sp_2048_mont_reduce_36(sp_digit* a, const sp_digit* m, sp_digit mp)
  1615. {
  1616. int i;
  1617. sp_digit mu;
  1618. sp_digit over;
  1619. sp_2048_norm_36(a + 36);
  1620. for (i=0; i<35; i++) {
  1621. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff;
  1622. sp_2048_mul_add_36(a+i, m, mu);
  1623. a[i+1] += a[i] >> 29;
  1624. }
  1625. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1ffL;
  1626. sp_2048_mul_add_36(a+i, m, mu);
  1627. a[i+1] += a[i] >> 29;
  1628. a[i] &= 0x1fffffff;
  1629. sp_2048_mont_shift_36(a, a);
  1630. over = a[35] - m[35];
  1631. sp_2048_cond_sub_36(a, a, m, ~((over - 1) >> 31));
  1632. sp_2048_norm_36(a);
  1633. }
  1634. /* Multiply two Montgomery form numbers mod the modulus (prime).
  1635. * (r = a * b mod m)
  1636. *
  1637. * r Result of multiplication.
  1638. * a First number to multiply in Montgomery form.
  1639. * b Second number to multiply in Montgomery form.
  1640. * m Modulus (prime).
  1641. * mp Montgomery mulitplier.
  1642. */
  1643. SP_NOINLINE static void sp_2048_mont_mul_36(sp_digit* r, const sp_digit* a,
  1644. const sp_digit* b, const sp_digit* m, sp_digit mp)
  1645. {
  1646. sp_2048_mul_36(r, a, b);
  1647. sp_2048_mont_reduce_36(r, m, mp);
  1648. }
  1649. /* Square the Montgomery form number. (r = a * a mod m)
  1650. *
  1651. * r Result of squaring.
  1652. * a Number to square in Montgomery form.
  1653. * m Modulus (prime).
  1654. * mp Montgomery mulitplier.
  1655. */
  1656. SP_NOINLINE static void sp_2048_mont_sqr_36(sp_digit* r, const sp_digit* a,
  1657. const sp_digit* m, sp_digit mp)
  1658. {
  1659. sp_2048_sqr_36(r, a);
  1660. sp_2048_mont_reduce_36(r, m, mp);
  1661. }
  1662. /* Multiply a by scalar b into r. (r = a * b)
  1663. *
  1664. * r A single precision integer.
  1665. * a A single precision integer.
  1666. * b A scalar.
  1667. */
  1668. SP_NOINLINE static void sp_2048_mul_d_36(sp_digit* r, const sp_digit* a,
  1669. sp_digit b)
  1670. {
  1671. #ifdef WOLFSSL_SP_SMALL
  1672. sp_int64 tb = b;
  1673. sp_int64 t = 0;
  1674. int i;
  1675. for (i = 0; i < 36; i++) {
  1676. t += tb * a[i];
  1677. r[i] = (sp_digit)(t & 0x1fffffff);
  1678. t >>= 29;
  1679. }
  1680. r[36] = (sp_digit)t;
  1681. #else
  1682. sp_int64 tb = b;
  1683. sp_int64 t = 0;
  1684. sp_digit t2;
  1685. sp_int64 p[4];
  1686. int i;
  1687. for (i = 0; i < 36; i += 4) {
  1688. p[0] = tb * a[i + 0];
  1689. p[1] = tb * a[i + 1];
  1690. p[2] = tb * a[i + 2];
  1691. p[3] = tb * a[i + 3];
  1692. t += p[0];
  1693. t2 = (sp_digit)(t & 0x1fffffff);
  1694. t >>= 29;
  1695. r[i + 0] = (sp_digit)t2;
  1696. t += p[1];
  1697. t2 = (sp_digit)(t & 0x1fffffff);
  1698. t >>= 29;
  1699. r[i + 1] = (sp_digit)t2;
  1700. t += p[2];
  1701. t2 = (sp_digit)(t & 0x1fffffff);
  1702. t >>= 29;
  1703. r[i + 2] = (sp_digit)t2;
  1704. t += p[3];
  1705. t2 = (sp_digit)(t & 0x1fffffff);
  1706. t >>= 29;
  1707. r[i + 3] = (sp_digit)t2;
  1708. }
  1709. r[36] = (sp_digit)(t & 0x1fffffff);
  1710. #endif /* WOLFSSL_SP_SMALL */
  1711. }
  1712. #ifdef WOLFSSL_SP_SMALL
  1713. /* Conditionally add a and b using the mask m.
  1714. * m is -1 to add and 0 when not.
  1715. *
  1716. * r A single precision number representing conditional add result.
  1717. * a A single precision number to add with.
  1718. * b A single precision number to add.
  1719. * m Mask value to apply.
  1720. */
  1721. static void sp_2048_cond_add_36(sp_digit* r, const sp_digit* a,
  1722. const sp_digit* b, const sp_digit m)
  1723. {
  1724. int i;
  1725. for (i = 0; i < 36; i++) {
  1726. r[i] = a[i] + (b[i] & m);
  1727. }
  1728. }
  1729. #endif /* WOLFSSL_SP_SMALL */
  1730. #ifndef WOLFSSL_SP_SMALL
  1731. /* Conditionally add a and b using the mask m.
  1732. * m is -1 to add and 0 when not.
  1733. *
  1734. * r A single precision number representing conditional add result.
  1735. * a A single precision number to add with.
  1736. * b A single precision number to add.
  1737. * m Mask value to apply.
  1738. */
  1739. static void sp_2048_cond_add_36(sp_digit* r, const sp_digit* a,
  1740. const sp_digit* b, const sp_digit m)
  1741. {
  1742. int i;
  1743. for (i = 0; i < 32; i += 8) {
  1744. r[i + 0] = a[i + 0] + (b[i + 0] & m);
  1745. r[i + 1] = a[i + 1] + (b[i + 1] & m);
  1746. r[i + 2] = a[i + 2] + (b[i + 2] & m);
  1747. r[i + 3] = a[i + 3] + (b[i + 3] & m);
  1748. r[i + 4] = a[i + 4] + (b[i + 4] & m);
  1749. r[i + 5] = a[i + 5] + (b[i + 5] & m);
  1750. r[i + 6] = a[i + 6] + (b[i + 6] & m);
  1751. r[i + 7] = a[i + 7] + (b[i + 7] & m);
  1752. }
  1753. r[32] = a[32] + (b[32] & m);
  1754. r[33] = a[33] + (b[33] & m);
  1755. r[34] = a[34] + (b[34] & m);
  1756. r[35] = a[35] + (b[35] & m);
  1757. }
  1758. #endif /* !WOLFSSL_SP_SMALL */
  1759. SP_NOINLINE static void sp_2048_rshift_36(sp_digit* r, const sp_digit* a,
  1760. byte n)
  1761. {
  1762. int i;
  1763. #ifdef WOLFSSL_SP_SMALL
  1764. for (i=0; i<35; i++) {
  1765. r[i] = ((a[i] >> n) | (a[i + 1] << (29 - n))) & 0x1fffffff;
  1766. }
  1767. #else
  1768. for (i=0; i<32; i += 8) {
  1769. r[i+0] = (a[i+0] >> n) | ((a[i+1] << (29 - n)) & 0x1fffffff);
  1770. r[i+1] = (a[i+1] >> n) | ((a[i+2] << (29 - n)) & 0x1fffffff);
  1771. r[i+2] = (a[i+2] >> n) | ((a[i+3] << (29 - n)) & 0x1fffffff);
  1772. r[i+3] = (a[i+3] >> n) | ((a[i+4] << (29 - n)) & 0x1fffffff);
  1773. r[i+4] = (a[i+4] >> n) | ((a[i+5] << (29 - n)) & 0x1fffffff);
  1774. r[i+5] = (a[i+5] >> n) | ((a[i+6] << (29 - n)) & 0x1fffffff);
  1775. r[i+6] = (a[i+6] >> n) | ((a[i+7] << (29 - n)) & 0x1fffffff);
  1776. r[i+7] = (a[i+7] >> n) | ((a[i+8] << (29 - n)) & 0x1fffffff);
  1777. }
  1778. r[32] = (a[32] >> n) | ((a[33] << (29 - n)) & 0x1fffffff);
  1779. r[33] = (a[33] >> n) | ((a[34] << (29 - n)) & 0x1fffffff);
  1780. r[34] = (a[34] >> n) | ((a[35] << (29 - n)) & 0x1fffffff);
  1781. #endif /* WOLFSSL_SP_SMALL */
  1782. r[35] = a[35] >> n;
  1783. }
  1784. static WC_INLINE sp_digit sp_2048_div_word_36(sp_digit d1, sp_digit d0,
  1785. sp_digit div)
  1786. {
  1787. #ifdef SP_USE_DIVTI3
  1788. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  1789. return d / div;
  1790. #elif defined(__x86_64__) || defined(__i386__)
  1791. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  1792. sp_uint32 lo = (sp_uint32)d;
  1793. sp_digit hi = (sp_digit)(d >> 32);
  1794. __asm__ __volatile__ (
  1795. "idiv %2"
  1796. : "+a" (lo)
  1797. : "d" (hi), "r" (div)
  1798. : "cc"
  1799. );
  1800. return (sp_digit)lo;
  1801. #elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV)
  1802. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  1803. sp_digit dv = (div >> 1) + 1;
  1804. sp_digit t1 = (sp_digit)(d >> 29);
  1805. sp_digit t0 = (sp_digit)(d & 0x1fffffff);
  1806. sp_digit t2;
  1807. sp_digit sign;
  1808. sp_digit r;
  1809. int i;
  1810. sp_int64 m;
  1811. r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
  1812. t1 -= dv & (0 - r);
  1813. for (i = 27; i >= 1; i--) {
  1814. t1 += t1 + (((sp_uint32)t0 >> 28) & 1);
  1815. t0 <<= 1;
  1816. t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
  1817. r += r + t2;
  1818. t1 -= dv & (0 - t2);
  1819. t1 += t2;
  1820. }
  1821. r += r + 1;
  1822. m = d - ((sp_int64)r * div);
  1823. r += (sp_digit)(m >> 29);
  1824. m = d - ((sp_int64)r * div);
  1825. r += (sp_digit)(m >> 58) - (sp_digit)(d >> 58);
  1826. m = d - ((sp_int64)r * div);
  1827. sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
  1828. m *= sign;
  1829. t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
  1830. r += sign * t2;
  1831. m = d - ((sp_int64)r * div);
  1832. sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
  1833. m *= sign;
  1834. t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
  1835. r += sign * t2;
  1836. return r;
  1837. #else
  1838. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  1839. sp_digit r = 0;
  1840. sp_digit t;
  1841. sp_digit dv = (div >> 14) + 1;
  1842. t = (sp_digit)(d >> 28);
  1843. t = (t / dv) << 14;
  1844. r += t;
  1845. d -= (sp_int64)t * div;
  1846. t = (sp_digit)(d >> 13);
  1847. t = t / (dv << 1);
  1848. r += t;
  1849. d -= (sp_int64)t * div;
  1850. t = (sp_digit)d;
  1851. t = t / div;
  1852. r += t;
  1853. d -= (sp_int64)t * div;
  1854. return r;
  1855. #endif
  1856. }
  1857. static WC_INLINE sp_digit sp_2048_word_div_word_36(sp_digit d, sp_digit div)
  1858. {
  1859. #if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
  1860. defined(SP_DIV_WORD_USE_DIV)
  1861. return d / div;
  1862. #else
  1863. return (sp_digit)((sp_uint32)(div - d) >> 31);
  1864. #endif
  1865. }
  1866. /* Divide d in a and put remainder into r (m*d + r = a)
  1867. * m is not calculated as it is not needed at this time.
  1868. *
  1869. * Full implementation.
  1870. *
  1871. * a Number to be divided.
  1872. * d Number to divide with.
  1873. * m Multiplier result.
  1874. * r Remainder from the division.
  1875. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  1876. */
  1877. static int sp_2048_div_36(const sp_digit* a, const sp_digit* d,
  1878. const sp_digit* m, sp_digit* r)
  1879. {
  1880. int i;
  1881. #ifndef WOLFSSL_SP_DIV_32
  1882. #endif
  1883. sp_digit dv;
  1884. sp_digit r1;
  1885. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  1886. sp_digit* t1 = NULL;
  1887. #else
  1888. sp_digit t1[4 * 36 + 3];
  1889. #endif
  1890. sp_digit* t2 = NULL;
  1891. sp_digit* sd = NULL;
  1892. int err = MP_OKAY;
  1893. (void)m;
  1894. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  1895. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 36 + 3), NULL,
  1896. DYNAMIC_TYPE_TMP_BUFFER);
  1897. if (t1 == NULL)
  1898. err = MEMORY_E;
  1899. #endif
  1900. (void)m;
  1901. if (err == MP_OKAY) {
  1902. t2 = t1 + 72 + 1;
  1903. sd = t2 + 36 + 1;
  1904. sp_2048_mul_d_36(sd, d, (sp_digit)1 << 20);
  1905. sp_2048_mul_d_72(t1, a, (sp_digit)1 << 20);
  1906. dv = sd[35];
  1907. t1[36 + 36] += t1[36 + 36 - 1] >> 29;
  1908. t1[36 + 36 - 1] &= 0x1fffffff;
  1909. for (i=36; i>=0; i--) {
  1910. r1 = sp_2048_div_word_36(t1[36 + i], t1[36 + i - 1], dv);
  1911. sp_2048_mul_d_36(t2, sd, r1);
  1912. (void)sp_2048_sub_36(&t1[i], &t1[i], t2);
  1913. sp_2048_norm_36(&t1[i]);
  1914. t1[36 + i] -= t2[36];
  1915. t1[36 + i] += t1[36 + i - 1] >> 29;
  1916. t1[36 + i - 1] &= 0x1fffffff;
  1917. r1 = sp_2048_div_word_36(-t1[36 + i], -t1[36 + i - 1], dv);
  1918. r1 -= t1[36 + i];
  1919. sp_2048_mul_d_36(t2, sd, r1);
  1920. (void)sp_2048_add_36(&t1[i], &t1[i], t2);
  1921. t1[36 + i] += t1[36 + i - 1] >> 29;
  1922. t1[36 + i - 1] &= 0x1fffffff;
  1923. }
  1924. t1[36 - 1] += t1[36 - 2] >> 29;
  1925. t1[36 - 2] &= 0x1fffffff;
  1926. r1 = sp_2048_word_div_word_36(t1[36 - 1], dv);
  1927. sp_2048_mul_d_36(t2, sd, r1);
  1928. sp_2048_sub_36(t1, t1, t2);
  1929. XMEMCPY(r, t1, sizeof(*r) * 72U);
  1930. for (i=0; i<35; i++) {
  1931. r[i+1] += r[i] >> 29;
  1932. r[i] &= 0x1fffffff;
  1933. }
  1934. sp_2048_cond_add_36(r, r, sd, r[35] >> 31);
  1935. sp_2048_norm_36(r);
  1936. sp_2048_rshift_36(r, r, 20);
  1937. }
  1938. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  1939. if (t1 != NULL)
  1940. XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  1941. #endif
  1942. return err;
  1943. }
  1944. /* Reduce a modulo m into r. (r = a mod m)
  1945. *
  1946. * r A single precision number that is the reduced result.
  1947. * a A single precision number that is to be reduced.
  1948. * m A single precision number that is the modulus to reduce with.
  1949. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  1950. */
  1951. static int sp_2048_mod_36(sp_digit* r, const sp_digit* a, const sp_digit* m)
  1952. {
  1953. return sp_2048_div_36(a, m, NULL, r);
  1954. }
  1955. /* Modular exponentiate a to the e mod m. (r = a^e mod m)
  1956. *
  1957. * r A single precision number that is the result of the operation.
  1958. * a A single precision number being exponentiated.
  1959. * e A single precision number that is the exponent.
  1960. * bits The number of bits in the exponent.
  1961. * m A single precision number that is the modulus.
  1962. * returns 0 on success.
  1963. * returns MEMORY_E on dynamic memory allocation failure.
  1964. * returns MP_VAL when base is even or exponent is 0.
  1965. */
  1966. static int sp_2048_mod_exp_36(sp_digit* r, const sp_digit* a, const sp_digit* e,
  1967. int bits, const sp_digit* m, int reduceA)
  1968. {
  1969. #if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP)
  1970. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  1971. sp_digit* td = NULL;
  1972. #else
  1973. sp_digit td[3 * 72];
  1974. #endif
  1975. sp_digit* t[3] = {0, 0, 0};
  1976. sp_digit* norm = NULL;
  1977. sp_digit mp = 1;
  1978. sp_digit n;
  1979. int i;
  1980. int c;
  1981. byte y;
  1982. int err = MP_OKAY;
  1983. if (bits == 0) {
  1984. err = MP_VAL;
  1985. }
  1986. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  1987. if (err == MP_OKAY) {
  1988. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 36 * 2, NULL,
  1989. DYNAMIC_TYPE_TMP_BUFFER);
  1990. if (td == NULL)
  1991. err = MEMORY_E;
  1992. }
  1993. #endif
  1994. if (err == MP_OKAY) {
  1995. norm = td;
  1996. for (i=0; i<3; i++) {
  1997. t[i] = td + (i * 36 * 2);
  1998. XMEMSET(t[i], 0, sizeof(sp_digit) * 36U * 2U);
  1999. }
  2000. sp_2048_mont_setup(m, &mp);
  2001. sp_2048_mont_norm_36(norm, m);
  2002. if (reduceA != 0) {
  2003. err = sp_2048_mod_36(t[1], a, m);
  2004. }
  2005. else {
  2006. XMEMCPY(t[1], a, sizeof(sp_digit) * 36U);
  2007. }
  2008. }
  2009. if (err == MP_OKAY) {
  2010. sp_2048_mul_36(t[1], t[1], norm);
  2011. err = sp_2048_mod_36(t[1], t[1], m);
  2012. }
  2013. if (err == MP_OKAY) {
  2014. i = bits / 29;
  2015. c = bits % 29;
  2016. n = e[i--] << (29 - c);
  2017. for (; ; c--) {
  2018. if (c == 0) {
  2019. if (i == -1) {
  2020. break;
  2021. }
  2022. n = e[i--];
  2023. c = 29;
  2024. }
  2025. y = (int)((n >> 28) & 1);
  2026. n <<= 1;
  2027. sp_2048_mont_mul_36(t[y^1], t[0], t[1], m, mp);
  2028. XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
  2029. ((size_t)t[1] & addr_mask[y])),
  2030. sizeof(*t[2]) * 36 * 2);
  2031. sp_2048_mont_sqr_36(t[2], t[2], m, mp);
  2032. XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
  2033. ((size_t)t[1] & addr_mask[y])), t[2],
  2034. sizeof(*t[2]) * 36 * 2);
  2035. }
  2036. sp_2048_mont_reduce_36(t[0], m, mp);
  2037. n = sp_2048_cmp_36(t[0], m);
  2038. sp_2048_cond_sub_36(t[0], t[0], m, ~(n >> 31));
  2039. XMEMCPY(r, t[0], sizeof(*r) * 36 * 2);
  2040. }
  2041. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  2042. if (td != NULL)
  2043. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  2044. #endif
  2045. return err;
  2046. #elif !defined(WC_NO_CACHE_RESISTANT)
  2047. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  2048. sp_digit* td = NULL;
  2049. #else
  2050. sp_digit td[3 * 72];
  2051. #endif
  2052. sp_digit* t[3] = {0, 0, 0};
  2053. sp_digit* norm = NULL;
  2054. sp_digit mp = 1;
  2055. sp_digit n;
  2056. int i;
  2057. int c;
  2058. byte y;
  2059. int err = MP_OKAY;
  2060. if (bits == 0) {
  2061. err = MP_VAL;
  2062. }
  2063. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  2064. if (err == MP_OKAY) {
  2065. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 36 * 2, NULL,
  2066. DYNAMIC_TYPE_TMP_BUFFER);
  2067. if (td == NULL)
  2068. err = MEMORY_E;
  2069. }
  2070. #endif
  2071. if (err == MP_OKAY) {
  2072. norm = td;
  2073. for (i=0; i<3; i++) {
  2074. t[i] = td + (i * 36 * 2);
  2075. }
  2076. sp_2048_mont_setup(m, &mp);
  2077. sp_2048_mont_norm_36(norm, m);
  2078. if (reduceA != 0) {
  2079. err = sp_2048_mod_36(t[1], a, m);
  2080. if (err == MP_OKAY) {
  2081. sp_2048_mul_36(t[1], t[1], norm);
  2082. err = sp_2048_mod_36(t[1], t[1], m);
  2083. }
  2084. }
  2085. else {
  2086. sp_2048_mul_36(t[1], a, norm);
  2087. err = sp_2048_mod_36(t[1], t[1], m);
  2088. }
  2089. }
  2090. if (err == MP_OKAY) {
  2091. i = bits / 29;
  2092. c = bits % 29;
  2093. n = e[i--] << (29 - c);
  2094. for (; ; c--) {
  2095. if (c == 0) {
  2096. if (i == -1) {
  2097. break;
  2098. }
  2099. n = e[i--];
  2100. c = 29;
  2101. }
  2102. y = (int)((n >> 28) & 1);
  2103. n <<= 1;
  2104. sp_2048_mont_mul_36(t[y^1], t[0], t[1], m, mp);
  2105. XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
  2106. ((size_t)t[1] & addr_mask[y])),
  2107. sizeof(*t[2]) * 36 * 2);
  2108. sp_2048_mont_sqr_36(t[2], t[2], m, mp);
  2109. XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
  2110. ((size_t)t[1] & addr_mask[y])), t[2],
  2111. sizeof(*t[2]) * 36 * 2);
  2112. }
  2113. sp_2048_mont_reduce_36(t[0], m, mp);
  2114. n = sp_2048_cmp_36(t[0], m);
  2115. sp_2048_cond_sub_36(t[0], t[0], m, ~(n >> 31));
  2116. XMEMCPY(r, t[0], sizeof(*r) * 36 * 2);
  2117. }
  2118. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  2119. if (td != NULL)
  2120. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  2121. #endif
  2122. return err;
  2123. #else
  2124. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  2125. sp_digit* td = NULL;
  2126. #else
  2127. sp_digit td[(32 * 72) + 72];
  2128. #endif
  2129. sp_digit* t[32];
  2130. sp_digit* rt = NULL;
  2131. sp_digit* norm = NULL;
  2132. sp_digit mp = 1;
  2133. sp_digit n;
  2134. int i;
  2135. int c;
  2136. byte y;
  2137. int err = MP_OKAY;
  2138. if (bits == 0) {
  2139. err = MP_VAL;
  2140. }
  2141. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  2142. if (err == MP_OKAY) {
  2143. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((32 * 72) + 72), NULL,
  2144. DYNAMIC_TYPE_TMP_BUFFER);
  2145. if (td == NULL)
  2146. err = MEMORY_E;
  2147. }
  2148. #endif
  2149. if (err == MP_OKAY) {
  2150. norm = td;
  2151. for (i=0; i<32; i++)
  2152. t[i] = td + i * 72;
  2153. rt = td + 2304;
  2154. sp_2048_mont_setup(m, &mp);
  2155. sp_2048_mont_norm_36(norm, m);
  2156. if (reduceA != 0) {
  2157. err = sp_2048_mod_36(t[1], a, m);
  2158. if (err == MP_OKAY) {
  2159. sp_2048_mul_36(t[1], t[1], norm);
  2160. err = sp_2048_mod_36(t[1], t[1], m);
  2161. }
  2162. }
  2163. else {
  2164. sp_2048_mul_36(t[1], a, norm);
  2165. err = sp_2048_mod_36(t[1], t[1], m);
  2166. }
  2167. }
  2168. if (err == MP_OKAY) {
  2169. sp_2048_mont_sqr_36(t[ 2], t[ 1], m, mp);
  2170. sp_2048_mont_mul_36(t[ 3], t[ 2], t[ 1], m, mp);
  2171. sp_2048_mont_sqr_36(t[ 4], t[ 2], m, mp);
  2172. sp_2048_mont_mul_36(t[ 5], t[ 3], t[ 2], m, mp);
  2173. sp_2048_mont_sqr_36(t[ 6], t[ 3], m, mp);
  2174. sp_2048_mont_mul_36(t[ 7], t[ 4], t[ 3], m, mp);
  2175. sp_2048_mont_sqr_36(t[ 8], t[ 4], m, mp);
  2176. sp_2048_mont_mul_36(t[ 9], t[ 5], t[ 4], m, mp);
  2177. sp_2048_mont_sqr_36(t[10], t[ 5], m, mp);
  2178. sp_2048_mont_mul_36(t[11], t[ 6], t[ 5], m, mp);
  2179. sp_2048_mont_sqr_36(t[12], t[ 6], m, mp);
  2180. sp_2048_mont_mul_36(t[13], t[ 7], t[ 6], m, mp);
  2181. sp_2048_mont_sqr_36(t[14], t[ 7], m, mp);
  2182. sp_2048_mont_mul_36(t[15], t[ 8], t[ 7], m, mp);
  2183. sp_2048_mont_sqr_36(t[16], t[ 8], m, mp);
  2184. sp_2048_mont_mul_36(t[17], t[ 9], t[ 8], m, mp);
  2185. sp_2048_mont_sqr_36(t[18], t[ 9], m, mp);
  2186. sp_2048_mont_mul_36(t[19], t[10], t[ 9], m, mp);
  2187. sp_2048_mont_sqr_36(t[20], t[10], m, mp);
  2188. sp_2048_mont_mul_36(t[21], t[11], t[10], m, mp);
  2189. sp_2048_mont_sqr_36(t[22], t[11], m, mp);
  2190. sp_2048_mont_mul_36(t[23], t[12], t[11], m, mp);
  2191. sp_2048_mont_sqr_36(t[24], t[12], m, mp);
  2192. sp_2048_mont_mul_36(t[25], t[13], t[12], m, mp);
  2193. sp_2048_mont_sqr_36(t[26], t[13], m, mp);
  2194. sp_2048_mont_mul_36(t[27], t[14], t[13], m, mp);
  2195. sp_2048_mont_sqr_36(t[28], t[14], m, mp);
  2196. sp_2048_mont_mul_36(t[29], t[15], t[14], m, mp);
  2197. sp_2048_mont_sqr_36(t[30], t[15], m, mp);
  2198. sp_2048_mont_mul_36(t[31], t[16], t[15], m, mp);
  2199. bits = ((bits + 4) / 5) * 5;
  2200. i = ((bits + 28) / 29) - 1;
  2201. c = bits % 29;
  2202. if (c == 0) {
  2203. c = 29;
  2204. }
  2205. if (i < 36) {
  2206. n = e[i--] << (32 - c);
  2207. }
  2208. else {
  2209. n = 0;
  2210. i--;
  2211. }
  2212. if (c < 5) {
  2213. n |= e[i--] << (3 - c);
  2214. c += 29;
  2215. }
  2216. y = (int)((n >> 27) & 0x1f);
  2217. n <<= 5;
  2218. c -= 5;
  2219. XMEMCPY(rt, t[y], sizeof(sp_digit) * 72);
  2220. while ((i >= 0) || (c >= 5)) {
  2221. if (c >= 5) {
  2222. y = (byte)((n >> 27) & 0x1f);
  2223. n <<= 5;
  2224. c -= 5;
  2225. }
  2226. else if (c == 0) {
  2227. n = e[i--] << 3;
  2228. y = (byte)((n >> 27) & 0x1f);
  2229. n <<= 5;
  2230. c = 24;
  2231. }
  2232. else {
  2233. y = (byte)((n >> 27) & 0x1f);
  2234. n = e[i--] << 3;
  2235. c = 5 - c;
  2236. y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
  2237. n <<= c;
  2238. c = 29 - c;
  2239. }
  2240. sp_2048_mont_sqr_36(rt, rt, m, mp);
  2241. sp_2048_mont_sqr_36(rt, rt, m, mp);
  2242. sp_2048_mont_sqr_36(rt, rt, m, mp);
  2243. sp_2048_mont_sqr_36(rt, rt, m, mp);
  2244. sp_2048_mont_sqr_36(rt, rt, m, mp);
  2245. sp_2048_mont_mul_36(rt, rt, t[y], m, mp);
  2246. }
  2247. sp_2048_mont_reduce_36(rt, m, mp);
  2248. n = sp_2048_cmp_36(rt, m);
  2249. sp_2048_cond_sub_36(rt, rt, m, ~(n >> 31));
  2250. XMEMCPY(r, rt, sizeof(sp_digit) * 72);
  2251. }
  2252. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  2253. if (td != NULL)
  2254. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  2255. #endif
  2256. return err;
  2257. #endif
  2258. }
  2259. #endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
  2260. /* r = 2^n mod m where n is the number of bits to reduce by.
  2261. * Given m must be 2048 bits, just need to subtract.
  2262. *
  2263. * r A single precision number.
  2264. * m A single precision number.
  2265. */
  2266. static void sp_2048_mont_norm_72(sp_digit* r, const sp_digit* m)
  2267. {
  2268. /* Set r = 2^n - 1. */
  2269. #ifdef WOLFSSL_SP_SMALL
  2270. int i;
  2271. for (i=0; i<70; i++) {
  2272. r[i] = 0x1fffffff;
  2273. }
  2274. #else
  2275. int i;
  2276. for (i = 0; i < 64; i += 8) {
  2277. r[i + 0] = 0x1fffffff;
  2278. r[i + 1] = 0x1fffffff;
  2279. r[i + 2] = 0x1fffffff;
  2280. r[i + 3] = 0x1fffffff;
  2281. r[i + 4] = 0x1fffffff;
  2282. r[i + 5] = 0x1fffffff;
  2283. r[i + 6] = 0x1fffffff;
  2284. r[i + 7] = 0x1fffffff;
  2285. }
  2286. r[64] = 0x1fffffff;
  2287. r[65] = 0x1fffffff;
  2288. r[66] = 0x1fffffff;
  2289. r[67] = 0x1fffffff;
  2290. r[68] = 0x1fffffff;
  2291. r[69] = 0x1fffffff;
  2292. #endif /* WOLFSSL_SP_SMALL */
  2293. r[70] = 0x3ffffL;
  2294. r[71] = 0;
  2295. /* r = (2^n - 1) mod n */
  2296. (void)sp_2048_sub_72(r, r, m);
  2297. /* Add one so r = 2^n mod m */
  2298. r[0] += 1;
  2299. }
  2300. /* Compare a with b in constant time.
  2301. *
  2302. * a A single precision integer.
  2303. * b A single precision integer.
  2304. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  2305. * respectively.
  2306. */
  2307. static sp_digit sp_2048_cmp_72(const sp_digit* a, const sp_digit* b)
  2308. {
  2309. sp_digit r = 0;
  2310. #ifdef WOLFSSL_SP_SMALL
  2311. int i;
  2312. for (i=71; i>=0; i--) {
  2313. r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 28);
  2314. }
  2315. #else
  2316. int i;
  2317. for (i = 64; i >= 0; i -= 8) {
  2318. r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 28);
  2319. r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 28);
  2320. r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 28);
  2321. r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 28);
  2322. r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 28);
  2323. r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 28);
  2324. r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 28);
  2325. r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 28);
  2326. }
  2327. #endif /* WOLFSSL_SP_SMALL */
  2328. return r;
  2329. }
  2330. /* Conditionally subtract b from a using the mask m.
  2331. * m is -1 to subtract and 0 when not.
  2332. *
  2333. * r A single precision number representing condition subtract result.
  2334. * a A single precision number to subtract from.
  2335. * b A single precision number to subtract.
  2336. * m Mask value to apply.
  2337. */
  2338. static void sp_2048_cond_sub_72(sp_digit* r, const sp_digit* a,
  2339. const sp_digit* b, const sp_digit m)
  2340. {
  2341. #ifdef WOLFSSL_SP_SMALL
  2342. int i;
  2343. for (i = 0; i < 72; i++) {
  2344. r[i] = a[i] - (b[i] & m);
  2345. }
  2346. #else
  2347. int i;
  2348. for (i = 0; i < 72; i += 8) {
  2349. r[i + 0] = a[i + 0] - (b[i + 0] & m);
  2350. r[i + 1] = a[i + 1] - (b[i + 1] & m);
  2351. r[i + 2] = a[i + 2] - (b[i + 2] & m);
  2352. r[i + 3] = a[i + 3] - (b[i + 3] & m);
  2353. r[i + 4] = a[i + 4] - (b[i + 4] & m);
  2354. r[i + 5] = a[i + 5] - (b[i + 5] & m);
  2355. r[i + 6] = a[i + 6] - (b[i + 6] & m);
  2356. r[i + 7] = a[i + 7] - (b[i + 7] & m);
  2357. }
  2358. #endif /* WOLFSSL_SP_SMALL */
  2359. }
  2360. /* Mul a by scalar b and add into r. (r += a * b)
  2361. *
  2362. * r A single precision integer.
  2363. * a A single precision integer.
  2364. * b A scalar.
  2365. */
  2366. SP_NOINLINE static void sp_2048_mul_add_72(sp_digit* r, const sp_digit* a,
  2367. const sp_digit b)
  2368. {
  2369. #ifndef WOLFSSL_SP_LARGE_CODE
  2370. sp_int64 tb = b;
  2371. sp_int64 t = 0;
  2372. int i;
  2373. for (i = 0; i < 72; i++) {
  2374. t += r[i];
  2375. t += tb * a[i];
  2376. r[i] = ((sp_digit)t) & 0x1fffffff;
  2377. t >>= 29;
  2378. }
  2379. r[72] += (sp_digit)t;
  2380. #else
  2381. #ifdef WOLFSSL_SP_SMALL
  2382. sp_int64 tb = b;
  2383. sp_int64 t[4];
  2384. int i;
  2385. t[0] = 0;
  2386. for (i = 0; i < 68; i += 4) {
  2387. t[0] += (tb * a[i+0]) + r[i+0];
  2388. t[1] = (tb * a[i+1]) + r[i+1];
  2389. t[2] = (tb * a[i+2]) + r[i+2];
  2390. t[3] = (tb * a[i+3]) + r[i+3];
  2391. r[i+0] = t[0] & 0x1fffffff;
  2392. t[1] += t[0] >> 29;
  2393. r[i+1] = t[1] & 0x1fffffff;
  2394. t[2] += t[1] >> 29;
  2395. r[i+2] = t[2] & 0x1fffffff;
  2396. t[3] += t[2] >> 29;
  2397. r[i+3] = t[3] & 0x1fffffff;
  2398. t[0] = t[3] >> 29;
  2399. }
  2400. t[0] += (tb * a[68]) + r[68];
  2401. t[1] = (tb * a[69]) + r[69];
  2402. t[2] = (tb * a[70]) + r[70];
  2403. t[3] = (tb * a[71]) + r[71];
  2404. r[68] = t[0] & 0x1fffffff;
  2405. t[1] += t[0] >> 29;
  2406. r[69] = t[1] & 0x1fffffff;
  2407. t[2] += t[1] >> 29;
  2408. r[70] = t[2] & 0x1fffffff;
  2409. t[3] += t[2] >> 29;
  2410. r[71] = t[3] & 0x1fffffff;
  2411. r[72] += (sp_digit)(t[3] >> 29);
  2412. #else
  2413. sp_int64 tb = b;
  2414. sp_int64 t[8];
  2415. int i;
  2416. t[0] = 0;
  2417. for (i = 0; i < 64; i += 8) {
  2418. t[0] += (tb * a[i+0]) + r[i+0];
  2419. t[1] = (tb * a[i+1]) + r[i+1];
  2420. t[2] = (tb * a[i+2]) + r[i+2];
  2421. t[3] = (tb * a[i+3]) + r[i+3];
  2422. t[4] = (tb * a[i+4]) + r[i+4];
  2423. t[5] = (tb * a[i+5]) + r[i+5];
  2424. t[6] = (tb * a[i+6]) + r[i+6];
  2425. t[7] = (tb * a[i+7]) + r[i+7];
  2426. r[i+0] = t[0] & 0x1fffffff;
  2427. t[1] += t[0] >> 29;
  2428. r[i+1] = t[1] & 0x1fffffff;
  2429. t[2] += t[1] >> 29;
  2430. r[i+2] = t[2] & 0x1fffffff;
  2431. t[3] += t[2] >> 29;
  2432. r[i+3] = t[3] & 0x1fffffff;
  2433. t[4] += t[3] >> 29;
  2434. r[i+4] = t[4] & 0x1fffffff;
  2435. t[5] += t[4] >> 29;
  2436. r[i+5] = t[5] & 0x1fffffff;
  2437. t[6] += t[5] >> 29;
  2438. r[i+6] = t[6] & 0x1fffffff;
  2439. t[7] += t[6] >> 29;
  2440. r[i+7] = t[7] & 0x1fffffff;
  2441. t[0] = t[7] >> 29;
  2442. }
  2443. t[0] += (tb * a[64]) + r[64];
  2444. t[1] = (tb * a[65]) + r[65];
  2445. t[2] = (tb * a[66]) + r[66];
  2446. t[3] = (tb * a[67]) + r[67];
  2447. t[4] = (tb * a[68]) + r[68];
  2448. t[5] = (tb * a[69]) + r[69];
  2449. t[6] = (tb * a[70]) + r[70];
  2450. t[7] = (tb * a[71]) + r[71];
  2451. r[64] = t[0] & 0x1fffffff;
  2452. t[1] += t[0] >> 29;
  2453. r[65] = t[1] & 0x1fffffff;
  2454. t[2] += t[1] >> 29;
  2455. r[66] = t[2] & 0x1fffffff;
  2456. t[3] += t[2] >> 29;
  2457. r[67] = t[3] & 0x1fffffff;
  2458. t[4] += t[3] >> 29;
  2459. r[68] = t[4] & 0x1fffffff;
  2460. t[5] += t[4] >> 29;
  2461. r[69] = t[5] & 0x1fffffff;
  2462. t[6] += t[5] >> 29;
  2463. r[70] = t[6] & 0x1fffffff;
  2464. t[7] += t[6] >> 29;
  2465. r[71] = t[7] & 0x1fffffff;
  2466. r[72] += (sp_digit)(t[7] >> 29);
  2467. #endif /* WOLFSSL_SP_SMALL */
  2468. #endif /* !WOLFSSL_SP_LARGE_CODE */
  2469. }
  2470. /* Shift the result in the high 2048 bits down to the bottom.
  2471. *
  2472. * r A single precision number.
  2473. * a A single precision number.
  2474. */
  2475. static void sp_2048_mont_shift_72(sp_digit* r, const sp_digit* a)
  2476. {
  2477. #ifdef WOLFSSL_SP_SMALL
  2478. int i;
  2479. sp_int64 n = a[70] >> 18;
  2480. n += ((sp_int64)a[71]) << 11;
  2481. for (i = 0; i < 70; i++) {
  2482. r[i] = n & 0x1fffffff;
  2483. n >>= 29;
  2484. n += ((sp_int64)a[72 + i]) << 11;
  2485. }
  2486. r[70] = (sp_digit)n;
  2487. #else
  2488. int i;
  2489. sp_int64 n = a[70] >> 18;
  2490. n += ((sp_int64)a[71]) << 11;
  2491. for (i = 0; i < 64; i += 8) {
  2492. r[i + 0] = n & 0x1fffffff;
  2493. n >>= 29; n += ((sp_int64)a[i + 72]) << 11;
  2494. r[i + 1] = n & 0x1fffffff;
  2495. n >>= 29; n += ((sp_int64)a[i + 73]) << 11;
  2496. r[i + 2] = n & 0x1fffffff;
  2497. n >>= 29; n += ((sp_int64)a[i + 74]) << 11;
  2498. r[i + 3] = n & 0x1fffffff;
  2499. n >>= 29; n += ((sp_int64)a[i + 75]) << 11;
  2500. r[i + 4] = n & 0x1fffffff;
  2501. n >>= 29; n += ((sp_int64)a[i + 76]) << 11;
  2502. r[i + 5] = n & 0x1fffffff;
  2503. n >>= 29; n += ((sp_int64)a[i + 77]) << 11;
  2504. r[i + 6] = n & 0x1fffffff;
  2505. n >>= 29; n += ((sp_int64)a[i + 78]) << 11;
  2506. r[i + 7] = n & 0x1fffffff;
  2507. n >>= 29; n += ((sp_int64)a[i + 79]) << 11;
  2508. }
  2509. r[64] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[136]) << 11;
  2510. r[65] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[137]) << 11;
  2511. r[66] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[138]) << 11;
  2512. r[67] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[139]) << 11;
  2513. r[68] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[140]) << 11;
  2514. r[69] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[141]) << 11;
  2515. r[70] = (sp_digit)n;
  2516. #endif /* WOLFSSL_SP_SMALL */
  2517. XMEMSET(&r[71], 0, sizeof(*r) * 71U);
  2518. }
  2519. /* Reduce the number back to 2048 bits using Montgomery reduction.
  2520. *
  2521. * a A single precision number to reduce in place.
  2522. * m The single precision number representing the modulus.
  2523. * mp The digit representing the negative inverse of m mod 2^n.
  2524. */
  2525. static void sp_2048_mont_reduce_72(sp_digit* a, const sp_digit* m, sp_digit mp)
  2526. {
  2527. int i;
  2528. sp_digit mu;
  2529. sp_digit over;
  2530. sp_2048_norm_72(a + 71);
  2531. #ifdef WOLFSSL_SP_DH
  2532. if (mp != 1) {
  2533. for (i=0; i<70; i++) {
  2534. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff;
  2535. sp_2048_mul_add_72(a+i, m, mu);
  2536. a[i+1] += a[i] >> 29;
  2537. }
  2538. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x3ffffL;
  2539. sp_2048_mul_add_72(a+i, m, mu);
  2540. a[i+1] += a[i] >> 29;
  2541. a[i] &= 0x1fffffff;
  2542. }
  2543. else {
  2544. for (i=0; i<70; i++) {
  2545. mu = a[i] & 0x1fffffff;
  2546. sp_2048_mul_add_72(a+i, m, mu);
  2547. a[i+1] += a[i] >> 29;
  2548. }
  2549. mu = a[i] & 0x3ffffL;
  2550. sp_2048_mul_add_72(a+i, m, mu);
  2551. a[i+1] += a[i] >> 29;
  2552. a[i] &= 0x1fffffff;
  2553. }
  2554. #else
  2555. for (i=0; i<70; i++) {
  2556. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff;
  2557. sp_2048_mul_add_72(a+i, m, mu);
  2558. a[i+1] += a[i] >> 29;
  2559. }
  2560. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x3ffffL;
  2561. sp_2048_mul_add_72(a+i, m, mu);
  2562. a[i+1] += a[i] >> 29;
  2563. a[i] &= 0x1fffffff;
  2564. #endif
  2565. sp_2048_mont_shift_72(a, a);
  2566. over = a[70] - m[70];
  2567. sp_2048_cond_sub_72(a, a, m, ~((over - 1) >> 31));
  2568. sp_2048_norm_72(a);
  2569. }
  2570. /* Multiply two Montgomery form numbers mod the modulus (prime).
  2571. * (r = a * b mod m)
  2572. *
  2573. * r Result of multiplication.
  2574. * a First number to multiply in Montgomery form.
  2575. * b Second number to multiply in Montgomery form.
  2576. * m Modulus (prime).
  2577. * mp Montgomery mulitplier.
  2578. */
  2579. SP_NOINLINE static void sp_2048_mont_mul_72(sp_digit* r, const sp_digit* a,
  2580. const sp_digit* b, const sp_digit* m, sp_digit mp)
  2581. {
  2582. sp_2048_mul_72(r, a, b);
  2583. sp_2048_mont_reduce_72(r, m, mp);
  2584. }
  2585. /* Square the Montgomery form number. (r = a * a mod m)
  2586. *
  2587. * r Result of squaring.
  2588. * a Number to square in Montgomery form.
  2589. * m Modulus (prime).
  2590. * mp Montgomery mulitplier.
  2591. */
  2592. SP_NOINLINE static void sp_2048_mont_sqr_72(sp_digit* r, const sp_digit* a,
  2593. const sp_digit* m, sp_digit mp)
  2594. {
  2595. sp_2048_sqr_72(r, a);
  2596. sp_2048_mont_reduce_72(r, m, mp);
  2597. }
  2598. /* Normalize the values in each word to 29 bits.
  2599. *
  2600. * a Array of sp_digit to normalize.
  2601. */
  2602. static void sp_2048_norm_71(sp_digit* a)
  2603. {
  2604. #ifdef WOLFSSL_SP_SMALL
  2605. int i;
  2606. for (i = 0; i < 70; i++) {
  2607. a[i+1] += a[i] >> 29;
  2608. a[i] &= 0x1fffffff;
  2609. }
  2610. #else
  2611. int i;
  2612. for (i = 0; i < 64; i += 8) {
  2613. a[i+1] += a[i+0] >> 29; a[i+0] &= 0x1fffffff;
  2614. a[i+2] += a[i+1] >> 29; a[i+1] &= 0x1fffffff;
  2615. a[i+3] += a[i+2] >> 29; a[i+2] &= 0x1fffffff;
  2616. a[i+4] += a[i+3] >> 29; a[i+3] &= 0x1fffffff;
  2617. a[i+5] += a[i+4] >> 29; a[i+4] &= 0x1fffffff;
  2618. a[i+6] += a[i+5] >> 29; a[i+5] &= 0x1fffffff;
  2619. a[i+7] += a[i+6] >> 29; a[i+6] &= 0x1fffffff;
  2620. a[i+8] += a[i+7] >> 29; a[i+7] &= 0x1fffffff;
  2621. }
  2622. a[65] += a[64] >> 29; a[64] &= 0x1fffffff;
  2623. a[66] += a[65] >> 29; a[65] &= 0x1fffffff;
  2624. a[67] += a[66] >> 29; a[66] &= 0x1fffffff;
  2625. a[68] += a[67] >> 29; a[67] &= 0x1fffffff;
  2626. a[69] += a[68] >> 29; a[68] &= 0x1fffffff;
  2627. a[70] += a[69] >> 29; a[69] &= 0x1fffffff;
  2628. #endif /* WOLFSSL_SP_SMALL */
  2629. }
  2630. /* Multiply a by scalar b into r. (r = a * b)
  2631. *
  2632. * r A single precision integer.
  2633. * a A single precision integer.
  2634. * b A scalar.
  2635. */
  2636. SP_NOINLINE static void sp_2048_mul_d_144(sp_digit* r, const sp_digit* a,
  2637. sp_digit b)
  2638. {
  2639. #ifdef WOLFSSL_SP_SMALL
  2640. sp_int64 tb = b;
  2641. sp_int64 t = 0;
  2642. int i;
  2643. for (i = 0; i < 144; i++) {
  2644. t += tb * a[i];
  2645. r[i] = (sp_digit)(t & 0x1fffffff);
  2646. t >>= 29;
  2647. }
  2648. r[144] = (sp_digit)t;
  2649. #else
  2650. sp_int64 tb = b;
  2651. sp_int64 t = 0;
  2652. sp_digit t2;
  2653. sp_int64 p[4];
  2654. int i;
  2655. for (i = 0; i < 144; i += 4) {
  2656. p[0] = tb * a[i + 0];
  2657. p[1] = tb * a[i + 1];
  2658. p[2] = tb * a[i + 2];
  2659. p[3] = tb * a[i + 3];
  2660. t += p[0];
  2661. t2 = (sp_digit)(t & 0x1fffffff);
  2662. t >>= 29;
  2663. r[i + 0] = (sp_digit)t2;
  2664. t += p[1];
  2665. t2 = (sp_digit)(t & 0x1fffffff);
  2666. t >>= 29;
  2667. r[i + 1] = (sp_digit)t2;
  2668. t += p[2];
  2669. t2 = (sp_digit)(t & 0x1fffffff);
  2670. t >>= 29;
  2671. r[i + 2] = (sp_digit)t2;
  2672. t += p[3];
  2673. t2 = (sp_digit)(t & 0x1fffffff);
  2674. t >>= 29;
  2675. r[i + 3] = (sp_digit)t2;
  2676. }
  2677. r[144] = (sp_digit)(t & 0x1fffffff);
  2678. #endif /* WOLFSSL_SP_SMALL */
  2679. }
  2680. #ifdef WOLFSSL_SP_SMALL
  2681. /* Conditionally add a and b using the mask m.
  2682. * m is -1 to add and 0 when not.
  2683. *
  2684. * r A single precision number representing conditional add result.
  2685. * a A single precision number to add with.
  2686. * b A single precision number to add.
  2687. * m Mask value to apply.
  2688. */
  2689. static void sp_2048_cond_add_72(sp_digit* r, const sp_digit* a,
  2690. const sp_digit* b, const sp_digit m)
  2691. {
  2692. int i;
  2693. for (i = 0; i < 72; i++) {
  2694. r[i] = a[i] + (b[i] & m);
  2695. }
  2696. }
  2697. #endif /* WOLFSSL_SP_SMALL */
  2698. #ifndef WOLFSSL_SP_SMALL
  2699. /* Conditionally add a and b using the mask m.
  2700. * m is -1 to add and 0 when not.
  2701. *
  2702. * r A single precision number representing conditional add result.
  2703. * a A single precision number to add with.
  2704. * b A single precision number to add.
  2705. * m Mask value to apply.
  2706. */
  2707. static void sp_2048_cond_add_72(sp_digit* r, const sp_digit* a,
  2708. const sp_digit* b, const sp_digit m)
  2709. {
  2710. int i;
  2711. for (i = 0; i < 72; i += 8) {
  2712. r[i + 0] = a[i + 0] + (b[i + 0] & m);
  2713. r[i + 1] = a[i + 1] + (b[i + 1] & m);
  2714. r[i + 2] = a[i + 2] + (b[i + 2] & m);
  2715. r[i + 3] = a[i + 3] + (b[i + 3] & m);
  2716. r[i + 4] = a[i + 4] + (b[i + 4] & m);
  2717. r[i + 5] = a[i + 5] + (b[i + 5] & m);
  2718. r[i + 6] = a[i + 6] + (b[i + 6] & m);
  2719. r[i + 7] = a[i + 7] + (b[i + 7] & m);
  2720. }
  2721. }
  2722. #endif /* !WOLFSSL_SP_SMALL */
  2723. SP_NOINLINE static void sp_2048_rshift_72(sp_digit* r, const sp_digit* a,
  2724. byte n)
  2725. {
  2726. int i;
  2727. #ifdef WOLFSSL_SP_SMALL
  2728. for (i=0; i<71; i++) {
  2729. r[i] = ((a[i] >> n) | (a[i + 1] << (29 - n))) & 0x1fffffff;
  2730. }
  2731. #else
  2732. for (i=0; i<64; i += 8) {
  2733. r[i+0] = (a[i+0] >> n) | ((a[i+1] << (29 - n)) & 0x1fffffff);
  2734. r[i+1] = (a[i+1] >> n) | ((a[i+2] << (29 - n)) & 0x1fffffff);
  2735. r[i+2] = (a[i+2] >> n) | ((a[i+3] << (29 - n)) & 0x1fffffff);
  2736. r[i+3] = (a[i+3] >> n) | ((a[i+4] << (29 - n)) & 0x1fffffff);
  2737. r[i+4] = (a[i+4] >> n) | ((a[i+5] << (29 - n)) & 0x1fffffff);
  2738. r[i+5] = (a[i+5] >> n) | ((a[i+6] << (29 - n)) & 0x1fffffff);
  2739. r[i+6] = (a[i+6] >> n) | ((a[i+7] << (29 - n)) & 0x1fffffff);
  2740. r[i+7] = (a[i+7] >> n) | ((a[i+8] << (29 - n)) & 0x1fffffff);
  2741. }
  2742. r[64] = (a[64] >> n) | ((a[65] << (29 - n)) & 0x1fffffff);
  2743. r[65] = (a[65] >> n) | ((a[66] << (29 - n)) & 0x1fffffff);
  2744. r[66] = (a[66] >> n) | ((a[67] << (29 - n)) & 0x1fffffff);
  2745. r[67] = (a[67] >> n) | ((a[68] << (29 - n)) & 0x1fffffff);
  2746. r[68] = (a[68] >> n) | ((a[69] << (29 - n)) & 0x1fffffff);
  2747. r[69] = (a[69] >> n) | ((a[70] << (29 - n)) & 0x1fffffff);
  2748. r[70] = (a[70] >> n) | ((a[71] << (29 - n)) & 0x1fffffff);
  2749. #endif /* WOLFSSL_SP_SMALL */
  2750. r[71] = a[71] >> n;
  2751. }
  2752. static WC_INLINE sp_digit sp_2048_div_word_72(sp_digit d1, sp_digit d0,
  2753. sp_digit div)
  2754. {
  2755. #ifdef SP_USE_DIVTI3
  2756. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  2757. return d / div;
  2758. #elif defined(__x86_64__) || defined(__i386__)
  2759. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  2760. sp_uint32 lo = (sp_uint32)d;
  2761. sp_digit hi = (sp_digit)(d >> 32);
  2762. __asm__ __volatile__ (
  2763. "idiv %2"
  2764. : "+a" (lo)
  2765. : "d" (hi), "r" (div)
  2766. : "cc"
  2767. );
  2768. return (sp_digit)lo;
  2769. #elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV)
  2770. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  2771. sp_digit dv = (div >> 1) + 1;
  2772. sp_digit t1 = (sp_digit)(d >> 29);
  2773. sp_digit t0 = (sp_digit)(d & 0x1fffffff);
  2774. sp_digit t2;
  2775. sp_digit sign;
  2776. sp_digit r;
  2777. int i;
  2778. sp_int64 m;
  2779. r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
  2780. t1 -= dv & (0 - r);
  2781. for (i = 27; i >= 1; i--) {
  2782. t1 += t1 + (((sp_uint32)t0 >> 28) & 1);
  2783. t0 <<= 1;
  2784. t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
  2785. r += r + t2;
  2786. t1 -= dv & (0 - t2);
  2787. t1 += t2;
  2788. }
  2789. r += r + 1;
  2790. m = d - ((sp_int64)r * div);
  2791. r += (sp_digit)(m >> 29);
  2792. m = d - ((sp_int64)r * div);
  2793. r += (sp_digit)(m >> 58) - (sp_digit)(d >> 58);
  2794. m = d - ((sp_int64)r * div);
  2795. sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
  2796. m *= sign;
  2797. t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
  2798. r += sign * t2;
  2799. m = d - ((sp_int64)r * div);
  2800. sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
  2801. m *= sign;
  2802. t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
  2803. r += sign * t2;
  2804. return r;
  2805. #else
  2806. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  2807. sp_digit r = 0;
  2808. sp_digit t;
  2809. sp_digit dv = (div >> 14) + 1;
  2810. t = (sp_digit)(d >> 28);
  2811. t = (t / dv) << 14;
  2812. r += t;
  2813. d -= (sp_int64)t * div;
  2814. t = (sp_digit)(d >> 13);
  2815. t = t / (dv << 1);
  2816. r += t;
  2817. d -= (sp_int64)t * div;
  2818. t = (sp_digit)d;
  2819. t = t / div;
  2820. r += t;
  2821. d -= (sp_int64)t * div;
  2822. return r;
  2823. #endif
  2824. }
  2825. static WC_INLINE sp_digit sp_2048_word_div_word_72(sp_digit d, sp_digit div)
  2826. {
  2827. #if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
  2828. defined(SP_DIV_WORD_USE_DIV)
  2829. return d / div;
  2830. #else
  2831. return (sp_digit)((sp_uint32)(div - d) >> 31);
  2832. #endif
  2833. }
  2834. /* Divide d in a and put remainder into r (m*d + r = a)
  2835. * m is not calculated as it is not needed at this time.
  2836. *
  2837. * Full implementation.
  2838. *
  2839. * a Number to be divided.
  2840. * d Number to divide with.
  2841. * m Multiplier result.
  2842. * r Remainder from the division.
  2843. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  2844. */
  2845. static int sp_2048_div_72(const sp_digit* a, const sp_digit* d,
  2846. const sp_digit* m, sp_digit* r)
  2847. {
  2848. int i;
  2849. #ifndef WOLFSSL_SP_DIV_32
  2850. #endif
  2851. sp_digit dv;
  2852. sp_digit r1;
  2853. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  2854. sp_digit* t1 = NULL;
  2855. #else
  2856. sp_digit t1[4 * 72 + 3];
  2857. #endif
  2858. sp_digit* t2 = NULL;
  2859. sp_digit* sd = NULL;
  2860. int err = MP_OKAY;
  2861. (void)m;
  2862. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  2863. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 72 + 3), NULL,
  2864. DYNAMIC_TYPE_TMP_BUFFER);
  2865. if (t1 == NULL)
  2866. err = MEMORY_E;
  2867. #endif
  2868. (void)m;
  2869. if (err == MP_OKAY) {
  2870. t2 = t1 + 144 + 1;
  2871. sd = t2 + 72 + 1;
  2872. sp_2048_mul_d_72(sd, d, (sp_digit)1 << 11);
  2873. sp_2048_mul_d_144(t1, a, (sp_digit)1 << 11);
  2874. dv = sd[70];
  2875. t1[71 + 71] += t1[71 + 71 - 1] >> 29;
  2876. t1[71 + 71 - 1] &= 0x1fffffff;
  2877. for (i=71; i>=0; i--) {
  2878. r1 = sp_2048_div_word_72(t1[71 + i], t1[71 + i - 1], dv);
  2879. sp_2048_mul_d_72(t2, sd, r1);
  2880. (void)sp_2048_sub_72(&t1[i], &t1[i], t2);
  2881. sp_2048_norm_71(&t1[i]);
  2882. t1[71 + i] += t1[71 + i - 1] >> 29;
  2883. t1[71 + i - 1] &= 0x1fffffff;
  2884. r1 = sp_2048_div_word_72(-t1[71 + i], -t1[71 + i - 1], dv);
  2885. r1 -= t1[71 + i];
  2886. sp_2048_mul_d_72(t2, sd, r1);
  2887. (void)sp_2048_add_72(&t1[i], &t1[i], t2);
  2888. t1[71 + i] += t1[71 + i - 1] >> 29;
  2889. t1[71 + i - 1] &= 0x1fffffff;
  2890. }
  2891. t1[71 - 1] += t1[71 - 2] >> 29;
  2892. t1[71 - 2] &= 0x1fffffff;
  2893. r1 = sp_2048_word_div_word_72(t1[71 - 1], dv);
  2894. sp_2048_mul_d_72(t2, sd, r1);
  2895. sp_2048_sub_72(t1, t1, t2);
  2896. XMEMCPY(r, t1, sizeof(*r) * 144U);
  2897. for (i=0; i<70; i++) {
  2898. r[i+1] += r[i] >> 29;
  2899. r[i] &= 0x1fffffff;
  2900. }
  2901. sp_2048_cond_add_72(r, r, sd, r[70] >> 31);
  2902. sp_2048_norm_71(r);
  2903. sp_2048_rshift_72(r, r, 11);
  2904. r[71] = 0;
  2905. }
  2906. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  2907. if (t1 != NULL)
  2908. XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  2909. #endif
  2910. return err;
  2911. }
  2912. /* Reduce a modulo m into r. (r = a mod m)
  2913. *
  2914. * r A single precision number that is the reduced result.
  2915. * a A single precision number that is to be reduced.
  2916. * m A single precision number that is the modulus to reduce with.
  2917. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  2918. */
  2919. static int sp_2048_mod_72(sp_digit* r, const sp_digit* a, const sp_digit* m)
  2920. {
  2921. return sp_2048_div_72(a, m, NULL, r);
  2922. }
  2923. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  2924. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \
  2925. defined(WOLFSSL_HAVE_SP_DH)
  2926. /* Modular exponentiate a to the e mod m. (r = a^e mod m)
  2927. *
  2928. * r A single precision number that is the result of the operation.
  2929. * a A single precision number being exponentiated.
  2930. * e A single precision number that is the exponent.
  2931. * bits The number of bits in the exponent.
  2932. * m A single precision number that is the modulus.
  2933. * returns 0 on success.
  2934. * returns MEMORY_E on dynamic memory allocation failure.
  2935. * returns MP_VAL when base is even or exponent is 0.
  2936. */
  2937. static int sp_2048_mod_exp_72(sp_digit* r, const sp_digit* a, const sp_digit* e,
  2938. int bits, const sp_digit* m, int reduceA)
  2939. {
  2940. #if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP)
  2941. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  2942. sp_digit* td = NULL;
  2943. #else
  2944. sp_digit td[3 * 144];
  2945. #endif
  2946. sp_digit* t[3] = {0, 0, 0};
  2947. sp_digit* norm = NULL;
  2948. sp_digit mp = 1;
  2949. sp_digit n;
  2950. int i;
  2951. int c;
  2952. byte y;
  2953. int err = MP_OKAY;
  2954. if (bits == 0) {
  2955. err = MP_VAL;
  2956. }
  2957. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  2958. if (err == MP_OKAY) {
  2959. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 72 * 2, NULL,
  2960. DYNAMIC_TYPE_TMP_BUFFER);
  2961. if (td == NULL)
  2962. err = MEMORY_E;
  2963. }
  2964. #endif
  2965. if (err == MP_OKAY) {
  2966. norm = td;
  2967. for (i=0; i<3; i++) {
  2968. t[i] = td + (i * 72 * 2);
  2969. XMEMSET(t[i], 0, sizeof(sp_digit) * 72U * 2U);
  2970. }
  2971. sp_2048_mont_setup(m, &mp);
  2972. sp_2048_mont_norm_72(norm, m);
  2973. if (reduceA != 0) {
  2974. err = sp_2048_mod_72(t[1], a, m);
  2975. }
  2976. else {
  2977. XMEMCPY(t[1], a, sizeof(sp_digit) * 72U);
  2978. }
  2979. }
  2980. if (err == MP_OKAY) {
  2981. sp_2048_mul_72(t[1], t[1], norm);
  2982. err = sp_2048_mod_72(t[1], t[1], m);
  2983. }
  2984. if (err == MP_OKAY) {
  2985. i = bits / 29;
  2986. c = bits % 29;
  2987. n = e[i--] << (29 - c);
  2988. for (; ; c--) {
  2989. if (c == 0) {
  2990. if (i == -1) {
  2991. break;
  2992. }
  2993. n = e[i--];
  2994. c = 29;
  2995. }
  2996. y = (int)((n >> 28) & 1);
  2997. n <<= 1;
  2998. sp_2048_mont_mul_72(t[y^1], t[0], t[1], m, mp);
  2999. XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
  3000. ((size_t)t[1] & addr_mask[y])),
  3001. sizeof(*t[2]) * 72 * 2);
  3002. sp_2048_mont_sqr_72(t[2], t[2], m, mp);
  3003. XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
  3004. ((size_t)t[1] & addr_mask[y])), t[2],
  3005. sizeof(*t[2]) * 72 * 2);
  3006. }
  3007. sp_2048_mont_reduce_72(t[0], m, mp);
  3008. n = sp_2048_cmp_72(t[0], m);
  3009. sp_2048_cond_sub_72(t[0], t[0], m, ~(n >> 31));
  3010. XMEMCPY(r, t[0], sizeof(*r) * 72 * 2);
  3011. }
  3012. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3013. if (td != NULL)
  3014. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  3015. #endif
  3016. return err;
  3017. #elif !defined(WC_NO_CACHE_RESISTANT)
  3018. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3019. sp_digit* td = NULL;
  3020. #else
  3021. sp_digit td[3 * 144];
  3022. #endif
  3023. sp_digit* t[3] = {0, 0, 0};
  3024. sp_digit* norm = NULL;
  3025. sp_digit mp = 1;
  3026. sp_digit n;
  3027. int i;
  3028. int c;
  3029. byte y;
  3030. int err = MP_OKAY;
  3031. if (bits == 0) {
  3032. err = MP_VAL;
  3033. }
  3034. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3035. if (err == MP_OKAY) {
  3036. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 72 * 2, NULL,
  3037. DYNAMIC_TYPE_TMP_BUFFER);
  3038. if (td == NULL)
  3039. err = MEMORY_E;
  3040. }
  3041. #endif
  3042. if (err == MP_OKAY) {
  3043. norm = td;
  3044. for (i=0; i<3; i++) {
  3045. t[i] = td + (i * 72 * 2);
  3046. }
  3047. sp_2048_mont_setup(m, &mp);
  3048. sp_2048_mont_norm_72(norm, m);
  3049. if (reduceA != 0) {
  3050. err = sp_2048_mod_72(t[1], a, m);
  3051. if (err == MP_OKAY) {
  3052. sp_2048_mul_72(t[1], t[1], norm);
  3053. err = sp_2048_mod_72(t[1], t[1], m);
  3054. }
  3055. }
  3056. else {
  3057. sp_2048_mul_72(t[1], a, norm);
  3058. err = sp_2048_mod_72(t[1], t[1], m);
  3059. }
  3060. }
  3061. if (err == MP_OKAY) {
  3062. i = bits / 29;
  3063. c = bits % 29;
  3064. n = e[i--] << (29 - c);
  3065. for (; ; c--) {
  3066. if (c == 0) {
  3067. if (i == -1) {
  3068. break;
  3069. }
  3070. n = e[i--];
  3071. c = 29;
  3072. }
  3073. y = (int)((n >> 28) & 1);
  3074. n <<= 1;
  3075. sp_2048_mont_mul_72(t[y^1], t[0], t[1], m, mp);
  3076. XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
  3077. ((size_t)t[1] & addr_mask[y])),
  3078. sizeof(*t[2]) * 72 * 2);
  3079. sp_2048_mont_sqr_72(t[2], t[2], m, mp);
  3080. XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
  3081. ((size_t)t[1] & addr_mask[y])), t[2],
  3082. sizeof(*t[2]) * 72 * 2);
  3083. }
  3084. sp_2048_mont_reduce_72(t[0], m, mp);
  3085. n = sp_2048_cmp_72(t[0], m);
  3086. sp_2048_cond_sub_72(t[0], t[0], m, ~(n >> 31));
  3087. XMEMCPY(r, t[0], sizeof(*r) * 72 * 2);
  3088. }
  3089. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3090. if (td != NULL)
  3091. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  3092. #endif
  3093. return err;
  3094. #else
  3095. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3096. sp_digit* td = NULL;
  3097. #else
  3098. sp_digit td[(16 * 144) + 144];
  3099. #endif
  3100. sp_digit* t[16];
  3101. sp_digit* rt = NULL;
  3102. sp_digit* norm = NULL;
  3103. sp_digit mp = 1;
  3104. sp_digit n;
  3105. int i;
  3106. int c;
  3107. byte y;
  3108. int err = MP_OKAY;
  3109. if (bits == 0) {
  3110. err = MP_VAL;
  3111. }
  3112. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3113. if (err == MP_OKAY) {
  3114. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((16 * 144) + 144), NULL,
  3115. DYNAMIC_TYPE_TMP_BUFFER);
  3116. if (td == NULL)
  3117. err = MEMORY_E;
  3118. }
  3119. #endif
  3120. if (err == MP_OKAY) {
  3121. norm = td;
  3122. for (i=0; i<16; i++)
  3123. t[i] = td + i * 144;
  3124. rt = td + 2304;
  3125. sp_2048_mont_setup(m, &mp);
  3126. sp_2048_mont_norm_72(norm, m);
  3127. if (reduceA != 0) {
  3128. err = sp_2048_mod_72(t[1], a, m);
  3129. if (err == MP_OKAY) {
  3130. sp_2048_mul_72(t[1], t[1], norm);
  3131. err = sp_2048_mod_72(t[1], t[1], m);
  3132. }
  3133. }
  3134. else {
  3135. sp_2048_mul_72(t[1], a, norm);
  3136. err = sp_2048_mod_72(t[1], t[1], m);
  3137. }
  3138. }
  3139. if (err == MP_OKAY) {
  3140. sp_2048_mont_sqr_72(t[ 2], t[ 1], m, mp);
  3141. sp_2048_mont_mul_72(t[ 3], t[ 2], t[ 1], m, mp);
  3142. sp_2048_mont_sqr_72(t[ 4], t[ 2], m, mp);
  3143. sp_2048_mont_mul_72(t[ 5], t[ 3], t[ 2], m, mp);
  3144. sp_2048_mont_sqr_72(t[ 6], t[ 3], m, mp);
  3145. sp_2048_mont_mul_72(t[ 7], t[ 4], t[ 3], m, mp);
  3146. sp_2048_mont_sqr_72(t[ 8], t[ 4], m, mp);
  3147. sp_2048_mont_mul_72(t[ 9], t[ 5], t[ 4], m, mp);
  3148. sp_2048_mont_sqr_72(t[10], t[ 5], m, mp);
  3149. sp_2048_mont_mul_72(t[11], t[ 6], t[ 5], m, mp);
  3150. sp_2048_mont_sqr_72(t[12], t[ 6], m, mp);
  3151. sp_2048_mont_mul_72(t[13], t[ 7], t[ 6], m, mp);
  3152. sp_2048_mont_sqr_72(t[14], t[ 7], m, mp);
  3153. sp_2048_mont_mul_72(t[15], t[ 8], t[ 7], m, mp);
  3154. bits = ((bits + 3) / 4) * 4;
  3155. i = ((bits + 28) / 29) - 1;
  3156. c = bits % 29;
  3157. if (c == 0) {
  3158. c = 29;
  3159. }
  3160. if (i < 72) {
  3161. n = e[i--] << (32 - c);
  3162. }
  3163. else {
  3164. n = 0;
  3165. i--;
  3166. }
  3167. if (c < 4) {
  3168. n |= e[i--] << (3 - c);
  3169. c += 29;
  3170. }
  3171. y = (int)((n >> 28) & 0xf);
  3172. n <<= 4;
  3173. c -= 4;
  3174. XMEMCPY(rt, t[y], sizeof(sp_digit) * 144);
  3175. while ((i >= 0) || (c >= 4)) {
  3176. if (c >= 4) {
  3177. y = (byte)((n >> 28) & 0xf);
  3178. n <<= 4;
  3179. c -= 4;
  3180. }
  3181. else if (c == 0) {
  3182. n = e[i--] << 3;
  3183. y = (byte)((n >> 28) & 0xf);
  3184. n <<= 4;
  3185. c = 25;
  3186. }
  3187. else {
  3188. y = (byte)((n >> 28) & 0xf);
  3189. n = e[i--] << 3;
  3190. c = 4 - c;
  3191. y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
  3192. n <<= c;
  3193. c = 29 - c;
  3194. }
  3195. sp_2048_mont_sqr_72(rt, rt, m, mp);
  3196. sp_2048_mont_sqr_72(rt, rt, m, mp);
  3197. sp_2048_mont_sqr_72(rt, rt, m, mp);
  3198. sp_2048_mont_sqr_72(rt, rt, m, mp);
  3199. sp_2048_mont_mul_72(rt, rt, t[y], m, mp);
  3200. }
  3201. sp_2048_mont_reduce_72(rt, m, mp);
  3202. n = sp_2048_cmp_72(rt, m);
  3203. sp_2048_cond_sub_72(rt, rt, m, ~(n >> 31));
  3204. XMEMCPY(r, rt, sizeof(sp_digit) * 144);
  3205. }
  3206. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3207. if (td != NULL)
  3208. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  3209. #endif
  3210. return err;
  3211. #endif
  3212. }
  3213. #endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) || */
  3214. /* WOLFSSL_HAVE_SP_DH */
  3215. #endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
  3216. #ifdef WOLFSSL_HAVE_SP_RSA
  3217. /* RSA public key operation.
  3218. *
  3219. * in Array of bytes representing the number to exponentiate, base.
  3220. * inLen Number of bytes in base.
  3221. * em Public exponent.
  3222. * mm Modulus.
  3223. * out Buffer to hold big-endian bytes of exponentiation result.
  3224. * Must be at least 256 bytes long.
  3225. * outLen Number of bytes in result.
  3226. * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
  3227. * an array is too long and MEMORY_E when dynamic memory allocation fails.
  3228. */
  3229. int sp_RsaPublic_2048(const byte* in, word32 inLen, const mp_int* em,
  3230. const mp_int* mm, byte* out, word32* outLen)
  3231. {
  3232. #ifdef WOLFSSL_SP_SMALL
  3233. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3234. sp_digit* a = NULL;
  3235. #else
  3236. sp_digit a[72 * 5];
  3237. #endif
  3238. sp_digit* m = NULL;
  3239. sp_digit* r = NULL;
  3240. sp_digit* norm = NULL;
  3241. sp_digit e[1] = {0};
  3242. sp_digit mp = 0;
  3243. int i;
  3244. int err = MP_OKAY;
  3245. if (*outLen < 256U) {
  3246. err = MP_TO_E;
  3247. }
  3248. if (err == MP_OKAY) {
  3249. if (mp_count_bits(em) > 29) {
  3250. err = MP_READ_E;
  3251. }
  3252. else if (inLen > 256U) {
  3253. err = MP_READ_E;
  3254. }
  3255. else if (mp_count_bits(mm) != 2048) {
  3256. err = MP_READ_E;
  3257. }
  3258. else if (mp_iseven(mm)) {
  3259. err = MP_VAL;
  3260. }
  3261. }
  3262. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3263. if (err == MP_OKAY) {
  3264. a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 72 * 5, NULL,
  3265. DYNAMIC_TYPE_RSA);
  3266. if (a == NULL)
  3267. err = MEMORY_E;
  3268. }
  3269. #endif
  3270. if (err == MP_OKAY) {
  3271. r = a + 72 * 2;
  3272. m = r + 72 * 2;
  3273. norm = r;
  3274. sp_2048_from_bin(a, 72, in, inLen);
  3275. #if DIGIT_BIT >= 29
  3276. e[0] = (sp_digit)em->dp[0];
  3277. #else
  3278. e[0] = (sp_digit)em->dp[0];
  3279. if (em->used > 1) {
  3280. e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
  3281. }
  3282. #endif
  3283. if (e[0] == 0) {
  3284. err = MP_EXPTMOD_E;
  3285. }
  3286. }
  3287. if (err == MP_OKAY) {
  3288. sp_2048_from_mp(m, 72, mm);
  3289. sp_2048_mont_setup(m, &mp);
  3290. sp_2048_mont_norm_72(norm, m);
  3291. }
  3292. if (err == MP_OKAY) {
  3293. sp_2048_mul_72(a, a, norm);
  3294. err = sp_2048_mod_72(a, a, m);
  3295. }
  3296. if (err == MP_OKAY) {
  3297. for (i=28; i>=0; i--) {
  3298. if ((e[0] >> i) != 0) {
  3299. break;
  3300. }
  3301. }
  3302. XMEMCPY(r, a, sizeof(sp_digit) * 72 * 2);
  3303. for (i--; i>=0; i--) {
  3304. sp_2048_mont_sqr_72(r, r, m, mp);
  3305. if (((e[0] >> i) & 1) == 1) {
  3306. sp_2048_mont_mul_72(r, r, a, m, mp);
  3307. }
  3308. }
  3309. sp_2048_mont_reduce_72(r, m, mp);
  3310. mp = sp_2048_cmp_72(r, m);
  3311. sp_2048_cond_sub_72(r, r, m, ~(mp >> 31));
  3312. sp_2048_to_bin_72(r, out);
  3313. *outLen = 256;
  3314. }
  3315. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3316. if (a != NULL)
  3317. XFREE(a, NULL, DYNAMIC_TYPE_RSA);
  3318. #endif
  3319. return err;
  3320. #else
  3321. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3322. sp_digit* d = NULL;
  3323. #else
  3324. sp_digit d[72 * 5];
  3325. #endif
  3326. sp_digit* a = NULL;
  3327. sp_digit* m = NULL;
  3328. sp_digit* r = NULL;
  3329. sp_digit e[1] = {0};
  3330. int err = MP_OKAY;
  3331. if (*outLen < 256U) {
  3332. err = MP_TO_E;
  3333. }
  3334. if (err == MP_OKAY) {
  3335. if (mp_count_bits(em) > 29) {
  3336. err = MP_READ_E;
  3337. }
  3338. else if (inLen > 256U) {
  3339. err = MP_READ_E;
  3340. }
  3341. else if (mp_count_bits(mm) != 2048) {
  3342. err = MP_READ_E;
  3343. }
  3344. else if (mp_iseven(mm)) {
  3345. err = MP_VAL;
  3346. }
  3347. }
  3348. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3349. if (err == MP_OKAY) {
  3350. d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 72 * 5, NULL,
  3351. DYNAMIC_TYPE_RSA);
  3352. if (d == NULL)
  3353. err = MEMORY_E;
  3354. }
  3355. #endif
  3356. if (err == MP_OKAY) {
  3357. a = d;
  3358. r = a + 72 * 2;
  3359. m = r + 72 * 2;
  3360. sp_2048_from_bin(a, 72, in, inLen);
  3361. #if DIGIT_BIT >= 29
  3362. e[0] = (sp_digit)em->dp[0];
  3363. #else
  3364. e[0] = (sp_digit)em->dp[0];
  3365. if (em->used > 1) {
  3366. e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
  3367. }
  3368. #endif
  3369. if (e[0] == 0) {
  3370. err = MP_EXPTMOD_E;
  3371. }
  3372. }
  3373. if (err == MP_OKAY) {
  3374. sp_2048_from_mp(m, 72, mm);
  3375. if (e[0] == 0x3) {
  3376. sp_2048_sqr_72(r, a);
  3377. err = sp_2048_mod_72(r, r, m);
  3378. if (err == MP_OKAY) {
  3379. sp_2048_mul_72(r, a, r);
  3380. err = sp_2048_mod_72(r, r, m);
  3381. }
  3382. }
  3383. else {
  3384. sp_digit* norm = r;
  3385. int i;
  3386. sp_digit mp;
  3387. sp_2048_mont_setup(m, &mp);
  3388. sp_2048_mont_norm_72(norm, m);
  3389. sp_2048_mul_72(a, a, norm);
  3390. err = sp_2048_mod_72(a, a, m);
  3391. if (err == MP_OKAY) {
  3392. for (i=28; i>=0; i--) {
  3393. if ((e[0] >> i) != 0) {
  3394. break;
  3395. }
  3396. }
  3397. XMEMCPY(r, a, sizeof(sp_digit) * 144U);
  3398. for (i--; i>=0; i--) {
  3399. sp_2048_mont_sqr_72(r, r, m, mp);
  3400. if (((e[0] >> i) & 1) == 1) {
  3401. sp_2048_mont_mul_72(r, r, a, m, mp);
  3402. }
  3403. }
  3404. sp_2048_mont_reduce_72(r, m, mp);
  3405. mp = sp_2048_cmp_72(r, m);
  3406. sp_2048_cond_sub_72(r, r, m, ~(mp >> 31));
  3407. }
  3408. }
  3409. }
  3410. if (err == MP_OKAY) {
  3411. sp_2048_to_bin_72(r, out);
  3412. *outLen = 256;
  3413. }
  3414. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3415. if (d != NULL)
  3416. XFREE(d, NULL, DYNAMIC_TYPE_RSA);
  3417. #endif
  3418. return err;
  3419. #endif /* WOLFSSL_SP_SMALL */
  3420. }
  3421. #ifndef WOLFSSL_RSA_PUBLIC_ONLY
  3422. #if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM)
  3423. #endif /* !SP_RSA_PRIVATE_EXP_D & !RSA_LOW_MEM */
  3424. /* RSA private key operation.
  3425. *
  3426. * in Array of bytes representing the number to exponentiate, base.
  3427. * inLen Number of bytes in base.
  3428. * dm Private exponent.
  3429. * pm First prime.
  3430. * qm Second prime.
  3431. * dpm First prime's CRT exponent.
  3432. * dqm Second prime's CRT exponent.
  3433. * qim Inverse of second prime mod p.
  3434. * mm Modulus.
  3435. * out Buffer to hold big-endian bytes of exponentiation result.
  3436. * Must be at least 256 bytes long.
  3437. * outLen Number of bytes in result.
  3438. * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
  3439. * an array is too long and MEMORY_E when dynamic memory allocation fails.
  3440. */
  3441. int sp_RsaPrivate_2048(const byte* in, word32 inLen, const mp_int* dm,
  3442. const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
  3443. const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
  3444. {
  3445. #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
  3446. #if defined(WOLFSSL_SP_SMALL)
  3447. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3448. sp_digit* d = NULL;
  3449. #else
  3450. sp_digit d[72 * 4];
  3451. #endif
  3452. sp_digit* a = NULL;
  3453. sp_digit* m = NULL;
  3454. sp_digit* r = NULL;
  3455. int err = MP_OKAY;
  3456. (void)pm;
  3457. (void)qm;
  3458. (void)dpm;
  3459. (void)dqm;
  3460. (void)qim;
  3461. if (*outLen < 256U) {
  3462. err = MP_TO_E;
  3463. }
  3464. if (err == MP_OKAY) {
  3465. if (mp_count_bits(dm) > 2048) {
  3466. err = MP_READ_E;
  3467. }
  3468. else if (inLen > 256) {
  3469. err = MP_READ_E;
  3470. }
  3471. else if (mp_count_bits(mm) != 2048) {
  3472. err = MP_READ_E;
  3473. }
  3474. else if (mp_iseven(mm)) {
  3475. err = MP_VAL;
  3476. }
  3477. }
  3478. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3479. if (err == MP_OKAY) {
  3480. d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 72 * 4, NULL,
  3481. DYNAMIC_TYPE_RSA);
  3482. if (d == NULL)
  3483. err = MEMORY_E;
  3484. }
  3485. #endif
  3486. if (err == MP_OKAY) {
  3487. a = d + 72;
  3488. m = a + 144;
  3489. r = a;
  3490. sp_2048_from_bin(a, 72, in, inLen);
  3491. sp_2048_from_mp(d, 72, dm);
  3492. sp_2048_from_mp(m, 72, mm);
  3493. err = sp_2048_mod_exp_72(r, a, d, 2048, m, 0);
  3494. }
  3495. if (err == MP_OKAY) {
  3496. sp_2048_to_bin_72(r, out);
  3497. *outLen = 256;
  3498. }
  3499. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3500. if (d != NULL)
  3501. #endif
  3502. {
  3503. /* only "a" and "r" are sensitive and need zeroized (same pointer) */
  3504. if (a != NULL)
  3505. ForceZero(a, sizeof(sp_digit) * 72);
  3506. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3507. XFREE(d, NULL, DYNAMIC_TYPE_RSA);
  3508. #endif
  3509. }
  3510. return err;
  3511. #else
  3512. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3513. sp_digit* d = NULL;
  3514. #else
  3515. sp_digit d[72 * 4];
  3516. #endif
  3517. sp_digit* a = NULL;
  3518. sp_digit* m = NULL;
  3519. sp_digit* r = NULL;
  3520. int err = MP_OKAY;
  3521. (void)pm;
  3522. (void)qm;
  3523. (void)dpm;
  3524. (void)dqm;
  3525. (void)qim;
  3526. if (*outLen < 256U) {
  3527. err = MP_TO_E;
  3528. }
  3529. if (err == MP_OKAY) {
  3530. if (mp_count_bits(dm) > 2048) {
  3531. err = MP_READ_E;
  3532. }
  3533. else if (inLen > 256U) {
  3534. err = MP_READ_E;
  3535. }
  3536. else if (mp_count_bits(mm) != 2048) {
  3537. err = MP_READ_E;
  3538. }
  3539. else if (mp_iseven(mm)) {
  3540. err = MP_VAL;
  3541. }
  3542. }
  3543. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3544. if (err == MP_OKAY) {
  3545. d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 72 * 4, NULL,
  3546. DYNAMIC_TYPE_RSA);
  3547. if (d == NULL)
  3548. err = MEMORY_E;
  3549. }
  3550. #endif
  3551. if (err == MP_OKAY) {
  3552. a = d + 72;
  3553. m = a + 144;
  3554. r = a;
  3555. sp_2048_from_bin(a, 72, in, inLen);
  3556. sp_2048_from_mp(d, 72, dm);
  3557. sp_2048_from_mp(m, 72, mm);
  3558. err = sp_2048_mod_exp_72(r, a, d, 2048, m, 0);
  3559. }
  3560. if (err == MP_OKAY) {
  3561. sp_2048_to_bin_72(r, out);
  3562. *outLen = 256;
  3563. }
  3564. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3565. if (d != NULL)
  3566. #endif
  3567. {
  3568. /* only "a" and "r" are sensitive and need zeroized (same pointer) */
  3569. if (a != NULL)
  3570. ForceZero(a, sizeof(sp_digit) * 72);
  3571. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3572. XFREE(d, NULL, DYNAMIC_TYPE_RSA);
  3573. #endif
  3574. }
  3575. return err;
  3576. #endif /* WOLFSSL_SP_SMALL */
  3577. #else
  3578. #if defined(WOLFSSL_SP_SMALL)
  3579. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3580. sp_digit* a = NULL;
  3581. #else
  3582. sp_digit a[36 * 8];
  3583. #endif
  3584. sp_digit* p = NULL;
  3585. sp_digit* dp = NULL;
  3586. sp_digit* dq = NULL;
  3587. sp_digit* qi = NULL;
  3588. sp_digit* tmpa = NULL;
  3589. sp_digit* tmpb = NULL;
  3590. sp_digit* r = NULL;
  3591. int err = MP_OKAY;
  3592. (void)dm;
  3593. (void)mm;
  3594. if (*outLen < 256U) {
  3595. err = MP_TO_E;
  3596. }
  3597. if (err == MP_OKAY) {
  3598. if (inLen > 256) {
  3599. err = MP_READ_E;
  3600. }
  3601. else if (mp_count_bits(mm) != 2048) {
  3602. err = MP_READ_E;
  3603. }
  3604. else if (mp_iseven(mm)) {
  3605. err = MP_VAL;
  3606. }
  3607. else if (mp_iseven(pm)) {
  3608. err = MP_VAL;
  3609. }
  3610. else if (mp_iseven(qm)) {
  3611. err = MP_VAL;
  3612. }
  3613. }
  3614. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3615. if (err == MP_OKAY) {
  3616. a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 8, NULL,
  3617. DYNAMIC_TYPE_RSA);
  3618. if (a == NULL)
  3619. err = MEMORY_E;
  3620. }
  3621. #endif
  3622. if (err == MP_OKAY) {
  3623. p = a + 72;
  3624. qi = dq = dp = p + 36;
  3625. tmpa = qi + 36;
  3626. tmpb = tmpa + 72;
  3627. r = a;
  3628. sp_2048_from_bin(a, 72, in, inLen);
  3629. sp_2048_from_mp(p, 36, pm);
  3630. sp_2048_from_mp(dp, 36, dpm);
  3631. err = sp_2048_mod_exp_36(tmpa, a, dp, 1024, p, 1);
  3632. }
  3633. if (err == MP_OKAY) {
  3634. sp_2048_from_mp(p, 36, qm);
  3635. sp_2048_from_mp(dq, 36, dqm);
  3636. err = sp_2048_mod_exp_36(tmpb, a, dq, 1024, p, 1);
  3637. }
  3638. if (err == MP_OKAY) {
  3639. sp_2048_from_mp(p, 36, pm);
  3640. (void)sp_2048_sub_36(tmpa, tmpa, tmpb);
  3641. sp_2048_norm_36(tmpa);
  3642. sp_2048_cond_add_36(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[35] >> 31));
  3643. sp_2048_cond_add_36(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[35] >> 31));
  3644. sp_2048_norm_36(tmpa);
  3645. sp_2048_from_mp(qi, 36, qim);
  3646. sp_2048_mul_36(tmpa, tmpa, qi);
  3647. err = sp_2048_mod_36(tmpa, tmpa, p);
  3648. }
  3649. if (err == MP_OKAY) {
  3650. sp_2048_from_mp(p, 36, qm);
  3651. sp_2048_mul_36(tmpa, p, tmpa);
  3652. (void)sp_2048_add_72(r, tmpb, tmpa);
  3653. sp_2048_norm_72(r);
  3654. sp_2048_to_bin_72(r, out);
  3655. *outLen = 256;
  3656. }
  3657. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3658. if (a != NULL)
  3659. #endif
  3660. {
  3661. ForceZero(a, sizeof(sp_digit) * 36 * 8);
  3662. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3663. XFREE(a, NULL, DYNAMIC_TYPE_RSA);
  3664. #endif
  3665. }
  3666. return err;
  3667. #else
  3668. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3669. sp_digit* a = NULL;
  3670. #else
  3671. sp_digit a[36 * 13];
  3672. #endif
  3673. sp_digit* p = NULL;
  3674. sp_digit* q = NULL;
  3675. sp_digit* dp = NULL;
  3676. sp_digit* dq = NULL;
  3677. sp_digit* qi = NULL;
  3678. sp_digit* tmpa = NULL;
  3679. sp_digit* tmpb = NULL;
  3680. sp_digit* r = NULL;
  3681. int err = MP_OKAY;
  3682. (void)dm;
  3683. (void)mm;
  3684. if (*outLen < 256U) {
  3685. err = MP_TO_E;
  3686. }
  3687. if (err == MP_OKAY) {
  3688. if (inLen > 256U) {
  3689. err = MP_READ_E;
  3690. }
  3691. else if (mp_count_bits(mm) != 2048) {
  3692. err = MP_READ_E;
  3693. }
  3694. else if (mp_iseven(mm)) {
  3695. err = MP_VAL;
  3696. }
  3697. else if (mp_iseven(pm)) {
  3698. err = MP_VAL;
  3699. }
  3700. else if (mp_iseven(qm)) {
  3701. err = MP_VAL;
  3702. }
  3703. }
  3704. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3705. if (err == MP_OKAY) {
  3706. a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 13, NULL,
  3707. DYNAMIC_TYPE_RSA);
  3708. if (a == NULL)
  3709. err = MEMORY_E;
  3710. }
  3711. #endif
  3712. if (err == MP_OKAY) {
  3713. p = a + 72 * 2;
  3714. q = p + 36;
  3715. dp = q + 36;
  3716. dq = dp + 36;
  3717. qi = dq + 36;
  3718. tmpa = qi + 36;
  3719. tmpb = tmpa + 72;
  3720. r = a;
  3721. sp_2048_from_bin(a, 72, in, inLen);
  3722. sp_2048_from_mp(p, 36, pm);
  3723. sp_2048_from_mp(q, 36, qm);
  3724. sp_2048_from_mp(dp, 36, dpm);
  3725. sp_2048_from_mp(dq, 36, dqm);
  3726. sp_2048_from_mp(qi, 36, qim);
  3727. err = sp_2048_mod_exp_36(tmpa, a, dp, 1024, p, 1);
  3728. }
  3729. if (err == MP_OKAY) {
  3730. err = sp_2048_mod_exp_36(tmpb, a, dq, 1024, q, 1);
  3731. }
  3732. if (err == MP_OKAY) {
  3733. (void)sp_2048_sub_36(tmpa, tmpa, tmpb);
  3734. sp_2048_norm_36(tmpa);
  3735. sp_2048_cond_add_36(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[35] >> 31));
  3736. sp_2048_cond_add_36(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[35] >> 31));
  3737. sp_2048_norm_36(tmpa);
  3738. sp_2048_mul_36(tmpa, tmpa, qi);
  3739. err = sp_2048_mod_36(tmpa, tmpa, p);
  3740. }
  3741. if (err == MP_OKAY) {
  3742. sp_2048_mul_36(tmpa, tmpa, q);
  3743. (void)sp_2048_add_72(r, tmpb, tmpa);
  3744. sp_2048_norm_72(r);
  3745. sp_2048_to_bin_72(r, out);
  3746. *outLen = 256;
  3747. }
  3748. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3749. if (a != NULL)
  3750. #endif
  3751. {
  3752. ForceZero(a, sizeof(sp_digit) * 36 * 13);
  3753. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3754. XFREE(a, NULL, DYNAMIC_TYPE_RSA);
  3755. #endif
  3756. }
  3757. return err;
  3758. #endif /* WOLFSSL_SP_SMALL */
  3759. #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
  3760. }
  3761. #endif /* !WOLFSSL_RSA_PUBLIC_ONLY */
  3762. #endif /* WOLFSSL_HAVE_SP_RSA */
  3763. #if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \
  3764. !defined(WOLFSSL_RSA_PUBLIC_ONLY))
  3765. /* Convert an array of sp_digit to an mp_int.
  3766. *
  3767. * a A single precision integer.
  3768. * r A multi-precision integer.
  3769. */
  3770. static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
  3771. {
  3772. int err;
  3773. err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT);
  3774. if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
  3775. #if DIGIT_BIT == 29
  3776. XMEMCPY(r->dp, a, sizeof(sp_digit) * 72);
  3777. r->used = 72;
  3778. mp_clamp(r);
  3779. #elif DIGIT_BIT < 29
  3780. int i;
  3781. int j = 0;
  3782. int s = 0;
  3783. r->dp[0] = 0;
  3784. for (i = 0; i < 72; i++) {
  3785. r->dp[j] |= (mp_digit)(a[i] << s);
  3786. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  3787. s = DIGIT_BIT - s;
  3788. r->dp[++j] = (mp_digit)(a[i] >> s);
  3789. while (s + DIGIT_BIT <= 29) {
  3790. s += DIGIT_BIT;
  3791. r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  3792. if (s == SP_WORD_SIZE) {
  3793. r->dp[j] = 0;
  3794. }
  3795. else {
  3796. r->dp[j] = (mp_digit)(a[i] >> s);
  3797. }
  3798. }
  3799. s = 29 - s;
  3800. }
  3801. r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
  3802. mp_clamp(r);
  3803. #else
  3804. int i;
  3805. int j = 0;
  3806. int s = 0;
  3807. r->dp[0] = 0;
  3808. for (i = 0; i < 72; i++) {
  3809. r->dp[j] |= ((mp_digit)a[i]) << s;
  3810. if (s + 29 >= DIGIT_BIT) {
  3811. #if DIGIT_BIT != 32 && DIGIT_BIT != 64
  3812. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  3813. #endif
  3814. s = DIGIT_BIT - s;
  3815. r->dp[++j] = a[i] >> s;
  3816. s = 29 - s;
  3817. }
  3818. else {
  3819. s += 29;
  3820. }
  3821. }
  3822. r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
  3823. mp_clamp(r);
  3824. #endif
  3825. }
  3826. return err;
  3827. }
  3828. /* Perform the modular exponentiation for Diffie-Hellman.
  3829. *
  3830. * base Base. MP integer.
  3831. * exp Exponent. MP integer.
  3832. * mod Modulus. MP integer.
  3833. * res Result. MP integer.
  3834. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  3835. * and MEMORY_E if memory allocation fails.
  3836. */
  3837. int sp_ModExp_2048(const mp_int* base, const mp_int* exp, const mp_int* mod,
  3838. mp_int* res)
  3839. {
  3840. #ifdef WOLFSSL_SP_SMALL
  3841. int err = MP_OKAY;
  3842. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3843. sp_digit* b = NULL;
  3844. #else
  3845. sp_digit b[72 * 4];
  3846. #endif
  3847. sp_digit* e = NULL;
  3848. sp_digit* m = NULL;
  3849. sp_digit* r = NULL;
  3850. int expBits = mp_count_bits(exp);
  3851. if (mp_count_bits(base) > 2048) {
  3852. err = MP_READ_E;
  3853. }
  3854. else if (expBits > 2048) {
  3855. err = MP_READ_E;
  3856. }
  3857. else if (mp_count_bits(mod) != 2048) {
  3858. err = MP_READ_E;
  3859. }
  3860. else if (mp_iseven(mod)) {
  3861. err = MP_VAL;
  3862. }
  3863. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3864. if (err == MP_OKAY) {
  3865. b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 72 * 4, NULL,
  3866. DYNAMIC_TYPE_DH);
  3867. if (b == NULL)
  3868. err = MEMORY_E;
  3869. }
  3870. #endif
  3871. if (err == MP_OKAY) {
  3872. e = b + 72 * 2;
  3873. m = e + 72;
  3874. r = b;
  3875. sp_2048_from_mp(b, 72, base);
  3876. sp_2048_from_mp(e, 72, exp);
  3877. sp_2048_from_mp(m, 72, mod);
  3878. err = sp_2048_mod_exp_72(r, b, e, mp_count_bits(exp), m, 0);
  3879. }
  3880. if (err == MP_OKAY) {
  3881. err = sp_2048_to_mp(r, res);
  3882. }
  3883. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3884. if (b != NULL)
  3885. #endif
  3886. {
  3887. /* only "e" is sensitive and needs zeroized */
  3888. if (e != NULL)
  3889. ForceZero(e, sizeof(sp_digit) * 72U);
  3890. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3891. XFREE(b, NULL, DYNAMIC_TYPE_DH);
  3892. #endif
  3893. }
  3894. return err;
  3895. #else
  3896. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3897. sp_digit* b = NULL;
  3898. #else
  3899. sp_digit b[72 * 4];
  3900. #endif
  3901. sp_digit* e = NULL;
  3902. sp_digit* m = NULL;
  3903. sp_digit* r = NULL;
  3904. int err = MP_OKAY;
  3905. int expBits = mp_count_bits(exp);
  3906. if (mp_count_bits(base) > 2048) {
  3907. err = MP_READ_E;
  3908. }
  3909. else if (expBits > 2048) {
  3910. err = MP_READ_E;
  3911. }
  3912. else if (mp_count_bits(mod) != 2048) {
  3913. err = MP_READ_E;
  3914. }
  3915. else if (mp_iseven(mod)) {
  3916. err = MP_VAL;
  3917. }
  3918. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3919. if (err == MP_OKAY) {
  3920. b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 72 * 4, NULL, DYNAMIC_TYPE_DH);
  3921. if (b == NULL)
  3922. err = MEMORY_E;
  3923. }
  3924. #endif
  3925. if (err == MP_OKAY) {
  3926. e = b + 72 * 2;
  3927. m = e + 72;
  3928. r = b;
  3929. sp_2048_from_mp(b, 72, base);
  3930. sp_2048_from_mp(e, 72, exp);
  3931. sp_2048_from_mp(m, 72, mod);
  3932. err = sp_2048_mod_exp_72(r, b, e, expBits, m, 0);
  3933. }
  3934. if (err == MP_OKAY) {
  3935. err = sp_2048_to_mp(r, res);
  3936. }
  3937. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3938. if (b != NULL)
  3939. #endif
  3940. {
  3941. /* only "e" is sensitive and needs zeroized */
  3942. if (e != NULL)
  3943. ForceZero(e, sizeof(sp_digit) * 72U);
  3944. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  3945. XFREE(b, NULL, DYNAMIC_TYPE_DH);
  3946. #endif
  3947. }
  3948. return err;
  3949. #endif
  3950. }
  3951. #ifdef WOLFSSL_HAVE_SP_DH
  3952. #ifdef HAVE_FFDHE_2048
  3953. SP_NOINLINE static void sp_2048_lshift_72(sp_digit* r, const sp_digit* a,
  3954. byte n)
  3955. {
  3956. #ifdef WOLFSSL_SP_SMALL
  3957. int i;
  3958. r[72] = a[71] >> (29 - n);
  3959. for (i=71; i>0; i--) {
  3960. r[i] = ((a[i] << n) | (a[i-1] >> (29 - n))) & 0x1fffffff;
  3961. }
  3962. #else
  3963. sp_int_digit s;
  3964. sp_int_digit t;
  3965. s = (sp_int_digit)a[71];
  3966. r[72] = s >> (29U - n);
  3967. s = (sp_int_digit)(a[71]); t = (sp_int_digit)(a[70]);
  3968. r[71] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  3969. s = (sp_int_digit)(a[70]); t = (sp_int_digit)(a[69]);
  3970. r[70] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  3971. s = (sp_int_digit)(a[69]); t = (sp_int_digit)(a[68]);
  3972. r[69] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  3973. s = (sp_int_digit)(a[68]); t = (sp_int_digit)(a[67]);
  3974. r[68] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  3975. s = (sp_int_digit)(a[67]); t = (sp_int_digit)(a[66]);
  3976. r[67] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  3977. s = (sp_int_digit)(a[66]); t = (sp_int_digit)(a[65]);
  3978. r[66] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  3979. s = (sp_int_digit)(a[65]); t = (sp_int_digit)(a[64]);
  3980. r[65] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  3981. s = (sp_int_digit)(a[64]); t = (sp_int_digit)(a[63]);
  3982. r[64] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  3983. s = (sp_int_digit)(a[63]); t = (sp_int_digit)(a[62]);
  3984. r[63] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  3985. s = (sp_int_digit)(a[62]); t = (sp_int_digit)(a[61]);
  3986. r[62] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  3987. s = (sp_int_digit)(a[61]); t = (sp_int_digit)(a[60]);
  3988. r[61] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  3989. s = (sp_int_digit)(a[60]); t = (sp_int_digit)(a[59]);
  3990. r[60] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  3991. s = (sp_int_digit)(a[59]); t = (sp_int_digit)(a[58]);
  3992. r[59] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  3993. s = (sp_int_digit)(a[58]); t = (sp_int_digit)(a[57]);
  3994. r[58] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  3995. s = (sp_int_digit)(a[57]); t = (sp_int_digit)(a[56]);
  3996. r[57] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  3997. s = (sp_int_digit)(a[56]); t = (sp_int_digit)(a[55]);
  3998. r[56] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  3999. s = (sp_int_digit)(a[55]); t = (sp_int_digit)(a[54]);
  4000. r[55] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4001. s = (sp_int_digit)(a[54]); t = (sp_int_digit)(a[53]);
  4002. r[54] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4003. s = (sp_int_digit)(a[53]); t = (sp_int_digit)(a[52]);
  4004. r[53] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4005. s = (sp_int_digit)(a[52]); t = (sp_int_digit)(a[51]);
  4006. r[52] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4007. s = (sp_int_digit)(a[51]); t = (sp_int_digit)(a[50]);
  4008. r[51] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4009. s = (sp_int_digit)(a[50]); t = (sp_int_digit)(a[49]);
  4010. r[50] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4011. s = (sp_int_digit)(a[49]); t = (sp_int_digit)(a[48]);
  4012. r[49] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4013. s = (sp_int_digit)(a[48]); t = (sp_int_digit)(a[47]);
  4014. r[48] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4015. s = (sp_int_digit)(a[47]); t = (sp_int_digit)(a[46]);
  4016. r[47] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4017. s = (sp_int_digit)(a[46]); t = (sp_int_digit)(a[45]);
  4018. r[46] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4019. s = (sp_int_digit)(a[45]); t = (sp_int_digit)(a[44]);
  4020. r[45] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4021. s = (sp_int_digit)(a[44]); t = (sp_int_digit)(a[43]);
  4022. r[44] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4023. s = (sp_int_digit)(a[43]); t = (sp_int_digit)(a[42]);
  4024. r[43] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4025. s = (sp_int_digit)(a[42]); t = (sp_int_digit)(a[41]);
  4026. r[42] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4027. s = (sp_int_digit)(a[41]); t = (sp_int_digit)(a[40]);
  4028. r[41] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4029. s = (sp_int_digit)(a[40]); t = (sp_int_digit)(a[39]);
  4030. r[40] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4031. s = (sp_int_digit)(a[39]); t = (sp_int_digit)(a[38]);
  4032. r[39] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4033. s = (sp_int_digit)(a[38]); t = (sp_int_digit)(a[37]);
  4034. r[38] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4035. s = (sp_int_digit)(a[37]); t = (sp_int_digit)(a[36]);
  4036. r[37] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4037. s = (sp_int_digit)(a[36]); t = (sp_int_digit)(a[35]);
  4038. r[36] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4039. s = (sp_int_digit)(a[35]); t = (sp_int_digit)(a[34]);
  4040. r[35] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4041. s = (sp_int_digit)(a[34]); t = (sp_int_digit)(a[33]);
  4042. r[34] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4043. s = (sp_int_digit)(a[33]); t = (sp_int_digit)(a[32]);
  4044. r[33] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4045. s = (sp_int_digit)(a[32]); t = (sp_int_digit)(a[31]);
  4046. r[32] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4047. s = (sp_int_digit)(a[31]); t = (sp_int_digit)(a[30]);
  4048. r[31] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4049. s = (sp_int_digit)(a[30]); t = (sp_int_digit)(a[29]);
  4050. r[30] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4051. s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]);
  4052. r[29] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4053. s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]);
  4054. r[28] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4055. s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]);
  4056. r[27] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4057. s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]);
  4058. r[26] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4059. s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]);
  4060. r[25] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4061. s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]);
  4062. r[24] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4063. s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]);
  4064. r[23] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4065. s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]);
  4066. r[22] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4067. s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]);
  4068. r[21] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4069. s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]);
  4070. r[20] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4071. s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]);
  4072. r[19] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4073. s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]);
  4074. r[18] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4075. s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]);
  4076. r[17] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4077. s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]);
  4078. r[16] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4079. s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]);
  4080. r[15] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4081. s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]);
  4082. r[14] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4083. s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]);
  4084. r[13] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4085. s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]);
  4086. r[12] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4087. s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]);
  4088. r[11] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4089. s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]);
  4090. r[10] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4091. s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]);
  4092. r[9] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4093. s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]);
  4094. r[8] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4095. s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]);
  4096. r[7] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4097. s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]);
  4098. r[6] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4099. s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]);
  4100. r[5] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4101. s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]);
  4102. r[4] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4103. s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]);
  4104. r[3] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4105. s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]);
  4106. r[2] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4107. s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]);
  4108. r[1] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  4109. #endif /* WOLFSSL_SP_SMALL */
  4110. r[0] = (a[0] << n) & 0x1fffffff;
  4111. }
  4112. /* Modular exponentiate 2 to the e mod m. (r = 2^e mod m)
  4113. *
  4114. * r A single precision number that is the result of the operation.
  4115. * e A single precision number that is the exponent.
  4116. * bits The number of bits in the exponent.
  4117. * m A single precision number that is the modulus.
  4118. * returns 0 on success.
  4119. * returns MEMORY_E on dynamic memory allocation failure.
  4120. * returns MP_VAL when base is even.
  4121. */
  4122. static int sp_2048_mod_exp_2_72(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m)
  4123. {
  4124. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  4125. sp_digit* td = NULL;
  4126. #else
  4127. sp_digit td[217];
  4128. #endif
  4129. sp_digit* norm = NULL;
  4130. sp_digit* tmp = NULL;
  4131. sp_digit mp = 1;
  4132. sp_digit n;
  4133. sp_digit o;
  4134. int i;
  4135. int c;
  4136. byte y;
  4137. int err = MP_OKAY;
  4138. if (bits == 0) {
  4139. err = MP_VAL;
  4140. }
  4141. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  4142. if (err == MP_OKAY) {
  4143. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 217, NULL,
  4144. DYNAMIC_TYPE_TMP_BUFFER);
  4145. if (td == NULL)
  4146. err = MEMORY_E;
  4147. }
  4148. #endif
  4149. if (err == MP_OKAY) {
  4150. norm = td;
  4151. tmp = td + 144;
  4152. XMEMSET(td, 0, sizeof(sp_digit) * 217);
  4153. sp_2048_mont_setup(m, &mp);
  4154. sp_2048_mont_norm_72(norm, m);
  4155. bits = ((bits + 3) / 4) * 4;
  4156. i = ((bits + 28) / 29) - 1;
  4157. c = bits % 29;
  4158. if (c == 0) {
  4159. c = 29;
  4160. }
  4161. if (i < 72) {
  4162. n = e[i--] << (32 - c);
  4163. }
  4164. else {
  4165. n = 0;
  4166. i--;
  4167. }
  4168. if (c < 4) {
  4169. n |= e[i--] << (3 - c);
  4170. c += 29;
  4171. }
  4172. y = (int)((n >> 28) & 0xf);
  4173. n <<= 4;
  4174. c -= 4;
  4175. sp_2048_lshift_72(r, norm, (byte)y);
  4176. while ((i >= 0) || (c >= 4)) {
  4177. if (c >= 4) {
  4178. y = (byte)((n >> 28) & 0xf);
  4179. n <<= 4;
  4180. c -= 4;
  4181. }
  4182. else if (c == 0) {
  4183. n = e[i--] << 3;
  4184. y = (byte)((n >> 28) & 0xf);
  4185. n <<= 4;
  4186. c = 25;
  4187. }
  4188. else {
  4189. y = (byte)((n >> 28) & 0xf);
  4190. n = e[i--] << 3;
  4191. c = 4 - c;
  4192. y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
  4193. n <<= c;
  4194. c = 29 - c;
  4195. }
  4196. sp_2048_mont_sqr_72(r, r, m, mp);
  4197. sp_2048_mont_sqr_72(r, r, m, mp);
  4198. sp_2048_mont_sqr_72(r, r, m, mp);
  4199. sp_2048_mont_sqr_72(r, r, m, mp);
  4200. sp_2048_lshift_72(r, r, (byte)y);
  4201. sp_2048_mul_d_72(tmp, norm, (r[71] << 11) + (r[70] >> 18));
  4202. r[71] = 0;
  4203. r[70] &= 0x3ffffL;
  4204. (void)sp_2048_add_72(r, r, tmp);
  4205. sp_2048_norm_72(r);
  4206. o = sp_2048_cmp_72(r, m);
  4207. sp_2048_cond_sub_72(r, r, m, ~(o >> 31));
  4208. }
  4209. sp_2048_mont_reduce_72(r, m, mp);
  4210. n = sp_2048_cmp_72(r, m);
  4211. sp_2048_cond_sub_72(r, r, m, ~(n >> 31));
  4212. }
  4213. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  4214. if (td != NULL)
  4215. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  4216. #endif
  4217. return err;
  4218. }
  4219. #endif /* HAVE_FFDHE_2048 */
  4220. /* Perform the modular exponentiation for Diffie-Hellman.
  4221. *
  4222. * base Base.
  4223. * exp Array of bytes that is the exponent.
  4224. * expLen Length of data, in bytes, in exponent.
  4225. * mod Modulus.
  4226. * out Buffer to hold big-endian bytes of exponentiation result.
  4227. * Must be at least 256 bytes long.
  4228. * outLen Length, in bytes, of exponentiation result.
  4229. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  4230. * and MEMORY_E if memory allocation fails.
  4231. */
  4232. int sp_DhExp_2048(const mp_int* base, const byte* exp, word32 expLen,
  4233. const mp_int* mod, byte* out, word32* outLen)
  4234. {
  4235. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  4236. sp_digit* b = NULL;
  4237. #else
  4238. sp_digit b[72 * 4];
  4239. #endif
  4240. sp_digit* e = NULL;
  4241. sp_digit* m = NULL;
  4242. sp_digit* r = NULL;
  4243. word32 i;
  4244. int err = MP_OKAY;
  4245. if (mp_count_bits(base) > 2048) {
  4246. err = MP_READ_E;
  4247. }
  4248. else if (expLen > 256U) {
  4249. err = MP_READ_E;
  4250. }
  4251. else if (mp_count_bits(mod) != 2048) {
  4252. err = MP_READ_E;
  4253. }
  4254. else if (mp_iseven(mod)) {
  4255. err = MP_VAL;
  4256. }
  4257. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  4258. if (err == MP_OKAY) {
  4259. b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 72 * 4, NULL,
  4260. DYNAMIC_TYPE_DH);
  4261. if (b == NULL)
  4262. err = MEMORY_E;
  4263. }
  4264. #endif
  4265. if (err == MP_OKAY) {
  4266. e = b + 72 * 2;
  4267. m = e + 72;
  4268. r = b;
  4269. sp_2048_from_mp(b, 72, base);
  4270. sp_2048_from_bin(e, 72, exp, expLen);
  4271. sp_2048_from_mp(m, 72, mod);
  4272. #ifdef HAVE_FFDHE_2048
  4273. if (base->used == 1 && base->dp[0] == 2U &&
  4274. (m[70] >> 2) == 0xffffL) {
  4275. err = sp_2048_mod_exp_2_72(r, e, expLen * 8U, m);
  4276. }
  4277. else {
  4278. #endif
  4279. err = sp_2048_mod_exp_72(r, b, e, expLen * 8U, m, 0);
  4280. #ifdef HAVE_FFDHE_2048
  4281. }
  4282. #endif
  4283. }
  4284. if (err == MP_OKAY) {
  4285. sp_2048_to_bin_72(r, out);
  4286. *outLen = 256;
  4287. for (i=0; i<256U && out[i] == 0U; i++) {
  4288. /* Search for first non-zero. */
  4289. }
  4290. *outLen -= i;
  4291. XMEMMOVE(out, out + i, *outLen);
  4292. }
  4293. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  4294. if (b != NULL)
  4295. #endif
  4296. {
  4297. /* only "e" is sensitive and needs zeroized */
  4298. if (e != NULL)
  4299. ForceZero(e, sizeof(sp_digit) * 72U);
  4300. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  4301. XFREE(b, NULL, DYNAMIC_TYPE_DH);
  4302. #endif
  4303. }
  4304. return err;
  4305. }
  4306. #endif /* WOLFSSL_HAVE_SP_DH */
  4307. /* Perform the modular exponentiation for Diffie-Hellman.
  4308. *
  4309. * base Base. MP integer.
  4310. * exp Exponent. MP integer.
  4311. * mod Modulus. MP integer.
  4312. * res Result. MP integer.
  4313. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  4314. * and MEMORY_E if memory allocation fails.
  4315. */
  4316. int sp_ModExp_1024(const mp_int* base, const mp_int* exp, const mp_int* mod,
  4317. mp_int* res)
  4318. {
  4319. #ifdef WOLFSSL_SP_SMALL
  4320. int err = MP_OKAY;
  4321. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  4322. sp_digit* b = NULL;
  4323. #else
  4324. sp_digit b[36 * 4];
  4325. #endif
  4326. sp_digit* e = NULL;
  4327. sp_digit* m = NULL;
  4328. sp_digit* r = NULL;
  4329. int expBits = mp_count_bits(exp);
  4330. if (mp_count_bits(base) > 1024) {
  4331. err = MP_READ_E;
  4332. }
  4333. else if (expBits > 1024) {
  4334. err = MP_READ_E;
  4335. }
  4336. else if (mp_count_bits(mod) != 1024) {
  4337. err = MP_READ_E;
  4338. }
  4339. else if (mp_iseven(mod)) {
  4340. err = MP_VAL;
  4341. }
  4342. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  4343. if (err == MP_OKAY) {
  4344. b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 4, NULL,
  4345. DYNAMIC_TYPE_DH);
  4346. if (b == NULL)
  4347. err = MEMORY_E;
  4348. }
  4349. #endif
  4350. if (err == MP_OKAY) {
  4351. e = b + 36 * 2;
  4352. m = e + 36;
  4353. r = b;
  4354. sp_2048_from_mp(b, 36, base);
  4355. sp_2048_from_mp(e, 36, exp);
  4356. sp_2048_from_mp(m, 36, mod);
  4357. err = sp_2048_mod_exp_36(r, b, e, mp_count_bits(exp), m, 0);
  4358. }
  4359. if (err == MP_OKAY) {
  4360. XMEMSET(r + 36, 0, sizeof(*r) * 36U);
  4361. err = sp_2048_to_mp(r, res);
  4362. }
  4363. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  4364. if (b != NULL)
  4365. #endif
  4366. {
  4367. /* only "e" is sensitive and needs zeroized */
  4368. if (e != NULL)
  4369. ForceZero(e, sizeof(sp_digit) * 72U);
  4370. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  4371. XFREE(b, NULL, DYNAMIC_TYPE_DH);
  4372. #endif
  4373. }
  4374. return err;
  4375. #else
  4376. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  4377. sp_digit* b = NULL;
  4378. #else
  4379. sp_digit b[36 * 4];
  4380. #endif
  4381. sp_digit* e = NULL;
  4382. sp_digit* m = NULL;
  4383. sp_digit* r = NULL;
  4384. int err = MP_OKAY;
  4385. int expBits = mp_count_bits(exp);
  4386. if (mp_count_bits(base) > 1024) {
  4387. err = MP_READ_E;
  4388. }
  4389. else if (expBits > 1024) {
  4390. err = MP_READ_E;
  4391. }
  4392. else if (mp_count_bits(mod) != 1024) {
  4393. err = MP_READ_E;
  4394. }
  4395. else if (mp_iseven(mod)) {
  4396. err = MP_VAL;
  4397. }
  4398. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  4399. if (err == MP_OKAY) {
  4400. b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 4, NULL, DYNAMIC_TYPE_DH);
  4401. if (b == NULL)
  4402. err = MEMORY_E;
  4403. }
  4404. #endif
  4405. if (err == MP_OKAY) {
  4406. e = b + 36 * 2;
  4407. m = e + 36;
  4408. r = b;
  4409. sp_2048_from_mp(b, 36, base);
  4410. sp_2048_from_mp(e, 36, exp);
  4411. sp_2048_from_mp(m, 36, mod);
  4412. err = sp_2048_mod_exp_36(r, b, e, expBits, m, 0);
  4413. }
  4414. if (err == MP_OKAY) {
  4415. XMEMSET(r + 36, 0, sizeof(*r) * 36U);
  4416. err = sp_2048_to_mp(r, res);
  4417. }
  4418. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  4419. if (b != NULL)
  4420. #endif
  4421. {
  4422. /* only "e" is sensitive and needs zeroized */
  4423. if (e != NULL)
  4424. ForceZero(e, sizeof(sp_digit) * 72U);
  4425. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  4426. XFREE(b, NULL, DYNAMIC_TYPE_DH);
  4427. #endif
  4428. }
  4429. return err;
  4430. #endif
  4431. }
  4432. #endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
  4433. #endif /* !WOLFSSL_SP_NO_2048 */
  4434. #ifndef WOLFSSL_SP_NO_3072
  4435. #ifdef WOLFSSL_SP_SMALL
  4436. /* Read big endian unsigned byte array into r.
  4437. *
  4438. * r A single precision integer.
  4439. * size Maximum number of bytes to convert
  4440. * a Byte array.
  4441. * n Number of bytes in array to read.
  4442. */
  4443. static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n)
  4444. {
  4445. int i;
  4446. int j = 0;
  4447. word32 s = 0;
  4448. r[0] = 0;
  4449. for (i = n-1; i >= 0; i--) {
  4450. r[j] |= (((sp_digit)a[i]) << s);
  4451. if (s >= 21U) {
  4452. r[j] &= 0x1fffffff;
  4453. s = 29U - s;
  4454. if (j + 1 >= size) {
  4455. break;
  4456. }
  4457. r[++j] = (sp_digit)a[i] >> s;
  4458. s = 8U - s;
  4459. }
  4460. else {
  4461. s += 8U;
  4462. }
  4463. }
  4464. for (j++; j < size; j++) {
  4465. r[j] = 0;
  4466. }
  4467. }
  4468. /* Convert an mp_int to an array of sp_digit.
  4469. *
  4470. * r A single precision integer.
  4471. * size Maximum number of bytes to convert
  4472. * a A multi-precision integer.
  4473. */
  4474. static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
  4475. {
  4476. #if DIGIT_BIT == 29
  4477. int j;
  4478. XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
  4479. for (j = a->used; j < size; j++) {
  4480. r[j] = 0;
  4481. }
  4482. #elif DIGIT_BIT > 29
  4483. int i;
  4484. int j = 0;
  4485. word32 s = 0;
  4486. r[0] = 0;
  4487. for (i = 0; i < a->used && j < size; i++) {
  4488. r[j] |= ((sp_digit)a->dp[i] << s);
  4489. r[j] &= 0x1fffffff;
  4490. s = 29U - s;
  4491. if (j + 1 >= size) {
  4492. break;
  4493. }
  4494. /* lint allow cast of mismatch word32 and mp_digit */
  4495. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  4496. while ((s + 29U) <= (word32)DIGIT_BIT) {
  4497. s += 29U;
  4498. r[j] &= 0x1fffffff;
  4499. if (j + 1 >= size) {
  4500. break;
  4501. }
  4502. if (s < (word32)DIGIT_BIT) {
  4503. /* lint allow cast of mismatch word32 and mp_digit */
  4504. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  4505. }
  4506. else {
  4507. r[++j] = (sp_digit)0;
  4508. }
  4509. }
  4510. s = (word32)DIGIT_BIT - s;
  4511. }
  4512. for (j++; j < size; j++) {
  4513. r[j] = 0;
  4514. }
  4515. #else
  4516. int i;
  4517. int j = 0;
  4518. int s = 0;
  4519. r[0] = 0;
  4520. for (i = 0; i < a->used && j < size; i++) {
  4521. r[j] |= ((sp_digit)a->dp[i]) << s;
  4522. if (s + DIGIT_BIT >= 29) {
  4523. r[j] &= 0x1fffffff;
  4524. if (j + 1 >= size) {
  4525. break;
  4526. }
  4527. s = 29 - s;
  4528. if (s == DIGIT_BIT) {
  4529. r[++j] = 0;
  4530. s = 0;
  4531. }
  4532. else {
  4533. r[++j] = a->dp[i] >> s;
  4534. s = DIGIT_BIT - s;
  4535. }
  4536. }
  4537. else {
  4538. s += DIGIT_BIT;
  4539. }
  4540. }
  4541. for (j++; j < size; j++) {
  4542. r[j] = 0;
  4543. }
  4544. #endif
  4545. }
  4546. /* Write r as big endian to byte array.
  4547. * Fixed length number of bytes written: 384
  4548. *
  4549. * r A single precision integer.
  4550. * a Byte array.
  4551. */
  4552. static void sp_3072_to_bin_106(sp_digit* r, byte* a)
  4553. {
  4554. int i;
  4555. int j;
  4556. int s = 0;
  4557. int b;
  4558. for (i=0; i<105; i++) {
  4559. r[i+1] += r[i] >> 29;
  4560. r[i] &= 0x1fffffff;
  4561. }
  4562. j = 3079 / 8 - 1;
  4563. a[j] = 0;
  4564. for (i=0; i<106 && j>=0; i++) {
  4565. b = 0;
  4566. /* lint allow cast of mismatch sp_digit and int */
  4567. a[j--] |= (byte)(r[i] << s); /*lint !e9033*/
  4568. b += 8 - s;
  4569. if (j < 0) {
  4570. break;
  4571. }
  4572. while (b < 29) {
  4573. a[j--] = (byte)(r[i] >> b);
  4574. b += 8;
  4575. if (j < 0) {
  4576. break;
  4577. }
  4578. }
  4579. s = 8 - (b - 29);
  4580. if (j >= 0) {
  4581. a[j] = 0;
  4582. }
  4583. if (s != 0) {
  4584. j++;
  4585. }
  4586. }
  4587. }
  4588. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  4589. /* Normalize the values in each word to 29 bits.
  4590. *
  4591. * a Array of sp_digit to normalize.
  4592. */
  4593. static void sp_3072_norm_53(sp_digit* a)
  4594. {
  4595. int i;
  4596. for (i = 0; i < 52; i++) {
  4597. a[i+1] += a[i] >> 29;
  4598. a[i] &= 0x1fffffff;
  4599. }
  4600. }
  4601. #endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
  4602. /* Normalize the values in each word to 29 bits.
  4603. *
  4604. * a Array of sp_digit to normalize.
  4605. */
  4606. static void sp_3072_norm_106(sp_digit* a)
  4607. {
  4608. int i;
  4609. for (i = 0; i < 105; i++) {
  4610. a[i+1] += a[i] >> 29;
  4611. a[i] &= 0x1fffffff;
  4612. }
  4613. }
  4614. /* Multiply a and b into r. (r = a * b)
  4615. *
  4616. * r A single precision integer.
  4617. * a A single precision integer.
  4618. * b A single precision integer.
  4619. */
  4620. SP_NOINLINE static void sp_3072_mul_106(sp_digit* r, const sp_digit* a,
  4621. const sp_digit* b)
  4622. {
  4623. int i;
  4624. int imax;
  4625. int k;
  4626. sp_uint64 c;
  4627. sp_uint64 lo;
  4628. c = ((sp_uint64)a[105]) * b[105];
  4629. r[211] = (sp_digit)(c >> 29);
  4630. c &= 0x1fffffff;
  4631. for (k = 209; k >= 0; k--) {
  4632. if (k >= 106) {
  4633. i = k - 105;
  4634. imax = 105;
  4635. }
  4636. else {
  4637. i = 0;
  4638. imax = k;
  4639. }
  4640. if (imax - i > 15) {
  4641. int imaxlo;
  4642. lo = 0;
  4643. for (imaxlo = i; imaxlo <= imax; imaxlo += 15) {
  4644. for (; i <= imax && i < imaxlo + 15; i++) {
  4645. lo += ((sp_uint64)a[i]) * b[k - i];
  4646. }
  4647. c += lo >> 29;
  4648. lo &= 0x1fffffff;
  4649. }
  4650. r[k + 2] += (sp_digit)(c >> 29);
  4651. r[k + 1] = (sp_digit)(c & 0x1fffffff);
  4652. c = lo & 0x1fffffff;
  4653. }
  4654. else {
  4655. lo = 0;
  4656. for (; i <= imax; i++) {
  4657. lo += ((sp_uint64)a[i]) * b[k - i];
  4658. }
  4659. c += lo >> 29;
  4660. r[k + 2] += (sp_digit)(c >> 29);
  4661. r[k + 1] = (sp_digit)(c & 0x1fffffff);
  4662. c = lo & 0x1fffffff;
  4663. }
  4664. }
  4665. r[0] = (sp_digit)c;
  4666. }
  4667. /* Square a and put result in r. (r = a * a)
  4668. *
  4669. * r A single precision integer.
  4670. * a A single precision integer.
  4671. */
  4672. SP_NOINLINE static void sp_3072_sqr_106(sp_digit* r, const sp_digit* a)
  4673. {
  4674. int i;
  4675. int imax;
  4676. int k;
  4677. sp_uint64 c;
  4678. sp_uint64 t;
  4679. c = ((sp_uint64)a[105]) * a[105];
  4680. r[211] = (sp_digit)(c >> 29);
  4681. c = (c & 0x1fffffff) << 29;
  4682. for (k = 209; k >= 0; k--) {
  4683. i = (k + 1) / 2;
  4684. if ((k & 1) == 0) {
  4685. c += ((sp_uint64)a[i]) * a[i];
  4686. i++;
  4687. }
  4688. if (k < 105) {
  4689. imax = k;
  4690. }
  4691. else {
  4692. imax = 105;
  4693. }
  4694. if (imax - i >= 14) {
  4695. int imaxlo;
  4696. sp_uint64 hi;
  4697. hi = c >> 29;
  4698. c &= 0x1fffffff;
  4699. for (imaxlo = i; imaxlo <= imax; imaxlo += 14) {
  4700. t = 0;
  4701. for (; i <= imax && i < imaxlo + 14; i++) {
  4702. t += ((sp_uint64)a[i]) * a[k - i];
  4703. }
  4704. c += t * 2;
  4705. hi += c >> 29;
  4706. c &= 0x1fffffff;
  4707. }
  4708. r[k + 2] += (sp_digit)(hi >> 29);
  4709. r[k + 1] = (sp_digit)(hi & 0x1fffffff);
  4710. c <<= 29;
  4711. }
  4712. else
  4713. {
  4714. t = 0;
  4715. for (; i <= imax; i++) {
  4716. t += ((sp_uint64)a[i]) * a[k - i];
  4717. }
  4718. c += t * 2;
  4719. r[k + 2] += (sp_digit) (c >> 58);
  4720. r[k + 1] = (sp_digit)((c >> 29) & 0x1fffffff);
  4721. c = (c & 0x1fffffff) << 29;
  4722. }
  4723. }
  4724. r[0] = (sp_digit)(c >> 29);
  4725. }
  4726. /* Caclulate the bottom digit of -1/a mod 2^n.
  4727. *
  4728. * a A single precision number.
  4729. * rho Bottom word of inverse.
  4730. */
  4731. static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho)
  4732. {
  4733. sp_digit x;
  4734. sp_digit b;
  4735. b = a[0];
  4736. x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
  4737. x *= 2 - b * x; /* here x*a==1 mod 2**8 */
  4738. x *= 2 - b * x; /* here x*a==1 mod 2**16 */
  4739. x *= 2 - b * x; /* here x*a==1 mod 2**32 */
  4740. x &= 0x1fffffff;
  4741. /* rho = -1/m mod b */
  4742. *rho = ((sp_digit)1 << 29) - x;
  4743. }
  4744. /* Multiply a by scalar b into r. (r = a * b)
  4745. *
  4746. * r A single precision integer.
  4747. * a A single precision integer.
  4748. * b A scalar.
  4749. */
  4750. SP_NOINLINE static void sp_3072_mul_d_106(sp_digit* r, const sp_digit* a,
  4751. sp_digit b)
  4752. {
  4753. sp_int64 tb = b;
  4754. sp_int64 t = 0;
  4755. int i;
  4756. for (i = 0; i < 106; i++) {
  4757. t += tb * a[i];
  4758. r[i] = (sp_digit)(t & 0x1fffffff);
  4759. t >>= 29;
  4760. }
  4761. r[106] = (sp_digit)t;
  4762. }
  4763. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  4764. /* Sub b from a into r. (r = a - b)
  4765. *
  4766. * r A single precision integer.
  4767. * a A single precision integer.
  4768. * b A single precision integer.
  4769. */
  4770. SP_NOINLINE static int sp_3072_sub_53(sp_digit* r, const sp_digit* a,
  4771. const sp_digit* b)
  4772. {
  4773. int i;
  4774. for (i = 0; i < 53; i++) {
  4775. r[i] = a[i] - b[i];
  4776. }
  4777. return 0;
  4778. }
  4779. /* r = 2^n mod m where n is the number of bits to reduce by.
  4780. * Given m must be 3072 bits, just need to subtract.
  4781. *
  4782. * r A single precision number.
  4783. * m A single precision number.
  4784. */
  4785. static void sp_3072_mont_norm_53(sp_digit* r, const sp_digit* m)
  4786. {
  4787. /* Set r = 2^n - 1. */
  4788. int i;
  4789. for (i=0; i<52; i++) {
  4790. r[i] = 0x1fffffff;
  4791. }
  4792. r[52] = 0xfffffffL;
  4793. /* r = (2^n - 1) mod n */
  4794. (void)sp_3072_sub_53(r, r, m);
  4795. /* Add one so r = 2^n mod m */
  4796. r[0] += 1;
  4797. }
  4798. /* Compare a with b in constant time.
  4799. *
  4800. * a A single precision integer.
  4801. * b A single precision integer.
  4802. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  4803. * respectively.
  4804. */
  4805. static sp_digit sp_3072_cmp_53(const sp_digit* a, const sp_digit* b)
  4806. {
  4807. sp_digit r = 0;
  4808. int i;
  4809. for (i=52; i>=0; i--) {
  4810. r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 28);
  4811. }
  4812. return r;
  4813. }
  4814. /* Conditionally subtract b from a using the mask m.
  4815. * m is -1 to subtract and 0 when not.
  4816. *
  4817. * r A single precision number representing condition subtract result.
  4818. * a A single precision number to subtract from.
  4819. * b A single precision number to subtract.
  4820. * m Mask value to apply.
  4821. */
  4822. static void sp_3072_cond_sub_53(sp_digit* r, const sp_digit* a,
  4823. const sp_digit* b, const sp_digit m)
  4824. {
  4825. int i;
  4826. for (i = 0; i < 53; i++) {
  4827. r[i] = a[i] - (b[i] & m);
  4828. }
  4829. }
  4830. /* Mul a by scalar b and add into r. (r += a * b)
  4831. *
  4832. * r A single precision integer.
  4833. * a A single precision integer.
  4834. * b A scalar.
  4835. */
  4836. SP_NOINLINE static void sp_3072_mul_add_53(sp_digit* r, const sp_digit* a,
  4837. const sp_digit b)
  4838. {
  4839. #ifndef WOLFSSL_SP_LARGE_CODE
  4840. sp_int64 tb = b;
  4841. sp_int64 t = 0;
  4842. int i;
  4843. for (i = 0; i < 53; i++) {
  4844. t += r[i];
  4845. t += tb * a[i];
  4846. r[i] = ((sp_digit)t) & 0x1fffffff;
  4847. t >>= 29;
  4848. }
  4849. r[53] += (sp_digit)t;
  4850. #else
  4851. sp_int64 tb = b;
  4852. sp_int64 t[4];
  4853. int i;
  4854. t[0] = 0;
  4855. for (i = 0; i < 52; i += 4) {
  4856. t[0] += (tb * a[i+0]) + r[i+0];
  4857. t[1] = (tb * a[i+1]) + r[i+1];
  4858. t[2] = (tb * a[i+2]) + r[i+2];
  4859. t[3] = (tb * a[i+3]) + r[i+3];
  4860. r[i+0] = t[0] & 0x1fffffff;
  4861. t[1] += t[0] >> 29;
  4862. r[i+1] = t[1] & 0x1fffffff;
  4863. t[2] += t[1] >> 29;
  4864. r[i+2] = t[2] & 0x1fffffff;
  4865. t[3] += t[2] >> 29;
  4866. r[i+3] = t[3] & 0x1fffffff;
  4867. t[0] = t[3] >> 29;
  4868. }
  4869. t[0] += (tb * a[52]) + r[52];
  4870. r[52] = t[0] & 0x1fffffff;
  4871. r[53] += (sp_digit)(t[0] >> 29);
  4872. #endif /* !WOLFSSL_SP_LARGE_CODE */
  4873. }
  4874. /* Shift the result in the high 1536 bits down to the bottom.
  4875. *
  4876. * r A single precision number.
  4877. * a A single precision number.
  4878. */
  4879. static void sp_3072_mont_shift_53(sp_digit* r, const sp_digit* a)
  4880. {
  4881. int i;
  4882. sp_int64 n = a[52] >> 28;
  4883. n += ((sp_int64)a[53]) << 1;
  4884. for (i = 0; i < 52; i++) {
  4885. r[i] = n & 0x1fffffff;
  4886. n >>= 29;
  4887. n += ((sp_int64)a[54 + i]) << 1;
  4888. }
  4889. r[52] = (sp_digit)n;
  4890. XMEMSET(&r[53], 0, sizeof(*r) * 53U);
  4891. }
  4892. /* Reduce the number back to 3072 bits using Montgomery reduction.
  4893. *
  4894. * a A single precision number to reduce in place.
  4895. * m The single precision number representing the modulus.
  4896. * mp The digit representing the negative inverse of m mod 2^n.
  4897. */
  4898. static void sp_3072_mont_reduce_53(sp_digit* a, const sp_digit* m, sp_digit mp)
  4899. {
  4900. int i;
  4901. sp_digit mu;
  4902. sp_digit over;
  4903. sp_3072_norm_53(a + 53);
  4904. for (i=0; i<52; i++) {
  4905. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff;
  4906. sp_3072_mul_add_53(a+i, m, mu);
  4907. a[i+1] += a[i] >> 29;
  4908. }
  4909. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffffL;
  4910. sp_3072_mul_add_53(a+i, m, mu);
  4911. a[i+1] += a[i] >> 29;
  4912. a[i] &= 0x1fffffff;
  4913. sp_3072_mont_shift_53(a, a);
  4914. over = a[52] - m[52];
  4915. sp_3072_cond_sub_53(a, a, m, ~((over - 1) >> 31));
  4916. sp_3072_norm_53(a);
  4917. }
  4918. /* Multiply a and b into r. (r = a * b)
  4919. *
  4920. * r A single precision integer.
  4921. * a A single precision integer.
  4922. * b A single precision integer.
  4923. */
  4924. SP_NOINLINE static void sp_3072_mul_53(sp_digit* r, const sp_digit* a,
  4925. const sp_digit* b)
  4926. {
  4927. int i;
  4928. int imax;
  4929. int k;
  4930. sp_uint64 c;
  4931. sp_uint64 lo;
  4932. c = ((sp_uint64)a[52]) * b[52];
  4933. r[105] = (sp_digit)(c >> 29);
  4934. c &= 0x1fffffff;
  4935. for (k = 103; k >= 0; k--) {
  4936. if (k >= 53) {
  4937. i = k - 52;
  4938. imax = 52;
  4939. }
  4940. else {
  4941. i = 0;
  4942. imax = k;
  4943. }
  4944. if (imax - i > 15) {
  4945. int imaxlo;
  4946. lo = 0;
  4947. for (imaxlo = i; imaxlo <= imax; imaxlo += 15) {
  4948. for (; i <= imax && i < imaxlo + 15; i++) {
  4949. lo += ((sp_uint64)a[i]) * b[k - i];
  4950. }
  4951. c += lo >> 29;
  4952. lo &= 0x1fffffff;
  4953. }
  4954. r[k + 2] += (sp_digit)(c >> 29);
  4955. r[k + 1] = (sp_digit)(c & 0x1fffffff);
  4956. c = lo & 0x1fffffff;
  4957. }
  4958. else {
  4959. lo = 0;
  4960. for (; i <= imax; i++) {
  4961. lo += ((sp_uint64)a[i]) * b[k - i];
  4962. }
  4963. c += lo >> 29;
  4964. r[k + 2] += (sp_digit)(c >> 29);
  4965. r[k + 1] = (sp_digit)(c & 0x1fffffff);
  4966. c = lo & 0x1fffffff;
  4967. }
  4968. }
  4969. r[0] = (sp_digit)c;
  4970. }
  4971. /* Multiply two Montgomery form numbers mod the modulus (prime).
  4972. * (r = a * b mod m)
  4973. *
  4974. * r Result of multiplication.
  4975. * a First number to multiply in Montgomery form.
  4976. * b Second number to multiply in Montgomery form.
  4977. * m Modulus (prime).
  4978. * mp Montgomery mulitplier.
  4979. */
  4980. SP_NOINLINE static void sp_3072_mont_mul_53(sp_digit* r, const sp_digit* a,
  4981. const sp_digit* b, const sp_digit* m, sp_digit mp)
  4982. {
  4983. sp_3072_mul_53(r, a, b);
  4984. sp_3072_mont_reduce_53(r, m, mp);
  4985. }
  4986. /* Square a and put result in r. (r = a * a)
  4987. *
  4988. * r A single precision integer.
  4989. * a A single precision integer.
  4990. */
  4991. SP_NOINLINE static void sp_3072_sqr_53(sp_digit* r, const sp_digit* a)
  4992. {
  4993. int i;
  4994. int imax;
  4995. int k;
  4996. sp_uint64 c;
  4997. sp_uint64 t;
  4998. c = ((sp_uint64)a[52]) * a[52];
  4999. r[105] = (sp_digit)(c >> 29);
  5000. c = (c & 0x1fffffff) << 29;
  5001. for (k = 103; k >= 0; k--) {
  5002. i = (k + 1) / 2;
  5003. if ((k & 1) == 0) {
  5004. c += ((sp_uint64)a[i]) * a[i];
  5005. i++;
  5006. }
  5007. if (k < 52) {
  5008. imax = k;
  5009. }
  5010. else {
  5011. imax = 52;
  5012. }
  5013. if (imax - i >= 14) {
  5014. int imaxlo;
  5015. sp_uint64 hi;
  5016. hi = c >> 29;
  5017. c &= 0x1fffffff;
  5018. for (imaxlo = i; imaxlo <= imax; imaxlo += 14) {
  5019. t = 0;
  5020. for (; i <= imax && i < imaxlo + 14; i++) {
  5021. t += ((sp_uint64)a[i]) * a[k - i];
  5022. }
  5023. c += t * 2;
  5024. hi += c >> 29;
  5025. c &= 0x1fffffff;
  5026. }
  5027. r[k + 2] += (sp_digit)(hi >> 29);
  5028. r[k + 1] = (sp_digit)(hi & 0x1fffffff);
  5029. c <<= 29;
  5030. }
  5031. else
  5032. {
  5033. t = 0;
  5034. for (; i <= imax; i++) {
  5035. t += ((sp_uint64)a[i]) * a[k - i];
  5036. }
  5037. c += t * 2;
  5038. r[k + 2] += (sp_digit) (c >> 58);
  5039. r[k + 1] = (sp_digit)((c >> 29) & 0x1fffffff);
  5040. c = (c & 0x1fffffff) << 29;
  5041. }
  5042. }
  5043. r[0] = (sp_digit)(c >> 29);
  5044. }
  5045. /* Square the Montgomery form number. (r = a * a mod m)
  5046. *
  5047. * r Result of squaring.
  5048. * a Number to square in Montgomery form.
  5049. * m Modulus (prime).
  5050. * mp Montgomery mulitplier.
  5051. */
  5052. SP_NOINLINE static void sp_3072_mont_sqr_53(sp_digit* r, const sp_digit* a,
  5053. const sp_digit* m, sp_digit mp)
  5054. {
  5055. sp_3072_sqr_53(r, a);
  5056. sp_3072_mont_reduce_53(r, m, mp);
  5057. }
  5058. /* Multiply a by scalar b into r. (r = a * b)
  5059. *
  5060. * r A single precision integer.
  5061. * a A single precision integer.
  5062. * b A scalar.
  5063. */
  5064. SP_NOINLINE static void sp_3072_mul_d_53(sp_digit* r, const sp_digit* a,
  5065. sp_digit b)
  5066. {
  5067. sp_int64 tb = b;
  5068. sp_int64 t = 0;
  5069. int i;
  5070. for (i = 0; i < 53; i++) {
  5071. t += tb * a[i];
  5072. r[i] = (sp_digit)(t & 0x1fffffff);
  5073. t >>= 29;
  5074. }
  5075. r[53] = (sp_digit)t;
  5076. }
  5077. #ifdef WOLFSSL_SP_SMALL
  5078. /* Conditionally add a and b using the mask m.
  5079. * m is -1 to add and 0 when not.
  5080. *
  5081. * r A single precision number representing conditional add result.
  5082. * a A single precision number to add with.
  5083. * b A single precision number to add.
  5084. * m Mask value to apply.
  5085. */
  5086. static void sp_3072_cond_add_53(sp_digit* r, const sp_digit* a,
  5087. const sp_digit* b, const sp_digit m)
  5088. {
  5089. int i;
  5090. for (i = 0; i < 53; i++) {
  5091. r[i] = a[i] + (b[i] & m);
  5092. }
  5093. }
  5094. #endif /* WOLFSSL_SP_SMALL */
  5095. /* Add b to a into r. (r = a + b)
  5096. *
  5097. * r A single precision integer.
  5098. * a A single precision integer.
  5099. * b A single precision integer.
  5100. */
  5101. SP_NOINLINE static int sp_3072_add_53(sp_digit* r, const sp_digit* a,
  5102. const sp_digit* b)
  5103. {
  5104. int i;
  5105. for (i = 0; i < 53; i++) {
  5106. r[i] = a[i] + b[i];
  5107. }
  5108. return 0;
  5109. }
  5110. SP_NOINLINE static void sp_3072_rshift_53(sp_digit* r, const sp_digit* a,
  5111. byte n)
  5112. {
  5113. int i;
  5114. for (i=0; i<52; i++) {
  5115. r[i] = ((a[i] >> n) | (a[i + 1] << (29 - n))) & 0x1fffffff;
  5116. }
  5117. r[52] = a[52] >> n;
  5118. }
  5119. static WC_INLINE sp_digit sp_3072_div_word_53(sp_digit d1, sp_digit d0,
  5120. sp_digit div)
  5121. {
  5122. #ifdef SP_USE_DIVTI3
  5123. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  5124. return d / div;
  5125. #elif defined(__x86_64__) || defined(__i386__)
  5126. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  5127. sp_uint32 lo = (sp_uint32)d;
  5128. sp_digit hi = (sp_digit)(d >> 32);
  5129. __asm__ __volatile__ (
  5130. "idiv %2"
  5131. : "+a" (lo)
  5132. : "d" (hi), "r" (div)
  5133. : "cc"
  5134. );
  5135. return (sp_digit)lo;
  5136. #elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV)
  5137. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  5138. sp_digit dv = (div >> 1) + 1;
  5139. sp_digit t1 = (sp_digit)(d >> 29);
  5140. sp_digit t0 = (sp_digit)(d & 0x1fffffff);
  5141. sp_digit t2;
  5142. sp_digit sign;
  5143. sp_digit r;
  5144. int i;
  5145. sp_int64 m;
  5146. r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
  5147. t1 -= dv & (0 - r);
  5148. for (i = 27; i >= 1; i--) {
  5149. t1 += t1 + (((sp_uint32)t0 >> 28) & 1);
  5150. t0 <<= 1;
  5151. t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
  5152. r += r + t2;
  5153. t1 -= dv & (0 - t2);
  5154. t1 += t2;
  5155. }
  5156. r += r + 1;
  5157. m = d - ((sp_int64)r * div);
  5158. r += (sp_digit)(m >> 29);
  5159. m = d - ((sp_int64)r * div);
  5160. r += (sp_digit)(m >> 58) - (sp_digit)(d >> 58);
  5161. m = d - ((sp_int64)r * div);
  5162. sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
  5163. m *= sign;
  5164. t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
  5165. r += sign * t2;
  5166. m = d - ((sp_int64)r * div);
  5167. sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
  5168. m *= sign;
  5169. t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
  5170. r += sign * t2;
  5171. return r;
  5172. #else
  5173. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  5174. sp_digit r = 0;
  5175. sp_digit t;
  5176. sp_digit dv = (div >> 14) + 1;
  5177. t = (sp_digit)(d >> 28);
  5178. t = (t / dv) << 14;
  5179. r += t;
  5180. d -= (sp_int64)t * div;
  5181. t = (sp_digit)(d >> 13);
  5182. t = t / (dv << 1);
  5183. r += t;
  5184. d -= (sp_int64)t * div;
  5185. t = (sp_digit)d;
  5186. t = t / div;
  5187. r += t;
  5188. d -= (sp_int64)t * div;
  5189. return r;
  5190. #endif
  5191. }
  5192. static WC_INLINE sp_digit sp_3072_word_div_word_53(sp_digit d, sp_digit div)
  5193. {
  5194. #if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
  5195. defined(SP_DIV_WORD_USE_DIV)
  5196. return d / div;
  5197. #else
  5198. return (sp_digit)((sp_uint32)(div - d) >> 31);
  5199. #endif
  5200. }
  5201. /* Divide d in a and put remainder into r (m*d + r = a)
  5202. * m is not calculated as it is not needed at this time.
  5203. *
  5204. * Full implementation.
  5205. *
  5206. * a Number to be divided.
  5207. * d Number to divide with.
  5208. * m Multiplier result.
  5209. * r Remainder from the division.
  5210. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  5211. */
  5212. static int sp_3072_div_53(const sp_digit* a, const sp_digit* d,
  5213. const sp_digit* m, sp_digit* r)
  5214. {
  5215. int i;
  5216. #ifndef WOLFSSL_SP_DIV_32
  5217. #endif
  5218. sp_digit dv;
  5219. sp_digit r1;
  5220. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  5221. sp_digit* t1 = NULL;
  5222. #else
  5223. sp_digit t1[4 * 53 + 3];
  5224. #endif
  5225. sp_digit* t2 = NULL;
  5226. sp_digit* sd = NULL;
  5227. int err = MP_OKAY;
  5228. (void)m;
  5229. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  5230. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 53 + 3), NULL,
  5231. DYNAMIC_TYPE_TMP_BUFFER);
  5232. if (t1 == NULL)
  5233. err = MEMORY_E;
  5234. #endif
  5235. (void)m;
  5236. if (err == MP_OKAY) {
  5237. t2 = t1 + 106 + 1;
  5238. sd = t2 + 53 + 1;
  5239. sp_3072_mul_d_53(sd, d, (sp_digit)1 << 1);
  5240. sp_3072_mul_d_106(t1, a, (sp_digit)1 << 1);
  5241. dv = sd[52];
  5242. t1[53 + 53] += t1[53 + 53 - 1] >> 29;
  5243. t1[53 + 53 - 1] &= 0x1fffffff;
  5244. for (i=53; i>=0; i--) {
  5245. r1 = sp_3072_div_word_53(t1[53 + i], t1[53 + i - 1], dv);
  5246. sp_3072_mul_d_53(t2, sd, r1);
  5247. (void)sp_3072_sub_53(&t1[i], &t1[i], t2);
  5248. sp_3072_norm_53(&t1[i]);
  5249. t1[53 + i] -= t2[53];
  5250. t1[53 + i] += t1[53 + i - 1] >> 29;
  5251. t1[53 + i - 1] &= 0x1fffffff;
  5252. r1 = sp_3072_div_word_53(-t1[53 + i], -t1[53 + i - 1], dv);
  5253. r1 -= t1[53 + i];
  5254. sp_3072_mul_d_53(t2, sd, r1);
  5255. (void)sp_3072_add_53(&t1[i], &t1[i], t2);
  5256. t1[53 + i] += t1[53 + i - 1] >> 29;
  5257. t1[53 + i - 1] &= 0x1fffffff;
  5258. }
  5259. t1[53 - 1] += t1[53 - 2] >> 29;
  5260. t1[53 - 2] &= 0x1fffffff;
  5261. r1 = sp_3072_word_div_word_53(t1[53 - 1], dv);
  5262. sp_3072_mul_d_53(t2, sd, r1);
  5263. sp_3072_sub_53(t1, t1, t2);
  5264. XMEMCPY(r, t1, sizeof(*r) * 106U);
  5265. for (i=0; i<52; i++) {
  5266. r[i+1] += r[i] >> 29;
  5267. r[i] &= 0x1fffffff;
  5268. }
  5269. sp_3072_cond_add_53(r, r, sd, r[52] >> 31);
  5270. sp_3072_norm_53(r);
  5271. sp_3072_rshift_53(r, r, 1);
  5272. }
  5273. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  5274. if (t1 != NULL)
  5275. XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  5276. #endif
  5277. return err;
  5278. }
  5279. /* Reduce a modulo m into r. (r = a mod m)
  5280. *
  5281. * r A single precision number that is the reduced result.
  5282. * a A single precision number that is to be reduced.
  5283. * m A single precision number that is the modulus to reduce with.
  5284. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  5285. */
  5286. static int sp_3072_mod_53(sp_digit* r, const sp_digit* a, const sp_digit* m)
  5287. {
  5288. return sp_3072_div_53(a, m, NULL, r);
  5289. }
  5290. /* Modular exponentiate a to the e mod m. (r = a^e mod m)
  5291. *
  5292. * r A single precision number that is the result of the operation.
  5293. * a A single precision number being exponentiated.
  5294. * e A single precision number that is the exponent.
  5295. * bits The number of bits in the exponent.
  5296. * m A single precision number that is the modulus.
  5297. * returns 0 on success.
  5298. * returns MEMORY_E on dynamic memory allocation failure.
  5299. * returns MP_VAL when base is even or exponent is 0.
  5300. */
  5301. static int sp_3072_mod_exp_53(sp_digit* r, const sp_digit* a, const sp_digit* e,
  5302. int bits, const sp_digit* m, int reduceA)
  5303. {
  5304. #if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP)
  5305. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  5306. sp_digit* td = NULL;
  5307. #else
  5308. sp_digit td[3 * 106];
  5309. #endif
  5310. sp_digit* t[3] = {0, 0, 0};
  5311. sp_digit* norm = NULL;
  5312. sp_digit mp = 1;
  5313. sp_digit n;
  5314. int i;
  5315. int c;
  5316. byte y;
  5317. int err = MP_OKAY;
  5318. if (bits == 0) {
  5319. err = MP_VAL;
  5320. }
  5321. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  5322. if (err == MP_OKAY) {
  5323. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 53 * 2, NULL,
  5324. DYNAMIC_TYPE_TMP_BUFFER);
  5325. if (td == NULL)
  5326. err = MEMORY_E;
  5327. }
  5328. #endif
  5329. if (err == MP_OKAY) {
  5330. norm = td;
  5331. for (i=0; i<3; i++) {
  5332. t[i] = td + (i * 53 * 2);
  5333. XMEMSET(t[i], 0, sizeof(sp_digit) * 53U * 2U);
  5334. }
  5335. sp_3072_mont_setup(m, &mp);
  5336. sp_3072_mont_norm_53(norm, m);
  5337. if (reduceA != 0) {
  5338. err = sp_3072_mod_53(t[1], a, m);
  5339. }
  5340. else {
  5341. XMEMCPY(t[1], a, sizeof(sp_digit) * 53U);
  5342. }
  5343. }
  5344. if (err == MP_OKAY) {
  5345. sp_3072_mul_53(t[1], t[1], norm);
  5346. err = sp_3072_mod_53(t[1], t[1], m);
  5347. }
  5348. if (err == MP_OKAY) {
  5349. i = bits / 29;
  5350. c = bits % 29;
  5351. n = e[i--] << (29 - c);
  5352. for (; ; c--) {
  5353. if (c == 0) {
  5354. if (i == -1) {
  5355. break;
  5356. }
  5357. n = e[i--];
  5358. c = 29;
  5359. }
  5360. y = (int)((n >> 28) & 1);
  5361. n <<= 1;
  5362. sp_3072_mont_mul_53(t[y^1], t[0], t[1], m, mp);
  5363. XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
  5364. ((size_t)t[1] & addr_mask[y])),
  5365. sizeof(*t[2]) * 53 * 2);
  5366. sp_3072_mont_sqr_53(t[2], t[2], m, mp);
  5367. XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
  5368. ((size_t)t[1] & addr_mask[y])), t[2],
  5369. sizeof(*t[2]) * 53 * 2);
  5370. }
  5371. sp_3072_mont_reduce_53(t[0], m, mp);
  5372. n = sp_3072_cmp_53(t[0], m);
  5373. sp_3072_cond_sub_53(t[0], t[0], m, ~(n >> 31));
  5374. XMEMCPY(r, t[0], sizeof(*r) * 53 * 2);
  5375. }
  5376. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  5377. if (td != NULL)
  5378. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  5379. #endif
  5380. return err;
  5381. #elif !defined(WC_NO_CACHE_RESISTANT)
  5382. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  5383. sp_digit* td = NULL;
  5384. #else
  5385. sp_digit td[3 * 106];
  5386. #endif
  5387. sp_digit* t[3] = {0, 0, 0};
  5388. sp_digit* norm = NULL;
  5389. sp_digit mp = 1;
  5390. sp_digit n;
  5391. int i;
  5392. int c;
  5393. byte y;
  5394. int err = MP_OKAY;
  5395. if (bits == 0) {
  5396. err = MP_VAL;
  5397. }
  5398. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  5399. if (err == MP_OKAY) {
  5400. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 53 * 2, NULL,
  5401. DYNAMIC_TYPE_TMP_BUFFER);
  5402. if (td == NULL)
  5403. err = MEMORY_E;
  5404. }
  5405. #endif
  5406. if (err == MP_OKAY) {
  5407. norm = td;
  5408. for (i=0; i<3; i++) {
  5409. t[i] = td + (i * 53 * 2);
  5410. }
  5411. sp_3072_mont_setup(m, &mp);
  5412. sp_3072_mont_norm_53(norm, m);
  5413. if (reduceA != 0) {
  5414. err = sp_3072_mod_53(t[1], a, m);
  5415. if (err == MP_OKAY) {
  5416. sp_3072_mul_53(t[1], t[1], norm);
  5417. err = sp_3072_mod_53(t[1], t[1], m);
  5418. }
  5419. }
  5420. else {
  5421. sp_3072_mul_53(t[1], a, norm);
  5422. err = sp_3072_mod_53(t[1], t[1], m);
  5423. }
  5424. }
  5425. if (err == MP_OKAY) {
  5426. i = bits / 29;
  5427. c = bits % 29;
  5428. n = e[i--] << (29 - c);
  5429. for (; ; c--) {
  5430. if (c == 0) {
  5431. if (i == -1) {
  5432. break;
  5433. }
  5434. n = e[i--];
  5435. c = 29;
  5436. }
  5437. y = (int)((n >> 28) & 1);
  5438. n <<= 1;
  5439. sp_3072_mont_mul_53(t[y^1], t[0], t[1], m, mp);
  5440. XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
  5441. ((size_t)t[1] & addr_mask[y])),
  5442. sizeof(*t[2]) * 53 * 2);
  5443. sp_3072_mont_sqr_53(t[2], t[2], m, mp);
  5444. XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
  5445. ((size_t)t[1] & addr_mask[y])), t[2],
  5446. sizeof(*t[2]) * 53 * 2);
  5447. }
  5448. sp_3072_mont_reduce_53(t[0], m, mp);
  5449. n = sp_3072_cmp_53(t[0], m);
  5450. sp_3072_cond_sub_53(t[0], t[0], m, ~(n >> 31));
  5451. XMEMCPY(r, t[0], sizeof(*r) * 53 * 2);
  5452. }
  5453. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  5454. if (td != NULL)
  5455. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  5456. #endif
  5457. return err;
  5458. #else
  5459. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  5460. sp_digit* td = NULL;
  5461. #else
  5462. sp_digit td[(32 * 106) + 106];
  5463. #endif
  5464. sp_digit* t[32];
  5465. sp_digit* rt = NULL;
  5466. sp_digit* norm = NULL;
  5467. sp_digit mp = 1;
  5468. sp_digit n;
  5469. int i;
  5470. int c;
  5471. byte y;
  5472. int err = MP_OKAY;
  5473. if (bits == 0) {
  5474. err = MP_VAL;
  5475. }
  5476. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  5477. if (err == MP_OKAY) {
  5478. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((32 * 106) + 106), NULL,
  5479. DYNAMIC_TYPE_TMP_BUFFER);
  5480. if (td == NULL)
  5481. err = MEMORY_E;
  5482. }
  5483. #endif
  5484. if (err == MP_OKAY) {
  5485. norm = td;
  5486. for (i=0; i<32; i++)
  5487. t[i] = td + i * 106;
  5488. rt = td + 3392;
  5489. sp_3072_mont_setup(m, &mp);
  5490. sp_3072_mont_norm_53(norm, m);
  5491. if (reduceA != 0) {
  5492. err = sp_3072_mod_53(t[1], a, m);
  5493. if (err == MP_OKAY) {
  5494. sp_3072_mul_53(t[1], t[1], norm);
  5495. err = sp_3072_mod_53(t[1], t[1], m);
  5496. }
  5497. }
  5498. else {
  5499. sp_3072_mul_53(t[1], a, norm);
  5500. err = sp_3072_mod_53(t[1], t[1], m);
  5501. }
  5502. }
  5503. if (err == MP_OKAY) {
  5504. sp_3072_mont_sqr_53(t[ 2], t[ 1], m, mp);
  5505. sp_3072_mont_mul_53(t[ 3], t[ 2], t[ 1], m, mp);
  5506. sp_3072_mont_sqr_53(t[ 4], t[ 2], m, mp);
  5507. sp_3072_mont_mul_53(t[ 5], t[ 3], t[ 2], m, mp);
  5508. sp_3072_mont_sqr_53(t[ 6], t[ 3], m, mp);
  5509. sp_3072_mont_mul_53(t[ 7], t[ 4], t[ 3], m, mp);
  5510. sp_3072_mont_sqr_53(t[ 8], t[ 4], m, mp);
  5511. sp_3072_mont_mul_53(t[ 9], t[ 5], t[ 4], m, mp);
  5512. sp_3072_mont_sqr_53(t[10], t[ 5], m, mp);
  5513. sp_3072_mont_mul_53(t[11], t[ 6], t[ 5], m, mp);
  5514. sp_3072_mont_sqr_53(t[12], t[ 6], m, mp);
  5515. sp_3072_mont_mul_53(t[13], t[ 7], t[ 6], m, mp);
  5516. sp_3072_mont_sqr_53(t[14], t[ 7], m, mp);
  5517. sp_3072_mont_mul_53(t[15], t[ 8], t[ 7], m, mp);
  5518. sp_3072_mont_sqr_53(t[16], t[ 8], m, mp);
  5519. sp_3072_mont_mul_53(t[17], t[ 9], t[ 8], m, mp);
  5520. sp_3072_mont_sqr_53(t[18], t[ 9], m, mp);
  5521. sp_3072_mont_mul_53(t[19], t[10], t[ 9], m, mp);
  5522. sp_3072_mont_sqr_53(t[20], t[10], m, mp);
  5523. sp_3072_mont_mul_53(t[21], t[11], t[10], m, mp);
  5524. sp_3072_mont_sqr_53(t[22], t[11], m, mp);
  5525. sp_3072_mont_mul_53(t[23], t[12], t[11], m, mp);
  5526. sp_3072_mont_sqr_53(t[24], t[12], m, mp);
  5527. sp_3072_mont_mul_53(t[25], t[13], t[12], m, mp);
  5528. sp_3072_mont_sqr_53(t[26], t[13], m, mp);
  5529. sp_3072_mont_mul_53(t[27], t[14], t[13], m, mp);
  5530. sp_3072_mont_sqr_53(t[28], t[14], m, mp);
  5531. sp_3072_mont_mul_53(t[29], t[15], t[14], m, mp);
  5532. sp_3072_mont_sqr_53(t[30], t[15], m, mp);
  5533. sp_3072_mont_mul_53(t[31], t[16], t[15], m, mp);
  5534. bits = ((bits + 4) / 5) * 5;
  5535. i = ((bits + 28) / 29) - 1;
  5536. c = bits % 29;
  5537. if (c == 0) {
  5538. c = 29;
  5539. }
  5540. if (i < 53) {
  5541. n = e[i--] << (32 - c);
  5542. }
  5543. else {
  5544. n = 0;
  5545. i--;
  5546. }
  5547. if (c < 5) {
  5548. n |= e[i--] << (3 - c);
  5549. c += 29;
  5550. }
  5551. y = (int)((n >> 27) & 0x1f);
  5552. n <<= 5;
  5553. c -= 5;
  5554. XMEMCPY(rt, t[y], sizeof(sp_digit) * 106);
  5555. while ((i >= 0) || (c >= 5)) {
  5556. if (c >= 5) {
  5557. y = (byte)((n >> 27) & 0x1f);
  5558. n <<= 5;
  5559. c -= 5;
  5560. }
  5561. else if (c == 0) {
  5562. n = e[i--] << 3;
  5563. y = (byte)((n >> 27) & 0x1f);
  5564. n <<= 5;
  5565. c = 24;
  5566. }
  5567. else {
  5568. y = (byte)((n >> 27) & 0x1f);
  5569. n = e[i--] << 3;
  5570. c = 5 - c;
  5571. y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
  5572. n <<= c;
  5573. c = 29 - c;
  5574. }
  5575. sp_3072_mont_sqr_53(rt, rt, m, mp);
  5576. sp_3072_mont_sqr_53(rt, rt, m, mp);
  5577. sp_3072_mont_sqr_53(rt, rt, m, mp);
  5578. sp_3072_mont_sqr_53(rt, rt, m, mp);
  5579. sp_3072_mont_sqr_53(rt, rt, m, mp);
  5580. sp_3072_mont_mul_53(rt, rt, t[y], m, mp);
  5581. }
  5582. sp_3072_mont_reduce_53(rt, m, mp);
  5583. n = sp_3072_cmp_53(rt, m);
  5584. sp_3072_cond_sub_53(rt, rt, m, ~(n >> 31));
  5585. XMEMCPY(r, rt, sizeof(sp_digit) * 106);
  5586. }
  5587. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  5588. if (td != NULL)
  5589. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  5590. #endif
  5591. return err;
  5592. #endif
  5593. }
  5594. #endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
  5595. /* Sub b from a into r. (r = a - b)
  5596. *
  5597. * r A single precision integer.
  5598. * a A single precision integer.
  5599. * b A single precision integer.
  5600. */
  5601. SP_NOINLINE static int sp_3072_sub_106(sp_digit* r, const sp_digit* a,
  5602. const sp_digit* b)
  5603. {
  5604. int i;
  5605. for (i = 0; i < 106; i++) {
  5606. r[i] = a[i] - b[i];
  5607. }
  5608. return 0;
  5609. }
  5610. /* r = 2^n mod m where n is the number of bits to reduce by.
  5611. * Given m must be 3072 bits, just need to subtract.
  5612. *
  5613. * r A single precision number.
  5614. * m A single precision number.
  5615. */
  5616. static void sp_3072_mont_norm_106(sp_digit* r, const sp_digit* m)
  5617. {
  5618. /* Set r = 2^n - 1. */
  5619. int i;
  5620. for (i=0; i<105; i++) {
  5621. r[i] = 0x1fffffff;
  5622. }
  5623. r[105] = 0x7ffffffL;
  5624. /* r = (2^n - 1) mod n */
  5625. (void)sp_3072_sub_106(r, r, m);
  5626. /* Add one so r = 2^n mod m */
  5627. r[0] += 1;
  5628. }
  5629. /* Compare a with b in constant time.
  5630. *
  5631. * a A single precision integer.
  5632. * b A single precision integer.
  5633. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  5634. * respectively.
  5635. */
  5636. static sp_digit sp_3072_cmp_106(const sp_digit* a, const sp_digit* b)
  5637. {
  5638. sp_digit r = 0;
  5639. int i;
  5640. for (i=105; i>=0; i--) {
  5641. r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 28);
  5642. }
  5643. return r;
  5644. }
  5645. /* Conditionally subtract b from a using the mask m.
  5646. * m is -1 to subtract and 0 when not.
  5647. *
  5648. * r A single precision number representing condition subtract result.
  5649. * a A single precision number to subtract from.
  5650. * b A single precision number to subtract.
  5651. * m Mask value to apply.
  5652. */
  5653. static void sp_3072_cond_sub_106(sp_digit* r, const sp_digit* a,
  5654. const sp_digit* b, const sp_digit m)
  5655. {
  5656. int i;
  5657. for (i = 0; i < 106; i++) {
  5658. r[i] = a[i] - (b[i] & m);
  5659. }
  5660. }
  5661. /* Mul a by scalar b and add into r. (r += a * b)
  5662. *
  5663. * r A single precision integer.
  5664. * a A single precision integer.
  5665. * b A scalar.
  5666. */
  5667. SP_NOINLINE static void sp_3072_mul_add_106(sp_digit* r, const sp_digit* a,
  5668. const sp_digit b)
  5669. {
  5670. #ifndef WOLFSSL_SP_LARGE_CODE
  5671. sp_int64 tb = b;
  5672. sp_int64 t = 0;
  5673. int i;
  5674. for (i = 0; i < 106; i++) {
  5675. t += r[i];
  5676. t += tb * a[i];
  5677. r[i] = ((sp_digit)t) & 0x1fffffff;
  5678. t >>= 29;
  5679. }
  5680. r[106] += (sp_digit)t;
  5681. #else
  5682. sp_int64 tb = b;
  5683. sp_int64 t[4];
  5684. int i;
  5685. t[0] = 0;
  5686. for (i = 0; i < 104; i += 4) {
  5687. t[0] += (tb * a[i+0]) + r[i+0];
  5688. t[1] = (tb * a[i+1]) + r[i+1];
  5689. t[2] = (tb * a[i+2]) + r[i+2];
  5690. t[3] = (tb * a[i+3]) + r[i+3];
  5691. r[i+0] = t[0] & 0x1fffffff;
  5692. t[1] += t[0] >> 29;
  5693. r[i+1] = t[1] & 0x1fffffff;
  5694. t[2] += t[1] >> 29;
  5695. r[i+2] = t[2] & 0x1fffffff;
  5696. t[3] += t[2] >> 29;
  5697. r[i+3] = t[3] & 0x1fffffff;
  5698. t[0] = t[3] >> 29;
  5699. }
  5700. t[0] += (tb * a[104]) + r[104];
  5701. t[1] = (tb * a[105]) + r[105];
  5702. r[104] = t[0] & 0x1fffffff;
  5703. t[1] += t[0] >> 29;
  5704. r[105] = t[1] & 0x1fffffff;
  5705. r[106] += (sp_digit)(t[1] >> 29);
  5706. #endif /* !WOLFSSL_SP_LARGE_CODE */
  5707. }
  5708. /* Shift the result in the high 3072 bits down to the bottom.
  5709. *
  5710. * r A single precision number.
  5711. * a A single precision number.
  5712. */
  5713. static void sp_3072_mont_shift_106(sp_digit* r, const sp_digit* a)
  5714. {
  5715. int i;
  5716. sp_int64 n = a[105] >> 27;
  5717. n += ((sp_int64)a[106]) << 2;
  5718. for (i = 0; i < 105; i++) {
  5719. r[i] = n & 0x1fffffff;
  5720. n >>= 29;
  5721. n += ((sp_int64)a[107 + i]) << 2;
  5722. }
  5723. r[105] = (sp_digit)n;
  5724. XMEMSET(&r[106], 0, sizeof(*r) * 106U);
  5725. }
  5726. /* Reduce the number back to 3072 bits using Montgomery reduction.
  5727. *
  5728. * a A single precision number to reduce in place.
  5729. * m The single precision number representing the modulus.
  5730. * mp The digit representing the negative inverse of m mod 2^n.
  5731. */
  5732. static void sp_3072_mont_reduce_106(sp_digit* a, const sp_digit* m, sp_digit mp)
  5733. {
  5734. int i;
  5735. sp_digit mu;
  5736. sp_digit over;
  5737. sp_3072_norm_106(a + 106);
  5738. #ifdef WOLFSSL_SP_DH
  5739. if (mp != 1) {
  5740. for (i=0; i<105; i++) {
  5741. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff;
  5742. sp_3072_mul_add_106(a+i, m, mu);
  5743. a[i+1] += a[i] >> 29;
  5744. }
  5745. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x7ffffffL;
  5746. sp_3072_mul_add_106(a+i, m, mu);
  5747. a[i+1] += a[i] >> 29;
  5748. a[i] &= 0x1fffffff;
  5749. }
  5750. else {
  5751. for (i=0; i<105; i++) {
  5752. mu = a[i] & 0x1fffffff;
  5753. sp_3072_mul_add_106(a+i, m, mu);
  5754. a[i+1] += a[i] >> 29;
  5755. }
  5756. mu = a[i] & 0x7ffffffL;
  5757. sp_3072_mul_add_106(a+i, m, mu);
  5758. a[i+1] += a[i] >> 29;
  5759. a[i] &= 0x1fffffff;
  5760. }
  5761. #else
  5762. for (i=0; i<105; i++) {
  5763. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff;
  5764. sp_3072_mul_add_106(a+i, m, mu);
  5765. a[i+1] += a[i] >> 29;
  5766. }
  5767. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x7ffffffL;
  5768. sp_3072_mul_add_106(a+i, m, mu);
  5769. a[i+1] += a[i] >> 29;
  5770. a[i] &= 0x1fffffff;
  5771. #endif
  5772. sp_3072_mont_shift_106(a, a);
  5773. over = a[105] - m[105];
  5774. sp_3072_cond_sub_106(a, a, m, ~((over - 1) >> 31));
  5775. sp_3072_norm_106(a);
  5776. }
  5777. /* Multiply two Montgomery form numbers mod the modulus (prime).
  5778. * (r = a * b mod m)
  5779. *
  5780. * r Result of multiplication.
  5781. * a First number to multiply in Montgomery form.
  5782. * b Second number to multiply in Montgomery form.
  5783. * m Modulus (prime).
  5784. * mp Montgomery mulitplier.
  5785. */
  5786. SP_NOINLINE static void sp_3072_mont_mul_106(sp_digit* r, const sp_digit* a,
  5787. const sp_digit* b, const sp_digit* m, sp_digit mp)
  5788. {
  5789. sp_3072_mul_106(r, a, b);
  5790. sp_3072_mont_reduce_106(r, m, mp);
  5791. }
  5792. /* Square the Montgomery form number. (r = a * a mod m)
  5793. *
  5794. * r Result of squaring.
  5795. * a Number to square in Montgomery form.
  5796. * m Modulus (prime).
  5797. * mp Montgomery mulitplier.
  5798. */
  5799. SP_NOINLINE static void sp_3072_mont_sqr_106(sp_digit* r, const sp_digit* a,
  5800. const sp_digit* m, sp_digit mp)
  5801. {
  5802. sp_3072_sqr_106(r, a);
  5803. sp_3072_mont_reduce_106(r, m, mp);
  5804. }
  5805. /* Multiply a by scalar b into r. (r = a * b)
  5806. *
  5807. * r A single precision integer.
  5808. * a A single precision integer.
  5809. * b A scalar.
  5810. */
  5811. SP_NOINLINE static void sp_3072_mul_d_212(sp_digit* r, const sp_digit* a,
  5812. sp_digit b)
  5813. {
  5814. sp_int64 tb = b;
  5815. sp_int64 t = 0;
  5816. int i;
  5817. for (i = 0; i < 212; i++) {
  5818. t += tb * a[i];
  5819. r[i] = (sp_digit)(t & 0x1fffffff);
  5820. t >>= 29;
  5821. }
  5822. r[212] = (sp_digit)t;
  5823. }
  5824. #ifdef WOLFSSL_SP_SMALL
  5825. /* Conditionally add a and b using the mask m.
  5826. * m is -1 to add and 0 when not.
  5827. *
  5828. * r A single precision number representing conditional add result.
  5829. * a A single precision number to add with.
  5830. * b A single precision number to add.
  5831. * m Mask value to apply.
  5832. */
  5833. static void sp_3072_cond_add_106(sp_digit* r, const sp_digit* a,
  5834. const sp_digit* b, const sp_digit m)
  5835. {
  5836. int i;
  5837. for (i = 0; i < 106; i++) {
  5838. r[i] = a[i] + (b[i] & m);
  5839. }
  5840. }
  5841. #endif /* WOLFSSL_SP_SMALL */
  5842. /* Add b to a into r. (r = a + b)
  5843. *
  5844. * r A single precision integer.
  5845. * a A single precision integer.
  5846. * b A single precision integer.
  5847. */
  5848. SP_NOINLINE static int sp_3072_add_106(sp_digit* r, const sp_digit* a,
  5849. const sp_digit* b)
  5850. {
  5851. int i;
  5852. for (i = 0; i < 106; i++) {
  5853. r[i] = a[i] + b[i];
  5854. }
  5855. return 0;
  5856. }
  5857. SP_NOINLINE static void sp_3072_rshift_106(sp_digit* r, const sp_digit* a,
  5858. byte n)
  5859. {
  5860. int i;
  5861. for (i=0; i<105; i++) {
  5862. r[i] = ((a[i] >> n) | (a[i + 1] << (29 - n))) & 0x1fffffff;
  5863. }
  5864. r[105] = a[105] >> n;
  5865. }
  5866. static WC_INLINE sp_digit sp_3072_div_word_106(sp_digit d1, sp_digit d0,
  5867. sp_digit div)
  5868. {
  5869. #ifdef SP_USE_DIVTI3
  5870. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  5871. return d / div;
  5872. #elif defined(__x86_64__) || defined(__i386__)
  5873. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  5874. sp_uint32 lo = (sp_uint32)d;
  5875. sp_digit hi = (sp_digit)(d >> 32);
  5876. __asm__ __volatile__ (
  5877. "idiv %2"
  5878. : "+a" (lo)
  5879. : "d" (hi), "r" (div)
  5880. : "cc"
  5881. );
  5882. return (sp_digit)lo;
  5883. #elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV)
  5884. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  5885. sp_digit dv = (div >> 1) + 1;
  5886. sp_digit t1 = (sp_digit)(d >> 29);
  5887. sp_digit t0 = (sp_digit)(d & 0x1fffffff);
  5888. sp_digit t2;
  5889. sp_digit sign;
  5890. sp_digit r;
  5891. int i;
  5892. sp_int64 m;
  5893. r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
  5894. t1 -= dv & (0 - r);
  5895. for (i = 27; i >= 1; i--) {
  5896. t1 += t1 + (((sp_uint32)t0 >> 28) & 1);
  5897. t0 <<= 1;
  5898. t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
  5899. r += r + t2;
  5900. t1 -= dv & (0 - t2);
  5901. t1 += t2;
  5902. }
  5903. r += r + 1;
  5904. m = d - ((sp_int64)r * div);
  5905. r += (sp_digit)(m >> 29);
  5906. m = d - ((sp_int64)r * div);
  5907. r += (sp_digit)(m >> 58) - (sp_digit)(d >> 58);
  5908. m = d - ((sp_int64)r * div);
  5909. sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
  5910. m *= sign;
  5911. t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
  5912. r += sign * t2;
  5913. m = d - ((sp_int64)r * div);
  5914. sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
  5915. m *= sign;
  5916. t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
  5917. r += sign * t2;
  5918. return r;
  5919. #else
  5920. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  5921. sp_digit r = 0;
  5922. sp_digit t;
  5923. sp_digit dv = (div >> 14) + 1;
  5924. t = (sp_digit)(d >> 28);
  5925. t = (t / dv) << 14;
  5926. r += t;
  5927. d -= (sp_int64)t * div;
  5928. t = (sp_digit)(d >> 13);
  5929. t = t / (dv << 1);
  5930. r += t;
  5931. d -= (sp_int64)t * div;
  5932. t = (sp_digit)d;
  5933. t = t / div;
  5934. r += t;
  5935. d -= (sp_int64)t * div;
  5936. return r;
  5937. #endif
  5938. }
  5939. static WC_INLINE sp_digit sp_3072_word_div_word_106(sp_digit d, sp_digit div)
  5940. {
  5941. #if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
  5942. defined(SP_DIV_WORD_USE_DIV)
  5943. return d / div;
  5944. #else
  5945. return (sp_digit)((sp_uint32)(div - d) >> 31);
  5946. #endif
  5947. }
  5948. /* Divide d in a and put remainder into r (m*d + r = a)
  5949. * m is not calculated as it is not needed at this time.
  5950. *
  5951. * Full implementation.
  5952. *
  5953. * a Number to be divided.
  5954. * d Number to divide with.
  5955. * m Multiplier result.
  5956. * r Remainder from the division.
  5957. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  5958. */
  5959. static int sp_3072_div_106(const sp_digit* a, const sp_digit* d,
  5960. const sp_digit* m, sp_digit* r)
  5961. {
  5962. int i;
  5963. #ifndef WOLFSSL_SP_DIV_32
  5964. #endif
  5965. sp_digit dv;
  5966. sp_digit r1;
  5967. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  5968. sp_digit* t1 = NULL;
  5969. #else
  5970. sp_digit t1[4 * 106 + 3];
  5971. #endif
  5972. sp_digit* t2 = NULL;
  5973. sp_digit* sd = NULL;
  5974. int err = MP_OKAY;
  5975. (void)m;
  5976. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  5977. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 106 + 3), NULL,
  5978. DYNAMIC_TYPE_TMP_BUFFER);
  5979. if (t1 == NULL)
  5980. err = MEMORY_E;
  5981. #endif
  5982. (void)m;
  5983. if (err == MP_OKAY) {
  5984. t2 = t1 + 212 + 1;
  5985. sd = t2 + 106 + 1;
  5986. sp_3072_mul_d_106(sd, d, (sp_digit)1 << 2);
  5987. sp_3072_mul_d_212(t1, a, (sp_digit)1 << 2);
  5988. dv = sd[105];
  5989. t1[106 + 106] += t1[106 + 106 - 1] >> 29;
  5990. t1[106 + 106 - 1] &= 0x1fffffff;
  5991. for (i=106; i>=0; i--) {
  5992. r1 = sp_3072_div_word_106(t1[106 + i], t1[106 + i - 1], dv);
  5993. sp_3072_mul_d_106(t2, sd, r1);
  5994. (void)sp_3072_sub_106(&t1[i], &t1[i], t2);
  5995. sp_3072_norm_106(&t1[i]);
  5996. t1[106 + i] -= t2[106];
  5997. t1[106 + i] += t1[106 + i - 1] >> 29;
  5998. t1[106 + i - 1] &= 0x1fffffff;
  5999. r1 = sp_3072_div_word_106(-t1[106 + i], -t1[106 + i - 1], dv);
  6000. r1 -= t1[106 + i];
  6001. sp_3072_mul_d_106(t2, sd, r1);
  6002. (void)sp_3072_add_106(&t1[i], &t1[i], t2);
  6003. t1[106 + i] += t1[106 + i - 1] >> 29;
  6004. t1[106 + i - 1] &= 0x1fffffff;
  6005. }
  6006. t1[106 - 1] += t1[106 - 2] >> 29;
  6007. t1[106 - 2] &= 0x1fffffff;
  6008. r1 = sp_3072_word_div_word_106(t1[106 - 1], dv);
  6009. sp_3072_mul_d_106(t2, sd, r1);
  6010. sp_3072_sub_106(t1, t1, t2);
  6011. XMEMCPY(r, t1, sizeof(*r) * 212U);
  6012. for (i=0; i<105; i++) {
  6013. r[i+1] += r[i] >> 29;
  6014. r[i] &= 0x1fffffff;
  6015. }
  6016. sp_3072_cond_add_106(r, r, sd, r[105] >> 31);
  6017. sp_3072_norm_106(r);
  6018. sp_3072_rshift_106(r, r, 2);
  6019. }
  6020. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6021. if (t1 != NULL)
  6022. XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  6023. #endif
  6024. return err;
  6025. }
  6026. /* Reduce a modulo m into r. (r = a mod m)
  6027. *
  6028. * r A single precision number that is the reduced result.
  6029. * a A single precision number that is to be reduced.
  6030. * m A single precision number that is the modulus to reduce with.
  6031. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  6032. */
  6033. static int sp_3072_mod_106(sp_digit* r, const sp_digit* a, const sp_digit* m)
  6034. {
  6035. return sp_3072_div_106(a, m, NULL, r);
  6036. }
  6037. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  6038. /* Modular exponentiate a to the e mod m. (r = a^e mod m)
  6039. *
  6040. * r A single precision number that is the result of the operation.
  6041. * a A single precision number being exponentiated.
  6042. * e A single precision number that is the exponent.
  6043. * bits The number of bits in the exponent.
  6044. * m A single precision number that is the modulus.
  6045. * returns 0 on success.
  6046. * returns MEMORY_E on dynamic memory allocation failure.
  6047. * returns MP_VAL when base is even or exponent is 0.
  6048. */
  6049. static int sp_3072_mod_exp_106(sp_digit* r, const sp_digit* a, const sp_digit* e,
  6050. int bits, const sp_digit* m, int reduceA)
  6051. {
  6052. #if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP)
  6053. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6054. sp_digit* td = NULL;
  6055. #else
  6056. sp_digit td[3 * 212];
  6057. #endif
  6058. sp_digit* t[3] = {0, 0, 0};
  6059. sp_digit* norm = NULL;
  6060. sp_digit mp = 1;
  6061. sp_digit n;
  6062. int i;
  6063. int c;
  6064. byte y;
  6065. int err = MP_OKAY;
  6066. if (bits == 0) {
  6067. err = MP_VAL;
  6068. }
  6069. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6070. if (err == MP_OKAY) {
  6071. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 106 * 2, NULL,
  6072. DYNAMIC_TYPE_TMP_BUFFER);
  6073. if (td == NULL)
  6074. err = MEMORY_E;
  6075. }
  6076. #endif
  6077. if (err == MP_OKAY) {
  6078. norm = td;
  6079. for (i=0; i<3; i++) {
  6080. t[i] = td + (i * 106 * 2);
  6081. XMEMSET(t[i], 0, sizeof(sp_digit) * 106U * 2U);
  6082. }
  6083. sp_3072_mont_setup(m, &mp);
  6084. sp_3072_mont_norm_106(norm, m);
  6085. if (reduceA != 0) {
  6086. err = sp_3072_mod_106(t[1], a, m);
  6087. }
  6088. else {
  6089. XMEMCPY(t[1], a, sizeof(sp_digit) * 106U);
  6090. }
  6091. }
  6092. if (err == MP_OKAY) {
  6093. sp_3072_mul_106(t[1], t[1], norm);
  6094. err = sp_3072_mod_106(t[1], t[1], m);
  6095. }
  6096. if (err == MP_OKAY) {
  6097. i = bits / 29;
  6098. c = bits % 29;
  6099. n = e[i--] << (29 - c);
  6100. for (; ; c--) {
  6101. if (c == 0) {
  6102. if (i == -1) {
  6103. break;
  6104. }
  6105. n = e[i--];
  6106. c = 29;
  6107. }
  6108. y = (int)((n >> 28) & 1);
  6109. n <<= 1;
  6110. sp_3072_mont_mul_106(t[y^1], t[0], t[1], m, mp);
  6111. XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
  6112. ((size_t)t[1] & addr_mask[y])),
  6113. sizeof(*t[2]) * 106 * 2);
  6114. sp_3072_mont_sqr_106(t[2], t[2], m, mp);
  6115. XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
  6116. ((size_t)t[1] & addr_mask[y])), t[2],
  6117. sizeof(*t[2]) * 106 * 2);
  6118. }
  6119. sp_3072_mont_reduce_106(t[0], m, mp);
  6120. n = sp_3072_cmp_106(t[0], m);
  6121. sp_3072_cond_sub_106(t[0], t[0], m, ~(n >> 31));
  6122. XMEMCPY(r, t[0], sizeof(*r) * 106 * 2);
  6123. }
  6124. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6125. if (td != NULL)
  6126. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  6127. #endif
  6128. return err;
  6129. #elif !defined(WC_NO_CACHE_RESISTANT)
  6130. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6131. sp_digit* td = NULL;
  6132. #else
  6133. sp_digit td[3 * 212];
  6134. #endif
  6135. sp_digit* t[3] = {0, 0, 0};
  6136. sp_digit* norm = NULL;
  6137. sp_digit mp = 1;
  6138. sp_digit n;
  6139. int i;
  6140. int c;
  6141. byte y;
  6142. int err = MP_OKAY;
  6143. if (bits == 0) {
  6144. err = MP_VAL;
  6145. }
  6146. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6147. if (err == MP_OKAY) {
  6148. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 106 * 2, NULL,
  6149. DYNAMIC_TYPE_TMP_BUFFER);
  6150. if (td == NULL)
  6151. err = MEMORY_E;
  6152. }
  6153. #endif
  6154. if (err == MP_OKAY) {
  6155. norm = td;
  6156. for (i=0; i<3; i++) {
  6157. t[i] = td + (i * 106 * 2);
  6158. }
  6159. sp_3072_mont_setup(m, &mp);
  6160. sp_3072_mont_norm_106(norm, m);
  6161. if (reduceA != 0) {
  6162. err = sp_3072_mod_106(t[1], a, m);
  6163. if (err == MP_OKAY) {
  6164. sp_3072_mul_106(t[1], t[1], norm);
  6165. err = sp_3072_mod_106(t[1], t[1], m);
  6166. }
  6167. }
  6168. else {
  6169. sp_3072_mul_106(t[1], a, norm);
  6170. err = sp_3072_mod_106(t[1], t[1], m);
  6171. }
  6172. }
  6173. if (err == MP_OKAY) {
  6174. i = bits / 29;
  6175. c = bits % 29;
  6176. n = e[i--] << (29 - c);
  6177. for (; ; c--) {
  6178. if (c == 0) {
  6179. if (i == -1) {
  6180. break;
  6181. }
  6182. n = e[i--];
  6183. c = 29;
  6184. }
  6185. y = (int)((n >> 28) & 1);
  6186. n <<= 1;
  6187. sp_3072_mont_mul_106(t[y^1], t[0], t[1], m, mp);
  6188. XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
  6189. ((size_t)t[1] & addr_mask[y])),
  6190. sizeof(*t[2]) * 106 * 2);
  6191. sp_3072_mont_sqr_106(t[2], t[2], m, mp);
  6192. XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
  6193. ((size_t)t[1] & addr_mask[y])), t[2],
  6194. sizeof(*t[2]) * 106 * 2);
  6195. }
  6196. sp_3072_mont_reduce_106(t[0], m, mp);
  6197. n = sp_3072_cmp_106(t[0], m);
  6198. sp_3072_cond_sub_106(t[0], t[0], m, ~(n >> 31));
  6199. XMEMCPY(r, t[0], sizeof(*r) * 106 * 2);
  6200. }
  6201. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6202. if (td != NULL)
  6203. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  6204. #endif
  6205. return err;
  6206. #else
  6207. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6208. sp_digit* td = NULL;
  6209. #else
  6210. sp_digit td[(16 * 212) + 212];
  6211. #endif
  6212. sp_digit* t[16];
  6213. sp_digit* rt = NULL;
  6214. sp_digit* norm = NULL;
  6215. sp_digit mp = 1;
  6216. sp_digit n;
  6217. int i;
  6218. int c;
  6219. byte y;
  6220. int err = MP_OKAY;
  6221. if (bits == 0) {
  6222. err = MP_VAL;
  6223. }
  6224. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6225. if (err == MP_OKAY) {
  6226. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((16 * 212) + 212), NULL,
  6227. DYNAMIC_TYPE_TMP_BUFFER);
  6228. if (td == NULL)
  6229. err = MEMORY_E;
  6230. }
  6231. #endif
  6232. if (err == MP_OKAY) {
  6233. norm = td;
  6234. for (i=0; i<16; i++)
  6235. t[i] = td + i * 212;
  6236. rt = td + 3392;
  6237. sp_3072_mont_setup(m, &mp);
  6238. sp_3072_mont_norm_106(norm, m);
  6239. if (reduceA != 0) {
  6240. err = sp_3072_mod_106(t[1], a, m);
  6241. if (err == MP_OKAY) {
  6242. sp_3072_mul_106(t[1], t[1], norm);
  6243. err = sp_3072_mod_106(t[1], t[1], m);
  6244. }
  6245. }
  6246. else {
  6247. sp_3072_mul_106(t[1], a, norm);
  6248. err = sp_3072_mod_106(t[1], t[1], m);
  6249. }
  6250. }
  6251. if (err == MP_OKAY) {
  6252. sp_3072_mont_sqr_106(t[ 2], t[ 1], m, mp);
  6253. sp_3072_mont_mul_106(t[ 3], t[ 2], t[ 1], m, mp);
  6254. sp_3072_mont_sqr_106(t[ 4], t[ 2], m, mp);
  6255. sp_3072_mont_mul_106(t[ 5], t[ 3], t[ 2], m, mp);
  6256. sp_3072_mont_sqr_106(t[ 6], t[ 3], m, mp);
  6257. sp_3072_mont_mul_106(t[ 7], t[ 4], t[ 3], m, mp);
  6258. sp_3072_mont_sqr_106(t[ 8], t[ 4], m, mp);
  6259. sp_3072_mont_mul_106(t[ 9], t[ 5], t[ 4], m, mp);
  6260. sp_3072_mont_sqr_106(t[10], t[ 5], m, mp);
  6261. sp_3072_mont_mul_106(t[11], t[ 6], t[ 5], m, mp);
  6262. sp_3072_mont_sqr_106(t[12], t[ 6], m, mp);
  6263. sp_3072_mont_mul_106(t[13], t[ 7], t[ 6], m, mp);
  6264. sp_3072_mont_sqr_106(t[14], t[ 7], m, mp);
  6265. sp_3072_mont_mul_106(t[15], t[ 8], t[ 7], m, mp);
  6266. bits = ((bits + 3) / 4) * 4;
  6267. i = ((bits + 28) / 29) - 1;
  6268. c = bits % 29;
  6269. if (c == 0) {
  6270. c = 29;
  6271. }
  6272. if (i < 106) {
  6273. n = e[i--] << (32 - c);
  6274. }
  6275. else {
  6276. n = 0;
  6277. i--;
  6278. }
  6279. if (c < 4) {
  6280. n |= e[i--] << (3 - c);
  6281. c += 29;
  6282. }
  6283. y = (int)((n >> 28) & 0xf);
  6284. n <<= 4;
  6285. c -= 4;
  6286. XMEMCPY(rt, t[y], sizeof(sp_digit) * 212);
  6287. while ((i >= 0) || (c >= 4)) {
  6288. if (c >= 4) {
  6289. y = (byte)((n >> 28) & 0xf);
  6290. n <<= 4;
  6291. c -= 4;
  6292. }
  6293. else if (c == 0) {
  6294. n = e[i--] << 3;
  6295. y = (byte)((n >> 28) & 0xf);
  6296. n <<= 4;
  6297. c = 25;
  6298. }
  6299. else {
  6300. y = (byte)((n >> 28) & 0xf);
  6301. n = e[i--] << 3;
  6302. c = 4 - c;
  6303. y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
  6304. n <<= c;
  6305. c = 29 - c;
  6306. }
  6307. sp_3072_mont_sqr_106(rt, rt, m, mp);
  6308. sp_3072_mont_sqr_106(rt, rt, m, mp);
  6309. sp_3072_mont_sqr_106(rt, rt, m, mp);
  6310. sp_3072_mont_sqr_106(rt, rt, m, mp);
  6311. sp_3072_mont_mul_106(rt, rt, t[y], m, mp);
  6312. }
  6313. sp_3072_mont_reduce_106(rt, m, mp);
  6314. n = sp_3072_cmp_106(rt, m);
  6315. sp_3072_cond_sub_106(rt, rt, m, ~(n >> 31));
  6316. XMEMCPY(r, rt, sizeof(sp_digit) * 212);
  6317. }
  6318. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6319. if (td != NULL)
  6320. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  6321. #endif
  6322. return err;
  6323. #endif
  6324. }
  6325. #endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
  6326. #ifdef WOLFSSL_HAVE_SP_RSA
  6327. /* RSA public key operation.
  6328. *
  6329. * in Array of bytes representing the number to exponentiate, base.
  6330. * inLen Number of bytes in base.
  6331. * em Public exponent.
  6332. * mm Modulus.
  6333. * out Buffer to hold big-endian bytes of exponentiation result.
  6334. * Must be at least 384 bytes long.
  6335. * outLen Number of bytes in result.
  6336. * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
  6337. * an array is too long and MEMORY_E when dynamic memory allocation fails.
  6338. */
  6339. int sp_RsaPublic_3072(const byte* in, word32 inLen, const mp_int* em,
  6340. const mp_int* mm, byte* out, word32* outLen)
  6341. {
  6342. #ifdef WOLFSSL_SP_SMALL
  6343. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6344. sp_digit* a = NULL;
  6345. #else
  6346. sp_digit a[106 * 5];
  6347. #endif
  6348. sp_digit* m = NULL;
  6349. sp_digit* r = NULL;
  6350. sp_digit* norm = NULL;
  6351. sp_digit e[1] = {0};
  6352. sp_digit mp = 0;
  6353. int i;
  6354. int err = MP_OKAY;
  6355. if (*outLen < 384U) {
  6356. err = MP_TO_E;
  6357. }
  6358. if (err == MP_OKAY) {
  6359. if (mp_count_bits(em) > 29) {
  6360. err = MP_READ_E;
  6361. }
  6362. else if (inLen > 384U) {
  6363. err = MP_READ_E;
  6364. }
  6365. else if (mp_count_bits(mm) != 3072) {
  6366. err = MP_READ_E;
  6367. }
  6368. else if (mp_iseven(mm)) {
  6369. err = MP_VAL;
  6370. }
  6371. }
  6372. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6373. if (err == MP_OKAY) {
  6374. a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 106 * 5, NULL,
  6375. DYNAMIC_TYPE_RSA);
  6376. if (a == NULL)
  6377. err = MEMORY_E;
  6378. }
  6379. #endif
  6380. if (err == MP_OKAY) {
  6381. r = a + 106 * 2;
  6382. m = r + 106 * 2;
  6383. norm = r;
  6384. sp_3072_from_bin(a, 106, in, inLen);
  6385. #if DIGIT_BIT >= 29
  6386. e[0] = (sp_digit)em->dp[0];
  6387. #else
  6388. e[0] = (sp_digit)em->dp[0];
  6389. if (em->used > 1) {
  6390. e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
  6391. }
  6392. #endif
  6393. if (e[0] == 0) {
  6394. err = MP_EXPTMOD_E;
  6395. }
  6396. }
  6397. if (err == MP_OKAY) {
  6398. sp_3072_from_mp(m, 106, mm);
  6399. sp_3072_mont_setup(m, &mp);
  6400. sp_3072_mont_norm_106(norm, m);
  6401. }
  6402. if (err == MP_OKAY) {
  6403. sp_3072_mul_106(a, a, norm);
  6404. err = sp_3072_mod_106(a, a, m);
  6405. }
  6406. if (err == MP_OKAY) {
  6407. for (i=28; i>=0; i--) {
  6408. if ((e[0] >> i) != 0) {
  6409. break;
  6410. }
  6411. }
  6412. XMEMCPY(r, a, sizeof(sp_digit) * 106 * 2);
  6413. for (i--; i>=0; i--) {
  6414. sp_3072_mont_sqr_106(r, r, m, mp);
  6415. if (((e[0] >> i) & 1) == 1) {
  6416. sp_3072_mont_mul_106(r, r, a, m, mp);
  6417. }
  6418. }
  6419. sp_3072_mont_reduce_106(r, m, mp);
  6420. mp = sp_3072_cmp_106(r, m);
  6421. sp_3072_cond_sub_106(r, r, m, ~(mp >> 31));
  6422. sp_3072_to_bin_106(r, out);
  6423. *outLen = 384;
  6424. }
  6425. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6426. if (a != NULL)
  6427. XFREE(a, NULL, DYNAMIC_TYPE_RSA);
  6428. #endif
  6429. return err;
  6430. #else
  6431. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6432. sp_digit* d = NULL;
  6433. #else
  6434. sp_digit d[106 * 5];
  6435. #endif
  6436. sp_digit* a = NULL;
  6437. sp_digit* m = NULL;
  6438. sp_digit* r = NULL;
  6439. sp_digit e[1] = {0};
  6440. int err = MP_OKAY;
  6441. if (*outLen < 384U) {
  6442. err = MP_TO_E;
  6443. }
  6444. if (err == MP_OKAY) {
  6445. if (mp_count_bits(em) > 29) {
  6446. err = MP_READ_E;
  6447. }
  6448. else if (inLen > 384U) {
  6449. err = MP_READ_E;
  6450. }
  6451. else if (mp_count_bits(mm) != 3072) {
  6452. err = MP_READ_E;
  6453. }
  6454. else if (mp_iseven(mm)) {
  6455. err = MP_VAL;
  6456. }
  6457. }
  6458. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6459. if (err == MP_OKAY) {
  6460. d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 106 * 5, NULL,
  6461. DYNAMIC_TYPE_RSA);
  6462. if (d == NULL)
  6463. err = MEMORY_E;
  6464. }
  6465. #endif
  6466. if (err == MP_OKAY) {
  6467. a = d;
  6468. r = a + 106 * 2;
  6469. m = r + 106 * 2;
  6470. sp_3072_from_bin(a, 106, in, inLen);
  6471. #if DIGIT_BIT >= 29
  6472. e[0] = (sp_digit)em->dp[0];
  6473. #else
  6474. e[0] = (sp_digit)em->dp[0];
  6475. if (em->used > 1) {
  6476. e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
  6477. }
  6478. #endif
  6479. if (e[0] == 0) {
  6480. err = MP_EXPTMOD_E;
  6481. }
  6482. }
  6483. if (err == MP_OKAY) {
  6484. sp_3072_from_mp(m, 106, mm);
  6485. if (e[0] == 0x3) {
  6486. sp_3072_sqr_106(r, a);
  6487. err = sp_3072_mod_106(r, r, m);
  6488. if (err == MP_OKAY) {
  6489. sp_3072_mul_106(r, a, r);
  6490. err = sp_3072_mod_106(r, r, m);
  6491. }
  6492. }
  6493. else {
  6494. sp_digit* norm = r;
  6495. int i;
  6496. sp_digit mp;
  6497. sp_3072_mont_setup(m, &mp);
  6498. sp_3072_mont_norm_106(norm, m);
  6499. sp_3072_mul_106(a, a, norm);
  6500. err = sp_3072_mod_106(a, a, m);
  6501. if (err == MP_OKAY) {
  6502. for (i=28; i>=0; i--) {
  6503. if ((e[0] >> i) != 0) {
  6504. break;
  6505. }
  6506. }
  6507. XMEMCPY(r, a, sizeof(sp_digit) * 212U);
  6508. for (i--; i>=0; i--) {
  6509. sp_3072_mont_sqr_106(r, r, m, mp);
  6510. if (((e[0] >> i) & 1) == 1) {
  6511. sp_3072_mont_mul_106(r, r, a, m, mp);
  6512. }
  6513. }
  6514. sp_3072_mont_reduce_106(r, m, mp);
  6515. mp = sp_3072_cmp_106(r, m);
  6516. sp_3072_cond_sub_106(r, r, m, ~(mp >> 31));
  6517. }
  6518. }
  6519. }
  6520. if (err == MP_OKAY) {
  6521. sp_3072_to_bin_106(r, out);
  6522. *outLen = 384;
  6523. }
  6524. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6525. if (d != NULL)
  6526. XFREE(d, NULL, DYNAMIC_TYPE_RSA);
  6527. #endif
  6528. return err;
  6529. #endif /* WOLFSSL_SP_SMALL */
  6530. }
  6531. #ifndef WOLFSSL_RSA_PUBLIC_ONLY
  6532. #if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM)
  6533. #endif /* !SP_RSA_PRIVATE_EXP_D & !RSA_LOW_MEM */
  6534. /* RSA private key operation.
  6535. *
  6536. * in Array of bytes representing the number to exponentiate, base.
  6537. * inLen Number of bytes in base.
  6538. * dm Private exponent.
  6539. * pm First prime.
  6540. * qm Second prime.
  6541. * dpm First prime's CRT exponent.
  6542. * dqm Second prime's CRT exponent.
  6543. * qim Inverse of second prime mod p.
  6544. * mm Modulus.
  6545. * out Buffer to hold big-endian bytes of exponentiation result.
  6546. * Must be at least 384 bytes long.
  6547. * outLen Number of bytes in result.
  6548. * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
  6549. * an array is too long and MEMORY_E when dynamic memory allocation fails.
  6550. */
  6551. int sp_RsaPrivate_3072(const byte* in, word32 inLen, const mp_int* dm,
  6552. const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
  6553. const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
  6554. {
  6555. #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
  6556. #if defined(WOLFSSL_SP_SMALL)
  6557. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6558. sp_digit* d = NULL;
  6559. #else
  6560. sp_digit d[106 * 4];
  6561. #endif
  6562. sp_digit* a = NULL;
  6563. sp_digit* m = NULL;
  6564. sp_digit* r = NULL;
  6565. int err = MP_OKAY;
  6566. (void)pm;
  6567. (void)qm;
  6568. (void)dpm;
  6569. (void)dqm;
  6570. (void)qim;
  6571. if (*outLen < 384U) {
  6572. err = MP_TO_E;
  6573. }
  6574. if (err == MP_OKAY) {
  6575. if (mp_count_bits(dm) > 3072) {
  6576. err = MP_READ_E;
  6577. }
  6578. else if (inLen > 384) {
  6579. err = MP_READ_E;
  6580. }
  6581. else if (mp_count_bits(mm) != 3072) {
  6582. err = MP_READ_E;
  6583. }
  6584. else if (mp_iseven(mm)) {
  6585. err = MP_VAL;
  6586. }
  6587. }
  6588. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6589. if (err == MP_OKAY) {
  6590. d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 106 * 4, NULL,
  6591. DYNAMIC_TYPE_RSA);
  6592. if (d == NULL)
  6593. err = MEMORY_E;
  6594. }
  6595. #endif
  6596. if (err == MP_OKAY) {
  6597. a = d + 106;
  6598. m = a + 212;
  6599. r = a;
  6600. sp_3072_from_bin(a, 106, in, inLen);
  6601. sp_3072_from_mp(d, 106, dm);
  6602. sp_3072_from_mp(m, 106, mm);
  6603. err = sp_3072_mod_exp_106(r, a, d, 3072, m, 0);
  6604. }
  6605. if (err == MP_OKAY) {
  6606. sp_3072_to_bin_106(r, out);
  6607. *outLen = 384;
  6608. }
  6609. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6610. if (d != NULL)
  6611. #endif
  6612. {
  6613. /* only "a" and "r" are sensitive and need zeroized (same pointer) */
  6614. if (a != NULL)
  6615. ForceZero(a, sizeof(sp_digit) * 106);
  6616. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6617. XFREE(d, NULL, DYNAMIC_TYPE_RSA);
  6618. #endif
  6619. }
  6620. return err;
  6621. #else
  6622. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6623. sp_digit* d = NULL;
  6624. #else
  6625. sp_digit d[106 * 4];
  6626. #endif
  6627. sp_digit* a = NULL;
  6628. sp_digit* m = NULL;
  6629. sp_digit* r = NULL;
  6630. int err = MP_OKAY;
  6631. (void)pm;
  6632. (void)qm;
  6633. (void)dpm;
  6634. (void)dqm;
  6635. (void)qim;
  6636. if (*outLen < 384U) {
  6637. err = MP_TO_E;
  6638. }
  6639. if (err == MP_OKAY) {
  6640. if (mp_count_bits(dm) > 3072) {
  6641. err = MP_READ_E;
  6642. }
  6643. else if (inLen > 384U) {
  6644. err = MP_READ_E;
  6645. }
  6646. else if (mp_count_bits(mm) != 3072) {
  6647. err = MP_READ_E;
  6648. }
  6649. else if (mp_iseven(mm)) {
  6650. err = MP_VAL;
  6651. }
  6652. }
  6653. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6654. if (err == MP_OKAY) {
  6655. d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 106 * 4, NULL,
  6656. DYNAMIC_TYPE_RSA);
  6657. if (d == NULL)
  6658. err = MEMORY_E;
  6659. }
  6660. #endif
  6661. if (err == MP_OKAY) {
  6662. a = d + 106;
  6663. m = a + 212;
  6664. r = a;
  6665. sp_3072_from_bin(a, 106, in, inLen);
  6666. sp_3072_from_mp(d, 106, dm);
  6667. sp_3072_from_mp(m, 106, mm);
  6668. err = sp_3072_mod_exp_106(r, a, d, 3072, m, 0);
  6669. }
  6670. if (err == MP_OKAY) {
  6671. sp_3072_to_bin_106(r, out);
  6672. *outLen = 384;
  6673. }
  6674. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6675. if (d != NULL)
  6676. #endif
  6677. {
  6678. /* only "a" and "r" are sensitive and need zeroized (same pointer) */
  6679. if (a != NULL)
  6680. ForceZero(a, sizeof(sp_digit) * 106);
  6681. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6682. XFREE(d, NULL, DYNAMIC_TYPE_RSA);
  6683. #endif
  6684. }
  6685. return err;
  6686. #endif /* WOLFSSL_SP_SMALL */
  6687. #else
  6688. #if defined(WOLFSSL_SP_SMALL)
  6689. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6690. sp_digit* a = NULL;
  6691. #else
  6692. sp_digit a[53 * 8];
  6693. #endif
  6694. sp_digit* p = NULL;
  6695. sp_digit* dp = NULL;
  6696. sp_digit* dq = NULL;
  6697. sp_digit* qi = NULL;
  6698. sp_digit* tmpa = NULL;
  6699. sp_digit* tmpb = NULL;
  6700. sp_digit* r = NULL;
  6701. int err = MP_OKAY;
  6702. (void)dm;
  6703. (void)mm;
  6704. if (*outLen < 384U) {
  6705. err = MP_TO_E;
  6706. }
  6707. if (err == MP_OKAY) {
  6708. if (inLen > 384) {
  6709. err = MP_READ_E;
  6710. }
  6711. else if (mp_count_bits(mm) != 3072) {
  6712. err = MP_READ_E;
  6713. }
  6714. else if (mp_iseven(mm)) {
  6715. err = MP_VAL;
  6716. }
  6717. else if (mp_iseven(pm)) {
  6718. err = MP_VAL;
  6719. }
  6720. else if (mp_iseven(qm)) {
  6721. err = MP_VAL;
  6722. }
  6723. }
  6724. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6725. if (err == MP_OKAY) {
  6726. a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 53 * 8, NULL,
  6727. DYNAMIC_TYPE_RSA);
  6728. if (a == NULL)
  6729. err = MEMORY_E;
  6730. }
  6731. #endif
  6732. if (err == MP_OKAY) {
  6733. p = a + 106;
  6734. qi = dq = dp = p + 53;
  6735. tmpa = qi + 53;
  6736. tmpb = tmpa + 106;
  6737. r = a;
  6738. sp_3072_from_bin(a, 106, in, inLen);
  6739. sp_3072_from_mp(p, 53, pm);
  6740. sp_3072_from_mp(dp, 53, dpm);
  6741. err = sp_3072_mod_exp_53(tmpa, a, dp, 1536, p, 1);
  6742. }
  6743. if (err == MP_OKAY) {
  6744. sp_3072_from_mp(p, 53, qm);
  6745. sp_3072_from_mp(dq, 53, dqm);
  6746. err = sp_3072_mod_exp_53(tmpb, a, dq, 1536, p, 1);
  6747. }
  6748. if (err == MP_OKAY) {
  6749. sp_3072_from_mp(p, 53, pm);
  6750. (void)sp_3072_sub_53(tmpa, tmpa, tmpb);
  6751. sp_3072_norm_53(tmpa);
  6752. sp_3072_cond_add_53(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[52] >> 31));
  6753. sp_3072_cond_add_53(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[52] >> 31));
  6754. sp_3072_norm_53(tmpa);
  6755. sp_3072_from_mp(qi, 53, qim);
  6756. sp_3072_mul_53(tmpa, tmpa, qi);
  6757. err = sp_3072_mod_53(tmpa, tmpa, p);
  6758. }
  6759. if (err == MP_OKAY) {
  6760. sp_3072_from_mp(p, 53, qm);
  6761. sp_3072_mul_53(tmpa, p, tmpa);
  6762. (void)sp_3072_add_106(r, tmpb, tmpa);
  6763. sp_3072_norm_106(r);
  6764. sp_3072_to_bin_106(r, out);
  6765. *outLen = 384;
  6766. }
  6767. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6768. if (a != NULL)
  6769. #endif
  6770. {
  6771. ForceZero(a, sizeof(sp_digit) * 53 * 8);
  6772. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6773. XFREE(a, NULL, DYNAMIC_TYPE_RSA);
  6774. #endif
  6775. }
  6776. return err;
  6777. #else
  6778. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6779. sp_digit* a = NULL;
  6780. #else
  6781. sp_digit a[53 * 13];
  6782. #endif
  6783. sp_digit* p = NULL;
  6784. sp_digit* q = NULL;
  6785. sp_digit* dp = NULL;
  6786. sp_digit* dq = NULL;
  6787. sp_digit* qi = NULL;
  6788. sp_digit* tmpa = NULL;
  6789. sp_digit* tmpb = NULL;
  6790. sp_digit* r = NULL;
  6791. int err = MP_OKAY;
  6792. (void)dm;
  6793. (void)mm;
  6794. if (*outLen < 384U) {
  6795. err = MP_TO_E;
  6796. }
  6797. if (err == MP_OKAY) {
  6798. if (inLen > 384U) {
  6799. err = MP_READ_E;
  6800. }
  6801. else if (mp_count_bits(mm) != 3072) {
  6802. err = MP_READ_E;
  6803. }
  6804. else if (mp_iseven(mm)) {
  6805. err = MP_VAL;
  6806. }
  6807. else if (mp_iseven(pm)) {
  6808. err = MP_VAL;
  6809. }
  6810. else if (mp_iseven(qm)) {
  6811. err = MP_VAL;
  6812. }
  6813. }
  6814. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6815. if (err == MP_OKAY) {
  6816. a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 53 * 13, NULL,
  6817. DYNAMIC_TYPE_RSA);
  6818. if (a == NULL)
  6819. err = MEMORY_E;
  6820. }
  6821. #endif
  6822. if (err == MP_OKAY) {
  6823. p = a + 106 * 2;
  6824. q = p + 53;
  6825. dp = q + 53;
  6826. dq = dp + 53;
  6827. qi = dq + 53;
  6828. tmpa = qi + 53;
  6829. tmpb = tmpa + 106;
  6830. r = a;
  6831. sp_3072_from_bin(a, 106, in, inLen);
  6832. sp_3072_from_mp(p, 53, pm);
  6833. sp_3072_from_mp(q, 53, qm);
  6834. sp_3072_from_mp(dp, 53, dpm);
  6835. sp_3072_from_mp(dq, 53, dqm);
  6836. sp_3072_from_mp(qi, 53, qim);
  6837. err = sp_3072_mod_exp_53(tmpa, a, dp, 1536, p, 1);
  6838. }
  6839. if (err == MP_OKAY) {
  6840. err = sp_3072_mod_exp_53(tmpb, a, dq, 1536, q, 1);
  6841. }
  6842. if (err == MP_OKAY) {
  6843. (void)sp_3072_sub_53(tmpa, tmpa, tmpb);
  6844. sp_3072_norm_53(tmpa);
  6845. sp_3072_cond_add_53(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[52] >> 31));
  6846. sp_3072_cond_add_53(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[52] >> 31));
  6847. sp_3072_norm_53(tmpa);
  6848. sp_3072_mul_53(tmpa, tmpa, qi);
  6849. err = sp_3072_mod_53(tmpa, tmpa, p);
  6850. }
  6851. if (err == MP_OKAY) {
  6852. sp_3072_mul_53(tmpa, tmpa, q);
  6853. (void)sp_3072_add_106(r, tmpb, tmpa);
  6854. sp_3072_norm_106(r);
  6855. sp_3072_to_bin_106(r, out);
  6856. *outLen = 384;
  6857. }
  6858. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6859. if (a != NULL)
  6860. #endif
  6861. {
  6862. ForceZero(a, sizeof(sp_digit) * 53 * 13);
  6863. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6864. XFREE(a, NULL, DYNAMIC_TYPE_RSA);
  6865. #endif
  6866. }
  6867. return err;
  6868. #endif /* WOLFSSL_SP_SMALL */
  6869. #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
  6870. }
  6871. #endif /* !WOLFSSL_RSA_PUBLIC_ONLY */
  6872. #endif /* WOLFSSL_HAVE_SP_RSA */
  6873. #if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \
  6874. !defined(WOLFSSL_RSA_PUBLIC_ONLY))
  6875. /* Convert an array of sp_digit to an mp_int.
  6876. *
  6877. * a A single precision integer.
  6878. * r A multi-precision integer.
  6879. */
  6880. static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
  6881. {
  6882. int err;
  6883. err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT);
  6884. if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
  6885. #if DIGIT_BIT == 29
  6886. XMEMCPY(r->dp, a, sizeof(sp_digit) * 106);
  6887. r->used = 106;
  6888. mp_clamp(r);
  6889. #elif DIGIT_BIT < 29
  6890. int i;
  6891. int j = 0;
  6892. int s = 0;
  6893. r->dp[0] = 0;
  6894. for (i = 0; i < 106; i++) {
  6895. r->dp[j] |= (mp_digit)(a[i] << s);
  6896. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  6897. s = DIGIT_BIT - s;
  6898. r->dp[++j] = (mp_digit)(a[i] >> s);
  6899. while (s + DIGIT_BIT <= 29) {
  6900. s += DIGIT_BIT;
  6901. r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  6902. if (s == SP_WORD_SIZE) {
  6903. r->dp[j] = 0;
  6904. }
  6905. else {
  6906. r->dp[j] = (mp_digit)(a[i] >> s);
  6907. }
  6908. }
  6909. s = 29 - s;
  6910. }
  6911. r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
  6912. mp_clamp(r);
  6913. #else
  6914. int i;
  6915. int j = 0;
  6916. int s = 0;
  6917. r->dp[0] = 0;
  6918. for (i = 0; i < 106; i++) {
  6919. r->dp[j] |= ((mp_digit)a[i]) << s;
  6920. if (s + 29 >= DIGIT_BIT) {
  6921. #if DIGIT_BIT != 32 && DIGIT_BIT != 64
  6922. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  6923. #endif
  6924. s = DIGIT_BIT - s;
  6925. r->dp[++j] = a[i] >> s;
  6926. s = 29 - s;
  6927. }
  6928. else {
  6929. s += 29;
  6930. }
  6931. }
  6932. r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
  6933. mp_clamp(r);
  6934. #endif
  6935. }
  6936. return err;
  6937. }
  6938. /* Perform the modular exponentiation for Diffie-Hellman.
  6939. *
  6940. * base Base. MP integer.
  6941. * exp Exponent. MP integer.
  6942. * mod Modulus. MP integer.
  6943. * res Result. MP integer.
  6944. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  6945. * and MEMORY_E if memory allocation fails.
  6946. */
  6947. int sp_ModExp_3072(const mp_int* base, const mp_int* exp, const mp_int* mod,
  6948. mp_int* res)
  6949. {
  6950. #ifdef WOLFSSL_SP_SMALL
  6951. int err = MP_OKAY;
  6952. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6953. sp_digit* b = NULL;
  6954. #else
  6955. sp_digit b[106 * 4];
  6956. #endif
  6957. sp_digit* e = NULL;
  6958. sp_digit* m = NULL;
  6959. sp_digit* r = NULL;
  6960. int expBits = mp_count_bits(exp);
  6961. if (mp_count_bits(base) > 3072) {
  6962. err = MP_READ_E;
  6963. }
  6964. else if (expBits > 3072) {
  6965. err = MP_READ_E;
  6966. }
  6967. else if (mp_count_bits(mod) != 3072) {
  6968. err = MP_READ_E;
  6969. }
  6970. else if (mp_iseven(mod)) {
  6971. err = MP_VAL;
  6972. }
  6973. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6974. if (err == MP_OKAY) {
  6975. b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 106 * 4, NULL,
  6976. DYNAMIC_TYPE_DH);
  6977. if (b == NULL)
  6978. err = MEMORY_E;
  6979. }
  6980. #endif
  6981. if (err == MP_OKAY) {
  6982. e = b + 106 * 2;
  6983. m = e + 106;
  6984. r = b;
  6985. sp_3072_from_mp(b, 106, base);
  6986. sp_3072_from_mp(e, 106, exp);
  6987. sp_3072_from_mp(m, 106, mod);
  6988. err = sp_3072_mod_exp_106(r, b, e, mp_count_bits(exp), m, 0);
  6989. }
  6990. if (err == MP_OKAY) {
  6991. err = sp_3072_to_mp(r, res);
  6992. }
  6993. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  6994. if (b != NULL)
  6995. #endif
  6996. {
  6997. /* only "e" is sensitive and needs zeroized */
  6998. if (e != NULL)
  6999. ForceZero(e, sizeof(sp_digit) * 106U);
  7000. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  7001. XFREE(b, NULL, DYNAMIC_TYPE_DH);
  7002. #endif
  7003. }
  7004. return err;
  7005. #else
  7006. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  7007. sp_digit* b = NULL;
  7008. #else
  7009. sp_digit b[106 * 4];
  7010. #endif
  7011. sp_digit* e = NULL;
  7012. sp_digit* m = NULL;
  7013. sp_digit* r = NULL;
  7014. int err = MP_OKAY;
  7015. int expBits = mp_count_bits(exp);
  7016. if (mp_count_bits(base) > 3072) {
  7017. err = MP_READ_E;
  7018. }
  7019. else if (expBits > 3072) {
  7020. err = MP_READ_E;
  7021. }
  7022. else if (mp_count_bits(mod) != 3072) {
  7023. err = MP_READ_E;
  7024. }
  7025. else if (mp_iseven(mod)) {
  7026. err = MP_VAL;
  7027. }
  7028. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  7029. if (err == MP_OKAY) {
  7030. b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 106 * 4, NULL, DYNAMIC_TYPE_DH);
  7031. if (b == NULL)
  7032. err = MEMORY_E;
  7033. }
  7034. #endif
  7035. if (err == MP_OKAY) {
  7036. e = b + 106 * 2;
  7037. m = e + 106;
  7038. r = b;
  7039. sp_3072_from_mp(b, 106, base);
  7040. sp_3072_from_mp(e, 106, exp);
  7041. sp_3072_from_mp(m, 106, mod);
  7042. err = sp_3072_mod_exp_106(r, b, e, expBits, m, 0);
  7043. }
  7044. if (err == MP_OKAY) {
  7045. err = sp_3072_to_mp(r, res);
  7046. }
  7047. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  7048. if (b != NULL)
  7049. #endif
  7050. {
  7051. /* only "e" is sensitive and needs zeroized */
  7052. if (e != NULL)
  7053. ForceZero(e, sizeof(sp_digit) * 106U);
  7054. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  7055. XFREE(b, NULL, DYNAMIC_TYPE_DH);
  7056. #endif
  7057. }
  7058. return err;
  7059. #endif
  7060. }
  7061. #ifdef WOLFSSL_HAVE_SP_DH
  7062. #ifdef HAVE_FFDHE_3072
  7063. SP_NOINLINE static void sp_3072_lshift_106(sp_digit* r, const sp_digit* a,
  7064. byte n)
  7065. {
  7066. int i;
  7067. r[106] = a[105] >> (29 - n);
  7068. for (i=105; i>0; i--) {
  7069. r[i] = ((a[i] << n) | (a[i-1] >> (29 - n))) & 0x1fffffff;
  7070. }
  7071. r[0] = (a[0] << n) & 0x1fffffff;
  7072. }
  7073. /* Modular exponentiate 2 to the e mod m. (r = 2^e mod m)
  7074. *
  7075. * r A single precision number that is the result of the operation.
  7076. * e A single precision number that is the exponent.
  7077. * bits The number of bits in the exponent.
  7078. * m A single precision number that is the modulus.
  7079. * returns 0 on success.
  7080. * returns MEMORY_E on dynamic memory allocation failure.
  7081. * returns MP_VAL when base is even.
  7082. */
  7083. static int sp_3072_mod_exp_2_106(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m)
  7084. {
  7085. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  7086. sp_digit* td = NULL;
  7087. #else
  7088. sp_digit td[319];
  7089. #endif
  7090. sp_digit* norm = NULL;
  7091. sp_digit* tmp = NULL;
  7092. sp_digit mp = 1;
  7093. sp_digit n;
  7094. sp_digit o;
  7095. int i;
  7096. int c;
  7097. byte y;
  7098. int err = MP_OKAY;
  7099. if (bits == 0) {
  7100. err = MP_VAL;
  7101. }
  7102. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  7103. if (err == MP_OKAY) {
  7104. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 319, NULL,
  7105. DYNAMIC_TYPE_TMP_BUFFER);
  7106. if (td == NULL)
  7107. err = MEMORY_E;
  7108. }
  7109. #endif
  7110. if (err == MP_OKAY) {
  7111. norm = td;
  7112. tmp = td + 212;
  7113. XMEMSET(td, 0, sizeof(sp_digit) * 319);
  7114. sp_3072_mont_setup(m, &mp);
  7115. sp_3072_mont_norm_106(norm, m);
  7116. bits = ((bits + 3) / 4) * 4;
  7117. i = ((bits + 28) / 29) - 1;
  7118. c = bits % 29;
  7119. if (c == 0) {
  7120. c = 29;
  7121. }
  7122. if (i < 106) {
  7123. n = e[i--] << (32 - c);
  7124. }
  7125. else {
  7126. n = 0;
  7127. i--;
  7128. }
  7129. if (c < 4) {
  7130. n |= e[i--] << (3 - c);
  7131. c += 29;
  7132. }
  7133. y = (int)((n >> 28) & 0xf);
  7134. n <<= 4;
  7135. c -= 4;
  7136. sp_3072_lshift_106(r, norm, (byte)y);
  7137. while ((i >= 0) || (c >= 4)) {
  7138. if (c >= 4) {
  7139. y = (byte)((n >> 28) & 0xf);
  7140. n <<= 4;
  7141. c -= 4;
  7142. }
  7143. else if (c == 0) {
  7144. n = e[i--] << 3;
  7145. y = (byte)((n >> 28) & 0xf);
  7146. n <<= 4;
  7147. c = 25;
  7148. }
  7149. else {
  7150. y = (byte)((n >> 28) & 0xf);
  7151. n = e[i--] << 3;
  7152. c = 4 - c;
  7153. y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
  7154. n <<= c;
  7155. c = 29 - c;
  7156. }
  7157. sp_3072_mont_sqr_106(r, r, m, mp);
  7158. sp_3072_mont_sqr_106(r, r, m, mp);
  7159. sp_3072_mont_sqr_106(r, r, m, mp);
  7160. sp_3072_mont_sqr_106(r, r, m, mp);
  7161. sp_3072_lshift_106(r, r, (byte)y);
  7162. sp_3072_mul_d_106(tmp, norm, (r[106] << 2) + (r[105] >> 27));
  7163. r[106] = 0;
  7164. r[105] &= 0x7ffffffL;
  7165. (void)sp_3072_add_106(r, r, tmp);
  7166. sp_3072_norm_106(r);
  7167. o = sp_3072_cmp_106(r, m);
  7168. sp_3072_cond_sub_106(r, r, m, ~(o >> 31));
  7169. }
  7170. sp_3072_mont_reduce_106(r, m, mp);
  7171. n = sp_3072_cmp_106(r, m);
  7172. sp_3072_cond_sub_106(r, r, m, ~(n >> 31));
  7173. }
  7174. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  7175. if (td != NULL)
  7176. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  7177. #endif
  7178. return err;
  7179. }
  7180. #endif /* HAVE_FFDHE_3072 */
  7181. /* Perform the modular exponentiation for Diffie-Hellman.
  7182. *
  7183. * base Base.
  7184. * exp Array of bytes that is the exponent.
  7185. * expLen Length of data, in bytes, in exponent.
  7186. * mod Modulus.
  7187. * out Buffer to hold big-endian bytes of exponentiation result.
  7188. * Must be at least 384 bytes long.
  7189. * outLen Length, in bytes, of exponentiation result.
  7190. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  7191. * and MEMORY_E if memory allocation fails.
  7192. */
  7193. int sp_DhExp_3072(const mp_int* base, const byte* exp, word32 expLen,
  7194. const mp_int* mod, byte* out, word32* outLen)
  7195. {
  7196. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  7197. sp_digit* b = NULL;
  7198. #else
  7199. sp_digit b[106 * 4];
  7200. #endif
  7201. sp_digit* e = NULL;
  7202. sp_digit* m = NULL;
  7203. sp_digit* r = NULL;
  7204. word32 i;
  7205. int err = MP_OKAY;
  7206. if (mp_count_bits(base) > 3072) {
  7207. err = MP_READ_E;
  7208. }
  7209. else if (expLen > 384U) {
  7210. err = MP_READ_E;
  7211. }
  7212. else if (mp_count_bits(mod) != 3072) {
  7213. err = MP_READ_E;
  7214. }
  7215. else if (mp_iseven(mod)) {
  7216. err = MP_VAL;
  7217. }
  7218. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  7219. if (err == MP_OKAY) {
  7220. b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 106 * 4, NULL,
  7221. DYNAMIC_TYPE_DH);
  7222. if (b == NULL)
  7223. err = MEMORY_E;
  7224. }
  7225. #endif
  7226. if (err == MP_OKAY) {
  7227. e = b + 106 * 2;
  7228. m = e + 106;
  7229. r = b;
  7230. sp_3072_from_mp(b, 106, base);
  7231. sp_3072_from_bin(e, 106, exp, expLen);
  7232. sp_3072_from_mp(m, 106, mod);
  7233. #ifdef HAVE_FFDHE_3072
  7234. if (base->used == 1 && base->dp[0] == 2U &&
  7235. (m[105] >> 11) == 0xffffL) {
  7236. err = sp_3072_mod_exp_2_106(r, e, expLen * 8U, m);
  7237. }
  7238. else {
  7239. #endif
  7240. err = sp_3072_mod_exp_106(r, b, e, expLen * 8U, m, 0);
  7241. #ifdef HAVE_FFDHE_3072
  7242. }
  7243. #endif
  7244. }
  7245. if (err == MP_OKAY) {
  7246. sp_3072_to_bin_106(r, out);
  7247. *outLen = 384;
  7248. for (i=0; i<384U && out[i] == 0U; i++) {
  7249. /* Search for first non-zero. */
  7250. }
  7251. *outLen -= i;
  7252. XMEMMOVE(out, out + i, *outLen);
  7253. }
  7254. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  7255. if (b != NULL)
  7256. #endif
  7257. {
  7258. /* only "e" is sensitive and needs zeroized */
  7259. if (e != NULL)
  7260. ForceZero(e, sizeof(sp_digit) * 106U);
  7261. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  7262. XFREE(b, NULL, DYNAMIC_TYPE_DH);
  7263. #endif
  7264. }
  7265. return err;
  7266. }
  7267. #endif /* WOLFSSL_HAVE_SP_DH */
  7268. /* Perform the modular exponentiation for Diffie-Hellman.
  7269. *
  7270. * base Base. MP integer.
  7271. * exp Exponent. MP integer.
  7272. * mod Modulus. MP integer.
  7273. * res Result. MP integer.
  7274. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  7275. * and MEMORY_E if memory allocation fails.
  7276. */
  7277. int sp_ModExp_1536(const mp_int* base, const mp_int* exp, const mp_int* mod,
  7278. mp_int* res)
  7279. {
  7280. #ifdef WOLFSSL_SP_SMALL
  7281. int err = MP_OKAY;
  7282. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  7283. sp_digit* b = NULL;
  7284. #else
  7285. sp_digit b[53 * 4];
  7286. #endif
  7287. sp_digit* e = NULL;
  7288. sp_digit* m = NULL;
  7289. sp_digit* r = NULL;
  7290. int expBits = mp_count_bits(exp);
  7291. if (mp_count_bits(base) > 1536) {
  7292. err = MP_READ_E;
  7293. }
  7294. else if (expBits > 1536) {
  7295. err = MP_READ_E;
  7296. }
  7297. else if (mp_count_bits(mod) != 1536) {
  7298. err = MP_READ_E;
  7299. }
  7300. else if (mp_iseven(mod)) {
  7301. err = MP_VAL;
  7302. }
  7303. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  7304. if (err == MP_OKAY) {
  7305. b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 53 * 4, NULL,
  7306. DYNAMIC_TYPE_DH);
  7307. if (b == NULL)
  7308. err = MEMORY_E;
  7309. }
  7310. #endif
  7311. if (err == MP_OKAY) {
  7312. e = b + 53 * 2;
  7313. m = e + 53;
  7314. r = b;
  7315. sp_3072_from_mp(b, 53, base);
  7316. sp_3072_from_mp(e, 53, exp);
  7317. sp_3072_from_mp(m, 53, mod);
  7318. err = sp_3072_mod_exp_53(r, b, e, mp_count_bits(exp), m, 0);
  7319. }
  7320. if (err == MP_OKAY) {
  7321. XMEMSET(r + 53, 0, sizeof(*r) * 53U);
  7322. err = sp_3072_to_mp(r, res);
  7323. }
  7324. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  7325. if (b != NULL)
  7326. #endif
  7327. {
  7328. /* only "e" is sensitive and needs zeroized */
  7329. if (e != NULL)
  7330. ForceZero(e, sizeof(sp_digit) * 106U);
  7331. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  7332. XFREE(b, NULL, DYNAMIC_TYPE_DH);
  7333. #endif
  7334. }
  7335. return err;
  7336. #else
  7337. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  7338. sp_digit* b = NULL;
  7339. #else
  7340. sp_digit b[53 * 4];
  7341. #endif
  7342. sp_digit* e = NULL;
  7343. sp_digit* m = NULL;
  7344. sp_digit* r = NULL;
  7345. int err = MP_OKAY;
  7346. int expBits = mp_count_bits(exp);
  7347. if (mp_count_bits(base) > 1536) {
  7348. err = MP_READ_E;
  7349. }
  7350. else if (expBits > 1536) {
  7351. err = MP_READ_E;
  7352. }
  7353. else if (mp_count_bits(mod) != 1536) {
  7354. err = MP_READ_E;
  7355. }
  7356. else if (mp_iseven(mod)) {
  7357. err = MP_VAL;
  7358. }
  7359. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  7360. if (err == MP_OKAY) {
  7361. b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 53 * 4, NULL, DYNAMIC_TYPE_DH);
  7362. if (b == NULL)
  7363. err = MEMORY_E;
  7364. }
  7365. #endif
  7366. if (err == MP_OKAY) {
  7367. e = b + 53 * 2;
  7368. m = e + 53;
  7369. r = b;
  7370. sp_3072_from_mp(b, 53, base);
  7371. sp_3072_from_mp(e, 53, exp);
  7372. sp_3072_from_mp(m, 53, mod);
  7373. err = sp_3072_mod_exp_53(r, b, e, expBits, m, 0);
  7374. }
  7375. if (err == MP_OKAY) {
  7376. XMEMSET(r + 53, 0, sizeof(*r) * 53U);
  7377. err = sp_3072_to_mp(r, res);
  7378. }
  7379. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  7380. if (b != NULL)
  7381. #endif
  7382. {
  7383. /* only "e" is sensitive and needs zeroized */
  7384. if (e != NULL)
  7385. ForceZero(e, sizeof(sp_digit) * 106U);
  7386. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  7387. XFREE(b, NULL, DYNAMIC_TYPE_DH);
  7388. #endif
  7389. }
  7390. return err;
  7391. #endif
  7392. }
  7393. #endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
  7394. #else
  7395. /* Read big endian unsigned byte array into r.
  7396. *
  7397. * r A single precision integer.
  7398. * size Maximum number of bytes to convert
  7399. * a Byte array.
  7400. * n Number of bytes in array to read.
  7401. */
  7402. static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n)
  7403. {
  7404. int i;
  7405. int j = 0;
  7406. word32 s = 0;
  7407. r[0] = 0;
  7408. for (i = n-1; i >= 0; i--) {
  7409. r[j] |= (((sp_digit)a[i]) << s);
  7410. if (s >= 20U) {
  7411. r[j] &= 0xfffffff;
  7412. s = 28U - s;
  7413. if (j + 1 >= size) {
  7414. break;
  7415. }
  7416. r[++j] = (sp_digit)a[i] >> s;
  7417. s = 8U - s;
  7418. }
  7419. else {
  7420. s += 8U;
  7421. }
  7422. }
  7423. for (j++; j < size; j++) {
  7424. r[j] = 0;
  7425. }
  7426. }
  7427. /* Convert an mp_int to an array of sp_digit.
  7428. *
  7429. * r A single precision integer.
  7430. * size Maximum number of bytes to convert
  7431. * a A multi-precision integer.
  7432. */
  7433. static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
  7434. {
  7435. #if DIGIT_BIT == 28
  7436. int j;
  7437. XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
  7438. for (j = a->used; j < size; j++) {
  7439. r[j] = 0;
  7440. }
  7441. #elif DIGIT_BIT > 28
  7442. int i;
  7443. int j = 0;
  7444. word32 s = 0;
  7445. r[0] = 0;
  7446. for (i = 0; i < a->used && j < size; i++) {
  7447. r[j] |= ((sp_digit)a->dp[i] << s);
  7448. r[j] &= 0xfffffff;
  7449. s = 28U - s;
  7450. if (j + 1 >= size) {
  7451. break;
  7452. }
  7453. /* lint allow cast of mismatch word32 and mp_digit */
  7454. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  7455. while ((s + 28U) <= (word32)DIGIT_BIT) {
  7456. s += 28U;
  7457. r[j] &= 0xfffffff;
  7458. if (j + 1 >= size) {
  7459. break;
  7460. }
  7461. if (s < (word32)DIGIT_BIT) {
  7462. /* lint allow cast of mismatch word32 and mp_digit */
  7463. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  7464. }
  7465. else {
  7466. r[++j] = (sp_digit)0;
  7467. }
  7468. }
  7469. s = (word32)DIGIT_BIT - s;
  7470. }
  7471. for (j++; j < size; j++) {
  7472. r[j] = 0;
  7473. }
  7474. #else
  7475. int i;
  7476. int j = 0;
  7477. int s = 0;
  7478. r[0] = 0;
  7479. for (i = 0; i < a->used && j < size; i++) {
  7480. r[j] |= ((sp_digit)a->dp[i]) << s;
  7481. if (s + DIGIT_BIT >= 28) {
  7482. r[j] &= 0xfffffff;
  7483. if (j + 1 >= size) {
  7484. break;
  7485. }
  7486. s = 28 - s;
  7487. if (s == DIGIT_BIT) {
  7488. r[++j] = 0;
  7489. s = 0;
  7490. }
  7491. else {
  7492. r[++j] = a->dp[i] >> s;
  7493. s = DIGIT_BIT - s;
  7494. }
  7495. }
  7496. else {
  7497. s += DIGIT_BIT;
  7498. }
  7499. }
  7500. for (j++; j < size; j++) {
  7501. r[j] = 0;
  7502. }
  7503. #endif
  7504. }
  7505. /* Write r as big endian to byte array.
  7506. * Fixed length number of bytes written: 384
  7507. *
  7508. * r A single precision integer.
  7509. * a Byte array.
  7510. */
  7511. static void sp_3072_to_bin_112(sp_digit* r, byte* a)
  7512. {
  7513. int i;
  7514. int j;
  7515. int s = 0;
  7516. int b;
  7517. for (i=0; i<111; i++) {
  7518. r[i+1] += r[i] >> 28;
  7519. r[i] &= 0xfffffff;
  7520. }
  7521. j = 3079 / 8 - 1;
  7522. a[j] = 0;
  7523. for (i=0; i<112 && j>=0; i++) {
  7524. b = 0;
  7525. /* lint allow cast of mismatch sp_digit and int */
  7526. a[j--] |= (byte)(r[i] << s); /*lint !e9033*/
  7527. b += 8 - s;
  7528. if (j < 0) {
  7529. break;
  7530. }
  7531. while (b < 28) {
  7532. a[j--] = (byte)(r[i] >> b);
  7533. b += 8;
  7534. if (j < 0) {
  7535. break;
  7536. }
  7537. }
  7538. s = 8 - (b - 28);
  7539. if (j >= 0) {
  7540. a[j] = 0;
  7541. }
  7542. if (s != 0) {
  7543. j++;
  7544. }
  7545. }
  7546. }
  7547. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  7548. /* Normalize the values in each word to 28 bits.
  7549. *
  7550. * a Array of sp_digit to normalize.
  7551. */
  7552. static void sp_3072_norm_56(sp_digit* a)
  7553. {
  7554. int i;
  7555. for (i = 0; i < 48; i += 8) {
  7556. a[i+1] += a[i+0] >> 28; a[i+0] &= 0xfffffff;
  7557. a[i+2] += a[i+1] >> 28; a[i+1] &= 0xfffffff;
  7558. a[i+3] += a[i+2] >> 28; a[i+2] &= 0xfffffff;
  7559. a[i+4] += a[i+3] >> 28; a[i+3] &= 0xfffffff;
  7560. a[i+5] += a[i+4] >> 28; a[i+4] &= 0xfffffff;
  7561. a[i+6] += a[i+5] >> 28; a[i+5] &= 0xfffffff;
  7562. a[i+7] += a[i+6] >> 28; a[i+6] &= 0xfffffff;
  7563. a[i+8] += a[i+7] >> 28; a[i+7] &= 0xfffffff;
  7564. }
  7565. a[49] += a[48] >> 28; a[48] &= 0xfffffff;
  7566. a[50] += a[49] >> 28; a[49] &= 0xfffffff;
  7567. a[51] += a[50] >> 28; a[50] &= 0xfffffff;
  7568. a[52] += a[51] >> 28; a[51] &= 0xfffffff;
  7569. a[53] += a[52] >> 28; a[52] &= 0xfffffff;
  7570. a[54] += a[53] >> 28; a[53] &= 0xfffffff;
  7571. a[55] += a[54] >> 28; a[54] &= 0xfffffff;
  7572. }
  7573. #endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
  7574. /* Normalize the values in each word to 28 bits.
  7575. *
  7576. * a Array of sp_digit to normalize.
  7577. */
  7578. static void sp_3072_norm_55(sp_digit* a)
  7579. {
  7580. int i;
  7581. for (i = 0; i < 48; i += 8) {
  7582. a[i+1] += a[i+0] >> 28; a[i+0] &= 0xfffffff;
  7583. a[i+2] += a[i+1] >> 28; a[i+1] &= 0xfffffff;
  7584. a[i+3] += a[i+2] >> 28; a[i+2] &= 0xfffffff;
  7585. a[i+4] += a[i+3] >> 28; a[i+3] &= 0xfffffff;
  7586. a[i+5] += a[i+4] >> 28; a[i+4] &= 0xfffffff;
  7587. a[i+6] += a[i+5] >> 28; a[i+5] &= 0xfffffff;
  7588. a[i+7] += a[i+6] >> 28; a[i+6] &= 0xfffffff;
  7589. a[i+8] += a[i+7] >> 28; a[i+7] &= 0xfffffff;
  7590. }
  7591. a[49] += a[48] >> 28; a[48] &= 0xfffffff;
  7592. a[50] += a[49] >> 28; a[49] &= 0xfffffff;
  7593. a[51] += a[50] >> 28; a[50] &= 0xfffffff;
  7594. a[52] += a[51] >> 28; a[51] &= 0xfffffff;
  7595. a[53] += a[52] >> 28; a[52] &= 0xfffffff;
  7596. a[54] += a[53] >> 28; a[53] &= 0xfffffff;
  7597. }
  7598. /* Normalize the values in each word to 28 bits.
  7599. *
  7600. * a Array of sp_digit to normalize.
  7601. */
  7602. static void sp_3072_norm_112(sp_digit* a)
  7603. {
  7604. int i;
  7605. for (i = 0; i < 104; i += 8) {
  7606. a[i+1] += a[i+0] >> 28; a[i+0] &= 0xfffffff;
  7607. a[i+2] += a[i+1] >> 28; a[i+1] &= 0xfffffff;
  7608. a[i+3] += a[i+2] >> 28; a[i+2] &= 0xfffffff;
  7609. a[i+4] += a[i+3] >> 28; a[i+3] &= 0xfffffff;
  7610. a[i+5] += a[i+4] >> 28; a[i+4] &= 0xfffffff;
  7611. a[i+6] += a[i+5] >> 28; a[i+5] &= 0xfffffff;
  7612. a[i+7] += a[i+6] >> 28; a[i+6] &= 0xfffffff;
  7613. a[i+8] += a[i+7] >> 28; a[i+7] &= 0xfffffff;
  7614. }
  7615. a[105] += a[104] >> 28; a[104] &= 0xfffffff;
  7616. a[106] += a[105] >> 28; a[105] &= 0xfffffff;
  7617. a[107] += a[106] >> 28; a[106] &= 0xfffffff;
  7618. a[108] += a[107] >> 28; a[107] &= 0xfffffff;
  7619. a[109] += a[108] >> 28; a[108] &= 0xfffffff;
  7620. a[110] += a[109] >> 28; a[109] &= 0xfffffff;
  7621. a[111] += a[110] >> 28; a[110] &= 0xfffffff;
  7622. }
  7623. /* Normalize the values in each word to 28 bits.
  7624. *
  7625. * a Array of sp_digit to normalize.
  7626. */
  7627. static void sp_3072_norm_110(sp_digit* a)
  7628. {
  7629. int i;
  7630. for (i = 0; i < 104; i += 8) {
  7631. a[i+1] += a[i+0] >> 28; a[i+0] &= 0xfffffff;
  7632. a[i+2] += a[i+1] >> 28; a[i+1] &= 0xfffffff;
  7633. a[i+3] += a[i+2] >> 28; a[i+2] &= 0xfffffff;
  7634. a[i+4] += a[i+3] >> 28; a[i+3] &= 0xfffffff;
  7635. a[i+5] += a[i+4] >> 28; a[i+4] &= 0xfffffff;
  7636. a[i+6] += a[i+5] >> 28; a[i+5] &= 0xfffffff;
  7637. a[i+7] += a[i+6] >> 28; a[i+6] &= 0xfffffff;
  7638. a[i+8] += a[i+7] >> 28; a[i+7] &= 0xfffffff;
  7639. }
  7640. a[105] += a[104] >> 28; a[104] &= 0xfffffff;
  7641. a[106] += a[105] >> 28; a[105] &= 0xfffffff;
  7642. a[107] += a[106] >> 28; a[106] &= 0xfffffff;
  7643. a[108] += a[107] >> 28; a[107] &= 0xfffffff;
  7644. a[109] += a[108] >> 28; a[108] &= 0xfffffff;
  7645. }
  7646. #ifndef WOLFSSL_SP_SMALL
  7647. /* Multiply a and b into r. (r = a * b)
  7648. *
  7649. * r A single precision integer.
  7650. * a A single precision integer.
  7651. * b A single precision integer.
  7652. */
  7653. SP_NOINLINE static void sp_3072_mul_14(sp_digit* r, const sp_digit* a,
  7654. const sp_digit* b)
  7655. {
  7656. sp_uint64 t0 = ((sp_uint64)a[ 0]) * b[ 0];
  7657. sp_uint64 t1 = ((sp_uint64)a[ 0]) * b[ 1]
  7658. + ((sp_uint64)a[ 1]) * b[ 0];
  7659. sp_uint64 t2 = ((sp_uint64)a[ 0]) * b[ 2]
  7660. + ((sp_uint64)a[ 1]) * b[ 1]
  7661. + ((sp_uint64)a[ 2]) * b[ 0];
  7662. sp_uint64 t3 = ((sp_uint64)a[ 0]) * b[ 3]
  7663. + ((sp_uint64)a[ 1]) * b[ 2]
  7664. + ((sp_uint64)a[ 2]) * b[ 1]
  7665. + ((sp_uint64)a[ 3]) * b[ 0];
  7666. sp_uint64 t4 = ((sp_uint64)a[ 0]) * b[ 4]
  7667. + ((sp_uint64)a[ 1]) * b[ 3]
  7668. + ((sp_uint64)a[ 2]) * b[ 2]
  7669. + ((sp_uint64)a[ 3]) * b[ 1]
  7670. + ((sp_uint64)a[ 4]) * b[ 0];
  7671. sp_uint64 t5 = ((sp_uint64)a[ 0]) * b[ 5]
  7672. + ((sp_uint64)a[ 1]) * b[ 4]
  7673. + ((sp_uint64)a[ 2]) * b[ 3]
  7674. + ((sp_uint64)a[ 3]) * b[ 2]
  7675. + ((sp_uint64)a[ 4]) * b[ 1]
  7676. + ((sp_uint64)a[ 5]) * b[ 0];
  7677. sp_uint64 t6 = ((sp_uint64)a[ 0]) * b[ 6]
  7678. + ((sp_uint64)a[ 1]) * b[ 5]
  7679. + ((sp_uint64)a[ 2]) * b[ 4]
  7680. + ((sp_uint64)a[ 3]) * b[ 3]
  7681. + ((sp_uint64)a[ 4]) * b[ 2]
  7682. + ((sp_uint64)a[ 5]) * b[ 1]
  7683. + ((sp_uint64)a[ 6]) * b[ 0];
  7684. sp_uint64 t7 = ((sp_uint64)a[ 0]) * b[ 7]
  7685. + ((sp_uint64)a[ 1]) * b[ 6]
  7686. + ((sp_uint64)a[ 2]) * b[ 5]
  7687. + ((sp_uint64)a[ 3]) * b[ 4]
  7688. + ((sp_uint64)a[ 4]) * b[ 3]
  7689. + ((sp_uint64)a[ 5]) * b[ 2]
  7690. + ((sp_uint64)a[ 6]) * b[ 1]
  7691. + ((sp_uint64)a[ 7]) * b[ 0];
  7692. sp_uint64 t8 = ((sp_uint64)a[ 0]) * b[ 8]
  7693. + ((sp_uint64)a[ 1]) * b[ 7]
  7694. + ((sp_uint64)a[ 2]) * b[ 6]
  7695. + ((sp_uint64)a[ 3]) * b[ 5]
  7696. + ((sp_uint64)a[ 4]) * b[ 4]
  7697. + ((sp_uint64)a[ 5]) * b[ 3]
  7698. + ((sp_uint64)a[ 6]) * b[ 2]
  7699. + ((sp_uint64)a[ 7]) * b[ 1]
  7700. + ((sp_uint64)a[ 8]) * b[ 0];
  7701. sp_uint64 t9 = ((sp_uint64)a[ 0]) * b[ 9]
  7702. + ((sp_uint64)a[ 1]) * b[ 8]
  7703. + ((sp_uint64)a[ 2]) * b[ 7]
  7704. + ((sp_uint64)a[ 3]) * b[ 6]
  7705. + ((sp_uint64)a[ 4]) * b[ 5]
  7706. + ((sp_uint64)a[ 5]) * b[ 4]
  7707. + ((sp_uint64)a[ 6]) * b[ 3]
  7708. + ((sp_uint64)a[ 7]) * b[ 2]
  7709. + ((sp_uint64)a[ 8]) * b[ 1]
  7710. + ((sp_uint64)a[ 9]) * b[ 0];
  7711. sp_uint64 t10 = ((sp_uint64)a[ 0]) * b[10]
  7712. + ((sp_uint64)a[ 1]) * b[ 9]
  7713. + ((sp_uint64)a[ 2]) * b[ 8]
  7714. + ((sp_uint64)a[ 3]) * b[ 7]
  7715. + ((sp_uint64)a[ 4]) * b[ 6]
  7716. + ((sp_uint64)a[ 5]) * b[ 5]
  7717. + ((sp_uint64)a[ 6]) * b[ 4]
  7718. + ((sp_uint64)a[ 7]) * b[ 3]
  7719. + ((sp_uint64)a[ 8]) * b[ 2]
  7720. + ((sp_uint64)a[ 9]) * b[ 1]
  7721. + ((sp_uint64)a[10]) * b[ 0];
  7722. sp_uint64 t11 = ((sp_uint64)a[ 0]) * b[11]
  7723. + ((sp_uint64)a[ 1]) * b[10]
  7724. + ((sp_uint64)a[ 2]) * b[ 9]
  7725. + ((sp_uint64)a[ 3]) * b[ 8]
  7726. + ((sp_uint64)a[ 4]) * b[ 7]
  7727. + ((sp_uint64)a[ 5]) * b[ 6]
  7728. + ((sp_uint64)a[ 6]) * b[ 5]
  7729. + ((sp_uint64)a[ 7]) * b[ 4]
  7730. + ((sp_uint64)a[ 8]) * b[ 3]
  7731. + ((sp_uint64)a[ 9]) * b[ 2]
  7732. + ((sp_uint64)a[10]) * b[ 1]
  7733. + ((sp_uint64)a[11]) * b[ 0];
  7734. sp_uint64 t12 = ((sp_uint64)a[ 0]) * b[12]
  7735. + ((sp_uint64)a[ 1]) * b[11]
  7736. + ((sp_uint64)a[ 2]) * b[10]
  7737. + ((sp_uint64)a[ 3]) * b[ 9]
  7738. + ((sp_uint64)a[ 4]) * b[ 8]
  7739. + ((sp_uint64)a[ 5]) * b[ 7]
  7740. + ((sp_uint64)a[ 6]) * b[ 6]
  7741. + ((sp_uint64)a[ 7]) * b[ 5]
  7742. + ((sp_uint64)a[ 8]) * b[ 4]
  7743. + ((sp_uint64)a[ 9]) * b[ 3]
  7744. + ((sp_uint64)a[10]) * b[ 2]
  7745. + ((sp_uint64)a[11]) * b[ 1]
  7746. + ((sp_uint64)a[12]) * b[ 0];
  7747. sp_uint64 t13 = ((sp_uint64)a[ 0]) * b[13]
  7748. + ((sp_uint64)a[ 1]) * b[12]
  7749. + ((sp_uint64)a[ 2]) * b[11]
  7750. + ((sp_uint64)a[ 3]) * b[10]
  7751. + ((sp_uint64)a[ 4]) * b[ 9]
  7752. + ((sp_uint64)a[ 5]) * b[ 8]
  7753. + ((sp_uint64)a[ 6]) * b[ 7]
  7754. + ((sp_uint64)a[ 7]) * b[ 6]
  7755. + ((sp_uint64)a[ 8]) * b[ 5]
  7756. + ((sp_uint64)a[ 9]) * b[ 4]
  7757. + ((sp_uint64)a[10]) * b[ 3]
  7758. + ((sp_uint64)a[11]) * b[ 2]
  7759. + ((sp_uint64)a[12]) * b[ 1]
  7760. + ((sp_uint64)a[13]) * b[ 0];
  7761. sp_uint64 t14 = ((sp_uint64)a[ 1]) * b[13]
  7762. + ((sp_uint64)a[ 2]) * b[12]
  7763. + ((sp_uint64)a[ 3]) * b[11]
  7764. + ((sp_uint64)a[ 4]) * b[10]
  7765. + ((sp_uint64)a[ 5]) * b[ 9]
  7766. + ((sp_uint64)a[ 6]) * b[ 8]
  7767. + ((sp_uint64)a[ 7]) * b[ 7]
  7768. + ((sp_uint64)a[ 8]) * b[ 6]
  7769. + ((sp_uint64)a[ 9]) * b[ 5]
  7770. + ((sp_uint64)a[10]) * b[ 4]
  7771. + ((sp_uint64)a[11]) * b[ 3]
  7772. + ((sp_uint64)a[12]) * b[ 2]
  7773. + ((sp_uint64)a[13]) * b[ 1];
  7774. sp_uint64 t15 = ((sp_uint64)a[ 2]) * b[13]
  7775. + ((sp_uint64)a[ 3]) * b[12]
  7776. + ((sp_uint64)a[ 4]) * b[11]
  7777. + ((sp_uint64)a[ 5]) * b[10]
  7778. + ((sp_uint64)a[ 6]) * b[ 9]
  7779. + ((sp_uint64)a[ 7]) * b[ 8]
  7780. + ((sp_uint64)a[ 8]) * b[ 7]
  7781. + ((sp_uint64)a[ 9]) * b[ 6]
  7782. + ((sp_uint64)a[10]) * b[ 5]
  7783. + ((sp_uint64)a[11]) * b[ 4]
  7784. + ((sp_uint64)a[12]) * b[ 3]
  7785. + ((sp_uint64)a[13]) * b[ 2];
  7786. sp_uint64 t16 = ((sp_uint64)a[ 3]) * b[13]
  7787. + ((sp_uint64)a[ 4]) * b[12]
  7788. + ((sp_uint64)a[ 5]) * b[11]
  7789. + ((sp_uint64)a[ 6]) * b[10]
  7790. + ((sp_uint64)a[ 7]) * b[ 9]
  7791. + ((sp_uint64)a[ 8]) * b[ 8]
  7792. + ((sp_uint64)a[ 9]) * b[ 7]
  7793. + ((sp_uint64)a[10]) * b[ 6]
  7794. + ((sp_uint64)a[11]) * b[ 5]
  7795. + ((sp_uint64)a[12]) * b[ 4]
  7796. + ((sp_uint64)a[13]) * b[ 3];
  7797. sp_uint64 t17 = ((sp_uint64)a[ 4]) * b[13]
  7798. + ((sp_uint64)a[ 5]) * b[12]
  7799. + ((sp_uint64)a[ 6]) * b[11]
  7800. + ((sp_uint64)a[ 7]) * b[10]
  7801. + ((sp_uint64)a[ 8]) * b[ 9]
  7802. + ((sp_uint64)a[ 9]) * b[ 8]
  7803. + ((sp_uint64)a[10]) * b[ 7]
  7804. + ((sp_uint64)a[11]) * b[ 6]
  7805. + ((sp_uint64)a[12]) * b[ 5]
  7806. + ((sp_uint64)a[13]) * b[ 4];
  7807. sp_uint64 t18 = ((sp_uint64)a[ 5]) * b[13]
  7808. + ((sp_uint64)a[ 6]) * b[12]
  7809. + ((sp_uint64)a[ 7]) * b[11]
  7810. + ((sp_uint64)a[ 8]) * b[10]
  7811. + ((sp_uint64)a[ 9]) * b[ 9]
  7812. + ((sp_uint64)a[10]) * b[ 8]
  7813. + ((sp_uint64)a[11]) * b[ 7]
  7814. + ((sp_uint64)a[12]) * b[ 6]
  7815. + ((sp_uint64)a[13]) * b[ 5];
  7816. sp_uint64 t19 = ((sp_uint64)a[ 6]) * b[13]
  7817. + ((sp_uint64)a[ 7]) * b[12]
  7818. + ((sp_uint64)a[ 8]) * b[11]
  7819. + ((sp_uint64)a[ 9]) * b[10]
  7820. + ((sp_uint64)a[10]) * b[ 9]
  7821. + ((sp_uint64)a[11]) * b[ 8]
  7822. + ((sp_uint64)a[12]) * b[ 7]
  7823. + ((sp_uint64)a[13]) * b[ 6];
  7824. sp_uint64 t20 = ((sp_uint64)a[ 7]) * b[13]
  7825. + ((sp_uint64)a[ 8]) * b[12]
  7826. + ((sp_uint64)a[ 9]) * b[11]
  7827. + ((sp_uint64)a[10]) * b[10]
  7828. + ((sp_uint64)a[11]) * b[ 9]
  7829. + ((sp_uint64)a[12]) * b[ 8]
  7830. + ((sp_uint64)a[13]) * b[ 7];
  7831. sp_uint64 t21 = ((sp_uint64)a[ 8]) * b[13]
  7832. + ((sp_uint64)a[ 9]) * b[12]
  7833. + ((sp_uint64)a[10]) * b[11]
  7834. + ((sp_uint64)a[11]) * b[10]
  7835. + ((sp_uint64)a[12]) * b[ 9]
  7836. + ((sp_uint64)a[13]) * b[ 8];
  7837. sp_uint64 t22 = ((sp_uint64)a[ 9]) * b[13]
  7838. + ((sp_uint64)a[10]) * b[12]
  7839. + ((sp_uint64)a[11]) * b[11]
  7840. + ((sp_uint64)a[12]) * b[10]
  7841. + ((sp_uint64)a[13]) * b[ 9];
  7842. sp_uint64 t23 = ((sp_uint64)a[10]) * b[13]
  7843. + ((sp_uint64)a[11]) * b[12]
  7844. + ((sp_uint64)a[12]) * b[11]
  7845. + ((sp_uint64)a[13]) * b[10];
  7846. sp_uint64 t24 = ((sp_uint64)a[11]) * b[13]
  7847. + ((sp_uint64)a[12]) * b[12]
  7848. + ((sp_uint64)a[13]) * b[11];
  7849. sp_uint64 t25 = ((sp_uint64)a[12]) * b[13]
  7850. + ((sp_uint64)a[13]) * b[12];
  7851. sp_uint64 t26 = ((sp_uint64)a[13]) * b[13];
  7852. t1 += t0 >> 28; r[ 0] = t0 & 0xfffffff;
  7853. t2 += t1 >> 28; r[ 1] = t1 & 0xfffffff;
  7854. t3 += t2 >> 28; r[ 2] = t2 & 0xfffffff;
  7855. t4 += t3 >> 28; r[ 3] = t3 & 0xfffffff;
  7856. t5 += t4 >> 28; r[ 4] = t4 & 0xfffffff;
  7857. t6 += t5 >> 28; r[ 5] = t5 & 0xfffffff;
  7858. t7 += t6 >> 28; r[ 6] = t6 & 0xfffffff;
  7859. t8 += t7 >> 28; r[ 7] = t7 & 0xfffffff;
  7860. t9 += t8 >> 28; r[ 8] = t8 & 0xfffffff;
  7861. t10 += t9 >> 28; r[ 9] = t9 & 0xfffffff;
  7862. t11 += t10 >> 28; r[10] = t10 & 0xfffffff;
  7863. t12 += t11 >> 28; r[11] = t11 & 0xfffffff;
  7864. t13 += t12 >> 28; r[12] = t12 & 0xfffffff;
  7865. t14 += t13 >> 28; r[13] = t13 & 0xfffffff;
  7866. t15 += t14 >> 28; r[14] = t14 & 0xfffffff;
  7867. t16 += t15 >> 28; r[15] = t15 & 0xfffffff;
  7868. t17 += t16 >> 28; r[16] = t16 & 0xfffffff;
  7869. t18 += t17 >> 28; r[17] = t17 & 0xfffffff;
  7870. t19 += t18 >> 28; r[18] = t18 & 0xfffffff;
  7871. t20 += t19 >> 28; r[19] = t19 & 0xfffffff;
  7872. t21 += t20 >> 28; r[20] = t20 & 0xfffffff;
  7873. t22 += t21 >> 28; r[21] = t21 & 0xfffffff;
  7874. t23 += t22 >> 28; r[22] = t22 & 0xfffffff;
  7875. t24 += t23 >> 28; r[23] = t23 & 0xfffffff;
  7876. t25 += t24 >> 28; r[24] = t24 & 0xfffffff;
  7877. t26 += t25 >> 28; r[25] = t25 & 0xfffffff;
  7878. r[27] = (sp_digit)(t26 >> 28);
  7879. r[26] = t26 & 0xfffffff;
  7880. }
  7881. /* Add b to a into r. (r = a + b)
  7882. *
  7883. * r A single precision integer.
  7884. * a A single precision integer.
  7885. * b A single precision integer.
  7886. */
  7887. SP_NOINLINE static int sp_3072_add_14(sp_digit* r, const sp_digit* a,
  7888. const sp_digit* b)
  7889. {
  7890. r[ 0] = a[ 0] + b[ 0];
  7891. r[ 1] = a[ 1] + b[ 1];
  7892. r[ 2] = a[ 2] + b[ 2];
  7893. r[ 3] = a[ 3] + b[ 3];
  7894. r[ 4] = a[ 4] + b[ 4];
  7895. r[ 5] = a[ 5] + b[ 5];
  7896. r[ 6] = a[ 6] + b[ 6];
  7897. r[ 7] = a[ 7] + b[ 7];
  7898. r[ 8] = a[ 8] + b[ 8];
  7899. r[ 9] = a[ 9] + b[ 9];
  7900. r[10] = a[10] + b[10];
  7901. r[11] = a[11] + b[11];
  7902. r[12] = a[12] + b[12];
  7903. r[13] = a[13] + b[13];
  7904. return 0;
  7905. }
  7906. /* Add b to a into r. (r = a + b)
  7907. *
  7908. * r A single precision integer.
  7909. * a A single precision integer.
  7910. * b A single precision integer.
  7911. */
  7912. SP_NOINLINE static int sp_3072_add_28(sp_digit* r, const sp_digit* a,
  7913. const sp_digit* b)
  7914. {
  7915. int i;
  7916. for (i = 0; i < 24; i += 8) {
  7917. r[i + 0] = a[i + 0] + b[i + 0];
  7918. r[i + 1] = a[i + 1] + b[i + 1];
  7919. r[i + 2] = a[i + 2] + b[i + 2];
  7920. r[i + 3] = a[i + 3] + b[i + 3];
  7921. r[i + 4] = a[i + 4] + b[i + 4];
  7922. r[i + 5] = a[i + 5] + b[i + 5];
  7923. r[i + 6] = a[i + 6] + b[i + 6];
  7924. r[i + 7] = a[i + 7] + b[i + 7];
  7925. }
  7926. r[24] = a[24] + b[24];
  7927. r[25] = a[25] + b[25];
  7928. r[26] = a[26] + b[26];
  7929. r[27] = a[27] + b[27];
  7930. return 0;
  7931. }
  7932. /* Sub b from a into r. (r = a - b)
  7933. *
  7934. * r A single precision integer.
  7935. * a A single precision integer.
  7936. * b A single precision integer.
  7937. */
  7938. SP_NOINLINE static int sp_3072_sub_28(sp_digit* r, const sp_digit* a,
  7939. const sp_digit* b)
  7940. {
  7941. int i;
  7942. for (i = 0; i < 24; i += 8) {
  7943. r[i + 0] = a[i + 0] - b[i + 0];
  7944. r[i + 1] = a[i + 1] - b[i + 1];
  7945. r[i + 2] = a[i + 2] - b[i + 2];
  7946. r[i + 3] = a[i + 3] - b[i + 3];
  7947. r[i + 4] = a[i + 4] - b[i + 4];
  7948. r[i + 5] = a[i + 5] - b[i + 5];
  7949. r[i + 6] = a[i + 6] - b[i + 6];
  7950. r[i + 7] = a[i + 7] - b[i + 7];
  7951. }
  7952. r[24] = a[24] - b[24];
  7953. r[25] = a[25] - b[25];
  7954. r[26] = a[26] - b[26];
  7955. r[27] = a[27] - b[27];
  7956. return 0;
  7957. }
  7958. /* Normalize the values in each word to 28 bits.
  7959. *
  7960. * a Array of sp_digit to normalize.
  7961. */
  7962. static void sp_3072_norm_14(sp_digit* a)
  7963. {
  7964. a[1] += a[0] >> 28; a[0] &= 0xfffffff;
  7965. a[2] += a[1] >> 28; a[1] &= 0xfffffff;
  7966. a[3] += a[2] >> 28; a[2] &= 0xfffffff;
  7967. a[4] += a[3] >> 28; a[3] &= 0xfffffff;
  7968. a[5] += a[4] >> 28; a[4] &= 0xfffffff;
  7969. a[6] += a[5] >> 28; a[5] &= 0xfffffff;
  7970. a[7] += a[6] >> 28; a[6] &= 0xfffffff;
  7971. a[8] += a[7] >> 28; a[7] &= 0xfffffff;
  7972. a[9] += a[8] >> 28; a[8] &= 0xfffffff;
  7973. a[10] += a[9] >> 28; a[9] &= 0xfffffff;
  7974. a[11] += a[10] >> 28; a[10] &= 0xfffffff;
  7975. a[12] += a[11] >> 28; a[11] &= 0xfffffff;
  7976. a[13] += a[12] >> 28; a[12] &= 0xfffffff;
  7977. }
  7978. /* Multiply a and b into r. (r = a * b)
  7979. *
  7980. * r A single precision integer.
  7981. * a A single precision integer.
  7982. * b A single precision integer.
  7983. */
  7984. SP_NOINLINE static void sp_3072_mul_28(sp_digit* r, const sp_digit* a,
  7985. const sp_digit* b)
  7986. {
  7987. sp_digit* z0 = r;
  7988. sp_digit z1[28];
  7989. sp_digit* a1 = z1;
  7990. sp_digit b1[14];
  7991. sp_digit* z2 = r + 28;
  7992. (void)sp_3072_add_14(a1, a, &a[14]);
  7993. sp_3072_norm_14(a1);
  7994. (void)sp_3072_add_14(b1, b, &b[14]);
  7995. sp_3072_norm_14(b1);
  7996. sp_3072_mul_14(z2, &a[14], &b[14]);
  7997. sp_3072_mul_14(z0, a, b);
  7998. sp_3072_mul_14(z1, a1, b1);
  7999. (void)sp_3072_sub_28(z1, z1, z2);
  8000. (void)sp_3072_sub_28(z1, z1, z0);
  8001. (void)sp_3072_add_28(r + 14, r + 14, z1);
  8002. sp_3072_norm_56(r);
  8003. }
  8004. /* Add b to a into r. (r = a + b)
  8005. *
  8006. * r A single precision integer.
  8007. * a A single precision integer.
  8008. * b A single precision integer.
  8009. */
  8010. SP_NOINLINE static int sp_3072_add_56(sp_digit* r, const sp_digit* a,
  8011. const sp_digit* b)
  8012. {
  8013. int i;
  8014. for (i = 0; i < 56; i += 8) {
  8015. r[i + 0] = a[i + 0] + b[i + 0];
  8016. r[i + 1] = a[i + 1] + b[i + 1];
  8017. r[i + 2] = a[i + 2] + b[i + 2];
  8018. r[i + 3] = a[i + 3] + b[i + 3];
  8019. r[i + 4] = a[i + 4] + b[i + 4];
  8020. r[i + 5] = a[i + 5] + b[i + 5];
  8021. r[i + 6] = a[i + 6] + b[i + 6];
  8022. r[i + 7] = a[i + 7] + b[i + 7];
  8023. }
  8024. return 0;
  8025. }
  8026. /* Sub b from a into r. (r = a - b)
  8027. *
  8028. * r A single precision integer.
  8029. * a A single precision integer.
  8030. * b A single precision integer.
  8031. */
  8032. SP_NOINLINE static int sp_3072_sub_56(sp_digit* r, const sp_digit* a,
  8033. const sp_digit* b)
  8034. {
  8035. int i;
  8036. for (i = 0; i < 56; i += 8) {
  8037. r[i + 0] = a[i + 0] - b[i + 0];
  8038. r[i + 1] = a[i + 1] - b[i + 1];
  8039. r[i + 2] = a[i + 2] - b[i + 2];
  8040. r[i + 3] = a[i + 3] - b[i + 3];
  8041. r[i + 4] = a[i + 4] - b[i + 4];
  8042. r[i + 5] = a[i + 5] - b[i + 5];
  8043. r[i + 6] = a[i + 6] - b[i + 6];
  8044. r[i + 7] = a[i + 7] - b[i + 7];
  8045. }
  8046. return 0;
  8047. }
  8048. /* Normalize the values in each word to 28 bits.
  8049. *
  8050. * a Array of sp_digit to normalize.
  8051. */
  8052. static void sp_3072_norm_28(sp_digit* a)
  8053. {
  8054. int i;
  8055. for (i = 0; i < 24; i += 8) {
  8056. a[i+1] += a[i+0] >> 28; a[i+0] &= 0xfffffff;
  8057. a[i+2] += a[i+1] >> 28; a[i+1] &= 0xfffffff;
  8058. a[i+3] += a[i+2] >> 28; a[i+2] &= 0xfffffff;
  8059. a[i+4] += a[i+3] >> 28; a[i+3] &= 0xfffffff;
  8060. a[i+5] += a[i+4] >> 28; a[i+4] &= 0xfffffff;
  8061. a[i+6] += a[i+5] >> 28; a[i+5] &= 0xfffffff;
  8062. a[i+7] += a[i+6] >> 28; a[i+6] &= 0xfffffff;
  8063. a[i+8] += a[i+7] >> 28; a[i+7] &= 0xfffffff;
  8064. }
  8065. a[25] += a[24] >> 28; a[24] &= 0xfffffff;
  8066. a[26] += a[25] >> 28; a[25] &= 0xfffffff;
  8067. a[27] += a[26] >> 28; a[26] &= 0xfffffff;
  8068. }
  8069. /* Multiply a and b into r. (r = a * b)
  8070. *
  8071. * r A single precision integer.
  8072. * a A single precision integer.
  8073. * b A single precision integer.
  8074. */
  8075. SP_NOINLINE static void sp_3072_mul_56(sp_digit* r, const sp_digit* a,
  8076. const sp_digit* b)
  8077. {
  8078. sp_digit* z0 = r;
  8079. sp_digit z1[56];
  8080. sp_digit* a1 = z1;
  8081. sp_digit b1[28];
  8082. sp_digit* z2 = r + 56;
  8083. (void)sp_3072_add_28(a1, a, &a[28]);
  8084. sp_3072_norm_28(a1);
  8085. (void)sp_3072_add_28(b1, b, &b[28]);
  8086. sp_3072_norm_28(b1);
  8087. sp_3072_mul_28(z2, &a[28], &b[28]);
  8088. sp_3072_mul_28(z0, a, b);
  8089. sp_3072_mul_28(z1, a1, b1);
  8090. (void)sp_3072_sub_56(z1, z1, z2);
  8091. (void)sp_3072_sub_56(z1, z1, z0);
  8092. (void)sp_3072_add_56(r + 28, r + 28, z1);
  8093. sp_3072_norm_112(r);
  8094. }
  8095. /* Add b to a into r. (r = a + b)
  8096. *
  8097. * r A single precision integer.
  8098. * a A single precision integer.
  8099. * b A single precision integer.
  8100. */
  8101. SP_NOINLINE static int sp_3072_add_112(sp_digit* r, const sp_digit* a,
  8102. const sp_digit* b)
  8103. {
  8104. int i;
  8105. for (i = 0; i < 112; i += 8) {
  8106. r[i + 0] = a[i + 0] + b[i + 0];
  8107. r[i + 1] = a[i + 1] + b[i + 1];
  8108. r[i + 2] = a[i + 2] + b[i + 2];
  8109. r[i + 3] = a[i + 3] + b[i + 3];
  8110. r[i + 4] = a[i + 4] + b[i + 4];
  8111. r[i + 5] = a[i + 5] + b[i + 5];
  8112. r[i + 6] = a[i + 6] + b[i + 6];
  8113. r[i + 7] = a[i + 7] + b[i + 7];
  8114. }
  8115. return 0;
  8116. }
  8117. /* Sub b from a into r. (r = a - b)
  8118. *
  8119. * r A single precision integer.
  8120. * a A single precision integer.
  8121. * b A single precision integer.
  8122. */
  8123. SP_NOINLINE static int sp_3072_sub_112(sp_digit* r, const sp_digit* a,
  8124. const sp_digit* b)
  8125. {
  8126. int i;
  8127. for (i = 0; i < 112; i += 8) {
  8128. r[i + 0] = a[i + 0] - b[i + 0];
  8129. r[i + 1] = a[i + 1] - b[i + 1];
  8130. r[i + 2] = a[i + 2] - b[i + 2];
  8131. r[i + 3] = a[i + 3] - b[i + 3];
  8132. r[i + 4] = a[i + 4] - b[i + 4];
  8133. r[i + 5] = a[i + 5] - b[i + 5];
  8134. r[i + 6] = a[i + 6] - b[i + 6];
  8135. r[i + 7] = a[i + 7] - b[i + 7];
  8136. }
  8137. return 0;
  8138. }
  8139. /* Normalize the values in each word to 28 bits.
  8140. *
  8141. * a Array of sp_digit to normalize.
  8142. */
  8143. static void sp_3072_norm_224(sp_digit* a)
  8144. {
  8145. int i;
  8146. for (i = 0; i < 216; i += 8) {
  8147. a[i+1] += a[i+0] >> 28; a[i+0] &= 0xfffffff;
  8148. a[i+2] += a[i+1] >> 28; a[i+1] &= 0xfffffff;
  8149. a[i+3] += a[i+2] >> 28; a[i+2] &= 0xfffffff;
  8150. a[i+4] += a[i+3] >> 28; a[i+3] &= 0xfffffff;
  8151. a[i+5] += a[i+4] >> 28; a[i+4] &= 0xfffffff;
  8152. a[i+6] += a[i+5] >> 28; a[i+5] &= 0xfffffff;
  8153. a[i+7] += a[i+6] >> 28; a[i+6] &= 0xfffffff;
  8154. a[i+8] += a[i+7] >> 28; a[i+7] &= 0xfffffff;
  8155. }
  8156. a[217] += a[216] >> 28; a[216] &= 0xfffffff;
  8157. a[218] += a[217] >> 28; a[217] &= 0xfffffff;
  8158. a[219] += a[218] >> 28; a[218] &= 0xfffffff;
  8159. a[220] += a[219] >> 28; a[219] &= 0xfffffff;
  8160. a[221] += a[220] >> 28; a[220] &= 0xfffffff;
  8161. a[222] += a[221] >> 28; a[221] &= 0xfffffff;
  8162. a[223] += a[222] >> 28; a[222] &= 0xfffffff;
  8163. }
  8164. /* Multiply a and b into r. (r = a * b)
  8165. *
  8166. * r A single precision integer.
  8167. * a A single precision integer.
  8168. * b A single precision integer.
  8169. */
  8170. SP_NOINLINE static void sp_3072_mul_112(sp_digit* r, const sp_digit* a,
  8171. const sp_digit* b)
  8172. {
  8173. sp_digit* z0 = r;
  8174. sp_digit z1[112];
  8175. sp_digit* a1 = z1;
  8176. sp_digit b1[56];
  8177. sp_digit* z2 = r + 112;
  8178. (void)sp_3072_add_56(a1, a, &a[56]);
  8179. sp_3072_norm_56(a1);
  8180. (void)sp_3072_add_56(b1, b, &b[56]);
  8181. sp_3072_norm_56(b1);
  8182. sp_3072_mul_56(z2, &a[56], &b[56]);
  8183. sp_3072_mul_56(z0, a, b);
  8184. sp_3072_mul_56(z1, a1, b1);
  8185. (void)sp_3072_sub_112(z1, z1, z2);
  8186. (void)sp_3072_sub_112(z1, z1, z0);
  8187. (void)sp_3072_add_112(r + 56, r + 56, z1);
  8188. sp_3072_norm_224(r);
  8189. }
  8190. /* Square a and put result in r. (r = a * a)
  8191. *
  8192. * r A single precision integer.
  8193. * a A single precision integer.
  8194. */
  8195. SP_NOINLINE static void sp_3072_sqr_14(sp_digit* r, const sp_digit* a)
  8196. {
  8197. sp_uint64 t0 = ((sp_uint64)a[ 0]) * a[ 0];
  8198. sp_uint64 t1 = (((sp_uint64)a[ 0]) * a[ 1]) * 2;
  8199. sp_uint64 t2 = (((sp_uint64)a[ 0]) * a[ 2]) * 2
  8200. + ((sp_uint64)a[ 1]) * a[ 1];
  8201. sp_uint64 t3 = (((sp_uint64)a[ 0]) * a[ 3]
  8202. + ((sp_uint64)a[ 1]) * a[ 2]) * 2;
  8203. sp_uint64 t4 = (((sp_uint64)a[ 0]) * a[ 4]
  8204. + ((sp_uint64)a[ 1]) * a[ 3]) * 2
  8205. + ((sp_uint64)a[ 2]) * a[ 2];
  8206. sp_uint64 t5 = (((sp_uint64)a[ 0]) * a[ 5]
  8207. + ((sp_uint64)a[ 1]) * a[ 4]
  8208. + ((sp_uint64)a[ 2]) * a[ 3]) * 2;
  8209. sp_uint64 t6 = (((sp_uint64)a[ 0]) * a[ 6]
  8210. + ((sp_uint64)a[ 1]) * a[ 5]
  8211. + ((sp_uint64)a[ 2]) * a[ 4]) * 2
  8212. + ((sp_uint64)a[ 3]) * a[ 3];
  8213. sp_uint64 t7 = (((sp_uint64)a[ 0]) * a[ 7]
  8214. + ((sp_uint64)a[ 1]) * a[ 6]
  8215. + ((sp_uint64)a[ 2]) * a[ 5]
  8216. + ((sp_uint64)a[ 3]) * a[ 4]) * 2;
  8217. sp_uint64 t8 = (((sp_uint64)a[ 0]) * a[ 8]
  8218. + ((sp_uint64)a[ 1]) * a[ 7]
  8219. + ((sp_uint64)a[ 2]) * a[ 6]
  8220. + ((sp_uint64)a[ 3]) * a[ 5]) * 2
  8221. + ((sp_uint64)a[ 4]) * a[ 4];
  8222. sp_uint64 t9 = (((sp_uint64)a[ 0]) * a[ 9]
  8223. + ((sp_uint64)a[ 1]) * a[ 8]
  8224. + ((sp_uint64)a[ 2]) * a[ 7]
  8225. + ((sp_uint64)a[ 3]) * a[ 6]
  8226. + ((sp_uint64)a[ 4]) * a[ 5]) * 2;
  8227. sp_uint64 t10 = (((sp_uint64)a[ 0]) * a[10]
  8228. + ((sp_uint64)a[ 1]) * a[ 9]
  8229. + ((sp_uint64)a[ 2]) * a[ 8]
  8230. + ((sp_uint64)a[ 3]) * a[ 7]
  8231. + ((sp_uint64)a[ 4]) * a[ 6]) * 2
  8232. + ((sp_uint64)a[ 5]) * a[ 5];
  8233. sp_uint64 t11 = (((sp_uint64)a[ 0]) * a[11]
  8234. + ((sp_uint64)a[ 1]) * a[10]
  8235. + ((sp_uint64)a[ 2]) * a[ 9]
  8236. + ((sp_uint64)a[ 3]) * a[ 8]
  8237. + ((sp_uint64)a[ 4]) * a[ 7]
  8238. + ((sp_uint64)a[ 5]) * a[ 6]) * 2;
  8239. sp_uint64 t12 = (((sp_uint64)a[ 0]) * a[12]
  8240. + ((sp_uint64)a[ 1]) * a[11]
  8241. + ((sp_uint64)a[ 2]) * a[10]
  8242. + ((sp_uint64)a[ 3]) * a[ 9]
  8243. + ((sp_uint64)a[ 4]) * a[ 8]
  8244. + ((sp_uint64)a[ 5]) * a[ 7]) * 2
  8245. + ((sp_uint64)a[ 6]) * a[ 6];
  8246. sp_uint64 t13 = (((sp_uint64)a[ 0]) * a[13]
  8247. + ((sp_uint64)a[ 1]) * a[12]
  8248. + ((sp_uint64)a[ 2]) * a[11]
  8249. + ((sp_uint64)a[ 3]) * a[10]
  8250. + ((sp_uint64)a[ 4]) * a[ 9]
  8251. + ((sp_uint64)a[ 5]) * a[ 8]
  8252. + ((sp_uint64)a[ 6]) * a[ 7]) * 2;
  8253. sp_uint64 t14 = (((sp_uint64)a[ 1]) * a[13]
  8254. + ((sp_uint64)a[ 2]) * a[12]
  8255. + ((sp_uint64)a[ 3]) * a[11]
  8256. + ((sp_uint64)a[ 4]) * a[10]
  8257. + ((sp_uint64)a[ 5]) * a[ 9]
  8258. + ((sp_uint64)a[ 6]) * a[ 8]) * 2
  8259. + ((sp_uint64)a[ 7]) * a[ 7];
  8260. sp_uint64 t15 = (((sp_uint64)a[ 2]) * a[13]
  8261. + ((sp_uint64)a[ 3]) * a[12]
  8262. + ((sp_uint64)a[ 4]) * a[11]
  8263. + ((sp_uint64)a[ 5]) * a[10]
  8264. + ((sp_uint64)a[ 6]) * a[ 9]
  8265. + ((sp_uint64)a[ 7]) * a[ 8]) * 2;
  8266. sp_uint64 t16 = (((sp_uint64)a[ 3]) * a[13]
  8267. + ((sp_uint64)a[ 4]) * a[12]
  8268. + ((sp_uint64)a[ 5]) * a[11]
  8269. + ((sp_uint64)a[ 6]) * a[10]
  8270. + ((sp_uint64)a[ 7]) * a[ 9]) * 2
  8271. + ((sp_uint64)a[ 8]) * a[ 8];
  8272. sp_uint64 t17 = (((sp_uint64)a[ 4]) * a[13]
  8273. + ((sp_uint64)a[ 5]) * a[12]
  8274. + ((sp_uint64)a[ 6]) * a[11]
  8275. + ((sp_uint64)a[ 7]) * a[10]
  8276. + ((sp_uint64)a[ 8]) * a[ 9]) * 2;
  8277. sp_uint64 t18 = (((sp_uint64)a[ 5]) * a[13]
  8278. + ((sp_uint64)a[ 6]) * a[12]
  8279. + ((sp_uint64)a[ 7]) * a[11]
  8280. + ((sp_uint64)a[ 8]) * a[10]) * 2
  8281. + ((sp_uint64)a[ 9]) * a[ 9];
  8282. sp_uint64 t19 = (((sp_uint64)a[ 6]) * a[13]
  8283. + ((sp_uint64)a[ 7]) * a[12]
  8284. + ((sp_uint64)a[ 8]) * a[11]
  8285. + ((sp_uint64)a[ 9]) * a[10]) * 2;
  8286. sp_uint64 t20 = (((sp_uint64)a[ 7]) * a[13]
  8287. + ((sp_uint64)a[ 8]) * a[12]
  8288. + ((sp_uint64)a[ 9]) * a[11]) * 2
  8289. + ((sp_uint64)a[10]) * a[10];
  8290. sp_uint64 t21 = (((sp_uint64)a[ 8]) * a[13]
  8291. + ((sp_uint64)a[ 9]) * a[12]
  8292. + ((sp_uint64)a[10]) * a[11]) * 2;
  8293. sp_uint64 t22 = (((sp_uint64)a[ 9]) * a[13]
  8294. + ((sp_uint64)a[10]) * a[12]) * 2
  8295. + ((sp_uint64)a[11]) * a[11];
  8296. sp_uint64 t23 = (((sp_uint64)a[10]) * a[13]
  8297. + ((sp_uint64)a[11]) * a[12]) * 2;
  8298. sp_uint64 t24 = (((sp_uint64)a[11]) * a[13]) * 2
  8299. + ((sp_uint64)a[12]) * a[12];
  8300. sp_uint64 t25 = (((sp_uint64)a[12]) * a[13]) * 2;
  8301. sp_uint64 t26 = ((sp_uint64)a[13]) * a[13];
  8302. t1 += t0 >> 28; r[ 0] = t0 & 0xfffffff;
  8303. t2 += t1 >> 28; r[ 1] = t1 & 0xfffffff;
  8304. t3 += t2 >> 28; r[ 2] = t2 & 0xfffffff;
  8305. t4 += t3 >> 28; r[ 3] = t3 & 0xfffffff;
  8306. t5 += t4 >> 28; r[ 4] = t4 & 0xfffffff;
  8307. t6 += t5 >> 28; r[ 5] = t5 & 0xfffffff;
  8308. t7 += t6 >> 28; r[ 6] = t6 & 0xfffffff;
  8309. t8 += t7 >> 28; r[ 7] = t7 & 0xfffffff;
  8310. t9 += t8 >> 28; r[ 8] = t8 & 0xfffffff;
  8311. t10 += t9 >> 28; r[ 9] = t9 & 0xfffffff;
  8312. t11 += t10 >> 28; r[10] = t10 & 0xfffffff;
  8313. t12 += t11 >> 28; r[11] = t11 & 0xfffffff;
  8314. t13 += t12 >> 28; r[12] = t12 & 0xfffffff;
  8315. t14 += t13 >> 28; r[13] = t13 & 0xfffffff;
  8316. t15 += t14 >> 28; r[14] = t14 & 0xfffffff;
  8317. t16 += t15 >> 28; r[15] = t15 & 0xfffffff;
  8318. t17 += t16 >> 28; r[16] = t16 & 0xfffffff;
  8319. t18 += t17 >> 28; r[17] = t17 & 0xfffffff;
  8320. t19 += t18 >> 28; r[18] = t18 & 0xfffffff;
  8321. t20 += t19 >> 28; r[19] = t19 & 0xfffffff;
  8322. t21 += t20 >> 28; r[20] = t20 & 0xfffffff;
  8323. t22 += t21 >> 28; r[21] = t21 & 0xfffffff;
  8324. t23 += t22 >> 28; r[22] = t22 & 0xfffffff;
  8325. t24 += t23 >> 28; r[23] = t23 & 0xfffffff;
  8326. t25 += t24 >> 28; r[24] = t24 & 0xfffffff;
  8327. t26 += t25 >> 28; r[25] = t25 & 0xfffffff;
  8328. r[27] = (sp_digit)(t26 >> 28);
  8329. r[26] = t26 & 0xfffffff;
  8330. }
  8331. /* Square a and put result in r. (r = a * a)
  8332. *
  8333. * r A single precision integer.
  8334. * a A single precision integer.
  8335. */
  8336. SP_NOINLINE static void sp_3072_sqr_28(sp_digit* r, const sp_digit* a)
  8337. {
  8338. sp_digit* z0 = r;
  8339. sp_digit z1[28];
  8340. sp_digit* a1 = z1;
  8341. sp_digit* z2 = r + 28;
  8342. (void)sp_3072_add_14(a1, a, &a[14]);
  8343. sp_3072_norm_14(a1);
  8344. sp_3072_sqr_14(z2, &a[14]);
  8345. sp_3072_sqr_14(z0, a);
  8346. sp_3072_sqr_14(z1, a1);
  8347. (void)sp_3072_sub_28(z1, z1, z2);
  8348. (void)sp_3072_sub_28(z1, z1, z0);
  8349. (void)sp_3072_add_28(r + 14, r + 14, z1);
  8350. sp_3072_norm_56(r);
  8351. }
  8352. /* Square a and put result in r. (r = a * a)
  8353. *
  8354. * r A single precision integer.
  8355. * a A single precision integer.
  8356. */
  8357. SP_NOINLINE static void sp_3072_sqr_56(sp_digit* r, const sp_digit* a)
  8358. {
  8359. sp_digit* z0 = r;
  8360. sp_digit z1[56];
  8361. sp_digit* a1 = z1;
  8362. sp_digit* z2 = r + 56;
  8363. (void)sp_3072_add_28(a1, a, &a[28]);
  8364. sp_3072_norm_28(a1);
  8365. sp_3072_sqr_28(z2, &a[28]);
  8366. sp_3072_sqr_28(z0, a);
  8367. sp_3072_sqr_28(z1, a1);
  8368. (void)sp_3072_sub_56(z1, z1, z2);
  8369. (void)sp_3072_sub_56(z1, z1, z0);
  8370. (void)sp_3072_add_56(r + 28, r + 28, z1);
  8371. sp_3072_norm_112(r);
  8372. }
  8373. /* Square a and put result in r. (r = a * a)
  8374. *
  8375. * r A single precision integer.
  8376. * a A single precision integer.
  8377. */
  8378. SP_NOINLINE static void sp_3072_sqr_112(sp_digit* r, const sp_digit* a)
  8379. {
  8380. sp_digit* z0 = r;
  8381. sp_digit z1[112];
  8382. sp_digit* a1 = z1;
  8383. sp_digit* z2 = r + 112;
  8384. (void)sp_3072_add_56(a1, a, &a[56]);
  8385. sp_3072_norm_56(a1);
  8386. sp_3072_sqr_56(z2, &a[56]);
  8387. sp_3072_sqr_56(z0, a);
  8388. sp_3072_sqr_56(z1, a1);
  8389. (void)sp_3072_sub_112(z1, z1, z2);
  8390. (void)sp_3072_sub_112(z1, z1, z0);
  8391. (void)sp_3072_add_112(r + 56, r + 56, z1);
  8392. sp_3072_norm_224(r);
  8393. }
  8394. #endif /* !WOLFSSL_SP_SMALL */
  8395. /* Caclulate the bottom digit of -1/a mod 2^n.
  8396. *
  8397. * a A single precision number.
  8398. * rho Bottom word of inverse.
  8399. */
  8400. static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho)
  8401. {
  8402. sp_digit x;
  8403. sp_digit b;
  8404. b = a[0];
  8405. x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
  8406. x *= 2 - b * x; /* here x*a==1 mod 2**8 */
  8407. x *= 2 - b * x; /* here x*a==1 mod 2**16 */
  8408. x *= 2 - b * x; /* here x*a==1 mod 2**32 */
  8409. x &= 0xfffffff;
  8410. /* rho = -1/m mod b */
  8411. *rho = ((sp_digit)1 << 28) - x;
  8412. }
  8413. /* Multiply a by scalar b into r. (r = a * b)
  8414. *
  8415. * r A single precision integer.
  8416. * a A single precision integer.
  8417. * b A scalar.
  8418. */
  8419. SP_NOINLINE static void sp_3072_mul_d_112(sp_digit* r, const sp_digit* a,
  8420. sp_digit b)
  8421. {
  8422. sp_int64 tb = b;
  8423. sp_int64 t = 0;
  8424. sp_digit t2;
  8425. sp_int64 p[4];
  8426. int i;
  8427. for (i = 0; i < 112; i += 4) {
  8428. p[0] = tb * a[i + 0];
  8429. p[1] = tb * a[i + 1];
  8430. p[2] = tb * a[i + 2];
  8431. p[3] = tb * a[i + 3];
  8432. t += p[0];
  8433. t2 = (sp_digit)(t & 0xfffffff);
  8434. t >>= 28;
  8435. r[i + 0] = (sp_digit)t2;
  8436. t += p[1];
  8437. t2 = (sp_digit)(t & 0xfffffff);
  8438. t >>= 28;
  8439. r[i + 1] = (sp_digit)t2;
  8440. t += p[2];
  8441. t2 = (sp_digit)(t & 0xfffffff);
  8442. t >>= 28;
  8443. r[i + 2] = (sp_digit)t2;
  8444. t += p[3];
  8445. t2 = (sp_digit)(t & 0xfffffff);
  8446. t >>= 28;
  8447. r[i + 3] = (sp_digit)t2;
  8448. }
  8449. r[112] = (sp_digit)(t & 0xfffffff);
  8450. }
  8451. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  8452. /* r = 2^n mod m where n is the number of bits to reduce by.
  8453. * Given m must be 3072 bits, just need to subtract.
  8454. *
  8455. * r A single precision number.
  8456. * m A single precision number.
  8457. */
  8458. static void sp_3072_mont_norm_56(sp_digit* r, const sp_digit* m)
  8459. {
  8460. /* Set r = 2^n - 1. */
  8461. int i;
  8462. for (i = 0; i < 48; i += 8) {
  8463. r[i + 0] = 0xfffffff;
  8464. r[i + 1] = 0xfffffff;
  8465. r[i + 2] = 0xfffffff;
  8466. r[i + 3] = 0xfffffff;
  8467. r[i + 4] = 0xfffffff;
  8468. r[i + 5] = 0xfffffff;
  8469. r[i + 6] = 0xfffffff;
  8470. r[i + 7] = 0xfffffff;
  8471. }
  8472. r[48] = 0xfffffff;
  8473. r[49] = 0xfffffff;
  8474. r[50] = 0xfffffff;
  8475. r[51] = 0xfffffff;
  8476. r[52] = 0xfffffff;
  8477. r[53] = 0xfffffff;
  8478. r[54] = 0xffffffL;
  8479. r[55] = 0;
  8480. /* r = (2^n - 1) mod n */
  8481. (void)sp_3072_sub_56(r, r, m);
  8482. /* Add one so r = 2^n mod m */
  8483. r[0] += 1;
  8484. }
  8485. /* Compare a with b in constant time.
  8486. *
  8487. * a A single precision integer.
  8488. * b A single precision integer.
  8489. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  8490. * respectively.
  8491. */
  8492. static sp_digit sp_3072_cmp_56(const sp_digit* a, const sp_digit* b)
  8493. {
  8494. sp_digit r = 0;
  8495. int i;
  8496. for (i = 48; i >= 0; i -= 8) {
  8497. r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 27);
  8498. r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 27);
  8499. r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 27);
  8500. r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 27);
  8501. r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 27);
  8502. r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 27);
  8503. r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 27);
  8504. r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 27);
  8505. }
  8506. return r;
  8507. }
  8508. /* Conditionally subtract b from a using the mask m.
  8509. * m is -1 to subtract and 0 when not.
  8510. *
  8511. * r A single precision number representing condition subtract result.
  8512. * a A single precision number to subtract from.
  8513. * b A single precision number to subtract.
  8514. * m Mask value to apply.
  8515. */
  8516. static void sp_3072_cond_sub_56(sp_digit* r, const sp_digit* a,
  8517. const sp_digit* b, const sp_digit m)
  8518. {
  8519. int i;
  8520. for (i = 0; i < 56; i += 8) {
  8521. r[i + 0] = a[i + 0] - (b[i + 0] & m);
  8522. r[i + 1] = a[i + 1] - (b[i + 1] & m);
  8523. r[i + 2] = a[i + 2] - (b[i + 2] & m);
  8524. r[i + 3] = a[i + 3] - (b[i + 3] & m);
  8525. r[i + 4] = a[i + 4] - (b[i + 4] & m);
  8526. r[i + 5] = a[i + 5] - (b[i + 5] & m);
  8527. r[i + 6] = a[i + 6] - (b[i + 6] & m);
  8528. r[i + 7] = a[i + 7] - (b[i + 7] & m);
  8529. }
  8530. }
  8531. /* Mul a by scalar b and add into r. (r += a * b)
  8532. *
  8533. * r A single precision integer.
  8534. * a A single precision integer.
  8535. * b A scalar.
  8536. */
  8537. SP_NOINLINE static void sp_3072_mul_add_56(sp_digit* r, const sp_digit* a,
  8538. const sp_digit b)
  8539. {
  8540. #ifndef WOLFSSL_SP_LARGE_CODE
  8541. sp_int64 tb = b;
  8542. sp_int64 t = 0;
  8543. int i;
  8544. for (i = 0; i < 56; i++) {
  8545. t += r[i];
  8546. t += tb * a[i];
  8547. r[i] = ((sp_digit)t) & 0xfffffff;
  8548. t >>= 28;
  8549. }
  8550. r[56] += (sp_digit)t;
  8551. #else
  8552. sp_int64 tb = b;
  8553. sp_int64 t[8];
  8554. int i;
  8555. t[0] = 0;
  8556. for (i = 0; i < 48; i += 8) {
  8557. t[0] += (tb * a[i+0]) + r[i+0];
  8558. t[1] = (tb * a[i+1]) + r[i+1];
  8559. t[2] = (tb * a[i+2]) + r[i+2];
  8560. t[3] = (tb * a[i+3]) + r[i+3];
  8561. t[4] = (tb * a[i+4]) + r[i+4];
  8562. t[5] = (tb * a[i+5]) + r[i+5];
  8563. t[6] = (tb * a[i+6]) + r[i+6];
  8564. t[7] = (tb * a[i+7]) + r[i+7];
  8565. r[i+0] = t[0] & 0xfffffff;
  8566. t[1] += t[0] >> 28;
  8567. r[i+1] = t[1] & 0xfffffff;
  8568. t[2] += t[1] >> 28;
  8569. r[i+2] = t[2] & 0xfffffff;
  8570. t[3] += t[2] >> 28;
  8571. r[i+3] = t[3] & 0xfffffff;
  8572. t[4] += t[3] >> 28;
  8573. r[i+4] = t[4] & 0xfffffff;
  8574. t[5] += t[4] >> 28;
  8575. r[i+5] = t[5] & 0xfffffff;
  8576. t[6] += t[5] >> 28;
  8577. r[i+6] = t[6] & 0xfffffff;
  8578. t[7] += t[6] >> 28;
  8579. r[i+7] = t[7] & 0xfffffff;
  8580. t[0] = t[7] >> 28;
  8581. }
  8582. t[0] += (tb * a[48]) + r[48];
  8583. t[1] = (tb * a[49]) + r[49];
  8584. t[2] = (tb * a[50]) + r[50];
  8585. t[3] = (tb * a[51]) + r[51];
  8586. t[4] = (tb * a[52]) + r[52];
  8587. t[5] = (tb * a[53]) + r[53];
  8588. t[6] = (tb * a[54]) + r[54];
  8589. t[7] = (tb * a[55]) + r[55];
  8590. r[48] = t[0] & 0xfffffff;
  8591. t[1] += t[0] >> 28;
  8592. r[49] = t[1] & 0xfffffff;
  8593. t[2] += t[1] >> 28;
  8594. r[50] = t[2] & 0xfffffff;
  8595. t[3] += t[2] >> 28;
  8596. r[51] = t[3] & 0xfffffff;
  8597. t[4] += t[3] >> 28;
  8598. r[52] = t[4] & 0xfffffff;
  8599. t[5] += t[4] >> 28;
  8600. r[53] = t[5] & 0xfffffff;
  8601. t[6] += t[5] >> 28;
  8602. r[54] = t[6] & 0xfffffff;
  8603. t[7] += t[6] >> 28;
  8604. r[55] = t[7] & 0xfffffff;
  8605. r[56] += (sp_digit)(t[7] >> 28);
  8606. #endif /* !WOLFSSL_SP_LARGE_CODE */
  8607. }
  8608. /* Shift the result in the high 1536 bits down to the bottom.
  8609. *
  8610. * r A single precision number.
  8611. * a A single precision number.
  8612. */
  8613. static void sp_3072_mont_shift_56(sp_digit* r, const sp_digit* a)
  8614. {
  8615. int i;
  8616. sp_int64 n = a[54] >> 24;
  8617. n += ((sp_int64)a[55]) << 4;
  8618. for (i = 0; i < 48; i += 8) {
  8619. r[i + 0] = n & 0xfffffff;
  8620. n >>= 28; n += ((sp_int64)a[i + 56]) << 4;
  8621. r[i + 1] = n & 0xfffffff;
  8622. n >>= 28; n += ((sp_int64)a[i + 57]) << 4;
  8623. r[i + 2] = n & 0xfffffff;
  8624. n >>= 28; n += ((sp_int64)a[i + 58]) << 4;
  8625. r[i + 3] = n & 0xfffffff;
  8626. n >>= 28; n += ((sp_int64)a[i + 59]) << 4;
  8627. r[i + 4] = n & 0xfffffff;
  8628. n >>= 28; n += ((sp_int64)a[i + 60]) << 4;
  8629. r[i + 5] = n & 0xfffffff;
  8630. n >>= 28; n += ((sp_int64)a[i + 61]) << 4;
  8631. r[i + 6] = n & 0xfffffff;
  8632. n >>= 28; n += ((sp_int64)a[i + 62]) << 4;
  8633. r[i + 7] = n & 0xfffffff;
  8634. n >>= 28; n += ((sp_int64)a[i + 63]) << 4;
  8635. }
  8636. r[48] = n & 0xfffffff; n >>= 28; n += ((sp_int64)a[104]) << 4;
  8637. r[49] = n & 0xfffffff; n >>= 28; n += ((sp_int64)a[105]) << 4;
  8638. r[50] = n & 0xfffffff; n >>= 28; n += ((sp_int64)a[106]) << 4;
  8639. r[51] = n & 0xfffffff; n >>= 28; n += ((sp_int64)a[107]) << 4;
  8640. r[52] = n & 0xfffffff; n >>= 28; n += ((sp_int64)a[108]) << 4;
  8641. r[53] = n & 0xfffffff; n >>= 28; n += ((sp_int64)a[109]) << 4;
  8642. r[54] = (sp_digit)n;
  8643. XMEMSET(&r[55], 0, sizeof(*r) * 55U);
  8644. }
  8645. /* Reduce the number back to 3072 bits using Montgomery reduction.
  8646. *
  8647. * a A single precision number to reduce in place.
  8648. * m The single precision number representing the modulus.
  8649. * mp The digit representing the negative inverse of m mod 2^n.
  8650. */
  8651. static void sp_3072_mont_reduce_56(sp_digit* a, const sp_digit* m, sp_digit mp)
  8652. {
  8653. int i;
  8654. sp_digit mu;
  8655. sp_digit over;
  8656. sp_3072_norm_56(a + 55);
  8657. for (i=0; i<54; i++) {
  8658. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffff;
  8659. sp_3072_mul_add_56(a+i, m, mu);
  8660. a[i+1] += a[i] >> 28;
  8661. }
  8662. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0xffffffL;
  8663. sp_3072_mul_add_56(a+i, m, mu);
  8664. a[i+1] += a[i] >> 28;
  8665. a[i] &= 0xfffffff;
  8666. sp_3072_mont_shift_56(a, a);
  8667. over = a[54] - m[54];
  8668. sp_3072_cond_sub_56(a, a, m, ~((over - 1) >> 31));
  8669. sp_3072_norm_56(a);
  8670. }
  8671. /* Multiply two Montgomery form numbers mod the modulus (prime).
  8672. * (r = a * b mod m)
  8673. *
  8674. * r Result of multiplication.
  8675. * a First number to multiply in Montgomery form.
  8676. * b Second number to multiply in Montgomery form.
  8677. * m Modulus (prime).
  8678. * mp Montgomery mulitplier.
  8679. */
  8680. SP_NOINLINE static void sp_3072_mont_mul_56(sp_digit* r, const sp_digit* a,
  8681. const sp_digit* b, const sp_digit* m, sp_digit mp)
  8682. {
  8683. sp_3072_mul_56(r, a, b);
  8684. sp_3072_mont_reduce_56(r, m, mp);
  8685. }
  8686. /* Square the Montgomery form number. (r = a * a mod m)
  8687. *
  8688. * r Result of squaring.
  8689. * a Number to square in Montgomery form.
  8690. * m Modulus (prime).
  8691. * mp Montgomery mulitplier.
  8692. */
  8693. SP_NOINLINE static void sp_3072_mont_sqr_56(sp_digit* r, const sp_digit* a,
  8694. const sp_digit* m, sp_digit mp)
  8695. {
  8696. sp_3072_sqr_56(r, a);
  8697. sp_3072_mont_reduce_56(r, m, mp);
  8698. }
  8699. /* Multiply a by scalar b into r. (r = a * b)
  8700. *
  8701. * r A single precision integer.
  8702. * a A single precision integer.
  8703. * b A scalar.
  8704. */
  8705. SP_NOINLINE static void sp_3072_mul_d_56(sp_digit* r, const sp_digit* a,
  8706. sp_digit b)
  8707. {
  8708. sp_int64 tb = b;
  8709. sp_int64 t = 0;
  8710. sp_digit t2;
  8711. sp_int64 p[4];
  8712. int i;
  8713. for (i = 0; i < 56; i += 4) {
  8714. p[0] = tb * a[i + 0];
  8715. p[1] = tb * a[i + 1];
  8716. p[2] = tb * a[i + 2];
  8717. p[3] = tb * a[i + 3];
  8718. t += p[0];
  8719. t2 = (sp_digit)(t & 0xfffffff);
  8720. t >>= 28;
  8721. r[i + 0] = (sp_digit)t2;
  8722. t += p[1];
  8723. t2 = (sp_digit)(t & 0xfffffff);
  8724. t >>= 28;
  8725. r[i + 1] = (sp_digit)t2;
  8726. t += p[2];
  8727. t2 = (sp_digit)(t & 0xfffffff);
  8728. t >>= 28;
  8729. r[i + 2] = (sp_digit)t2;
  8730. t += p[3];
  8731. t2 = (sp_digit)(t & 0xfffffff);
  8732. t >>= 28;
  8733. r[i + 3] = (sp_digit)t2;
  8734. }
  8735. r[56] = (sp_digit)(t & 0xfffffff);
  8736. }
  8737. #ifndef WOLFSSL_SP_SMALL
  8738. /* Conditionally add a and b using the mask m.
  8739. * m is -1 to add and 0 when not.
  8740. *
  8741. * r A single precision number representing conditional add result.
  8742. * a A single precision number to add with.
  8743. * b A single precision number to add.
  8744. * m Mask value to apply.
  8745. */
  8746. static void sp_3072_cond_add_56(sp_digit* r, const sp_digit* a,
  8747. const sp_digit* b, const sp_digit m)
  8748. {
  8749. int i;
  8750. for (i = 0; i < 56; i += 8) {
  8751. r[i + 0] = a[i + 0] + (b[i + 0] & m);
  8752. r[i + 1] = a[i + 1] + (b[i + 1] & m);
  8753. r[i + 2] = a[i + 2] + (b[i + 2] & m);
  8754. r[i + 3] = a[i + 3] + (b[i + 3] & m);
  8755. r[i + 4] = a[i + 4] + (b[i + 4] & m);
  8756. r[i + 5] = a[i + 5] + (b[i + 5] & m);
  8757. r[i + 6] = a[i + 6] + (b[i + 6] & m);
  8758. r[i + 7] = a[i + 7] + (b[i + 7] & m);
  8759. }
  8760. }
  8761. #endif /* !WOLFSSL_SP_SMALL */
  8762. SP_NOINLINE static void sp_3072_rshift_56(sp_digit* r, const sp_digit* a,
  8763. byte n)
  8764. {
  8765. int i;
  8766. for (i=0; i<48; i += 8) {
  8767. r[i+0] = (a[i+0] >> n) | ((a[i+1] << (28 - n)) & 0xfffffff);
  8768. r[i+1] = (a[i+1] >> n) | ((a[i+2] << (28 - n)) & 0xfffffff);
  8769. r[i+2] = (a[i+2] >> n) | ((a[i+3] << (28 - n)) & 0xfffffff);
  8770. r[i+3] = (a[i+3] >> n) | ((a[i+4] << (28 - n)) & 0xfffffff);
  8771. r[i+4] = (a[i+4] >> n) | ((a[i+5] << (28 - n)) & 0xfffffff);
  8772. r[i+5] = (a[i+5] >> n) | ((a[i+6] << (28 - n)) & 0xfffffff);
  8773. r[i+6] = (a[i+6] >> n) | ((a[i+7] << (28 - n)) & 0xfffffff);
  8774. r[i+7] = (a[i+7] >> n) | ((a[i+8] << (28 - n)) & 0xfffffff);
  8775. }
  8776. r[48] = (a[48] >> n) | ((a[49] << (28 - n)) & 0xfffffff);
  8777. r[49] = (a[49] >> n) | ((a[50] << (28 - n)) & 0xfffffff);
  8778. r[50] = (a[50] >> n) | ((a[51] << (28 - n)) & 0xfffffff);
  8779. r[51] = (a[51] >> n) | ((a[52] << (28 - n)) & 0xfffffff);
  8780. r[52] = (a[52] >> n) | ((a[53] << (28 - n)) & 0xfffffff);
  8781. r[53] = (a[53] >> n) | ((a[54] << (28 - n)) & 0xfffffff);
  8782. r[54] = (a[54] >> n) | ((a[55] << (28 - n)) & 0xfffffff);
  8783. r[55] = a[55] >> n;
  8784. }
  8785. static WC_INLINE sp_digit sp_3072_div_word_56(sp_digit d1, sp_digit d0,
  8786. sp_digit div)
  8787. {
  8788. #ifdef SP_USE_DIVTI3
  8789. sp_int64 d = ((sp_int64)d1 << 28) + d0;
  8790. return d / div;
  8791. #elif defined(__x86_64__) || defined(__i386__)
  8792. sp_int64 d = ((sp_int64)d1 << 28) + d0;
  8793. sp_uint32 lo = (sp_uint32)d;
  8794. sp_digit hi = (sp_digit)(d >> 32);
  8795. __asm__ __volatile__ (
  8796. "idiv %2"
  8797. : "+a" (lo)
  8798. : "d" (hi), "r" (div)
  8799. : "cc"
  8800. );
  8801. return (sp_digit)lo;
  8802. #elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV)
  8803. sp_int64 d = ((sp_int64)d1 << 28) + d0;
  8804. sp_digit dv = (div >> 1) + 1;
  8805. sp_digit t1 = (sp_digit)(d >> 28);
  8806. sp_digit t0 = (sp_digit)(d & 0xfffffff);
  8807. sp_digit t2;
  8808. sp_digit sign;
  8809. sp_digit r;
  8810. int i;
  8811. sp_int64 m;
  8812. r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
  8813. t1 -= dv & (0 - r);
  8814. for (i = 26; i >= 1; i--) {
  8815. t1 += t1 + (((sp_uint32)t0 >> 27) & 1);
  8816. t0 <<= 1;
  8817. t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
  8818. r += r + t2;
  8819. t1 -= dv & (0 - t2);
  8820. t1 += t2;
  8821. }
  8822. r += r + 1;
  8823. m = d - ((sp_int64)r * div);
  8824. r += (sp_digit)(m >> 28);
  8825. m = d - ((sp_int64)r * div);
  8826. r += (sp_digit)(m >> 56) - (sp_digit)(d >> 56);
  8827. m = d - ((sp_int64)r * div);
  8828. sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
  8829. m *= sign;
  8830. t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
  8831. r += sign * t2;
  8832. m = d - ((sp_int64)r * div);
  8833. sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
  8834. m *= sign;
  8835. t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
  8836. r += sign * t2;
  8837. return r;
  8838. #else
  8839. sp_int64 d = ((sp_int64)d1 << 28) + d0;
  8840. sp_digit r = 0;
  8841. sp_digit t;
  8842. sp_digit dv = (div >> 13) + 1;
  8843. t = (sp_digit)(d >> 26);
  8844. t = (t / dv) << 13;
  8845. r += t;
  8846. d -= (sp_int64)t * div;
  8847. t = (sp_digit)(d >> 11);
  8848. t = t / (dv << 2);
  8849. r += t;
  8850. d -= (sp_int64)t * div;
  8851. t = (sp_digit)d;
  8852. t = t / div;
  8853. r += t;
  8854. d -= (sp_int64)t * div;
  8855. return r;
  8856. #endif
  8857. }
  8858. static WC_INLINE sp_digit sp_3072_word_div_word_56(sp_digit d, sp_digit div)
  8859. {
  8860. #if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
  8861. defined(SP_DIV_WORD_USE_DIV)
  8862. return d / div;
  8863. #else
  8864. return (sp_digit)((sp_uint32)(div - d) >> 31);
  8865. #endif
  8866. }
  8867. /* Divide d in a and put remainder into r (m*d + r = a)
  8868. * m is not calculated as it is not needed at this time.
  8869. *
  8870. * Full implementation.
  8871. *
  8872. * a Number to be divided.
  8873. * d Number to divide with.
  8874. * m Multiplier result.
  8875. * r Remainder from the division.
  8876. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  8877. */
  8878. static int sp_3072_div_56(const sp_digit* a, const sp_digit* d,
  8879. const sp_digit* m, sp_digit* r)
  8880. {
  8881. int i;
  8882. #ifndef WOLFSSL_SP_DIV_32
  8883. #endif
  8884. sp_digit dv;
  8885. sp_digit r1;
  8886. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  8887. sp_digit* t1 = NULL;
  8888. #else
  8889. sp_digit t1[4 * 56 + 3];
  8890. #endif
  8891. sp_digit* t2 = NULL;
  8892. sp_digit* sd = NULL;
  8893. int err = MP_OKAY;
  8894. (void)m;
  8895. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  8896. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 56 + 3), NULL,
  8897. DYNAMIC_TYPE_TMP_BUFFER);
  8898. if (t1 == NULL)
  8899. err = MEMORY_E;
  8900. #endif
  8901. (void)m;
  8902. if (err == MP_OKAY) {
  8903. t2 = t1 + 112 + 1;
  8904. sd = t2 + 56 + 1;
  8905. sp_3072_mul_d_56(sd, d, (sp_digit)1 << 4);
  8906. sp_3072_mul_d_112(t1, a, (sp_digit)1 << 4);
  8907. dv = sd[54];
  8908. t1[55 + 55] += t1[55 + 55 - 1] >> 28;
  8909. t1[55 + 55 - 1] &= 0xfffffff;
  8910. for (i=55; i>=0; i--) {
  8911. r1 = sp_3072_div_word_56(t1[55 + i], t1[55 + i - 1], dv);
  8912. sp_3072_mul_d_56(t2, sd, r1);
  8913. (void)sp_3072_sub_56(&t1[i], &t1[i], t2);
  8914. sp_3072_norm_55(&t1[i]);
  8915. t1[55 + i] += t1[55 + i - 1] >> 28;
  8916. t1[55 + i - 1] &= 0xfffffff;
  8917. r1 = sp_3072_div_word_56(-t1[55 + i], -t1[55 + i - 1], dv);
  8918. r1 -= t1[55 + i];
  8919. sp_3072_mul_d_56(t2, sd, r1);
  8920. (void)sp_3072_add_56(&t1[i], &t1[i], t2);
  8921. t1[55 + i] += t1[55 + i - 1] >> 28;
  8922. t1[55 + i - 1] &= 0xfffffff;
  8923. }
  8924. t1[55 - 1] += t1[55 - 2] >> 28;
  8925. t1[55 - 2] &= 0xfffffff;
  8926. r1 = sp_3072_word_div_word_56(t1[55 - 1], dv);
  8927. sp_3072_mul_d_56(t2, sd, r1);
  8928. sp_3072_sub_56(t1, t1, t2);
  8929. XMEMCPY(r, t1, sizeof(*r) * 112U);
  8930. for (i=0; i<54; i++) {
  8931. r[i+1] += r[i] >> 28;
  8932. r[i] &= 0xfffffff;
  8933. }
  8934. sp_3072_cond_add_56(r, r, sd, r[54] >> 31);
  8935. sp_3072_norm_55(r);
  8936. sp_3072_rshift_56(r, r, 4);
  8937. r[55] = 0;
  8938. }
  8939. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  8940. if (t1 != NULL)
  8941. XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  8942. #endif
  8943. return err;
  8944. }
  8945. /* Reduce a modulo m into r. (r = a mod m)
  8946. *
  8947. * r A single precision number that is the reduced result.
  8948. * a A single precision number that is to be reduced.
  8949. * m A single precision number that is the modulus to reduce with.
  8950. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  8951. */
  8952. static int sp_3072_mod_56(sp_digit* r, const sp_digit* a, const sp_digit* m)
  8953. {
  8954. return sp_3072_div_56(a, m, NULL, r);
  8955. }
  8956. /* Modular exponentiate a to the e mod m. (r = a^e mod m)
  8957. *
  8958. * r A single precision number that is the result of the operation.
  8959. * a A single precision number being exponentiated.
  8960. * e A single precision number that is the exponent.
  8961. * bits The number of bits in the exponent.
  8962. * m A single precision number that is the modulus.
  8963. * returns 0 on success.
  8964. * returns MEMORY_E on dynamic memory allocation failure.
  8965. * returns MP_VAL when base is even or exponent is 0.
  8966. */
  8967. static int sp_3072_mod_exp_56(sp_digit* r, const sp_digit* a, const sp_digit* e,
  8968. int bits, const sp_digit* m, int reduceA)
  8969. {
  8970. #if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP)
  8971. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  8972. sp_digit* td = NULL;
  8973. #else
  8974. sp_digit td[3 * 112];
  8975. #endif
  8976. sp_digit* t[3] = {0, 0, 0};
  8977. sp_digit* norm = NULL;
  8978. sp_digit mp = 1;
  8979. sp_digit n;
  8980. int i;
  8981. int c;
  8982. byte y;
  8983. int err = MP_OKAY;
  8984. if (bits == 0) {
  8985. err = MP_VAL;
  8986. }
  8987. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  8988. if (err == MP_OKAY) {
  8989. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 56 * 2, NULL,
  8990. DYNAMIC_TYPE_TMP_BUFFER);
  8991. if (td == NULL)
  8992. err = MEMORY_E;
  8993. }
  8994. #endif
  8995. if (err == MP_OKAY) {
  8996. norm = td;
  8997. for (i=0; i<3; i++) {
  8998. t[i] = td + (i * 56 * 2);
  8999. XMEMSET(t[i], 0, sizeof(sp_digit) * 56U * 2U);
  9000. }
  9001. sp_3072_mont_setup(m, &mp);
  9002. sp_3072_mont_norm_56(norm, m);
  9003. if (reduceA != 0) {
  9004. err = sp_3072_mod_56(t[1], a, m);
  9005. }
  9006. else {
  9007. XMEMCPY(t[1], a, sizeof(sp_digit) * 56U);
  9008. }
  9009. }
  9010. if (err == MP_OKAY) {
  9011. sp_3072_mul_56(t[1], t[1], norm);
  9012. err = sp_3072_mod_56(t[1], t[1], m);
  9013. }
  9014. if (err == MP_OKAY) {
  9015. i = bits / 28;
  9016. c = bits % 28;
  9017. n = e[i--] << (28 - c);
  9018. for (; ; c--) {
  9019. if (c == 0) {
  9020. if (i == -1) {
  9021. break;
  9022. }
  9023. n = e[i--];
  9024. c = 28;
  9025. }
  9026. y = (int)((n >> 27) & 1);
  9027. n <<= 1;
  9028. sp_3072_mont_mul_56(t[y^1], t[0], t[1], m, mp);
  9029. XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
  9030. ((size_t)t[1] & addr_mask[y])),
  9031. sizeof(*t[2]) * 56 * 2);
  9032. sp_3072_mont_sqr_56(t[2], t[2], m, mp);
  9033. XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
  9034. ((size_t)t[1] & addr_mask[y])), t[2],
  9035. sizeof(*t[2]) * 56 * 2);
  9036. }
  9037. sp_3072_mont_reduce_56(t[0], m, mp);
  9038. n = sp_3072_cmp_56(t[0], m);
  9039. sp_3072_cond_sub_56(t[0], t[0], m, ~(n >> 31));
  9040. XMEMCPY(r, t[0], sizeof(*r) * 56 * 2);
  9041. }
  9042. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  9043. if (td != NULL)
  9044. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  9045. #endif
  9046. return err;
  9047. #elif !defined(WC_NO_CACHE_RESISTANT)
  9048. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  9049. sp_digit* td = NULL;
  9050. #else
  9051. sp_digit td[3 * 112];
  9052. #endif
  9053. sp_digit* t[3] = {0, 0, 0};
  9054. sp_digit* norm = NULL;
  9055. sp_digit mp = 1;
  9056. sp_digit n;
  9057. int i;
  9058. int c;
  9059. byte y;
  9060. int err = MP_OKAY;
  9061. if (bits == 0) {
  9062. err = MP_VAL;
  9063. }
  9064. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  9065. if (err == MP_OKAY) {
  9066. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 56 * 2, NULL,
  9067. DYNAMIC_TYPE_TMP_BUFFER);
  9068. if (td == NULL)
  9069. err = MEMORY_E;
  9070. }
  9071. #endif
  9072. if (err == MP_OKAY) {
  9073. norm = td;
  9074. for (i=0; i<3; i++) {
  9075. t[i] = td + (i * 56 * 2);
  9076. }
  9077. sp_3072_mont_setup(m, &mp);
  9078. sp_3072_mont_norm_56(norm, m);
  9079. if (reduceA != 0) {
  9080. err = sp_3072_mod_56(t[1], a, m);
  9081. if (err == MP_OKAY) {
  9082. sp_3072_mul_56(t[1], t[1], norm);
  9083. err = sp_3072_mod_56(t[1], t[1], m);
  9084. }
  9085. }
  9086. else {
  9087. sp_3072_mul_56(t[1], a, norm);
  9088. err = sp_3072_mod_56(t[1], t[1], m);
  9089. }
  9090. }
  9091. if (err == MP_OKAY) {
  9092. i = bits / 28;
  9093. c = bits % 28;
  9094. n = e[i--] << (28 - c);
  9095. for (; ; c--) {
  9096. if (c == 0) {
  9097. if (i == -1) {
  9098. break;
  9099. }
  9100. n = e[i--];
  9101. c = 28;
  9102. }
  9103. y = (int)((n >> 27) & 1);
  9104. n <<= 1;
  9105. sp_3072_mont_mul_56(t[y^1], t[0], t[1], m, mp);
  9106. XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
  9107. ((size_t)t[1] & addr_mask[y])),
  9108. sizeof(*t[2]) * 56 * 2);
  9109. sp_3072_mont_sqr_56(t[2], t[2], m, mp);
  9110. XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
  9111. ((size_t)t[1] & addr_mask[y])), t[2],
  9112. sizeof(*t[2]) * 56 * 2);
  9113. }
  9114. sp_3072_mont_reduce_56(t[0], m, mp);
  9115. n = sp_3072_cmp_56(t[0], m);
  9116. sp_3072_cond_sub_56(t[0], t[0], m, ~(n >> 31));
  9117. XMEMCPY(r, t[0], sizeof(*r) * 56 * 2);
  9118. }
  9119. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  9120. if (td != NULL)
  9121. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  9122. #endif
  9123. return err;
  9124. #else
  9125. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  9126. sp_digit* td = NULL;
  9127. #else
  9128. sp_digit td[(32 * 112) + 112];
  9129. #endif
  9130. sp_digit* t[32];
  9131. sp_digit* rt = NULL;
  9132. sp_digit* norm = NULL;
  9133. sp_digit mp = 1;
  9134. sp_digit n;
  9135. int i;
  9136. int c;
  9137. byte y;
  9138. int err = MP_OKAY;
  9139. if (bits == 0) {
  9140. err = MP_VAL;
  9141. }
  9142. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  9143. if (err == MP_OKAY) {
  9144. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((32 * 112) + 112), NULL,
  9145. DYNAMIC_TYPE_TMP_BUFFER);
  9146. if (td == NULL)
  9147. err = MEMORY_E;
  9148. }
  9149. #endif
  9150. if (err == MP_OKAY) {
  9151. norm = td;
  9152. for (i=0; i<32; i++)
  9153. t[i] = td + i * 112;
  9154. rt = td + 3584;
  9155. sp_3072_mont_setup(m, &mp);
  9156. sp_3072_mont_norm_56(norm, m);
  9157. if (reduceA != 0) {
  9158. err = sp_3072_mod_56(t[1], a, m);
  9159. if (err == MP_OKAY) {
  9160. sp_3072_mul_56(t[1], t[1], norm);
  9161. err = sp_3072_mod_56(t[1], t[1], m);
  9162. }
  9163. }
  9164. else {
  9165. sp_3072_mul_56(t[1], a, norm);
  9166. err = sp_3072_mod_56(t[1], t[1], m);
  9167. }
  9168. }
  9169. if (err == MP_OKAY) {
  9170. sp_3072_mont_sqr_56(t[ 2], t[ 1], m, mp);
  9171. sp_3072_mont_mul_56(t[ 3], t[ 2], t[ 1], m, mp);
  9172. sp_3072_mont_sqr_56(t[ 4], t[ 2], m, mp);
  9173. sp_3072_mont_mul_56(t[ 5], t[ 3], t[ 2], m, mp);
  9174. sp_3072_mont_sqr_56(t[ 6], t[ 3], m, mp);
  9175. sp_3072_mont_mul_56(t[ 7], t[ 4], t[ 3], m, mp);
  9176. sp_3072_mont_sqr_56(t[ 8], t[ 4], m, mp);
  9177. sp_3072_mont_mul_56(t[ 9], t[ 5], t[ 4], m, mp);
  9178. sp_3072_mont_sqr_56(t[10], t[ 5], m, mp);
  9179. sp_3072_mont_mul_56(t[11], t[ 6], t[ 5], m, mp);
  9180. sp_3072_mont_sqr_56(t[12], t[ 6], m, mp);
  9181. sp_3072_mont_mul_56(t[13], t[ 7], t[ 6], m, mp);
  9182. sp_3072_mont_sqr_56(t[14], t[ 7], m, mp);
  9183. sp_3072_mont_mul_56(t[15], t[ 8], t[ 7], m, mp);
  9184. sp_3072_mont_sqr_56(t[16], t[ 8], m, mp);
  9185. sp_3072_mont_mul_56(t[17], t[ 9], t[ 8], m, mp);
  9186. sp_3072_mont_sqr_56(t[18], t[ 9], m, mp);
  9187. sp_3072_mont_mul_56(t[19], t[10], t[ 9], m, mp);
  9188. sp_3072_mont_sqr_56(t[20], t[10], m, mp);
  9189. sp_3072_mont_mul_56(t[21], t[11], t[10], m, mp);
  9190. sp_3072_mont_sqr_56(t[22], t[11], m, mp);
  9191. sp_3072_mont_mul_56(t[23], t[12], t[11], m, mp);
  9192. sp_3072_mont_sqr_56(t[24], t[12], m, mp);
  9193. sp_3072_mont_mul_56(t[25], t[13], t[12], m, mp);
  9194. sp_3072_mont_sqr_56(t[26], t[13], m, mp);
  9195. sp_3072_mont_mul_56(t[27], t[14], t[13], m, mp);
  9196. sp_3072_mont_sqr_56(t[28], t[14], m, mp);
  9197. sp_3072_mont_mul_56(t[29], t[15], t[14], m, mp);
  9198. sp_3072_mont_sqr_56(t[30], t[15], m, mp);
  9199. sp_3072_mont_mul_56(t[31], t[16], t[15], m, mp);
  9200. bits = ((bits + 4) / 5) * 5;
  9201. i = ((bits + 27) / 28) - 1;
  9202. c = bits % 28;
  9203. if (c == 0) {
  9204. c = 28;
  9205. }
  9206. if (i < 56) {
  9207. n = e[i--] << (32 - c);
  9208. }
  9209. else {
  9210. n = 0;
  9211. i--;
  9212. }
  9213. if (c < 5) {
  9214. n |= e[i--] << (4 - c);
  9215. c += 28;
  9216. }
  9217. y = (int)((n >> 27) & 0x1f);
  9218. n <<= 5;
  9219. c -= 5;
  9220. XMEMCPY(rt, t[y], sizeof(sp_digit) * 112);
  9221. while ((i >= 0) || (c >= 5)) {
  9222. if (c >= 5) {
  9223. y = (byte)((n >> 27) & 0x1f);
  9224. n <<= 5;
  9225. c -= 5;
  9226. }
  9227. else if (c == 0) {
  9228. n = e[i--] << 4;
  9229. y = (byte)((n >> 27) & 0x1f);
  9230. n <<= 5;
  9231. c = 23;
  9232. }
  9233. else {
  9234. y = (byte)((n >> 27) & 0x1f);
  9235. n = e[i--] << 4;
  9236. c = 5 - c;
  9237. y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
  9238. n <<= c;
  9239. c = 28 - c;
  9240. }
  9241. sp_3072_mont_sqr_56(rt, rt, m, mp);
  9242. sp_3072_mont_sqr_56(rt, rt, m, mp);
  9243. sp_3072_mont_sqr_56(rt, rt, m, mp);
  9244. sp_3072_mont_sqr_56(rt, rt, m, mp);
  9245. sp_3072_mont_sqr_56(rt, rt, m, mp);
  9246. sp_3072_mont_mul_56(rt, rt, t[y], m, mp);
  9247. }
  9248. sp_3072_mont_reduce_56(rt, m, mp);
  9249. n = sp_3072_cmp_56(rt, m);
  9250. sp_3072_cond_sub_56(rt, rt, m, ~(n >> 31));
  9251. XMEMCPY(r, rt, sizeof(sp_digit) * 112);
  9252. }
  9253. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  9254. if (td != NULL)
  9255. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  9256. #endif
  9257. return err;
  9258. #endif
  9259. }
  9260. #endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
  9261. /* r = 2^n mod m where n is the number of bits to reduce by.
  9262. * Given m must be 3072 bits, just need to subtract.
  9263. *
  9264. * r A single precision number.
  9265. * m A single precision number.
  9266. */
  9267. static void sp_3072_mont_norm_112(sp_digit* r, const sp_digit* m)
  9268. {
  9269. /* Set r = 2^n - 1. */
  9270. int i;
  9271. for (i = 0; i < 104; i += 8) {
  9272. r[i + 0] = 0xfffffff;
  9273. r[i + 1] = 0xfffffff;
  9274. r[i + 2] = 0xfffffff;
  9275. r[i + 3] = 0xfffffff;
  9276. r[i + 4] = 0xfffffff;
  9277. r[i + 5] = 0xfffffff;
  9278. r[i + 6] = 0xfffffff;
  9279. r[i + 7] = 0xfffffff;
  9280. }
  9281. r[104] = 0xfffffff;
  9282. r[105] = 0xfffffff;
  9283. r[106] = 0xfffffff;
  9284. r[107] = 0xfffffff;
  9285. r[108] = 0xfffffff;
  9286. r[109] = 0xfffffL;
  9287. r[110] = 0;
  9288. r[111] = 0;
  9289. /* r = (2^n - 1) mod n */
  9290. (void)sp_3072_sub_112(r, r, m);
  9291. /* Add one so r = 2^n mod m */
  9292. r[0] += 1;
  9293. }
  9294. /* Compare a with b in constant time.
  9295. *
  9296. * a A single precision integer.
  9297. * b A single precision integer.
  9298. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  9299. * respectively.
  9300. */
  9301. static sp_digit sp_3072_cmp_112(const sp_digit* a, const sp_digit* b)
  9302. {
  9303. sp_digit r = 0;
  9304. int i;
  9305. for (i = 104; i >= 0; i -= 8) {
  9306. r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 27);
  9307. r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 27);
  9308. r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 27);
  9309. r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 27);
  9310. r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 27);
  9311. r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 27);
  9312. r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 27);
  9313. r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 27);
  9314. }
  9315. return r;
  9316. }
  9317. /* Conditionally subtract b from a using the mask m.
  9318. * m is -1 to subtract and 0 when not.
  9319. *
  9320. * r A single precision number representing condition subtract result.
  9321. * a A single precision number to subtract from.
  9322. * b A single precision number to subtract.
  9323. * m Mask value to apply.
  9324. */
  9325. static void sp_3072_cond_sub_112(sp_digit* r, const sp_digit* a,
  9326. const sp_digit* b, const sp_digit m)
  9327. {
  9328. int i;
  9329. for (i = 0; i < 112; i += 8) {
  9330. r[i + 0] = a[i + 0] - (b[i + 0] & m);
  9331. r[i + 1] = a[i + 1] - (b[i + 1] & m);
  9332. r[i + 2] = a[i + 2] - (b[i + 2] & m);
  9333. r[i + 3] = a[i + 3] - (b[i + 3] & m);
  9334. r[i + 4] = a[i + 4] - (b[i + 4] & m);
  9335. r[i + 5] = a[i + 5] - (b[i + 5] & m);
  9336. r[i + 6] = a[i + 6] - (b[i + 6] & m);
  9337. r[i + 7] = a[i + 7] - (b[i + 7] & m);
  9338. }
  9339. }
  9340. /* Mul a by scalar b and add into r. (r += a * b)
  9341. *
  9342. * r A single precision integer.
  9343. * a A single precision integer.
  9344. * b A scalar.
  9345. */
  9346. SP_NOINLINE static void sp_3072_mul_add_112(sp_digit* r, const sp_digit* a,
  9347. const sp_digit b)
  9348. {
  9349. #ifndef WOLFSSL_SP_LARGE_CODE
  9350. sp_int64 tb = b;
  9351. sp_int64 t = 0;
  9352. int i;
  9353. for (i = 0; i < 112; i++) {
  9354. t += r[i];
  9355. t += tb * a[i];
  9356. r[i] = ((sp_digit)t) & 0xfffffff;
  9357. t >>= 28;
  9358. }
  9359. r[112] += (sp_digit)t;
  9360. #else
  9361. sp_int64 tb = b;
  9362. sp_int64 t[8];
  9363. int i;
  9364. t[0] = 0;
  9365. for (i = 0; i < 104; i += 8) {
  9366. t[0] += (tb * a[i+0]) + r[i+0];
  9367. t[1] = (tb * a[i+1]) + r[i+1];
  9368. t[2] = (tb * a[i+2]) + r[i+2];
  9369. t[3] = (tb * a[i+3]) + r[i+3];
  9370. t[4] = (tb * a[i+4]) + r[i+4];
  9371. t[5] = (tb * a[i+5]) + r[i+5];
  9372. t[6] = (tb * a[i+6]) + r[i+6];
  9373. t[7] = (tb * a[i+7]) + r[i+7];
  9374. r[i+0] = t[0] & 0xfffffff;
  9375. t[1] += t[0] >> 28;
  9376. r[i+1] = t[1] & 0xfffffff;
  9377. t[2] += t[1] >> 28;
  9378. r[i+2] = t[2] & 0xfffffff;
  9379. t[3] += t[2] >> 28;
  9380. r[i+3] = t[3] & 0xfffffff;
  9381. t[4] += t[3] >> 28;
  9382. r[i+4] = t[4] & 0xfffffff;
  9383. t[5] += t[4] >> 28;
  9384. r[i+5] = t[5] & 0xfffffff;
  9385. t[6] += t[5] >> 28;
  9386. r[i+6] = t[6] & 0xfffffff;
  9387. t[7] += t[6] >> 28;
  9388. r[i+7] = t[7] & 0xfffffff;
  9389. t[0] = t[7] >> 28;
  9390. }
  9391. t[0] += (tb * a[104]) + r[104];
  9392. t[1] = (tb * a[105]) + r[105];
  9393. t[2] = (tb * a[106]) + r[106];
  9394. t[3] = (tb * a[107]) + r[107];
  9395. t[4] = (tb * a[108]) + r[108];
  9396. t[5] = (tb * a[109]) + r[109];
  9397. t[6] = (tb * a[110]) + r[110];
  9398. t[7] = (tb * a[111]) + r[111];
  9399. r[104] = t[0] & 0xfffffff;
  9400. t[1] += t[0] >> 28;
  9401. r[105] = t[1] & 0xfffffff;
  9402. t[2] += t[1] >> 28;
  9403. r[106] = t[2] & 0xfffffff;
  9404. t[3] += t[2] >> 28;
  9405. r[107] = t[3] & 0xfffffff;
  9406. t[4] += t[3] >> 28;
  9407. r[108] = t[4] & 0xfffffff;
  9408. t[5] += t[4] >> 28;
  9409. r[109] = t[5] & 0xfffffff;
  9410. t[6] += t[5] >> 28;
  9411. r[110] = t[6] & 0xfffffff;
  9412. t[7] += t[6] >> 28;
  9413. r[111] = t[7] & 0xfffffff;
  9414. r[112] += (sp_digit)(t[7] >> 28);
  9415. #endif /* !WOLFSSL_SP_LARGE_CODE */
  9416. }
  9417. /* Shift the result in the high 3072 bits down to the bottom.
  9418. *
  9419. * r A single precision number.
  9420. * a A single precision number.
  9421. */
  9422. static void sp_3072_mont_shift_112(sp_digit* r, const sp_digit* a)
  9423. {
  9424. int i;
  9425. sp_int64 n = a[109] >> 20;
  9426. n += ((sp_int64)a[110]) << 8;
  9427. for (i = 0; i < 104; i += 8) {
  9428. r[i + 0] = n & 0xfffffff;
  9429. n >>= 28; n += ((sp_int64)a[i + 111]) << 8;
  9430. r[i + 1] = n & 0xfffffff;
  9431. n >>= 28; n += ((sp_int64)a[i + 112]) << 8;
  9432. r[i + 2] = n & 0xfffffff;
  9433. n >>= 28; n += ((sp_int64)a[i + 113]) << 8;
  9434. r[i + 3] = n & 0xfffffff;
  9435. n >>= 28; n += ((sp_int64)a[i + 114]) << 8;
  9436. r[i + 4] = n & 0xfffffff;
  9437. n >>= 28; n += ((sp_int64)a[i + 115]) << 8;
  9438. r[i + 5] = n & 0xfffffff;
  9439. n >>= 28; n += ((sp_int64)a[i + 116]) << 8;
  9440. r[i + 6] = n & 0xfffffff;
  9441. n >>= 28; n += ((sp_int64)a[i + 117]) << 8;
  9442. r[i + 7] = n & 0xfffffff;
  9443. n >>= 28; n += ((sp_int64)a[i + 118]) << 8;
  9444. }
  9445. r[104] = n & 0xfffffff; n >>= 28; n += ((sp_int64)a[215]) << 8;
  9446. r[105] = n & 0xfffffff; n >>= 28; n += ((sp_int64)a[216]) << 8;
  9447. r[106] = n & 0xfffffff; n >>= 28; n += ((sp_int64)a[217]) << 8;
  9448. r[107] = n & 0xfffffff; n >>= 28; n += ((sp_int64)a[218]) << 8;
  9449. r[108] = n & 0xfffffff; n >>= 28; n += ((sp_int64)a[219]) << 8;
  9450. r[109] = (sp_digit)n;
  9451. XMEMSET(&r[110], 0, sizeof(*r) * 110U);
  9452. }
  9453. /* Reduce the number back to 3072 bits using Montgomery reduction.
  9454. *
  9455. * a A single precision number to reduce in place.
  9456. * m The single precision number representing the modulus.
  9457. * mp The digit representing the negative inverse of m mod 2^n.
  9458. */
  9459. static void sp_3072_mont_reduce_112(sp_digit* a, const sp_digit* m, sp_digit mp)
  9460. {
  9461. int i;
  9462. sp_digit mu;
  9463. sp_digit over;
  9464. sp_3072_norm_112(a + 110);
  9465. #ifdef WOLFSSL_SP_DH
  9466. if (mp != 1) {
  9467. for (i=0; i<109; i++) {
  9468. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffff;
  9469. sp_3072_mul_add_112(a+i, m, mu);
  9470. a[i+1] += a[i] >> 28;
  9471. }
  9472. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffL;
  9473. sp_3072_mul_add_112(a+i, m, mu);
  9474. a[i+1] += a[i] >> 28;
  9475. a[i] &= 0xfffffff;
  9476. }
  9477. else {
  9478. for (i=0; i<109; i++) {
  9479. mu = a[i] & 0xfffffff;
  9480. sp_3072_mul_add_112(a+i, m, mu);
  9481. a[i+1] += a[i] >> 28;
  9482. }
  9483. mu = a[i] & 0xfffffL;
  9484. sp_3072_mul_add_112(a+i, m, mu);
  9485. a[i+1] += a[i] >> 28;
  9486. a[i] &= 0xfffffff;
  9487. }
  9488. #else
  9489. for (i=0; i<109; i++) {
  9490. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffff;
  9491. sp_3072_mul_add_112(a+i, m, mu);
  9492. a[i+1] += a[i] >> 28;
  9493. }
  9494. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffL;
  9495. sp_3072_mul_add_112(a+i, m, mu);
  9496. a[i+1] += a[i] >> 28;
  9497. a[i] &= 0xfffffff;
  9498. #endif
  9499. sp_3072_mont_shift_112(a, a);
  9500. over = a[109] - m[109];
  9501. sp_3072_cond_sub_112(a, a, m, ~((over - 1) >> 31));
  9502. sp_3072_norm_112(a);
  9503. }
  9504. /* Multiply two Montgomery form numbers mod the modulus (prime).
  9505. * (r = a * b mod m)
  9506. *
  9507. * r Result of multiplication.
  9508. * a First number to multiply in Montgomery form.
  9509. * b Second number to multiply in Montgomery form.
  9510. * m Modulus (prime).
  9511. * mp Montgomery mulitplier.
  9512. */
  9513. SP_NOINLINE static void sp_3072_mont_mul_112(sp_digit* r, const sp_digit* a,
  9514. const sp_digit* b, const sp_digit* m, sp_digit mp)
  9515. {
  9516. sp_3072_mul_112(r, a, b);
  9517. sp_3072_mont_reduce_112(r, m, mp);
  9518. }
  9519. /* Square the Montgomery form number. (r = a * a mod m)
  9520. *
  9521. * r Result of squaring.
  9522. * a Number to square in Montgomery form.
  9523. * m Modulus (prime).
  9524. * mp Montgomery mulitplier.
  9525. */
  9526. SP_NOINLINE static void sp_3072_mont_sqr_112(sp_digit* r, const sp_digit* a,
  9527. const sp_digit* m, sp_digit mp)
  9528. {
  9529. sp_3072_sqr_112(r, a);
  9530. sp_3072_mont_reduce_112(r, m, mp);
  9531. }
  9532. /* Multiply a by scalar b into r. (r = a * b)
  9533. *
  9534. * r A single precision integer.
  9535. * a A single precision integer.
  9536. * b A scalar.
  9537. */
  9538. SP_NOINLINE static void sp_3072_mul_d_224(sp_digit* r, const sp_digit* a,
  9539. sp_digit b)
  9540. {
  9541. sp_int64 tb = b;
  9542. sp_int64 t = 0;
  9543. sp_digit t2;
  9544. sp_int64 p[4];
  9545. int i;
  9546. for (i = 0; i < 224; i += 4) {
  9547. p[0] = tb * a[i + 0];
  9548. p[1] = tb * a[i + 1];
  9549. p[2] = tb * a[i + 2];
  9550. p[3] = tb * a[i + 3];
  9551. t += p[0];
  9552. t2 = (sp_digit)(t & 0xfffffff);
  9553. t >>= 28;
  9554. r[i + 0] = (sp_digit)t2;
  9555. t += p[1];
  9556. t2 = (sp_digit)(t & 0xfffffff);
  9557. t >>= 28;
  9558. r[i + 1] = (sp_digit)t2;
  9559. t += p[2];
  9560. t2 = (sp_digit)(t & 0xfffffff);
  9561. t >>= 28;
  9562. r[i + 2] = (sp_digit)t2;
  9563. t += p[3];
  9564. t2 = (sp_digit)(t & 0xfffffff);
  9565. t >>= 28;
  9566. r[i + 3] = (sp_digit)t2;
  9567. }
  9568. r[224] = (sp_digit)(t & 0xfffffff);
  9569. }
  9570. #ifndef WOLFSSL_SP_SMALL
  9571. /* Conditionally add a and b using the mask m.
  9572. * m is -1 to add and 0 when not.
  9573. *
  9574. * r A single precision number representing conditional add result.
  9575. * a A single precision number to add with.
  9576. * b A single precision number to add.
  9577. * m Mask value to apply.
  9578. */
  9579. static void sp_3072_cond_add_112(sp_digit* r, const sp_digit* a,
  9580. const sp_digit* b, const sp_digit m)
  9581. {
  9582. int i;
  9583. for (i = 0; i < 112; i += 8) {
  9584. r[i + 0] = a[i + 0] + (b[i + 0] & m);
  9585. r[i + 1] = a[i + 1] + (b[i + 1] & m);
  9586. r[i + 2] = a[i + 2] + (b[i + 2] & m);
  9587. r[i + 3] = a[i + 3] + (b[i + 3] & m);
  9588. r[i + 4] = a[i + 4] + (b[i + 4] & m);
  9589. r[i + 5] = a[i + 5] + (b[i + 5] & m);
  9590. r[i + 6] = a[i + 6] + (b[i + 6] & m);
  9591. r[i + 7] = a[i + 7] + (b[i + 7] & m);
  9592. }
  9593. }
  9594. #endif /* !WOLFSSL_SP_SMALL */
  9595. SP_NOINLINE static void sp_3072_rshift_112(sp_digit* r, const sp_digit* a,
  9596. byte n)
  9597. {
  9598. int i;
  9599. for (i=0; i<104; i += 8) {
  9600. r[i+0] = (a[i+0] >> n) | ((a[i+1] << (28 - n)) & 0xfffffff);
  9601. r[i+1] = (a[i+1] >> n) | ((a[i+2] << (28 - n)) & 0xfffffff);
  9602. r[i+2] = (a[i+2] >> n) | ((a[i+3] << (28 - n)) & 0xfffffff);
  9603. r[i+3] = (a[i+3] >> n) | ((a[i+4] << (28 - n)) & 0xfffffff);
  9604. r[i+4] = (a[i+4] >> n) | ((a[i+5] << (28 - n)) & 0xfffffff);
  9605. r[i+5] = (a[i+5] >> n) | ((a[i+6] << (28 - n)) & 0xfffffff);
  9606. r[i+6] = (a[i+6] >> n) | ((a[i+7] << (28 - n)) & 0xfffffff);
  9607. r[i+7] = (a[i+7] >> n) | ((a[i+8] << (28 - n)) & 0xfffffff);
  9608. }
  9609. r[104] = (a[104] >> n) | ((a[105] << (28 - n)) & 0xfffffff);
  9610. r[105] = (a[105] >> n) | ((a[106] << (28 - n)) & 0xfffffff);
  9611. r[106] = (a[106] >> n) | ((a[107] << (28 - n)) & 0xfffffff);
  9612. r[107] = (a[107] >> n) | ((a[108] << (28 - n)) & 0xfffffff);
  9613. r[108] = (a[108] >> n) | ((a[109] << (28 - n)) & 0xfffffff);
  9614. r[109] = (a[109] >> n) | ((a[110] << (28 - n)) & 0xfffffff);
  9615. r[110] = (a[110] >> n) | ((a[111] << (28 - n)) & 0xfffffff);
  9616. r[111] = a[111] >> n;
  9617. }
  9618. static WC_INLINE sp_digit sp_3072_div_word_112(sp_digit d1, sp_digit d0,
  9619. sp_digit div)
  9620. {
  9621. #ifdef SP_USE_DIVTI3
  9622. sp_int64 d = ((sp_int64)d1 << 28) + d0;
  9623. return d / div;
  9624. #elif defined(__x86_64__) || defined(__i386__)
  9625. sp_int64 d = ((sp_int64)d1 << 28) + d0;
  9626. sp_uint32 lo = (sp_uint32)d;
  9627. sp_digit hi = (sp_digit)(d >> 32);
  9628. __asm__ __volatile__ (
  9629. "idiv %2"
  9630. : "+a" (lo)
  9631. : "d" (hi), "r" (div)
  9632. : "cc"
  9633. );
  9634. return (sp_digit)lo;
  9635. #elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV)
  9636. sp_int64 d = ((sp_int64)d1 << 28) + d0;
  9637. sp_digit dv = (div >> 1) + 1;
  9638. sp_digit t1 = (sp_digit)(d >> 28);
  9639. sp_digit t0 = (sp_digit)(d & 0xfffffff);
  9640. sp_digit t2;
  9641. sp_digit sign;
  9642. sp_digit r;
  9643. int i;
  9644. sp_int64 m;
  9645. r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
  9646. t1 -= dv & (0 - r);
  9647. for (i = 26; i >= 1; i--) {
  9648. t1 += t1 + (((sp_uint32)t0 >> 27) & 1);
  9649. t0 <<= 1;
  9650. t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
  9651. r += r + t2;
  9652. t1 -= dv & (0 - t2);
  9653. t1 += t2;
  9654. }
  9655. r += r + 1;
  9656. m = d - ((sp_int64)r * div);
  9657. r += (sp_digit)(m >> 28);
  9658. m = d - ((sp_int64)r * div);
  9659. r += (sp_digit)(m >> 56) - (sp_digit)(d >> 56);
  9660. m = d - ((sp_int64)r * div);
  9661. sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
  9662. m *= sign;
  9663. t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
  9664. r += sign * t2;
  9665. m = d - ((sp_int64)r * div);
  9666. sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
  9667. m *= sign;
  9668. t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
  9669. r += sign * t2;
  9670. return r;
  9671. #else
  9672. sp_int64 d = ((sp_int64)d1 << 28) + d0;
  9673. sp_digit r = 0;
  9674. sp_digit t;
  9675. sp_digit dv = (div >> 13) + 1;
  9676. t = (sp_digit)(d >> 26);
  9677. t = (t / dv) << 13;
  9678. r += t;
  9679. d -= (sp_int64)t * div;
  9680. t = (sp_digit)(d >> 11);
  9681. t = t / (dv << 2);
  9682. r += t;
  9683. d -= (sp_int64)t * div;
  9684. t = (sp_digit)d;
  9685. t = t / div;
  9686. r += t;
  9687. d -= (sp_int64)t * div;
  9688. return r;
  9689. #endif
  9690. }
  9691. static WC_INLINE sp_digit sp_3072_word_div_word_112(sp_digit d, sp_digit div)
  9692. {
  9693. #if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
  9694. defined(SP_DIV_WORD_USE_DIV)
  9695. return d / div;
  9696. #else
  9697. return (sp_digit)((sp_uint32)(div - d) >> 31);
  9698. #endif
  9699. }
  9700. /* Divide d in a and put remainder into r (m*d + r = a)
  9701. * m is not calculated as it is not needed at this time.
  9702. *
  9703. * Full implementation.
  9704. *
  9705. * a Number to be divided.
  9706. * d Number to divide with.
  9707. * m Multiplier result.
  9708. * r Remainder from the division.
  9709. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  9710. */
  9711. static int sp_3072_div_112(const sp_digit* a, const sp_digit* d,
  9712. const sp_digit* m, sp_digit* r)
  9713. {
  9714. int i;
  9715. #ifndef WOLFSSL_SP_DIV_32
  9716. #endif
  9717. sp_digit dv;
  9718. sp_digit r1;
  9719. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  9720. sp_digit* t1 = NULL;
  9721. #else
  9722. sp_digit t1[4 * 112 + 3];
  9723. #endif
  9724. sp_digit* t2 = NULL;
  9725. sp_digit* sd = NULL;
  9726. int err = MP_OKAY;
  9727. (void)m;
  9728. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  9729. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 112 + 3), NULL,
  9730. DYNAMIC_TYPE_TMP_BUFFER);
  9731. if (t1 == NULL)
  9732. err = MEMORY_E;
  9733. #endif
  9734. (void)m;
  9735. if (err == MP_OKAY) {
  9736. t2 = t1 + 224 + 1;
  9737. sd = t2 + 112 + 1;
  9738. sp_3072_mul_d_112(sd, d, (sp_digit)1 << 8);
  9739. sp_3072_mul_d_224(t1, a, (sp_digit)1 << 8);
  9740. dv = sd[109];
  9741. t1[110 + 110] += t1[110 + 110 - 1] >> 28;
  9742. t1[110 + 110 - 1] &= 0xfffffff;
  9743. for (i=110; i>=0; i--) {
  9744. r1 = sp_3072_div_word_112(t1[110 + i], t1[110 + i - 1], dv);
  9745. sp_3072_mul_d_112(t2, sd, r1);
  9746. (void)sp_3072_sub_112(&t1[i], &t1[i], t2);
  9747. sp_3072_norm_110(&t1[i]);
  9748. t1[110 + i] += t1[110 + i - 1] >> 28;
  9749. t1[110 + i - 1] &= 0xfffffff;
  9750. r1 = sp_3072_div_word_112(-t1[110 + i], -t1[110 + i - 1], dv);
  9751. r1 -= t1[110 + i];
  9752. sp_3072_mul_d_112(t2, sd, r1);
  9753. (void)sp_3072_add_112(&t1[i], &t1[i], t2);
  9754. t1[110 + i] += t1[110 + i - 1] >> 28;
  9755. t1[110 + i - 1] &= 0xfffffff;
  9756. }
  9757. t1[110 - 1] += t1[110 - 2] >> 28;
  9758. t1[110 - 2] &= 0xfffffff;
  9759. r1 = sp_3072_word_div_word_112(t1[110 - 1], dv);
  9760. sp_3072_mul_d_112(t2, sd, r1);
  9761. sp_3072_sub_112(t1, t1, t2);
  9762. XMEMCPY(r, t1, sizeof(*r) * 224U);
  9763. for (i=0; i<109; i++) {
  9764. r[i+1] += r[i] >> 28;
  9765. r[i] &= 0xfffffff;
  9766. }
  9767. sp_3072_cond_add_112(r, r, sd, r[109] >> 31);
  9768. sp_3072_norm_110(r);
  9769. sp_3072_rshift_112(r, r, 8);
  9770. r[110] = 0;
  9771. r[111] = 0;
  9772. }
  9773. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  9774. if (t1 != NULL)
  9775. XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  9776. #endif
  9777. return err;
  9778. }
  9779. /* Reduce a modulo m into r. (r = a mod m)
  9780. *
  9781. * r A single precision number that is the reduced result.
  9782. * a A single precision number that is to be reduced.
  9783. * m A single precision number that is the modulus to reduce with.
  9784. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  9785. */
  9786. static int sp_3072_mod_112(sp_digit* r, const sp_digit* a, const sp_digit* m)
  9787. {
  9788. return sp_3072_div_112(a, m, NULL, r);
  9789. }
  9790. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  9791. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \
  9792. defined(WOLFSSL_HAVE_SP_DH)
  9793. /* Modular exponentiate a to the e mod m. (r = a^e mod m)
  9794. *
  9795. * r A single precision number that is the result of the operation.
  9796. * a A single precision number being exponentiated.
  9797. * e A single precision number that is the exponent.
  9798. * bits The number of bits in the exponent.
  9799. * m A single precision number that is the modulus.
  9800. * returns 0 on success.
  9801. * returns MEMORY_E on dynamic memory allocation failure.
  9802. * returns MP_VAL when base is even or exponent is 0.
  9803. */
  9804. static int sp_3072_mod_exp_112(sp_digit* r, const sp_digit* a, const sp_digit* e,
  9805. int bits, const sp_digit* m, int reduceA)
  9806. {
  9807. #if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP)
  9808. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  9809. sp_digit* td = NULL;
  9810. #else
  9811. sp_digit td[3 * 224];
  9812. #endif
  9813. sp_digit* t[3] = {0, 0, 0};
  9814. sp_digit* norm = NULL;
  9815. sp_digit mp = 1;
  9816. sp_digit n;
  9817. int i;
  9818. int c;
  9819. byte y;
  9820. int err = MP_OKAY;
  9821. if (bits == 0) {
  9822. err = MP_VAL;
  9823. }
  9824. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  9825. if (err == MP_OKAY) {
  9826. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 112 * 2, NULL,
  9827. DYNAMIC_TYPE_TMP_BUFFER);
  9828. if (td == NULL)
  9829. err = MEMORY_E;
  9830. }
  9831. #endif
  9832. if (err == MP_OKAY) {
  9833. norm = td;
  9834. for (i=0; i<3; i++) {
  9835. t[i] = td + (i * 112 * 2);
  9836. XMEMSET(t[i], 0, sizeof(sp_digit) * 112U * 2U);
  9837. }
  9838. sp_3072_mont_setup(m, &mp);
  9839. sp_3072_mont_norm_112(norm, m);
  9840. if (reduceA != 0) {
  9841. err = sp_3072_mod_112(t[1], a, m);
  9842. }
  9843. else {
  9844. XMEMCPY(t[1], a, sizeof(sp_digit) * 112U);
  9845. }
  9846. }
  9847. if (err == MP_OKAY) {
  9848. sp_3072_mul_112(t[1], t[1], norm);
  9849. err = sp_3072_mod_112(t[1], t[1], m);
  9850. }
  9851. if (err == MP_OKAY) {
  9852. i = bits / 28;
  9853. c = bits % 28;
  9854. n = e[i--] << (28 - c);
  9855. for (; ; c--) {
  9856. if (c == 0) {
  9857. if (i == -1) {
  9858. break;
  9859. }
  9860. n = e[i--];
  9861. c = 28;
  9862. }
  9863. y = (int)((n >> 27) & 1);
  9864. n <<= 1;
  9865. sp_3072_mont_mul_112(t[y^1], t[0], t[1], m, mp);
  9866. XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
  9867. ((size_t)t[1] & addr_mask[y])),
  9868. sizeof(*t[2]) * 112 * 2);
  9869. sp_3072_mont_sqr_112(t[2], t[2], m, mp);
  9870. XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
  9871. ((size_t)t[1] & addr_mask[y])), t[2],
  9872. sizeof(*t[2]) * 112 * 2);
  9873. }
  9874. sp_3072_mont_reduce_112(t[0], m, mp);
  9875. n = sp_3072_cmp_112(t[0], m);
  9876. sp_3072_cond_sub_112(t[0], t[0], m, ~(n >> 31));
  9877. XMEMCPY(r, t[0], sizeof(*r) * 112 * 2);
  9878. }
  9879. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  9880. if (td != NULL)
  9881. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  9882. #endif
  9883. return err;
  9884. #elif !defined(WC_NO_CACHE_RESISTANT)
  9885. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  9886. sp_digit* td = NULL;
  9887. #else
  9888. sp_digit td[3 * 224];
  9889. #endif
  9890. sp_digit* t[3] = {0, 0, 0};
  9891. sp_digit* norm = NULL;
  9892. sp_digit mp = 1;
  9893. sp_digit n;
  9894. int i;
  9895. int c;
  9896. byte y;
  9897. int err = MP_OKAY;
  9898. if (bits == 0) {
  9899. err = MP_VAL;
  9900. }
  9901. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  9902. if (err == MP_OKAY) {
  9903. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 112 * 2, NULL,
  9904. DYNAMIC_TYPE_TMP_BUFFER);
  9905. if (td == NULL)
  9906. err = MEMORY_E;
  9907. }
  9908. #endif
  9909. if (err == MP_OKAY) {
  9910. norm = td;
  9911. for (i=0; i<3; i++) {
  9912. t[i] = td + (i * 112 * 2);
  9913. }
  9914. sp_3072_mont_setup(m, &mp);
  9915. sp_3072_mont_norm_112(norm, m);
  9916. if (reduceA != 0) {
  9917. err = sp_3072_mod_112(t[1], a, m);
  9918. if (err == MP_OKAY) {
  9919. sp_3072_mul_112(t[1], t[1], norm);
  9920. err = sp_3072_mod_112(t[1], t[1], m);
  9921. }
  9922. }
  9923. else {
  9924. sp_3072_mul_112(t[1], a, norm);
  9925. err = sp_3072_mod_112(t[1], t[1], m);
  9926. }
  9927. }
  9928. if (err == MP_OKAY) {
  9929. i = bits / 28;
  9930. c = bits % 28;
  9931. n = e[i--] << (28 - c);
  9932. for (; ; c--) {
  9933. if (c == 0) {
  9934. if (i == -1) {
  9935. break;
  9936. }
  9937. n = e[i--];
  9938. c = 28;
  9939. }
  9940. y = (int)((n >> 27) & 1);
  9941. n <<= 1;
  9942. sp_3072_mont_mul_112(t[y^1], t[0], t[1], m, mp);
  9943. XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
  9944. ((size_t)t[1] & addr_mask[y])),
  9945. sizeof(*t[2]) * 112 * 2);
  9946. sp_3072_mont_sqr_112(t[2], t[2], m, mp);
  9947. XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
  9948. ((size_t)t[1] & addr_mask[y])), t[2],
  9949. sizeof(*t[2]) * 112 * 2);
  9950. }
  9951. sp_3072_mont_reduce_112(t[0], m, mp);
  9952. n = sp_3072_cmp_112(t[0], m);
  9953. sp_3072_cond_sub_112(t[0], t[0], m, ~(n >> 31));
  9954. XMEMCPY(r, t[0], sizeof(*r) * 112 * 2);
  9955. }
  9956. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  9957. if (td != NULL)
  9958. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  9959. #endif
  9960. return err;
  9961. #else
  9962. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  9963. sp_digit* td = NULL;
  9964. #else
  9965. sp_digit td[(16 * 224) + 224];
  9966. #endif
  9967. sp_digit* t[16];
  9968. sp_digit* rt = NULL;
  9969. sp_digit* norm = NULL;
  9970. sp_digit mp = 1;
  9971. sp_digit n;
  9972. int i;
  9973. int c;
  9974. byte y;
  9975. int err = MP_OKAY;
  9976. if (bits == 0) {
  9977. err = MP_VAL;
  9978. }
  9979. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  9980. if (err == MP_OKAY) {
  9981. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((16 * 224) + 224), NULL,
  9982. DYNAMIC_TYPE_TMP_BUFFER);
  9983. if (td == NULL)
  9984. err = MEMORY_E;
  9985. }
  9986. #endif
  9987. if (err == MP_OKAY) {
  9988. norm = td;
  9989. for (i=0; i<16; i++)
  9990. t[i] = td + i * 224;
  9991. rt = td + 3584;
  9992. sp_3072_mont_setup(m, &mp);
  9993. sp_3072_mont_norm_112(norm, m);
  9994. if (reduceA != 0) {
  9995. err = sp_3072_mod_112(t[1], a, m);
  9996. if (err == MP_OKAY) {
  9997. sp_3072_mul_112(t[1], t[1], norm);
  9998. err = sp_3072_mod_112(t[1], t[1], m);
  9999. }
  10000. }
  10001. else {
  10002. sp_3072_mul_112(t[1], a, norm);
  10003. err = sp_3072_mod_112(t[1], t[1], m);
  10004. }
  10005. }
  10006. if (err == MP_OKAY) {
  10007. sp_3072_mont_sqr_112(t[ 2], t[ 1], m, mp);
  10008. sp_3072_mont_mul_112(t[ 3], t[ 2], t[ 1], m, mp);
  10009. sp_3072_mont_sqr_112(t[ 4], t[ 2], m, mp);
  10010. sp_3072_mont_mul_112(t[ 5], t[ 3], t[ 2], m, mp);
  10011. sp_3072_mont_sqr_112(t[ 6], t[ 3], m, mp);
  10012. sp_3072_mont_mul_112(t[ 7], t[ 4], t[ 3], m, mp);
  10013. sp_3072_mont_sqr_112(t[ 8], t[ 4], m, mp);
  10014. sp_3072_mont_mul_112(t[ 9], t[ 5], t[ 4], m, mp);
  10015. sp_3072_mont_sqr_112(t[10], t[ 5], m, mp);
  10016. sp_3072_mont_mul_112(t[11], t[ 6], t[ 5], m, mp);
  10017. sp_3072_mont_sqr_112(t[12], t[ 6], m, mp);
  10018. sp_3072_mont_mul_112(t[13], t[ 7], t[ 6], m, mp);
  10019. sp_3072_mont_sqr_112(t[14], t[ 7], m, mp);
  10020. sp_3072_mont_mul_112(t[15], t[ 8], t[ 7], m, mp);
  10021. bits = ((bits + 3) / 4) * 4;
  10022. i = ((bits + 27) / 28) - 1;
  10023. c = bits % 28;
  10024. if (c == 0) {
  10025. c = 28;
  10026. }
  10027. if (i < 112) {
  10028. n = e[i--] << (32 - c);
  10029. }
  10030. else {
  10031. n = 0;
  10032. i--;
  10033. }
  10034. if (c < 4) {
  10035. n |= e[i--] << (4 - c);
  10036. c += 28;
  10037. }
  10038. y = (int)((n >> 28) & 0xf);
  10039. n <<= 4;
  10040. c -= 4;
  10041. XMEMCPY(rt, t[y], sizeof(sp_digit) * 224);
  10042. while ((i >= 0) || (c >= 4)) {
  10043. if (c >= 4) {
  10044. y = (byte)((n >> 28) & 0xf);
  10045. n <<= 4;
  10046. c -= 4;
  10047. }
  10048. else if (c == 0) {
  10049. n = e[i--] << 4;
  10050. y = (byte)((n >> 28) & 0xf);
  10051. n <<= 4;
  10052. c = 24;
  10053. }
  10054. else {
  10055. y = (byte)((n >> 28) & 0xf);
  10056. n = e[i--] << 4;
  10057. c = 4 - c;
  10058. y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
  10059. n <<= c;
  10060. c = 28 - c;
  10061. }
  10062. sp_3072_mont_sqr_112(rt, rt, m, mp);
  10063. sp_3072_mont_sqr_112(rt, rt, m, mp);
  10064. sp_3072_mont_sqr_112(rt, rt, m, mp);
  10065. sp_3072_mont_sqr_112(rt, rt, m, mp);
  10066. sp_3072_mont_mul_112(rt, rt, t[y], m, mp);
  10067. }
  10068. sp_3072_mont_reduce_112(rt, m, mp);
  10069. n = sp_3072_cmp_112(rt, m);
  10070. sp_3072_cond_sub_112(rt, rt, m, ~(n >> 31));
  10071. XMEMCPY(r, rt, sizeof(sp_digit) * 224);
  10072. }
  10073. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10074. if (td != NULL)
  10075. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  10076. #endif
  10077. return err;
  10078. #endif
  10079. }
  10080. #endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) || */
  10081. /* WOLFSSL_HAVE_SP_DH */
  10082. #endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
  10083. #ifdef WOLFSSL_HAVE_SP_RSA
  10084. /* RSA public key operation.
  10085. *
  10086. * in Array of bytes representing the number to exponentiate, base.
  10087. * inLen Number of bytes in base.
  10088. * em Public exponent.
  10089. * mm Modulus.
  10090. * out Buffer to hold big-endian bytes of exponentiation result.
  10091. * Must be at least 384 bytes long.
  10092. * outLen Number of bytes in result.
  10093. * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
  10094. * an array is too long and MEMORY_E when dynamic memory allocation fails.
  10095. */
  10096. int sp_RsaPublic_3072(const byte* in, word32 inLen, const mp_int* em,
  10097. const mp_int* mm, byte* out, word32* outLen)
  10098. {
  10099. #ifdef WOLFSSL_SP_SMALL
  10100. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10101. sp_digit* a = NULL;
  10102. #else
  10103. sp_digit a[112 * 5];
  10104. #endif
  10105. sp_digit* m = NULL;
  10106. sp_digit* r = NULL;
  10107. sp_digit* norm = NULL;
  10108. sp_digit e[1] = {0};
  10109. sp_digit mp = 0;
  10110. int i;
  10111. int err = MP_OKAY;
  10112. if (*outLen < 384U) {
  10113. err = MP_TO_E;
  10114. }
  10115. if (err == MP_OKAY) {
  10116. if (mp_count_bits(em) > 28) {
  10117. err = MP_READ_E;
  10118. }
  10119. else if (inLen > 384U) {
  10120. err = MP_READ_E;
  10121. }
  10122. else if (mp_count_bits(mm) != 3072) {
  10123. err = MP_READ_E;
  10124. }
  10125. else if (mp_iseven(mm)) {
  10126. err = MP_VAL;
  10127. }
  10128. }
  10129. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10130. if (err == MP_OKAY) {
  10131. a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 112 * 5, NULL,
  10132. DYNAMIC_TYPE_RSA);
  10133. if (a == NULL)
  10134. err = MEMORY_E;
  10135. }
  10136. #endif
  10137. if (err == MP_OKAY) {
  10138. r = a + 112 * 2;
  10139. m = r + 112 * 2;
  10140. norm = r;
  10141. sp_3072_from_bin(a, 112, in, inLen);
  10142. #if DIGIT_BIT >= 28
  10143. e[0] = (sp_digit)em->dp[0];
  10144. #else
  10145. e[0] = (sp_digit)em->dp[0];
  10146. if (em->used > 1) {
  10147. e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
  10148. }
  10149. #endif
  10150. if (e[0] == 0) {
  10151. err = MP_EXPTMOD_E;
  10152. }
  10153. }
  10154. if (err == MP_OKAY) {
  10155. sp_3072_from_mp(m, 112, mm);
  10156. sp_3072_mont_setup(m, &mp);
  10157. sp_3072_mont_norm_112(norm, m);
  10158. }
  10159. if (err == MP_OKAY) {
  10160. sp_3072_mul_112(a, a, norm);
  10161. err = sp_3072_mod_112(a, a, m);
  10162. }
  10163. if (err == MP_OKAY) {
  10164. for (i=27; i>=0; i--) {
  10165. if ((e[0] >> i) != 0) {
  10166. break;
  10167. }
  10168. }
  10169. XMEMCPY(r, a, sizeof(sp_digit) * 112 * 2);
  10170. for (i--; i>=0; i--) {
  10171. sp_3072_mont_sqr_112(r, r, m, mp);
  10172. if (((e[0] >> i) & 1) == 1) {
  10173. sp_3072_mont_mul_112(r, r, a, m, mp);
  10174. }
  10175. }
  10176. sp_3072_mont_reduce_112(r, m, mp);
  10177. mp = sp_3072_cmp_112(r, m);
  10178. sp_3072_cond_sub_112(r, r, m, ~(mp >> 31));
  10179. sp_3072_to_bin_112(r, out);
  10180. *outLen = 384;
  10181. }
  10182. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10183. if (a != NULL)
  10184. XFREE(a, NULL, DYNAMIC_TYPE_RSA);
  10185. #endif
  10186. return err;
  10187. #else
  10188. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10189. sp_digit* d = NULL;
  10190. #else
  10191. sp_digit d[112 * 5];
  10192. #endif
  10193. sp_digit* a = NULL;
  10194. sp_digit* m = NULL;
  10195. sp_digit* r = NULL;
  10196. sp_digit e[1] = {0};
  10197. int err = MP_OKAY;
  10198. if (*outLen < 384U) {
  10199. err = MP_TO_E;
  10200. }
  10201. if (err == MP_OKAY) {
  10202. if (mp_count_bits(em) > 28) {
  10203. err = MP_READ_E;
  10204. }
  10205. else if (inLen > 384U) {
  10206. err = MP_READ_E;
  10207. }
  10208. else if (mp_count_bits(mm) != 3072) {
  10209. err = MP_READ_E;
  10210. }
  10211. else if (mp_iseven(mm)) {
  10212. err = MP_VAL;
  10213. }
  10214. }
  10215. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10216. if (err == MP_OKAY) {
  10217. d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 112 * 5, NULL,
  10218. DYNAMIC_TYPE_RSA);
  10219. if (d == NULL)
  10220. err = MEMORY_E;
  10221. }
  10222. #endif
  10223. if (err == MP_OKAY) {
  10224. a = d;
  10225. r = a + 112 * 2;
  10226. m = r + 112 * 2;
  10227. sp_3072_from_bin(a, 112, in, inLen);
  10228. #if DIGIT_BIT >= 28
  10229. e[0] = (sp_digit)em->dp[0];
  10230. #else
  10231. e[0] = (sp_digit)em->dp[0];
  10232. if (em->used > 1) {
  10233. e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
  10234. }
  10235. #endif
  10236. if (e[0] == 0) {
  10237. err = MP_EXPTMOD_E;
  10238. }
  10239. }
  10240. if (err == MP_OKAY) {
  10241. sp_3072_from_mp(m, 112, mm);
  10242. if (e[0] == 0x3) {
  10243. sp_3072_sqr_112(r, a);
  10244. err = sp_3072_mod_112(r, r, m);
  10245. if (err == MP_OKAY) {
  10246. sp_3072_mul_112(r, a, r);
  10247. err = sp_3072_mod_112(r, r, m);
  10248. }
  10249. }
  10250. else {
  10251. sp_digit* norm = r;
  10252. int i;
  10253. sp_digit mp;
  10254. sp_3072_mont_setup(m, &mp);
  10255. sp_3072_mont_norm_112(norm, m);
  10256. sp_3072_mul_112(a, a, norm);
  10257. err = sp_3072_mod_112(a, a, m);
  10258. if (err == MP_OKAY) {
  10259. for (i=27; i>=0; i--) {
  10260. if ((e[0] >> i) != 0) {
  10261. break;
  10262. }
  10263. }
  10264. XMEMCPY(r, a, sizeof(sp_digit) * 224U);
  10265. for (i--; i>=0; i--) {
  10266. sp_3072_mont_sqr_112(r, r, m, mp);
  10267. if (((e[0] >> i) & 1) == 1) {
  10268. sp_3072_mont_mul_112(r, r, a, m, mp);
  10269. }
  10270. }
  10271. sp_3072_mont_reduce_112(r, m, mp);
  10272. mp = sp_3072_cmp_112(r, m);
  10273. sp_3072_cond_sub_112(r, r, m, ~(mp >> 31));
  10274. }
  10275. }
  10276. }
  10277. if (err == MP_OKAY) {
  10278. sp_3072_to_bin_112(r, out);
  10279. *outLen = 384;
  10280. }
  10281. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10282. if (d != NULL)
  10283. XFREE(d, NULL, DYNAMIC_TYPE_RSA);
  10284. #endif
  10285. return err;
  10286. #endif /* WOLFSSL_SP_SMALL */
  10287. }
  10288. #ifndef WOLFSSL_RSA_PUBLIC_ONLY
  10289. #if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM)
  10290. #endif /* !SP_RSA_PRIVATE_EXP_D & !RSA_LOW_MEM */
  10291. /* RSA private key operation.
  10292. *
  10293. * in Array of bytes representing the number to exponentiate, base.
  10294. * inLen Number of bytes in base.
  10295. * dm Private exponent.
  10296. * pm First prime.
  10297. * qm Second prime.
  10298. * dpm First prime's CRT exponent.
  10299. * dqm Second prime's CRT exponent.
  10300. * qim Inverse of second prime mod p.
  10301. * mm Modulus.
  10302. * out Buffer to hold big-endian bytes of exponentiation result.
  10303. * Must be at least 384 bytes long.
  10304. * outLen Number of bytes in result.
  10305. * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
  10306. * an array is too long and MEMORY_E when dynamic memory allocation fails.
  10307. */
  10308. int sp_RsaPrivate_3072(const byte* in, word32 inLen, const mp_int* dm,
  10309. const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
  10310. const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
  10311. {
  10312. #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
  10313. #if defined(WOLFSSL_SP_SMALL)
  10314. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10315. sp_digit* d = NULL;
  10316. #else
  10317. sp_digit d[112 * 4];
  10318. #endif
  10319. sp_digit* a = NULL;
  10320. sp_digit* m = NULL;
  10321. sp_digit* r = NULL;
  10322. int err = MP_OKAY;
  10323. (void)pm;
  10324. (void)qm;
  10325. (void)dpm;
  10326. (void)dqm;
  10327. (void)qim;
  10328. if (*outLen < 384U) {
  10329. err = MP_TO_E;
  10330. }
  10331. if (err == MP_OKAY) {
  10332. if (mp_count_bits(dm) > 3072) {
  10333. err = MP_READ_E;
  10334. }
  10335. else if (inLen > 384) {
  10336. err = MP_READ_E;
  10337. }
  10338. else if (mp_count_bits(mm) != 3072) {
  10339. err = MP_READ_E;
  10340. }
  10341. else if (mp_iseven(mm)) {
  10342. err = MP_VAL;
  10343. }
  10344. }
  10345. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10346. if (err == MP_OKAY) {
  10347. d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 112 * 4, NULL,
  10348. DYNAMIC_TYPE_RSA);
  10349. if (d == NULL)
  10350. err = MEMORY_E;
  10351. }
  10352. #endif
  10353. if (err == MP_OKAY) {
  10354. a = d + 112;
  10355. m = a + 224;
  10356. r = a;
  10357. sp_3072_from_bin(a, 112, in, inLen);
  10358. sp_3072_from_mp(d, 112, dm);
  10359. sp_3072_from_mp(m, 112, mm);
  10360. err = sp_3072_mod_exp_112(r, a, d, 3072, m, 0);
  10361. }
  10362. if (err == MP_OKAY) {
  10363. sp_3072_to_bin_112(r, out);
  10364. *outLen = 384;
  10365. }
  10366. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10367. if (d != NULL)
  10368. #endif
  10369. {
  10370. /* only "a" and "r" are sensitive and need zeroized (same pointer) */
  10371. if (a != NULL)
  10372. ForceZero(a, sizeof(sp_digit) * 112);
  10373. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10374. XFREE(d, NULL, DYNAMIC_TYPE_RSA);
  10375. #endif
  10376. }
  10377. return err;
  10378. #else
  10379. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10380. sp_digit* d = NULL;
  10381. #else
  10382. sp_digit d[112 * 4];
  10383. #endif
  10384. sp_digit* a = NULL;
  10385. sp_digit* m = NULL;
  10386. sp_digit* r = NULL;
  10387. int err = MP_OKAY;
  10388. (void)pm;
  10389. (void)qm;
  10390. (void)dpm;
  10391. (void)dqm;
  10392. (void)qim;
  10393. if (*outLen < 384U) {
  10394. err = MP_TO_E;
  10395. }
  10396. if (err == MP_OKAY) {
  10397. if (mp_count_bits(dm) > 3072) {
  10398. err = MP_READ_E;
  10399. }
  10400. else if (inLen > 384U) {
  10401. err = MP_READ_E;
  10402. }
  10403. else if (mp_count_bits(mm) != 3072) {
  10404. err = MP_READ_E;
  10405. }
  10406. else if (mp_iseven(mm)) {
  10407. err = MP_VAL;
  10408. }
  10409. }
  10410. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10411. if (err == MP_OKAY) {
  10412. d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 112 * 4, NULL,
  10413. DYNAMIC_TYPE_RSA);
  10414. if (d == NULL)
  10415. err = MEMORY_E;
  10416. }
  10417. #endif
  10418. if (err == MP_OKAY) {
  10419. a = d + 112;
  10420. m = a + 224;
  10421. r = a;
  10422. sp_3072_from_bin(a, 112, in, inLen);
  10423. sp_3072_from_mp(d, 112, dm);
  10424. sp_3072_from_mp(m, 112, mm);
  10425. err = sp_3072_mod_exp_112(r, a, d, 3072, m, 0);
  10426. }
  10427. if (err == MP_OKAY) {
  10428. sp_3072_to_bin_112(r, out);
  10429. *outLen = 384;
  10430. }
  10431. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10432. if (d != NULL)
  10433. #endif
  10434. {
  10435. /* only "a" and "r" are sensitive and need zeroized (same pointer) */
  10436. if (a != NULL)
  10437. ForceZero(a, sizeof(sp_digit) * 112);
  10438. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10439. XFREE(d, NULL, DYNAMIC_TYPE_RSA);
  10440. #endif
  10441. }
  10442. return err;
  10443. #endif /* WOLFSSL_SP_SMALL */
  10444. #else
  10445. #if defined(WOLFSSL_SP_SMALL)
  10446. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10447. sp_digit* a = NULL;
  10448. #else
  10449. sp_digit a[56 * 8];
  10450. #endif
  10451. sp_digit* p = NULL;
  10452. sp_digit* dp = NULL;
  10453. sp_digit* dq = NULL;
  10454. sp_digit* qi = NULL;
  10455. sp_digit* tmpa = NULL;
  10456. sp_digit* tmpb = NULL;
  10457. sp_digit* r = NULL;
  10458. int err = MP_OKAY;
  10459. (void)dm;
  10460. (void)mm;
  10461. if (*outLen < 384U) {
  10462. err = MP_TO_E;
  10463. }
  10464. if (err == MP_OKAY) {
  10465. if (inLen > 384) {
  10466. err = MP_READ_E;
  10467. }
  10468. else if (mp_count_bits(mm) != 3072) {
  10469. err = MP_READ_E;
  10470. }
  10471. else if (mp_iseven(mm)) {
  10472. err = MP_VAL;
  10473. }
  10474. else if (mp_iseven(pm)) {
  10475. err = MP_VAL;
  10476. }
  10477. else if (mp_iseven(qm)) {
  10478. err = MP_VAL;
  10479. }
  10480. }
  10481. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10482. if (err == MP_OKAY) {
  10483. a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 8, NULL,
  10484. DYNAMIC_TYPE_RSA);
  10485. if (a == NULL)
  10486. err = MEMORY_E;
  10487. }
  10488. #endif
  10489. if (err == MP_OKAY) {
  10490. p = a + 112;
  10491. qi = dq = dp = p + 56;
  10492. tmpa = qi + 56;
  10493. tmpb = tmpa + 112;
  10494. r = a;
  10495. sp_3072_from_bin(a, 112, in, inLen);
  10496. sp_3072_from_mp(p, 56, pm);
  10497. sp_3072_from_mp(dp, 56, dpm);
  10498. err = sp_3072_mod_exp_56(tmpa, a, dp, 1536, p, 1);
  10499. }
  10500. if (err == MP_OKAY) {
  10501. sp_3072_from_mp(p, 56, qm);
  10502. sp_3072_from_mp(dq, 56, dqm);
  10503. err = sp_3072_mod_exp_56(tmpb, a, dq, 1536, p, 1);
  10504. }
  10505. if (err == MP_OKAY) {
  10506. sp_3072_from_mp(p, 56, pm);
  10507. (void)sp_3072_sub_56(tmpa, tmpa, tmpb);
  10508. sp_3072_norm_55(tmpa);
  10509. sp_3072_cond_add_56(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[54] >> 31));
  10510. sp_3072_cond_add_56(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[54] >> 31));
  10511. sp_3072_norm_56(tmpa);
  10512. sp_3072_from_mp(qi, 56, qim);
  10513. sp_3072_mul_56(tmpa, tmpa, qi);
  10514. err = sp_3072_mod_56(tmpa, tmpa, p);
  10515. }
  10516. if (err == MP_OKAY) {
  10517. sp_3072_from_mp(p, 56, qm);
  10518. sp_3072_mul_56(tmpa, p, tmpa);
  10519. (void)sp_3072_add_112(r, tmpb, tmpa);
  10520. sp_3072_norm_112(r);
  10521. sp_3072_to_bin_112(r, out);
  10522. *outLen = 384;
  10523. }
  10524. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10525. if (a != NULL)
  10526. #endif
  10527. {
  10528. ForceZero(a, sizeof(sp_digit) * 56 * 8);
  10529. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10530. XFREE(a, NULL, DYNAMIC_TYPE_RSA);
  10531. #endif
  10532. }
  10533. return err;
  10534. #else
  10535. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10536. sp_digit* a = NULL;
  10537. #else
  10538. sp_digit a[56 * 13];
  10539. #endif
  10540. sp_digit* p = NULL;
  10541. sp_digit* q = NULL;
  10542. sp_digit* dp = NULL;
  10543. sp_digit* dq = NULL;
  10544. sp_digit* qi = NULL;
  10545. sp_digit* tmpa = NULL;
  10546. sp_digit* tmpb = NULL;
  10547. sp_digit* r = NULL;
  10548. int err = MP_OKAY;
  10549. (void)dm;
  10550. (void)mm;
  10551. if (*outLen < 384U) {
  10552. err = MP_TO_E;
  10553. }
  10554. if (err == MP_OKAY) {
  10555. if (inLen > 384U) {
  10556. err = MP_READ_E;
  10557. }
  10558. else if (mp_count_bits(mm) != 3072) {
  10559. err = MP_READ_E;
  10560. }
  10561. else if (mp_iseven(mm)) {
  10562. err = MP_VAL;
  10563. }
  10564. else if (mp_iseven(pm)) {
  10565. err = MP_VAL;
  10566. }
  10567. else if (mp_iseven(qm)) {
  10568. err = MP_VAL;
  10569. }
  10570. }
  10571. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10572. if (err == MP_OKAY) {
  10573. a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 13, NULL,
  10574. DYNAMIC_TYPE_RSA);
  10575. if (a == NULL)
  10576. err = MEMORY_E;
  10577. }
  10578. #endif
  10579. if (err == MP_OKAY) {
  10580. p = a + 112 * 2;
  10581. q = p + 56;
  10582. dp = q + 56;
  10583. dq = dp + 56;
  10584. qi = dq + 56;
  10585. tmpa = qi + 56;
  10586. tmpb = tmpa + 112;
  10587. r = a;
  10588. sp_3072_from_bin(a, 112, in, inLen);
  10589. sp_3072_from_mp(p, 56, pm);
  10590. sp_3072_from_mp(q, 56, qm);
  10591. sp_3072_from_mp(dp, 56, dpm);
  10592. sp_3072_from_mp(dq, 56, dqm);
  10593. sp_3072_from_mp(qi, 56, qim);
  10594. err = sp_3072_mod_exp_56(tmpa, a, dp, 1536, p, 1);
  10595. }
  10596. if (err == MP_OKAY) {
  10597. err = sp_3072_mod_exp_56(tmpb, a, dq, 1536, q, 1);
  10598. }
  10599. if (err == MP_OKAY) {
  10600. (void)sp_3072_sub_56(tmpa, tmpa, tmpb);
  10601. sp_3072_norm_55(tmpa);
  10602. sp_3072_cond_add_56(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[54] >> 31));
  10603. sp_3072_cond_add_56(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[54] >> 31));
  10604. sp_3072_norm_56(tmpa);
  10605. sp_3072_mul_56(tmpa, tmpa, qi);
  10606. err = sp_3072_mod_56(tmpa, tmpa, p);
  10607. }
  10608. if (err == MP_OKAY) {
  10609. sp_3072_mul_56(tmpa, tmpa, q);
  10610. (void)sp_3072_add_112(r, tmpb, tmpa);
  10611. sp_3072_norm_112(r);
  10612. sp_3072_to_bin_112(r, out);
  10613. *outLen = 384;
  10614. }
  10615. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10616. if (a != NULL)
  10617. #endif
  10618. {
  10619. ForceZero(a, sizeof(sp_digit) * 56 * 13);
  10620. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10621. XFREE(a, NULL, DYNAMIC_TYPE_RSA);
  10622. #endif
  10623. }
  10624. return err;
  10625. #endif /* WOLFSSL_SP_SMALL */
  10626. #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
  10627. }
  10628. #endif /* !WOLFSSL_RSA_PUBLIC_ONLY */
  10629. #endif /* WOLFSSL_HAVE_SP_RSA */
  10630. #if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \
  10631. !defined(WOLFSSL_RSA_PUBLIC_ONLY))
  10632. /* Convert an array of sp_digit to an mp_int.
  10633. *
  10634. * a A single precision integer.
  10635. * r A multi-precision integer.
  10636. */
  10637. static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
  10638. {
  10639. int err;
  10640. err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT);
  10641. if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
  10642. #if DIGIT_BIT == 28
  10643. XMEMCPY(r->dp, a, sizeof(sp_digit) * 112);
  10644. r->used = 112;
  10645. mp_clamp(r);
  10646. #elif DIGIT_BIT < 28
  10647. int i;
  10648. int j = 0;
  10649. int s = 0;
  10650. r->dp[0] = 0;
  10651. for (i = 0; i < 112; i++) {
  10652. r->dp[j] |= (mp_digit)(a[i] << s);
  10653. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  10654. s = DIGIT_BIT - s;
  10655. r->dp[++j] = (mp_digit)(a[i] >> s);
  10656. while (s + DIGIT_BIT <= 28) {
  10657. s += DIGIT_BIT;
  10658. r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  10659. if (s == SP_WORD_SIZE) {
  10660. r->dp[j] = 0;
  10661. }
  10662. else {
  10663. r->dp[j] = (mp_digit)(a[i] >> s);
  10664. }
  10665. }
  10666. s = 28 - s;
  10667. }
  10668. r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
  10669. mp_clamp(r);
  10670. #else
  10671. int i;
  10672. int j = 0;
  10673. int s = 0;
  10674. r->dp[0] = 0;
  10675. for (i = 0; i < 112; i++) {
  10676. r->dp[j] |= ((mp_digit)a[i]) << s;
  10677. if (s + 28 >= DIGIT_BIT) {
  10678. #if DIGIT_BIT != 32 && DIGIT_BIT != 64
  10679. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  10680. #endif
  10681. s = DIGIT_BIT - s;
  10682. r->dp[++j] = a[i] >> s;
  10683. s = 28 - s;
  10684. }
  10685. else {
  10686. s += 28;
  10687. }
  10688. }
  10689. r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
  10690. mp_clamp(r);
  10691. #endif
  10692. }
  10693. return err;
  10694. }
  10695. /* Perform the modular exponentiation for Diffie-Hellman.
  10696. *
  10697. * base Base. MP integer.
  10698. * exp Exponent. MP integer.
  10699. * mod Modulus. MP integer.
  10700. * res Result. MP integer.
  10701. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  10702. * and MEMORY_E if memory allocation fails.
  10703. */
  10704. int sp_ModExp_3072(const mp_int* base, const mp_int* exp, const mp_int* mod,
  10705. mp_int* res)
  10706. {
  10707. #ifdef WOLFSSL_SP_SMALL
  10708. int err = MP_OKAY;
  10709. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10710. sp_digit* b = NULL;
  10711. #else
  10712. sp_digit b[112 * 4];
  10713. #endif
  10714. sp_digit* e = NULL;
  10715. sp_digit* m = NULL;
  10716. sp_digit* r = NULL;
  10717. int expBits = mp_count_bits(exp);
  10718. if (mp_count_bits(base) > 3072) {
  10719. err = MP_READ_E;
  10720. }
  10721. else if (expBits > 3072) {
  10722. err = MP_READ_E;
  10723. }
  10724. else if (mp_count_bits(mod) != 3072) {
  10725. err = MP_READ_E;
  10726. }
  10727. else if (mp_iseven(mod)) {
  10728. err = MP_VAL;
  10729. }
  10730. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10731. if (err == MP_OKAY) {
  10732. b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 112 * 4, NULL,
  10733. DYNAMIC_TYPE_DH);
  10734. if (b == NULL)
  10735. err = MEMORY_E;
  10736. }
  10737. #endif
  10738. if (err == MP_OKAY) {
  10739. e = b + 112 * 2;
  10740. m = e + 112;
  10741. r = b;
  10742. sp_3072_from_mp(b, 112, base);
  10743. sp_3072_from_mp(e, 112, exp);
  10744. sp_3072_from_mp(m, 112, mod);
  10745. err = sp_3072_mod_exp_112(r, b, e, mp_count_bits(exp), m, 0);
  10746. }
  10747. if (err == MP_OKAY) {
  10748. err = sp_3072_to_mp(r, res);
  10749. }
  10750. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10751. if (b != NULL)
  10752. #endif
  10753. {
  10754. /* only "e" is sensitive and needs zeroized */
  10755. if (e != NULL)
  10756. ForceZero(e, sizeof(sp_digit) * 112U);
  10757. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10758. XFREE(b, NULL, DYNAMIC_TYPE_DH);
  10759. #endif
  10760. }
  10761. return err;
  10762. #else
  10763. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10764. sp_digit* b = NULL;
  10765. #else
  10766. sp_digit b[112 * 4];
  10767. #endif
  10768. sp_digit* e = NULL;
  10769. sp_digit* m = NULL;
  10770. sp_digit* r = NULL;
  10771. int err = MP_OKAY;
  10772. int expBits = mp_count_bits(exp);
  10773. if (mp_count_bits(base) > 3072) {
  10774. err = MP_READ_E;
  10775. }
  10776. else if (expBits > 3072) {
  10777. err = MP_READ_E;
  10778. }
  10779. else if (mp_count_bits(mod) != 3072) {
  10780. err = MP_READ_E;
  10781. }
  10782. else if (mp_iseven(mod)) {
  10783. err = MP_VAL;
  10784. }
  10785. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10786. if (err == MP_OKAY) {
  10787. b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 112 * 4, NULL, DYNAMIC_TYPE_DH);
  10788. if (b == NULL)
  10789. err = MEMORY_E;
  10790. }
  10791. #endif
  10792. if (err == MP_OKAY) {
  10793. e = b + 112 * 2;
  10794. m = e + 112;
  10795. r = b;
  10796. sp_3072_from_mp(b, 112, base);
  10797. sp_3072_from_mp(e, 112, exp);
  10798. sp_3072_from_mp(m, 112, mod);
  10799. err = sp_3072_mod_exp_112(r, b, e, expBits, m, 0);
  10800. }
  10801. if (err == MP_OKAY) {
  10802. err = sp_3072_to_mp(r, res);
  10803. }
  10804. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10805. if (b != NULL)
  10806. #endif
  10807. {
  10808. /* only "e" is sensitive and needs zeroized */
  10809. if (e != NULL)
  10810. ForceZero(e, sizeof(sp_digit) * 112U);
  10811. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  10812. XFREE(b, NULL, DYNAMIC_TYPE_DH);
  10813. #endif
  10814. }
  10815. return err;
  10816. #endif
  10817. }
  10818. #ifdef WOLFSSL_HAVE_SP_DH
  10819. #ifdef HAVE_FFDHE_3072
  10820. SP_NOINLINE static void sp_3072_lshift_112(sp_digit* r, const sp_digit* a,
  10821. byte n)
  10822. {
  10823. sp_int_digit s;
  10824. sp_int_digit t;
  10825. s = (sp_int_digit)a[111];
  10826. r[112] = s >> (28U - n);
  10827. s = (sp_int_digit)(a[111]); t = (sp_int_digit)(a[110]);
  10828. r[111] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10829. s = (sp_int_digit)(a[110]); t = (sp_int_digit)(a[109]);
  10830. r[110] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10831. s = (sp_int_digit)(a[109]); t = (sp_int_digit)(a[108]);
  10832. r[109] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10833. s = (sp_int_digit)(a[108]); t = (sp_int_digit)(a[107]);
  10834. r[108] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10835. s = (sp_int_digit)(a[107]); t = (sp_int_digit)(a[106]);
  10836. r[107] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10837. s = (sp_int_digit)(a[106]); t = (sp_int_digit)(a[105]);
  10838. r[106] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10839. s = (sp_int_digit)(a[105]); t = (sp_int_digit)(a[104]);
  10840. r[105] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10841. s = (sp_int_digit)(a[104]); t = (sp_int_digit)(a[103]);
  10842. r[104] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10843. s = (sp_int_digit)(a[103]); t = (sp_int_digit)(a[102]);
  10844. r[103] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10845. s = (sp_int_digit)(a[102]); t = (sp_int_digit)(a[101]);
  10846. r[102] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10847. s = (sp_int_digit)(a[101]); t = (sp_int_digit)(a[100]);
  10848. r[101] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10849. s = (sp_int_digit)(a[100]); t = (sp_int_digit)(a[99]);
  10850. r[100] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10851. s = (sp_int_digit)(a[99]); t = (sp_int_digit)(a[98]);
  10852. r[99] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10853. s = (sp_int_digit)(a[98]); t = (sp_int_digit)(a[97]);
  10854. r[98] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10855. s = (sp_int_digit)(a[97]); t = (sp_int_digit)(a[96]);
  10856. r[97] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10857. s = (sp_int_digit)(a[96]); t = (sp_int_digit)(a[95]);
  10858. r[96] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10859. s = (sp_int_digit)(a[95]); t = (sp_int_digit)(a[94]);
  10860. r[95] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10861. s = (sp_int_digit)(a[94]); t = (sp_int_digit)(a[93]);
  10862. r[94] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10863. s = (sp_int_digit)(a[93]); t = (sp_int_digit)(a[92]);
  10864. r[93] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10865. s = (sp_int_digit)(a[92]); t = (sp_int_digit)(a[91]);
  10866. r[92] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10867. s = (sp_int_digit)(a[91]); t = (sp_int_digit)(a[90]);
  10868. r[91] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10869. s = (sp_int_digit)(a[90]); t = (sp_int_digit)(a[89]);
  10870. r[90] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10871. s = (sp_int_digit)(a[89]); t = (sp_int_digit)(a[88]);
  10872. r[89] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10873. s = (sp_int_digit)(a[88]); t = (sp_int_digit)(a[87]);
  10874. r[88] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10875. s = (sp_int_digit)(a[87]); t = (sp_int_digit)(a[86]);
  10876. r[87] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10877. s = (sp_int_digit)(a[86]); t = (sp_int_digit)(a[85]);
  10878. r[86] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10879. s = (sp_int_digit)(a[85]); t = (sp_int_digit)(a[84]);
  10880. r[85] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10881. s = (sp_int_digit)(a[84]); t = (sp_int_digit)(a[83]);
  10882. r[84] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10883. s = (sp_int_digit)(a[83]); t = (sp_int_digit)(a[82]);
  10884. r[83] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10885. s = (sp_int_digit)(a[82]); t = (sp_int_digit)(a[81]);
  10886. r[82] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10887. s = (sp_int_digit)(a[81]); t = (sp_int_digit)(a[80]);
  10888. r[81] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10889. s = (sp_int_digit)(a[80]); t = (sp_int_digit)(a[79]);
  10890. r[80] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10891. s = (sp_int_digit)(a[79]); t = (sp_int_digit)(a[78]);
  10892. r[79] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10893. s = (sp_int_digit)(a[78]); t = (sp_int_digit)(a[77]);
  10894. r[78] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10895. s = (sp_int_digit)(a[77]); t = (sp_int_digit)(a[76]);
  10896. r[77] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10897. s = (sp_int_digit)(a[76]); t = (sp_int_digit)(a[75]);
  10898. r[76] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10899. s = (sp_int_digit)(a[75]); t = (sp_int_digit)(a[74]);
  10900. r[75] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10901. s = (sp_int_digit)(a[74]); t = (sp_int_digit)(a[73]);
  10902. r[74] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10903. s = (sp_int_digit)(a[73]); t = (sp_int_digit)(a[72]);
  10904. r[73] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10905. s = (sp_int_digit)(a[72]); t = (sp_int_digit)(a[71]);
  10906. r[72] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10907. s = (sp_int_digit)(a[71]); t = (sp_int_digit)(a[70]);
  10908. r[71] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10909. s = (sp_int_digit)(a[70]); t = (sp_int_digit)(a[69]);
  10910. r[70] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10911. s = (sp_int_digit)(a[69]); t = (sp_int_digit)(a[68]);
  10912. r[69] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10913. s = (sp_int_digit)(a[68]); t = (sp_int_digit)(a[67]);
  10914. r[68] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10915. s = (sp_int_digit)(a[67]); t = (sp_int_digit)(a[66]);
  10916. r[67] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10917. s = (sp_int_digit)(a[66]); t = (sp_int_digit)(a[65]);
  10918. r[66] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10919. s = (sp_int_digit)(a[65]); t = (sp_int_digit)(a[64]);
  10920. r[65] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10921. s = (sp_int_digit)(a[64]); t = (sp_int_digit)(a[63]);
  10922. r[64] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10923. s = (sp_int_digit)(a[63]); t = (sp_int_digit)(a[62]);
  10924. r[63] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10925. s = (sp_int_digit)(a[62]); t = (sp_int_digit)(a[61]);
  10926. r[62] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10927. s = (sp_int_digit)(a[61]); t = (sp_int_digit)(a[60]);
  10928. r[61] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10929. s = (sp_int_digit)(a[60]); t = (sp_int_digit)(a[59]);
  10930. r[60] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10931. s = (sp_int_digit)(a[59]); t = (sp_int_digit)(a[58]);
  10932. r[59] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10933. s = (sp_int_digit)(a[58]); t = (sp_int_digit)(a[57]);
  10934. r[58] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10935. s = (sp_int_digit)(a[57]); t = (sp_int_digit)(a[56]);
  10936. r[57] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10937. s = (sp_int_digit)(a[56]); t = (sp_int_digit)(a[55]);
  10938. r[56] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10939. s = (sp_int_digit)(a[55]); t = (sp_int_digit)(a[54]);
  10940. r[55] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10941. s = (sp_int_digit)(a[54]); t = (sp_int_digit)(a[53]);
  10942. r[54] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10943. s = (sp_int_digit)(a[53]); t = (sp_int_digit)(a[52]);
  10944. r[53] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10945. s = (sp_int_digit)(a[52]); t = (sp_int_digit)(a[51]);
  10946. r[52] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10947. s = (sp_int_digit)(a[51]); t = (sp_int_digit)(a[50]);
  10948. r[51] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10949. s = (sp_int_digit)(a[50]); t = (sp_int_digit)(a[49]);
  10950. r[50] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10951. s = (sp_int_digit)(a[49]); t = (sp_int_digit)(a[48]);
  10952. r[49] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10953. s = (sp_int_digit)(a[48]); t = (sp_int_digit)(a[47]);
  10954. r[48] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10955. s = (sp_int_digit)(a[47]); t = (sp_int_digit)(a[46]);
  10956. r[47] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10957. s = (sp_int_digit)(a[46]); t = (sp_int_digit)(a[45]);
  10958. r[46] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10959. s = (sp_int_digit)(a[45]); t = (sp_int_digit)(a[44]);
  10960. r[45] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10961. s = (sp_int_digit)(a[44]); t = (sp_int_digit)(a[43]);
  10962. r[44] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10963. s = (sp_int_digit)(a[43]); t = (sp_int_digit)(a[42]);
  10964. r[43] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10965. s = (sp_int_digit)(a[42]); t = (sp_int_digit)(a[41]);
  10966. r[42] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10967. s = (sp_int_digit)(a[41]); t = (sp_int_digit)(a[40]);
  10968. r[41] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10969. s = (sp_int_digit)(a[40]); t = (sp_int_digit)(a[39]);
  10970. r[40] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10971. s = (sp_int_digit)(a[39]); t = (sp_int_digit)(a[38]);
  10972. r[39] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10973. s = (sp_int_digit)(a[38]); t = (sp_int_digit)(a[37]);
  10974. r[38] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10975. s = (sp_int_digit)(a[37]); t = (sp_int_digit)(a[36]);
  10976. r[37] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10977. s = (sp_int_digit)(a[36]); t = (sp_int_digit)(a[35]);
  10978. r[36] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10979. s = (sp_int_digit)(a[35]); t = (sp_int_digit)(a[34]);
  10980. r[35] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10981. s = (sp_int_digit)(a[34]); t = (sp_int_digit)(a[33]);
  10982. r[34] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10983. s = (sp_int_digit)(a[33]); t = (sp_int_digit)(a[32]);
  10984. r[33] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10985. s = (sp_int_digit)(a[32]); t = (sp_int_digit)(a[31]);
  10986. r[32] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10987. s = (sp_int_digit)(a[31]); t = (sp_int_digit)(a[30]);
  10988. r[31] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10989. s = (sp_int_digit)(a[30]); t = (sp_int_digit)(a[29]);
  10990. r[30] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10991. s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]);
  10992. r[29] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10993. s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]);
  10994. r[28] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10995. s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]);
  10996. r[27] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10997. s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]);
  10998. r[26] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  10999. s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]);
  11000. r[25] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11001. s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]);
  11002. r[24] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11003. s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]);
  11004. r[23] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11005. s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]);
  11006. r[22] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11007. s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]);
  11008. r[21] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11009. s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]);
  11010. r[20] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11011. s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]);
  11012. r[19] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11013. s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]);
  11014. r[18] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11015. s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]);
  11016. r[17] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11017. s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]);
  11018. r[16] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11019. s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]);
  11020. r[15] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11021. s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]);
  11022. r[14] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11023. s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]);
  11024. r[13] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11025. s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]);
  11026. r[12] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11027. s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]);
  11028. r[11] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11029. s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]);
  11030. r[10] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11031. s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]);
  11032. r[9] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11033. s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]);
  11034. r[8] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11035. s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]);
  11036. r[7] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11037. s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]);
  11038. r[6] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11039. s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]);
  11040. r[5] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11041. s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]);
  11042. r[4] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11043. s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]);
  11044. r[3] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11045. s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]);
  11046. r[2] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11047. s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]);
  11048. r[1] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
  11049. r[0] = (a[0] << n) & 0xfffffff;
  11050. }
  11051. /* Modular exponentiate 2 to the e mod m. (r = 2^e mod m)
  11052. *
  11053. * r A single precision number that is the result of the operation.
  11054. * e A single precision number that is the exponent.
  11055. * bits The number of bits in the exponent.
  11056. * m A single precision number that is the modulus.
  11057. * returns 0 on success.
  11058. * returns MEMORY_E on dynamic memory allocation failure.
  11059. * returns MP_VAL when base is even.
  11060. */
  11061. static int sp_3072_mod_exp_2_112(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m)
  11062. {
  11063. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  11064. sp_digit* td = NULL;
  11065. #else
  11066. sp_digit td[337];
  11067. #endif
  11068. sp_digit* norm = NULL;
  11069. sp_digit* tmp = NULL;
  11070. sp_digit mp = 1;
  11071. sp_digit n;
  11072. sp_digit o;
  11073. int i;
  11074. int c;
  11075. byte y;
  11076. int err = MP_OKAY;
  11077. if (bits == 0) {
  11078. err = MP_VAL;
  11079. }
  11080. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  11081. if (err == MP_OKAY) {
  11082. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 337, NULL,
  11083. DYNAMIC_TYPE_TMP_BUFFER);
  11084. if (td == NULL)
  11085. err = MEMORY_E;
  11086. }
  11087. #endif
  11088. if (err == MP_OKAY) {
  11089. norm = td;
  11090. tmp = td + 224;
  11091. XMEMSET(td, 0, sizeof(sp_digit) * 337);
  11092. sp_3072_mont_setup(m, &mp);
  11093. sp_3072_mont_norm_112(norm, m);
  11094. bits = ((bits + 3) / 4) * 4;
  11095. i = ((bits + 27) / 28) - 1;
  11096. c = bits % 28;
  11097. if (c == 0) {
  11098. c = 28;
  11099. }
  11100. if (i < 112) {
  11101. n = e[i--] << (32 - c);
  11102. }
  11103. else {
  11104. n = 0;
  11105. i--;
  11106. }
  11107. if (c < 4) {
  11108. n |= e[i--] << (4 - c);
  11109. c += 28;
  11110. }
  11111. y = (int)((n >> 28) & 0xf);
  11112. n <<= 4;
  11113. c -= 4;
  11114. sp_3072_lshift_112(r, norm, (byte)y);
  11115. while ((i >= 0) || (c >= 4)) {
  11116. if (c >= 4) {
  11117. y = (byte)((n >> 28) & 0xf);
  11118. n <<= 4;
  11119. c -= 4;
  11120. }
  11121. else if (c == 0) {
  11122. n = e[i--] << 4;
  11123. y = (byte)((n >> 28) & 0xf);
  11124. n <<= 4;
  11125. c = 24;
  11126. }
  11127. else {
  11128. y = (byte)((n >> 28) & 0xf);
  11129. n = e[i--] << 4;
  11130. c = 4 - c;
  11131. y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
  11132. n <<= c;
  11133. c = 28 - c;
  11134. }
  11135. sp_3072_mont_sqr_112(r, r, m, mp);
  11136. sp_3072_mont_sqr_112(r, r, m, mp);
  11137. sp_3072_mont_sqr_112(r, r, m, mp);
  11138. sp_3072_mont_sqr_112(r, r, m, mp);
  11139. sp_3072_lshift_112(r, r, (byte)y);
  11140. sp_3072_mul_d_112(tmp, norm, (r[110] << 8) + (r[109] >> 20));
  11141. r[110] = 0;
  11142. r[109] &= 0xfffffL;
  11143. (void)sp_3072_add_112(r, r, tmp);
  11144. sp_3072_norm_112(r);
  11145. o = sp_3072_cmp_112(r, m);
  11146. sp_3072_cond_sub_112(r, r, m, ~(o >> 31));
  11147. }
  11148. sp_3072_mont_reduce_112(r, m, mp);
  11149. n = sp_3072_cmp_112(r, m);
  11150. sp_3072_cond_sub_112(r, r, m, ~(n >> 31));
  11151. }
  11152. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  11153. if (td != NULL)
  11154. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  11155. #endif
  11156. return err;
  11157. }
  11158. #endif /* HAVE_FFDHE_3072 */
  11159. /* Perform the modular exponentiation for Diffie-Hellman.
  11160. *
  11161. * base Base.
  11162. * exp Array of bytes that is the exponent.
  11163. * expLen Length of data, in bytes, in exponent.
  11164. * mod Modulus.
  11165. * out Buffer to hold big-endian bytes of exponentiation result.
  11166. * Must be at least 384 bytes long.
  11167. * outLen Length, in bytes, of exponentiation result.
  11168. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  11169. * and MEMORY_E if memory allocation fails.
  11170. */
  11171. int sp_DhExp_3072(const mp_int* base, const byte* exp, word32 expLen,
  11172. const mp_int* mod, byte* out, word32* outLen)
  11173. {
  11174. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  11175. sp_digit* b = NULL;
  11176. #else
  11177. sp_digit b[112 * 4];
  11178. #endif
  11179. sp_digit* e = NULL;
  11180. sp_digit* m = NULL;
  11181. sp_digit* r = NULL;
  11182. word32 i;
  11183. int err = MP_OKAY;
  11184. if (mp_count_bits(base) > 3072) {
  11185. err = MP_READ_E;
  11186. }
  11187. else if (expLen > 384U) {
  11188. err = MP_READ_E;
  11189. }
  11190. else if (mp_count_bits(mod) != 3072) {
  11191. err = MP_READ_E;
  11192. }
  11193. else if (mp_iseven(mod)) {
  11194. err = MP_VAL;
  11195. }
  11196. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  11197. if (err == MP_OKAY) {
  11198. b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 112 * 4, NULL,
  11199. DYNAMIC_TYPE_DH);
  11200. if (b == NULL)
  11201. err = MEMORY_E;
  11202. }
  11203. #endif
  11204. if (err == MP_OKAY) {
  11205. e = b + 112 * 2;
  11206. m = e + 112;
  11207. r = b;
  11208. sp_3072_from_mp(b, 112, base);
  11209. sp_3072_from_bin(e, 112, exp, expLen);
  11210. sp_3072_from_mp(m, 112, mod);
  11211. #ifdef HAVE_FFDHE_3072
  11212. if (base->used == 1 && base->dp[0] == 2U &&
  11213. (m[109] >> 4) == 0xffffL) {
  11214. err = sp_3072_mod_exp_2_112(r, e, expLen * 8U, m);
  11215. }
  11216. else {
  11217. #endif
  11218. err = sp_3072_mod_exp_112(r, b, e, expLen * 8U, m, 0);
  11219. #ifdef HAVE_FFDHE_3072
  11220. }
  11221. #endif
  11222. }
  11223. if (err == MP_OKAY) {
  11224. sp_3072_to_bin_112(r, out);
  11225. *outLen = 384;
  11226. for (i=0; i<384U && out[i] == 0U; i++) {
  11227. /* Search for first non-zero. */
  11228. }
  11229. *outLen -= i;
  11230. XMEMMOVE(out, out + i, *outLen);
  11231. }
  11232. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  11233. if (b != NULL)
  11234. #endif
  11235. {
  11236. /* only "e" is sensitive and needs zeroized */
  11237. if (e != NULL)
  11238. ForceZero(e, sizeof(sp_digit) * 112U);
  11239. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  11240. XFREE(b, NULL, DYNAMIC_TYPE_DH);
  11241. #endif
  11242. }
  11243. return err;
  11244. }
  11245. #endif /* WOLFSSL_HAVE_SP_DH */
  11246. /* Perform the modular exponentiation for Diffie-Hellman.
  11247. *
  11248. * base Base. MP integer.
  11249. * exp Exponent. MP integer.
  11250. * mod Modulus. MP integer.
  11251. * res Result. MP integer.
  11252. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  11253. * and MEMORY_E if memory allocation fails.
  11254. */
  11255. int sp_ModExp_1536(const mp_int* base, const mp_int* exp, const mp_int* mod,
  11256. mp_int* res)
  11257. {
  11258. #ifdef WOLFSSL_SP_SMALL
  11259. int err = MP_OKAY;
  11260. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  11261. sp_digit* b = NULL;
  11262. #else
  11263. sp_digit b[56 * 4];
  11264. #endif
  11265. sp_digit* e = NULL;
  11266. sp_digit* m = NULL;
  11267. sp_digit* r = NULL;
  11268. int expBits = mp_count_bits(exp);
  11269. if (mp_count_bits(base) > 1536) {
  11270. err = MP_READ_E;
  11271. }
  11272. else if (expBits > 1536) {
  11273. err = MP_READ_E;
  11274. }
  11275. else if (mp_count_bits(mod) != 1536) {
  11276. err = MP_READ_E;
  11277. }
  11278. else if (mp_iseven(mod)) {
  11279. err = MP_VAL;
  11280. }
  11281. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  11282. if (err == MP_OKAY) {
  11283. b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 4, NULL,
  11284. DYNAMIC_TYPE_DH);
  11285. if (b == NULL)
  11286. err = MEMORY_E;
  11287. }
  11288. #endif
  11289. if (err == MP_OKAY) {
  11290. e = b + 56 * 2;
  11291. m = e + 56;
  11292. r = b;
  11293. sp_3072_from_mp(b, 56, base);
  11294. sp_3072_from_mp(e, 56, exp);
  11295. sp_3072_from_mp(m, 56, mod);
  11296. err = sp_3072_mod_exp_56(r, b, e, mp_count_bits(exp), m, 0);
  11297. }
  11298. if (err == MP_OKAY) {
  11299. XMEMSET(r + 56, 0, sizeof(*r) * 56U);
  11300. err = sp_3072_to_mp(r, res);
  11301. }
  11302. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  11303. if (b != NULL)
  11304. #endif
  11305. {
  11306. /* only "e" is sensitive and needs zeroized */
  11307. if (e != NULL)
  11308. ForceZero(e, sizeof(sp_digit) * 112U);
  11309. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  11310. XFREE(b, NULL, DYNAMIC_TYPE_DH);
  11311. #endif
  11312. }
  11313. return err;
  11314. #else
  11315. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  11316. sp_digit* b = NULL;
  11317. #else
  11318. sp_digit b[56 * 4];
  11319. #endif
  11320. sp_digit* e = NULL;
  11321. sp_digit* m = NULL;
  11322. sp_digit* r = NULL;
  11323. int err = MP_OKAY;
  11324. int expBits = mp_count_bits(exp);
  11325. if (mp_count_bits(base) > 1536) {
  11326. err = MP_READ_E;
  11327. }
  11328. else if (expBits > 1536) {
  11329. err = MP_READ_E;
  11330. }
  11331. else if (mp_count_bits(mod) != 1536) {
  11332. err = MP_READ_E;
  11333. }
  11334. else if (mp_iseven(mod)) {
  11335. err = MP_VAL;
  11336. }
  11337. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  11338. if (err == MP_OKAY) {
  11339. b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 4, NULL, DYNAMIC_TYPE_DH);
  11340. if (b == NULL)
  11341. err = MEMORY_E;
  11342. }
  11343. #endif
  11344. if (err == MP_OKAY) {
  11345. e = b + 56 * 2;
  11346. m = e + 56;
  11347. r = b;
  11348. sp_3072_from_mp(b, 56, base);
  11349. sp_3072_from_mp(e, 56, exp);
  11350. sp_3072_from_mp(m, 56, mod);
  11351. err = sp_3072_mod_exp_56(r, b, e, expBits, m, 0);
  11352. }
  11353. if (err == MP_OKAY) {
  11354. XMEMSET(r + 56, 0, sizeof(*r) * 56U);
  11355. err = sp_3072_to_mp(r, res);
  11356. }
  11357. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  11358. if (b != NULL)
  11359. #endif
  11360. {
  11361. /* only "e" is sensitive and needs zeroized */
  11362. if (e != NULL)
  11363. ForceZero(e, sizeof(sp_digit) * 112U);
  11364. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  11365. XFREE(b, NULL, DYNAMIC_TYPE_DH);
  11366. #endif
  11367. }
  11368. return err;
  11369. #endif
  11370. }
  11371. #endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
  11372. #endif /* WOLFSSL_SP_SMALL */
  11373. #endif /* !WOLFSSL_SP_NO_3072 */
  11374. #ifdef WOLFSSL_SP_4096
  11375. #ifdef WOLFSSL_SP_SMALL
  11376. /* Read big endian unsigned byte array into r.
  11377. *
  11378. * r A single precision integer.
  11379. * size Maximum number of bytes to convert
  11380. * a Byte array.
  11381. * n Number of bytes in array to read.
  11382. */
  11383. static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n)
  11384. {
  11385. int i;
  11386. int j = 0;
  11387. word32 s = 0;
  11388. r[0] = 0;
  11389. for (i = n-1; i >= 0; i--) {
  11390. r[j] |= (((sp_digit)a[i]) << s);
  11391. if (s >= 21U) {
  11392. r[j] &= 0x1fffffff;
  11393. s = 29U - s;
  11394. if (j + 1 >= size) {
  11395. break;
  11396. }
  11397. r[++j] = (sp_digit)a[i] >> s;
  11398. s = 8U - s;
  11399. }
  11400. else {
  11401. s += 8U;
  11402. }
  11403. }
  11404. for (j++; j < size; j++) {
  11405. r[j] = 0;
  11406. }
  11407. }
  11408. /* Convert an mp_int to an array of sp_digit.
  11409. *
  11410. * r A single precision integer.
  11411. * size Maximum number of bytes to convert
  11412. * a A multi-precision integer.
  11413. */
  11414. static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
  11415. {
  11416. #if DIGIT_BIT == 29
  11417. int j;
  11418. XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
  11419. for (j = a->used; j < size; j++) {
  11420. r[j] = 0;
  11421. }
  11422. #elif DIGIT_BIT > 29
  11423. int i;
  11424. int j = 0;
  11425. word32 s = 0;
  11426. r[0] = 0;
  11427. for (i = 0; i < a->used && j < size; i++) {
  11428. r[j] |= ((sp_digit)a->dp[i] << s);
  11429. r[j] &= 0x1fffffff;
  11430. s = 29U - s;
  11431. if (j + 1 >= size) {
  11432. break;
  11433. }
  11434. /* lint allow cast of mismatch word32 and mp_digit */
  11435. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  11436. while ((s + 29U) <= (word32)DIGIT_BIT) {
  11437. s += 29U;
  11438. r[j] &= 0x1fffffff;
  11439. if (j + 1 >= size) {
  11440. break;
  11441. }
  11442. if (s < (word32)DIGIT_BIT) {
  11443. /* lint allow cast of mismatch word32 and mp_digit */
  11444. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  11445. }
  11446. else {
  11447. r[++j] = (sp_digit)0;
  11448. }
  11449. }
  11450. s = (word32)DIGIT_BIT - s;
  11451. }
  11452. for (j++; j < size; j++) {
  11453. r[j] = 0;
  11454. }
  11455. #else
  11456. int i;
  11457. int j = 0;
  11458. int s = 0;
  11459. r[0] = 0;
  11460. for (i = 0; i < a->used && j < size; i++) {
  11461. r[j] |= ((sp_digit)a->dp[i]) << s;
  11462. if (s + DIGIT_BIT >= 29) {
  11463. r[j] &= 0x1fffffff;
  11464. if (j + 1 >= size) {
  11465. break;
  11466. }
  11467. s = 29 - s;
  11468. if (s == DIGIT_BIT) {
  11469. r[++j] = 0;
  11470. s = 0;
  11471. }
  11472. else {
  11473. r[++j] = a->dp[i] >> s;
  11474. s = DIGIT_BIT - s;
  11475. }
  11476. }
  11477. else {
  11478. s += DIGIT_BIT;
  11479. }
  11480. }
  11481. for (j++; j < size; j++) {
  11482. r[j] = 0;
  11483. }
  11484. #endif
  11485. }
  11486. /* Write r as big endian to byte array.
  11487. * Fixed length number of bytes written: 512
  11488. *
  11489. * r A single precision integer.
  11490. * a Byte array.
  11491. */
  11492. static void sp_4096_to_bin_142(sp_digit* r, byte* a)
  11493. {
  11494. int i;
  11495. int j;
  11496. int s = 0;
  11497. int b;
  11498. for (i=0; i<141; i++) {
  11499. r[i+1] += r[i] >> 29;
  11500. r[i] &= 0x1fffffff;
  11501. }
  11502. j = 4103 / 8 - 1;
  11503. a[j] = 0;
  11504. for (i=0; i<142 && j>=0; i++) {
  11505. b = 0;
  11506. /* lint allow cast of mismatch sp_digit and int */
  11507. a[j--] |= (byte)(r[i] << s); /*lint !e9033*/
  11508. b += 8 - s;
  11509. if (j < 0) {
  11510. break;
  11511. }
  11512. while (b < 29) {
  11513. a[j--] = (byte)(r[i] >> b);
  11514. b += 8;
  11515. if (j < 0) {
  11516. break;
  11517. }
  11518. }
  11519. s = 8 - (b - 29);
  11520. if (j >= 0) {
  11521. a[j] = 0;
  11522. }
  11523. if (s != 0) {
  11524. j++;
  11525. }
  11526. }
  11527. }
  11528. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  11529. #if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D)
  11530. /* Normalize the values in each word to 29 bits.
  11531. *
  11532. * a Array of sp_digit to normalize.
  11533. */
  11534. static void sp_4096_norm_71(sp_digit* a)
  11535. {
  11536. int i;
  11537. for (i = 0; i < 70; i++) {
  11538. a[i+1] += a[i] >> 29;
  11539. a[i] &= 0x1fffffff;
  11540. }
  11541. }
  11542. #endif /* WOLFSSL_HAVE_SP_RSA & !SP_RSA_PRIVATE_EXP_D */
  11543. #endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
  11544. /* Normalize the values in each word to 29 bits.
  11545. *
  11546. * a Array of sp_digit to normalize.
  11547. */
  11548. static void sp_4096_norm_142(sp_digit* a)
  11549. {
  11550. int i;
  11551. for (i = 0; i < 141; i++) {
  11552. a[i+1] += a[i] >> 29;
  11553. a[i] &= 0x1fffffff;
  11554. }
  11555. }
  11556. /* Multiply a and b into r. (r = a * b)
  11557. *
  11558. * r A single precision integer.
  11559. * a A single precision integer.
  11560. * b A single precision integer.
  11561. */
  11562. SP_NOINLINE static void sp_4096_mul_142(sp_digit* r, const sp_digit* a,
  11563. const sp_digit* b)
  11564. {
  11565. int i;
  11566. int imax;
  11567. int k;
  11568. sp_uint64 c;
  11569. sp_uint64 lo;
  11570. c = ((sp_uint64)a[141]) * b[141];
  11571. r[283] = (sp_digit)(c >> 29);
  11572. c &= 0x1fffffff;
  11573. for (k = 281; k >= 0; k--) {
  11574. if (k >= 142) {
  11575. i = k - 141;
  11576. imax = 141;
  11577. }
  11578. else {
  11579. i = 0;
  11580. imax = k;
  11581. }
  11582. if (imax - i > 15) {
  11583. int imaxlo;
  11584. lo = 0;
  11585. for (imaxlo = i; imaxlo <= imax; imaxlo += 15) {
  11586. for (; i <= imax && i < imaxlo + 15; i++) {
  11587. lo += ((sp_uint64)a[i]) * b[k - i];
  11588. }
  11589. c += lo >> 29;
  11590. lo &= 0x1fffffff;
  11591. }
  11592. r[k + 2] += (sp_digit)(c >> 29);
  11593. r[k + 1] = (sp_digit)(c & 0x1fffffff);
  11594. c = lo & 0x1fffffff;
  11595. }
  11596. else {
  11597. lo = 0;
  11598. for (; i <= imax; i++) {
  11599. lo += ((sp_uint64)a[i]) * b[k - i];
  11600. }
  11601. c += lo >> 29;
  11602. r[k + 2] += (sp_digit)(c >> 29);
  11603. r[k + 1] = (sp_digit)(c & 0x1fffffff);
  11604. c = lo & 0x1fffffff;
  11605. }
  11606. }
  11607. r[0] = (sp_digit)c;
  11608. }
  11609. /* Square a and put result in r. (r = a * a)
  11610. *
  11611. * r A single precision integer.
  11612. * a A single precision integer.
  11613. */
  11614. SP_NOINLINE static void sp_4096_sqr_142(sp_digit* r, const sp_digit* a)
  11615. {
  11616. int i;
  11617. int imax;
  11618. int k;
  11619. sp_uint64 c;
  11620. sp_uint64 t;
  11621. c = ((sp_uint64)a[141]) * a[141];
  11622. r[283] = (sp_digit)(c >> 29);
  11623. c = (c & 0x1fffffff) << 29;
  11624. for (k = 281; k >= 0; k--) {
  11625. i = (k + 1) / 2;
  11626. if ((k & 1) == 0) {
  11627. c += ((sp_uint64)a[i]) * a[i];
  11628. i++;
  11629. }
  11630. if (k < 141) {
  11631. imax = k;
  11632. }
  11633. else {
  11634. imax = 141;
  11635. }
  11636. if (imax - i >= 14) {
  11637. int imaxlo;
  11638. sp_uint64 hi;
  11639. hi = c >> 29;
  11640. c &= 0x1fffffff;
  11641. for (imaxlo = i; imaxlo <= imax; imaxlo += 14) {
  11642. t = 0;
  11643. for (; i <= imax && i < imaxlo + 14; i++) {
  11644. t += ((sp_uint64)a[i]) * a[k - i];
  11645. }
  11646. c += t * 2;
  11647. hi += c >> 29;
  11648. c &= 0x1fffffff;
  11649. }
  11650. r[k + 2] += (sp_digit)(hi >> 29);
  11651. r[k + 1] = (sp_digit)(hi & 0x1fffffff);
  11652. c <<= 29;
  11653. }
  11654. else
  11655. {
  11656. t = 0;
  11657. for (; i <= imax; i++) {
  11658. t += ((sp_uint64)a[i]) * a[k - i];
  11659. }
  11660. c += t * 2;
  11661. r[k + 2] += (sp_digit) (c >> 58);
  11662. r[k + 1] = (sp_digit)((c >> 29) & 0x1fffffff);
  11663. c = (c & 0x1fffffff) << 29;
  11664. }
  11665. }
  11666. r[0] = (sp_digit)(c >> 29);
  11667. }
  11668. /* Caclulate the bottom digit of -1/a mod 2^n.
  11669. *
  11670. * a A single precision number.
  11671. * rho Bottom word of inverse.
  11672. */
  11673. static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho)
  11674. {
  11675. sp_digit x;
  11676. sp_digit b;
  11677. b = a[0];
  11678. x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
  11679. x *= 2 - b * x; /* here x*a==1 mod 2**8 */
  11680. x *= 2 - b * x; /* here x*a==1 mod 2**16 */
  11681. x *= 2 - b * x; /* here x*a==1 mod 2**32 */
  11682. x &= 0x1fffffff;
  11683. /* rho = -1/m mod b */
  11684. *rho = ((sp_digit)1 << 29) - x;
  11685. }
  11686. /* Multiply a by scalar b into r. (r = a * b)
  11687. *
  11688. * r A single precision integer.
  11689. * a A single precision integer.
  11690. * b A scalar.
  11691. */
  11692. SP_NOINLINE static void sp_4096_mul_d_142(sp_digit* r, const sp_digit* a,
  11693. sp_digit b)
  11694. {
  11695. sp_int64 tb = b;
  11696. sp_int64 t = 0;
  11697. int i;
  11698. for (i = 0; i < 142; i++) {
  11699. t += tb * a[i];
  11700. r[i] = (sp_digit)(t & 0x1fffffff);
  11701. t >>= 29;
  11702. }
  11703. r[142] = (sp_digit)t;
  11704. }
  11705. #if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)
  11706. #if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D)
  11707. /* Sub b from a into r. (r = a - b)
  11708. *
  11709. * r A single precision integer.
  11710. * a A single precision integer.
  11711. * b A single precision integer.
  11712. */
  11713. SP_NOINLINE static int sp_4096_sub_71(sp_digit* r, const sp_digit* a,
  11714. const sp_digit* b)
  11715. {
  11716. int i;
  11717. for (i = 0; i < 71; i++) {
  11718. r[i] = a[i] - b[i];
  11719. }
  11720. return 0;
  11721. }
  11722. /* r = 2^n mod m where n is the number of bits to reduce by.
  11723. * Given m must be 4096 bits, just need to subtract.
  11724. *
  11725. * r A single precision number.
  11726. * m A single precision number.
  11727. */
  11728. static void sp_4096_mont_norm_71(sp_digit* r, const sp_digit* m)
  11729. {
  11730. /* Set r = 2^n - 1. */
  11731. int i;
  11732. for (i=0; i<70; i++) {
  11733. r[i] = 0x1fffffff;
  11734. }
  11735. r[70] = 0x3ffffL;
  11736. /* r = (2^n - 1) mod n */
  11737. (void)sp_4096_sub_71(r, r, m);
  11738. /* Add one so r = 2^n mod m */
  11739. r[0] += 1;
  11740. }
  11741. /* Compare a with b in constant time.
  11742. *
  11743. * a A single precision integer.
  11744. * b A single precision integer.
  11745. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  11746. * respectively.
  11747. */
  11748. static sp_digit sp_4096_cmp_71(const sp_digit* a, const sp_digit* b)
  11749. {
  11750. sp_digit r = 0;
  11751. int i;
  11752. for (i=70; i>=0; i--) {
  11753. r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 28);
  11754. }
  11755. return r;
  11756. }
  11757. /* Conditionally subtract b from a using the mask m.
  11758. * m is -1 to subtract and 0 when not.
  11759. *
  11760. * r A single precision number representing condition subtract result.
  11761. * a A single precision number to subtract from.
  11762. * b A single precision number to subtract.
  11763. * m Mask value to apply.
  11764. */
  11765. static void sp_4096_cond_sub_71(sp_digit* r, const sp_digit* a,
  11766. const sp_digit* b, const sp_digit m)
  11767. {
  11768. int i;
  11769. for (i = 0; i < 71; i++) {
  11770. r[i] = a[i] - (b[i] & m);
  11771. }
  11772. }
  11773. /* Mul a by scalar b and add into r. (r += a * b)
  11774. *
  11775. * r A single precision integer.
  11776. * a A single precision integer.
  11777. * b A scalar.
  11778. */
  11779. SP_NOINLINE static void sp_4096_mul_add_71(sp_digit* r, const sp_digit* a,
  11780. const sp_digit b)
  11781. {
  11782. #ifndef WOLFSSL_SP_LARGE_CODE
  11783. sp_int64 tb = b;
  11784. sp_int64 t = 0;
  11785. int i;
  11786. for (i = 0; i < 71; i++) {
  11787. t += r[i];
  11788. t += tb * a[i];
  11789. r[i] = ((sp_digit)t) & 0x1fffffff;
  11790. t >>= 29;
  11791. }
  11792. r[71] += (sp_digit)t;
  11793. #else
  11794. sp_int64 tb = b;
  11795. sp_int64 t[4];
  11796. int i;
  11797. t[0] = 0;
  11798. for (i = 0; i < 68; i += 4) {
  11799. t[0] += (tb * a[i+0]) + r[i+0];
  11800. t[1] = (tb * a[i+1]) + r[i+1];
  11801. t[2] = (tb * a[i+2]) + r[i+2];
  11802. t[3] = (tb * a[i+3]) + r[i+3];
  11803. r[i+0] = t[0] & 0x1fffffff;
  11804. t[1] += t[0] >> 29;
  11805. r[i+1] = t[1] & 0x1fffffff;
  11806. t[2] += t[1] >> 29;
  11807. r[i+2] = t[2] & 0x1fffffff;
  11808. t[3] += t[2] >> 29;
  11809. r[i+3] = t[3] & 0x1fffffff;
  11810. t[0] = t[3] >> 29;
  11811. }
  11812. t[0] += (tb * a[68]) + r[68];
  11813. t[1] = (tb * a[69]) + r[69];
  11814. t[2] = (tb * a[70]) + r[70];
  11815. r[68] = t[0] & 0x1fffffff;
  11816. t[1] += t[0] >> 29;
  11817. r[69] = t[1] & 0x1fffffff;
  11818. t[2] += t[1] >> 29;
  11819. r[70] = t[2] & 0x1fffffff;
  11820. r[71] += (sp_digit)(t[2] >> 29);
  11821. #endif /* !WOLFSSL_SP_LARGE_CODE */
  11822. }
  11823. /* Shift the result in the high 2048 bits down to the bottom.
  11824. *
  11825. * r A single precision number.
  11826. * a A single precision number.
  11827. */
  11828. static void sp_4096_mont_shift_71(sp_digit* r, const sp_digit* a)
  11829. {
  11830. int i;
  11831. sp_int64 n = a[70] >> 18;
  11832. n += ((sp_int64)a[71]) << 11;
  11833. for (i = 0; i < 70; i++) {
  11834. r[i] = n & 0x1fffffff;
  11835. n >>= 29;
  11836. n += ((sp_int64)a[72 + i]) << 11;
  11837. }
  11838. r[70] = (sp_digit)n;
  11839. XMEMSET(&r[71], 0, sizeof(*r) * 71U);
  11840. }
  11841. /* Reduce the number back to 4096 bits using Montgomery reduction.
  11842. *
  11843. * a A single precision number to reduce in place.
  11844. * m The single precision number representing the modulus.
  11845. * mp The digit representing the negative inverse of m mod 2^n.
  11846. */
  11847. static void sp_4096_mont_reduce_71(sp_digit* a, const sp_digit* m, sp_digit mp)
  11848. {
  11849. int i;
  11850. sp_digit mu;
  11851. sp_digit over;
  11852. sp_4096_norm_71(a + 71);
  11853. for (i=0; i<70; i++) {
  11854. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff;
  11855. sp_4096_mul_add_71(a+i, m, mu);
  11856. a[i+1] += a[i] >> 29;
  11857. }
  11858. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x3ffffL;
  11859. sp_4096_mul_add_71(a+i, m, mu);
  11860. a[i+1] += a[i] >> 29;
  11861. a[i] &= 0x1fffffff;
  11862. sp_4096_mont_shift_71(a, a);
  11863. over = a[70] - m[70];
  11864. sp_4096_cond_sub_71(a, a, m, ~((over - 1) >> 31));
  11865. sp_4096_norm_71(a);
  11866. }
  11867. /* Multiply a and b into r. (r = a * b)
  11868. *
  11869. * r A single precision integer.
  11870. * a A single precision integer.
  11871. * b A single precision integer.
  11872. */
  11873. SP_NOINLINE static void sp_4096_mul_71(sp_digit* r, const sp_digit* a,
  11874. const sp_digit* b)
  11875. {
  11876. int i;
  11877. int imax;
  11878. int k;
  11879. sp_uint64 c;
  11880. sp_uint64 lo;
  11881. c = ((sp_uint64)a[70]) * b[70];
  11882. r[141] = (sp_digit)(c >> 29);
  11883. c &= 0x1fffffff;
  11884. for (k = 139; k >= 0; k--) {
  11885. if (k >= 71) {
  11886. i = k - 70;
  11887. imax = 70;
  11888. }
  11889. else {
  11890. i = 0;
  11891. imax = k;
  11892. }
  11893. if (imax - i > 15) {
  11894. int imaxlo;
  11895. lo = 0;
  11896. for (imaxlo = i; imaxlo <= imax; imaxlo += 15) {
  11897. for (; i <= imax && i < imaxlo + 15; i++) {
  11898. lo += ((sp_uint64)a[i]) * b[k - i];
  11899. }
  11900. c += lo >> 29;
  11901. lo &= 0x1fffffff;
  11902. }
  11903. r[k + 2] += (sp_digit)(c >> 29);
  11904. r[k + 1] = (sp_digit)(c & 0x1fffffff);
  11905. c = lo & 0x1fffffff;
  11906. }
  11907. else {
  11908. lo = 0;
  11909. for (; i <= imax; i++) {
  11910. lo += ((sp_uint64)a[i]) * b[k - i];
  11911. }
  11912. c += lo >> 29;
  11913. r[k + 2] += (sp_digit)(c >> 29);
  11914. r[k + 1] = (sp_digit)(c & 0x1fffffff);
  11915. c = lo & 0x1fffffff;
  11916. }
  11917. }
  11918. r[0] = (sp_digit)c;
  11919. }
  11920. /* Multiply two Montgomery form numbers mod the modulus (prime).
  11921. * (r = a * b mod m)
  11922. *
  11923. * r Result of multiplication.
  11924. * a First number to multiply in Montgomery form.
  11925. * b Second number to multiply in Montgomery form.
  11926. * m Modulus (prime).
  11927. * mp Montgomery mulitplier.
  11928. */
  11929. SP_NOINLINE static void sp_4096_mont_mul_71(sp_digit* r, const sp_digit* a,
  11930. const sp_digit* b, const sp_digit* m, sp_digit mp)
  11931. {
  11932. sp_4096_mul_71(r, a, b);
  11933. sp_4096_mont_reduce_71(r, m, mp);
  11934. }
  11935. /* Square a and put result in r. (r = a * a)
  11936. *
  11937. * r A single precision integer.
  11938. * a A single precision integer.
  11939. */
  11940. SP_NOINLINE static void sp_4096_sqr_71(sp_digit* r, const sp_digit* a)
  11941. {
  11942. int i;
  11943. int imax;
  11944. int k;
  11945. sp_uint64 c;
  11946. sp_uint64 t;
  11947. c = ((sp_uint64)a[70]) * a[70];
  11948. r[141] = (sp_digit)(c >> 29);
  11949. c = (c & 0x1fffffff) << 29;
  11950. for (k = 139; k >= 0; k--) {
  11951. i = (k + 1) / 2;
  11952. if ((k & 1) == 0) {
  11953. c += ((sp_uint64)a[i]) * a[i];
  11954. i++;
  11955. }
  11956. if (k < 70) {
  11957. imax = k;
  11958. }
  11959. else {
  11960. imax = 70;
  11961. }
  11962. if (imax - i >= 14) {
  11963. int imaxlo;
  11964. sp_uint64 hi;
  11965. hi = c >> 29;
  11966. c &= 0x1fffffff;
  11967. for (imaxlo = i; imaxlo <= imax; imaxlo += 14) {
  11968. t = 0;
  11969. for (; i <= imax && i < imaxlo + 14; i++) {
  11970. t += ((sp_uint64)a[i]) * a[k - i];
  11971. }
  11972. c += t * 2;
  11973. hi += c >> 29;
  11974. c &= 0x1fffffff;
  11975. }
  11976. r[k + 2] += (sp_digit)(hi >> 29);
  11977. r[k + 1] = (sp_digit)(hi & 0x1fffffff);
  11978. c <<= 29;
  11979. }
  11980. else
  11981. {
  11982. t = 0;
  11983. for (; i <= imax; i++) {
  11984. t += ((sp_uint64)a[i]) * a[k - i];
  11985. }
  11986. c += t * 2;
  11987. r[k + 2] += (sp_digit) (c >> 58);
  11988. r[k + 1] = (sp_digit)((c >> 29) & 0x1fffffff);
  11989. c = (c & 0x1fffffff) << 29;
  11990. }
  11991. }
  11992. r[0] = (sp_digit)(c >> 29);
  11993. }
  11994. /* Square the Montgomery form number. (r = a * a mod m)
  11995. *
  11996. * r Result of squaring.
  11997. * a Number to square in Montgomery form.
  11998. * m Modulus (prime).
  11999. * mp Montgomery mulitplier.
  12000. */
  12001. SP_NOINLINE static void sp_4096_mont_sqr_71(sp_digit* r, const sp_digit* a,
  12002. const sp_digit* m, sp_digit mp)
  12003. {
  12004. sp_4096_sqr_71(r, a);
  12005. sp_4096_mont_reduce_71(r, m, mp);
  12006. }
  12007. /* Multiply a by scalar b into r. (r = a * b)
  12008. *
  12009. * r A single precision integer.
  12010. * a A single precision integer.
  12011. * b A scalar.
  12012. */
  12013. SP_NOINLINE static void sp_4096_mul_d_71(sp_digit* r, const sp_digit* a,
  12014. sp_digit b)
  12015. {
  12016. sp_int64 tb = b;
  12017. sp_int64 t = 0;
  12018. int i;
  12019. for (i = 0; i < 71; i++) {
  12020. t += tb * a[i];
  12021. r[i] = (sp_digit)(t & 0x1fffffff);
  12022. t >>= 29;
  12023. }
  12024. r[71] = (sp_digit)t;
  12025. }
  12026. #ifdef WOLFSSL_SP_SMALL
  12027. /* Conditionally add a and b using the mask m.
  12028. * m is -1 to add and 0 when not.
  12029. *
  12030. * r A single precision number representing conditional add result.
  12031. * a A single precision number to add with.
  12032. * b A single precision number to add.
  12033. * m Mask value to apply.
  12034. */
  12035. static void sp_4096_cond_add_71(sp_digit* r, const sp_digit* a,
  12036. const sp_digit* b, const sp_digit m)
  12037. {
  12038. int i;
  12039. for (i = 0; i < 71; i++) {
  12040. r[i] = a[i] + (b[i] & m);
  12041. }
  12042. }
  12043. #endif /* WOLFSSL_SP_SMALL */
  12044. /* Add b to a into r. (r = a + b)
  12045. *
  12046. * r A single precision integer.
  12047. * a A single precision integer.
  12048. * b A single precision integer.
  12049. */
  12050. SP_NOINLINE static int sp_4096_add_71(sp_digit* r, const sp_digit* a,
  12051. const sp_digit* b)
  12052. {
  12053. int i;
  12054. for (i = 0; i < 71; i++) {
  12055. r[i] = a[i] + b[i];
  12056. }
  12057. return 0;
  12058. }
  12059. SP_NOINLINE static void sp_4096_rshift_71(sp_digit* r, const sp_digit* a,
  12060. byte n)
  12061. {
  12062. int i;
  12063. for (i=0; i<70; i++) {
  12064. r[i] = ((a[i] >> n) | (a[i + 1] << (29 - n))) & 0x1fffffff;
  12065. }
  12066. r[70] = a[70] >> n;
  12067. }
  12068. static WC_INLINE sp_digit sp_4096_div_word_71(sp_digit d1, sp_digit d0,
  12069. sp_digit div)
  12070. {
  12071. #ifdef SP_USE_DIVTI3
  12072. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  12073. return d / div;
  12074. #elif defined(__x86_64__) || defined(__i386__)
  12075. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  12076. sp_uint32 lo = (sp_uint32)d;
  12077. sp_digit hi = (sp_digit)(d >> 32);
  12078. __asm__ __volatile__ (
  12079. "idiv %2"
  12080. : "+a" (lo)
  12081. : "d" (hi), "r" (div)
  12082. : "cc"
  12083. );
  12084. return (sp_digit)lo;
  12085. #elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV)
  12086. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  12087. sp_digit dv = (div >> 1) + 1;
  12088. sp_digit t1 = (sp_digit)(d >> 29);
  12089. sp_digit t0 = (sp_digit)(d & 0x1fffffff);
  12090. sp_digit t2;
  12091. sp_digit sign;
  12092. sp_digit r;
  12093. int i;
  12094. sp_int64 m;
  12095. r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
  12096. t1 -= dv & (0 - r);
  12097. for (i = 27; i >= 1; i--) {
  12098. t1 += t1 + (((sp_uint32)t0 >> 28) & 1);
  12099. t0 <<= 1;
  12100. t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
  12101. r += r + t2;
  12102. t1 -= dv & (0 - t2);
  12103. t1 += t2;
  12104. }
  12105. r += r + 1;
  12106. m = d - ((sp_int64)r * div);
  12107. r += (sp_digit)(m >> 29);
  12108. m = d - ((sp_int64)r * div);
  12109. r += (sp_digit)(m >> 58) - (sp_digit)(d >> 58);
  12110. m = d - ((sp_int64)r * div);
  12111. sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
  12112. m *= sign;
  12113. t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
  12114. r += sign * t2;
  12115. m = d - ((sp_int64)r * div);
  12116. sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
  12117. m *= sign;
  12118. t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
  12119. r += sign * t2;
  12120. return r;
  12121. #else
  12122. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  12123. sp_digit r = 0;
  12124. sp_digit t;
  12125. sp_digit dv = (div >> 14) + 1;
  12126. t = (sp_digit)(d >> 28);
  12127. t = (t / dv) << 14;
  12128. r += t;
  12129. d -= (sp_int64)t * div;
  12130. t = (sp_digit)(d >> 13);
  12131. t = t / (dv << 1);
  12132. r += t;
  12133. d -= (sp_int64)t * div;
  12134. t = (sp_digit)d;
  12135. t = t / div;
  12136. r += t;
  12137. d -= (sp_int64)t * div;
  12138. return r;
  12139. #endif
  12140. }
  12141. static WC_INLINE sp_digit sp_4096_word_div_word_71(sp_digit d, sp_digit div)
  12142. {
  12143. #if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
  12144. defined(SP_DIV_WORD_USE_DIV)
  12145. return d / div;
  12146. #else
  12147. return (sp_digit)((sp_uint32)(div - d) >> 31);
  12148. #endif
  12149. }
  12150. /* Divide d in a and put remainder into r (m*d + r = a)
  12151. * m is not calculated as it is not needed at this time.
  12152. *
  12153. * Full implementation.
  12154. *
  12155. * a Number to be divided.
  12156. * d Number to divide with.
  12157. * m Multiplier result.
  12158. * r Remainder from the division.
  12159. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  12160. */
  12161. static int sp_4096_div_71(const sp_digit* a, const sp_digit* d,
  12162. const sp_digit* m, sp_digit* r)
  12163. {
  12164. int i;
  12165. #ifndef WOLFSSL_SP_DIV_32
  12166. #endif
  12167. sp_digit dv;
  12168. sp_digit r1;
  12169. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  12170. sp_digit* t1 = NULL;
  12171. #else
  12172. sp_digit t1[4 * 71 + 3];
  12173. #endif
  12174. sp_digit* t2 = NULL;
  12175. sp_digit* sd = NULL;
  12176. int err = MP_OKAY;
  12177. (void)m;
  12178. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  12179. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 71 + 3), NULL,
  12180. DYNAMIC_TYPE_TMP_BUFFER);
  12181. if (t1 == NULL)
  12182. err = MEMORY_E;
  12183. #endif
  12184. (void)m;
  12185. if (err == MP_OKAY) {
  12186. t2 = t1 + 142 + 1;
  12187. sd = t2 + 71 + 1;
  12188. sp_4096_mul_d_71(sd, d, (sp_digit)1 << 11);
  12189. sp_4096_mul_d_142(t1, a, (sp_digit)1 << 11);
  12190. dv = sd[70];
  12191. t1[71 + 71] += t1[71 + 71 - 1] >> 29;
  12192. t1[71 + 71 - 1] &= 0x1fffffff;
  12193. for (i=71; i>=0; i--) {
  12194. r1 = sp_4096_div_word_71(t1[71 + i], t1[71 + i - 1], dv);
  12195. sp_4096_mul_d_71(t2, sd, r1);
  12196. (void)sp_4096_sub_71(&t1[i], &t1[i], t2);
  12197. sp_4096_norm_71(&t1[i]);
  12198. t1[71 + i] -= t2[71];
  12199. t1[71 + i] += t1[71 + i - 1] >> 29;
  12200. t1[71 + i - 1] &= 0x1fffffff;
  12201. r1 = sp_4096_div_word_71(-t1[71 + i], -t1[71 + i - 1], dv);
  12202. r1 -= t1[71 + i];
  12203. sp_4096_mul_d_71(t2, sd, r1);
  12204. (void)sp_4096_add_71(&t1[i], &t1[i], t2);
  12205. t1[71 + i] += t1[71 + i - 1] >> 29;
  12206. t1[71 + i - 1] &= 0x1fffffff;
  12207. }
  12208. t1[71 - 1] += t1[71 - 2] >> 29;
  12209. t1[71 - 2] &= 0x1fffffff;
  12210. r1 = sp_4096_word_div_word_71(t1[71 - 1], dv);
  12211. sp_4096_mul_d_71(t2, sd, r1);
  12212. sp_4096_sub_71(t1, t1, t2);
  12213. XMEMCPY(r, t1, sizeof(*r) * 142U);
  12214. for (i=0; i<70; i++) {
  12215. r[i+1] += r[i] >> 29;
  12216. r[i] &= 0x1fffffff;
  12217. }
  12218. sp_4096_cond_add_71(r, r, sd, r[70] >> 31);
  12219. sp_4096_norm_71(r);
  12220. sp_4096_rshift_71(r, r, 11);
  12221. }
  12222. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  12223. if (t1 != NULL)
  12224. XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  12225. #endif
  12226. return err;
  12227. }
  12228. /* Reduce a modulo m into r. (r = a mod m)
  12229. *
  12230. * r A single precision number that is the reduced result.
  12231. * a A single precision number that is to be reduced.
  12232. * m A single precision number that is the modulus to reduce with.
  12233. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  12234. */
  12235. static int sp_4096_mod_71(sp_digit* r, const sp_digit* a, const sp_digit* m)
  12236. {
  12237. return sp_4096_div_71(a, m, NULL, r);
  12238. }
  12239. /* Modular exponentiate a to the e mod m. (r = a^e mod m)
  12240. *
  12241. * r A single precision number that is the result of the operation.
  12242. * a A single precision number being exponentiated.
  12243. * e A single precision number that is the exponent.
  12244. * bits The number of bits in the exponent.
  12245. * m A single precision number that is the modulus.
  12246. * returns 0 on success.
  12247. * returns MEMORY_E on dynamic memory allocation failure.
  12248. * returns MP_VAL when base is even or exponent is 0.
  12249. */
  12250. static int sp_4096_mod_exp_71(sp_digit* r, const sp_digit* a, const sp_digit* e,
  12251. int bits, const sp_digit* m, int reduceA)
  12252. {
  12253. #if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP)
  12254. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  12255. sp_digit* td = NULL;
  12256. #else
  12257. sp_digit td[3 * 142];
  12258. #endif
  12259. sp_digit* t[3] = {0, 0, 0};
  12260. sp_digit* norm = NULL;
  12261. sp_digit mp = 1;
  12262. sp_digit n;
  12263. int i;
  12264. int c;
  12265. byte y;
  12266. int err = MP_OKAY;
  12267. if (bits == 0) {
  12268. err = MP_VAL;
  12269. }
  12270. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  12271. if (err == MP_OKAY) {
  12272. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 71 * 2, NULL,
  12273. DYNAMIC_TYPE_TMP_BUFFER);
  12274. if (td == NULL)
  12275. err = MEMORY_E;
  12276. }
  12277. #endif
  12278. if (err == MP_OKAY) {
  12279. norm = td;
  12280. for (i=0; i<3; i++) {
  12281. t[i] = td + (i * 71 * 2);
  12282. XMEMSET(t[i], 0, sizeof(sp_digit) * 71U * 2U);
  12283. }
  12284. sp_4096_mont_setup(m, &mp);
  12285. sp_4096_mont_norm_71(norm, m);
  12286. if (reduceA != 0) {
  12287. err = sp_4096_mod_71(t[1], a, m);
  12288. }
  12289. else {
  12290. XMEMCPY(t[1], a, sizeof(sp_digit) * 71U);
  12291. }
  12292. }
  12293. if (err == MP_OKAY) {
  12294. sp_4096_mul_71(t[1], t[1], norm);
  12295. err = sp_4096_mod_71(t[1], t[1], m);
  12296. }
  12297. if (err == MP_OKAY) {
  12298. i = bits / 29;
  12299. c = bits % 29;
  12300. n = e[i--] << (29 - c);
  12301. for (; ; c--) {
  12302. if (c == 0) {
  12303. if (i == -1) {
  12304. break;
  12305. }
  12306. n = e[i--];
  12307. c = 29;
  12308. }
  12309. y = (int)((n >> 28) & 1);
  12310. n <<= 1;
  12311. sp_4096_mont_mul_71(t[y^1], t[0], t[1], m, mp);
  12312. XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
  12313. ((size_t)t[1] & addr_mask[y])),
  12314. sizeof(*t[2]) * 71 * 2);
  12315. sp_4096_mont_sqr_71(t[2], t[2], m, mp);
  12316. XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
  12317. ((size_t)t[1] & addr_mask[y])), t[2],
  12318. sizeof(*t[2]) * 71 * 2);
  12319. }
  12320. sp_4096_mont_reduce_71(t[0], m, mp);
  12321. n = sp_4096_cmp_71(t[0], m);
  12322. sp_4096_cond_sub_71(t[0], t[0], m, ~(n >> 31));
  12323. XMEMCPY(r, t[0], sizeof(*r) * 71 * 2);
  12324. }
  12325. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  12326. if (td != NULL)
  12327. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  12328. #endif
  12329. return err;
  12330. #elif !defined(WC_NO_CACHE_RESISTANT)
  12331. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  12332. sp_digit* td = NULL;
  12333. #else
  12334. sp_digit td[3 * 142];
  12335. #endif
  12336. sp_digit* t[3] = {0, 0, 0};
  12337. sp_digit* norm = NULL;
  12338. sp_digit mp = 1;
  12339. sp_digit n;
  12340. int i;
  12341. int c;
  12342. byte y;
  12343. int err = MP_OKAY;
  12344. if (bits == 0) {
  12345. err = MP_VAL;
  12346. }
  12347. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  12348. if (err == MP_OKAY) {
  12349. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 71 * 2, NULL,
  12350. DYNAMIC_TYPE_TMP_BUFFER);
  12351. if (td == NULL)
  12352. err = MEMORY_E;
  12353. }
  12354. #endif
  12355. if (err == MP_OKAY) {
  12356. norm = td;
  12357. for (i=0; i<3; i++) {
  12358. t[i] = td + (i * 71 * 2);
  12359. }
  12360. sp_4096_mont_setup(m, &mp);
  12361. sp_4096_mont_norm_71(norm, m);
  12362. if (reduceA != 0) {
  12363. err = sp_4096_mod_71(t[1], a, m);
  12364. if (err == MP_OKAY) {
  12365. sp_4096_mul_71(t[1], t[1], norm);
  12366. err = sp_4096_mod_71(t[1], t[1], m);
  12367. }
  12368. }
  12369. else {
  12370. sp_4096_mul_71(t[1], a, norm);
  12371. err = sp_4096_mod_71(t[1], t[1], m);
  12372. }
  12373. }
  12374. if (err == MP_OKAY) {
  12375. i = bits / 29;
  12376. c = bits % 29;
  12377. n = e[i--] << (29 - c);
  12378. for (; ; c--) {
  12379. if (c == 0) {
  12380. if (i == -1) {
  12381. break;
  12382. }
  12383. n = e[i--];
  12384. c = 29;
  12385. }
  12386. y = (int)((n >> 28) & 1);
  12387. n <<= 1;
  12388. sp_4096_mont_mul_71(t[y^1], t[0], t[1], m, mp);
  12389. XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
  12390. ((size_t)t[1] & addr_mask[y])),
  12391. sizeof(*t[2]) * 71 * 2);
  12392. sp_4096_mont_sqr_71(t[2], t[2], m, mp);
  12393. XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
  12394. ((size_t)t[1] & addr_mask[y])), t[2],
  12395. sizeof(*t[2]) * 71 * 2);
  12396. }
  12397. sp_4096_mont_reduce_71(t[0], m, mp);
  12398. n = sp_4096_cmp_71(t[0], m);
  12399. sp_4096_cond_sub_71(t[0], t[0], m, ~(n >> 31));
  12400. XMEMCPY(r, t[0], sizeof(*r) * 71 * 2);
  12401. }
  12402. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  12403. if (td != NULL)
  12404. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  12405. #endif
  12406. return err;
  12407. #else
  12408. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  12409. sp_digit* td = NULL;
  12410. #else
  12411. sp_digit td[(32 * 142) + 142];
  12412. #endif
  12413. sp_digit* t[32];
  12414. sp_digit* rt = NULL;
  12415. sp_digit* norm = NULL;
  12416. sp_digit mp = 1;
  12417. sp_digit n;
  12418. int i;
  12419. int c;
  12420. byte y;
  12421. int err = MP_OKAY;
  12422. if (bits == 0) {
  12423. err = MP_VAL;
  12424. }
  12425. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  12426. if (err == MP_OKAY) {
  12427. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((32 * 142) + 142), NULL,
  12428. DYNAMIC_TYPE_TMP_BUFFER);
  12429. if (td == NULL)
  12430. err = MEMORY_E;
  12431. }
  12432. #endif
  12433. if (err == MP_OKAY) {
  12434. norm = td;
  12435. for (i=0; i<32; i++)
  12436. t[i] = td + i * 142;
  12437. rt = td + 4544;
  12438. sp_4096_mont_setup(m, &mp);
  12439. sp_4096_mont_norm_71(norm, m);
  12440. if (reduceA != 0) {
  12441. err = sp_4096_mod_71(t[1], a, m);
  12442. if (err == MP_OKAY) {
  12443. sp_4096_mul_71(t[1], t[1], norm);
  12444. err = sp_4096_mod_71(t[1], t[1], m);
  12445. }
  12446. }
  12447. else {
  12448. sp_4096_mul_71(t[1], a, norm);
  12449. err = sp_4096_mod_71(t[1], t[1], m);
  12450. }
  12451. }
  12452. if (err == MP_OKAY) {
  12453. sp_4096_mont_sqr_71(t[ 2], t[ 1], m, mp);
  12454. sp_4096_mont_mul_71(t[ 3], t[ 2], t[ 1], m, mp);
  12455. sp_4096_mont_sqr_71(t[ 4], t[ 2], m, mp);
  12456. sp_4096_mont_mul_71(t[ 5], t[ 3], t[ 2], m, mp);
  12457. sp_4096_mont_sqr_71(t[ 6], t[ 3], m, mp);
  12458. sp_4096_mont_mul_71(t[ 7], t[ 4], t[ 3], m, mp);
  12459. sp_4096_mont_sqr_71(t[ 8], t[ 4], m, mp);
  12460. sp_4096_mont_mul_71(t[ 9], t[ 5], t[ 4], m, mp);
  12461. sp_4096_mont_sqr_71(t[10], t[ 5], m, mp);
  12462. sp_4096_mont_mul_71(t[11], t[ 6], t[ 5], m, mp);
  12463. sp_4096_mont_sqr_71(t[12], t[ 6], m, mp);
  12464. sp_4096_mont_mul_71(t[13], t[ 7], t[ 6], m, mp);
  12465. sp_4096_mont_sqr_71(t[14], t[ 7], m, mp);
  12466. sp_4096_mont_mul_71(t[15], t[ 8], t[ 7], m, mp);
  12467. sp_4096_mont_sqr_71(t[16], t[ 8], m, mp);
  12468. sp_4096_mont_mul_71(t[17], t[ 9], t[ 8], m, mp);
  12469. sp_4096_mont_sqr_71(t[18], t[ 9], m, mp);
  12470. sp_4096_mont_mul_71(t[19], t[10], t[ 9], m, mp);
  12471. sp_4096_mont_sqr_71(t[20], t[10], m, mp);
  12472. sp_4096_mont_mul_71(t[21], t[11], t[10], m, mp);
  12473. sp_4096_mont_sqr_71(t[22], t[11], m, mp);
  12474. sp_4096_mont_mul_71(t[23], t[12], t[11], m, mp);
  12475. sp_4096_mont_sqr_71(t[24], t[12], m, mp);
  12476. sp_4096_mont_mul_71(t[25], t[13], t[12], m, mp);
  12477. sp_4096_mont_sqr_71(t[26], t[13], m, mp);
  12478. sp_4096_mont_mul_71(t[27], t[14], t[13], m, mp);
  12479. sp_4096_mont_sqr_71(t[28], t[14], m, mp);
  12480. sp_4096_mont_mul_71(t[29], t[15], t[14], m, mp);
  12481. sp_4096_mont_sqr_71(t[30], t[15], m, mp);
  12482. sp_4096_mont_mul_71(t[31], t[16], t[15], m, mp);
  12483. bits = ((bits + 4) / 5) * 5;
  12484. i = ((bits + 28) / 29) - 1;
  12485. c = bits % 29;
  12486. if (c == 0) {
  12487. c = 29;
  12488. }
  12489. if (i < 71) {
  12490. n = e[i--] << (32 - c);
  12491. }
  12492. else {
  12493. n = 0;
  12494. i--;
  12495. }
  12496. if (c < 5) {
  12497. n |= e[i--] << (3 - c);
  12498. c += 29;
  12499. }
  12500. y = (int)((n >> 27) & 0x1f);
  12501. n <<= 5;
  12502. c -= 5;
  12503. XMEMCPY(rt, t[y], sizeof(sp_digit) * 142);
  12504. while ((i >= 0) || (c >= 5)) {
  12505. if (c >= 5) {
  12506. y = (byte)((n >> 27) & 0x1f);
  12507. n <<= 5;
  12508. c -= 5;
  12509. }
  12510. else if (c == 0) {
  12511. n = e[i--] << 3;
  12512. y = (byte)((n >> 27) & 0x1f);
  12513. n <<= 5;
  12514. c = 24;
  12515. }
  12516. else {
  12517. y = (byte)((n >> 27) & 0x1f);
  12518. n = e[i--] << 3;
  12519. c = 5 - c;
  12520. y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
  12521. n <<= c;
  12522. c = 29 - c;
  12523. }
  12524. sp_4096_mont_sqr_71(rt, rt, m, mp);
  12525. sp_4096_mont_sqr_71(rt, rt, m, mp);
  12526. sp_4096_mont_sqr_71(rt, rt, m, mp);
  12527. sp_4096_mont_sqr_71(rt, rt, m, mp);
  12528. sp_4096_mont_sqr_71(rt, rt, m, mp);
  12529. sp_4096_mont_mul_71(rt, rt, t[y], m, mp);
  12530. }
  12531. sp_4096_mont_reduce_71(rt, m, mp);
  12532. n = sp_4096_cmp_71(rt, m);
  12533. sp_4096_cond_sub_71(rt, rt, m, ~(n >> 31));
  12534. XMEMCPY(r, rt, sizeof(sp_digit) * 142);
  12535. }
  12536. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  12537. if (td != NULL)
  12538. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  12539. #endif
  12540. return err;
  12541. #endif
  12542. }
  12543. #endif /* WOLFSSL_HAVE_SP_RSA & !SP_RSA_PRIVATE_EXP_D */
  12544. #endif /* (WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH) & !WOLFSSL_RSA_PUBLIC_ONLY */
  12545. /* Sub b from a into r. (r = a - b)
  12546. *
  12547. * r A single precision integer.
  12548. * a A single precision integer.
  12549. * b A single precision integer.
  12550. */
  12551. SP_NOINLINE static int sp_4096_sub_142(sp_digit* r, const sp_digit* a,
  12552. const sp_digit* b)
  12553. {
  12554. int i;
  12555. for (i = 0; i < 142; i++) {
  12556. r[i] = a[i] - b[i];
  12557. }
  12558. return 0;
  12559. }
  12560. /* r = 2^n mod m where n is the number of bits to reduce by.
  12561. * Given m must be 4096 bits, just need to subtract.
  12562. *
  12563. * r A single precision number.
  12564. * m A single precision number.
  12565. */
  12566. static void sp_4096_mont_norm_142(sp_digit* r, const sp_digit* m)
  12567. {
  12568. /* Set r = 2^n - 1. */
  12569. int i;
  12570. for (i=0; i<141; i++) {
  12571. r[i] = 0x1fffffff;
  12572. }
  12573. r[141] = 0x7fL;
  12574. /* r = (2^n - 1) mod n */
  12575. (void)sp_4096_sub_142(r, r, m);
  12576. /* Add one so r = 2^n mod m */
  12577. r[0] += 1;
  12578. }
  12579. /* Compare a with b in constant time.
  12580. *
  12581. * a A single precision integer.
  12582. * b A single precision integer.
  12583. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  12584. * respectively.
  12585. */
  12586. static sp_digit sp_4096_cmp_142(const sp_digit* a, const sp_digit* b)
  12587. {
  12588. sp_digit r = 0;
  12589. int i;
  12590. for (i=141; i>=0; i--) {
  12591. r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 28);
  12592. }
  12593. return r;
  12594. }
  12595. /* Conditionally subtract b from a using the mask m.
  12596. * m is -1 to subtract and 0 when not.
  12597. *
  12598. * r A single precision number representing condition subtract result.
  12599. * a A single precision number to subtract from.
  12600. * b A single precision number to subtract.
  12601. * m Mask value to apply.
  12602. */
  12603. static void sp_4096_cond_sub_142(sp_digit* r, const sp_digit* a,
  12604. const sp_digit* b, const sp_digit m)
  12605. {
  12606. int i;
  12607. for (i = 0; i < 142; i++) {
  12608. r[i] = a[i] - (b[i] & m);
  12609. }
  12610. }
  12611. /* Mul a by scalar b and add into r. (r += a * b)
  12612. *
  12613. * r A single precision integer.
  12614. * a A single precision integer.
  12615. * b A scalar.
  12616. */
  12617. SP_NOINLINE static void sp_4096_mul_add_142(sp_digit* r, const sp_digit* a,
  12618. const sp_digit b)
  12619. {
  12620. #ifndef WOLFSSL_SP_LARGE_CODE
  12621. sp_int64 tb = b;
  12622. sp_int64 t = 0;
  12623. int i;
  12624. for (i = 0; i < 142; i++) {
  12625. t += r[i];
  12626. t += tb * a[i];
  12627. r[i] = ((sp_digit)t) & 0x1fffffff;
  12628. t >>= 29;
  12629. }
  12630. r[142] += (sp_digit)t;
  12631. #else
  12632. sp_int64 tb = b;
  12633. sp_int64 t[4];
  12634. int i;
  12635. t[0] = 0;
  12636. for (i = 0; i < 140; i += 4) {
  12637. t[0] += (tb * a[i+0]) + r[i+0];
  12638. t[1] = (tb * a[i+1]) + r[i+1];
  12639. t[2] = (tb * a[i+2]) + r[i+2];
  12640. t[3] = (tb * a[i+3]) + r[i+3];
  12641. r[i+0] = t[0] & 0x1fffffff;
  12642. t[1] += t[0] >> 29;
  12643. r[i+1] = t[1] & 0x1fffffff;
  12644. t[2] += t[1] >> 29;
  12645. r[i+2] = t[2] & 0x1fffffff;
  12646. t[3] += t[2] >> 29;
  12647. r[i+3] = t[3] & 0x1fffffff;
  12648. t[0] = t[3] >> 29;
  12649. }
  12650. t[0] += (tb * a[140]) + r[140];
  12651. t[1] = (tb * a[141]) + r[141];
  12652. r[140] = t[0] & 0x1fffffff;
  12653. t[1] += t[0] >> 29;
  12654. r[141] = t[1] & 0x1fffffff;
  12655. r[142] += (sp_digit)(t[1] >> 29);
  12656. #endif /* !WOLFSSL_SP_LARGE_CODE */
  12657. }
  12658. /* Shift the result in the high 4096 bits down to the bottom.
  12659. *
  12660. * r A single precision number.
  12661. * a A single precision number.
  12662. */
  12663. static void sp_4096_mont_shift_142(sp_digit* r, const sp_digit* a)
  12664. {
  12665. int i;
  12666. sp_int64 n = a[141] >> 7;
  12667. n += ((sp_int64)a[142]) << 22;
  12668. for (i = 0; i < 141; i++) {
  12669. r[i] = n & 0x1fffffff;
  12670. n >>= 29;
  12671. n += ((sp_int64)a[143 + i]) << 22;
  12672. }
  12673. r[141] = (sp_digit)n;
  12674. XMEMSET(&r[142], 0, sizeof(*r) * 142U);
  12675. }
  12676. /* Reduce the number back to 4096 bits using Montgomery reduction.
  12677. *
  12678. * a A single precision number to reduce in place.
  12679. * m The single precision number representing the modulus.
  12680. * mp The digit representing the negative inverse of m mod 2^n.
  12681. */
  12682. static void sp_4096_mont_reduce_142(sp_digit* a, const sp_digit* m, sp_digit mp)
  12683. {
  12684. int i;
  12685. sp_digit mu;
  12686. sp_digit over;
  12687. sp_4096_norm_142(a + 142);
  12688. #ifdef WOLFSSL_SP_DH
  12689. if (mp != 1) {
  12690. for (i=0; i<141; i++) {
  12691. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff;
  12692. sp_4096_mul_add_142(a+i, m, mu);
  12693. a[i+1] += a[i] >> 29;
  12694. }
  12695. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x7fL;
  12696. sp_4096_mul_add_142(a+i, m, mu);
  12697. a[i+1] += a[i] >> 29;
  12698. a[i] &= 0x1fffffff;
  12699. }
  12700. else {
  12701. for (i=0; i<141; i++) {
  12702. mu = a[i] & 0x1fffffff;
  12703. sp_4096_mul_add_142(a+i, m, mu);
  12704. a[i+1] += a[i] >> 29;
  12705. }
  12706. mu = a[i] & 0x7fL;
  12707. sp_4096_mul_add_142(a+i, m, mu);
  12708. a[i+1] += a[i] >> 29;
  12709. a[i] &= 0x1fffffff;
  12710. }
  12711. #else
  12712. for (i=0; i<141; i++) {
  12713. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff;
  12714. sp_4096_mul_add_142(a+i, m, mu);
  12715. a[i+1] += a[i] >> 29;
  12716. }
  12717. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x7fL;
  12718. sp_4096_mul_add_142(a+i, m, mu);
  12719. a[i+1] += a[i] >> 29;
  12720. a[i] &= 0x1fffffff;
  12721. #endif
  12722. sp_4096_mont_shift_142(a, a);
  12723. over = a[141] - m[141];
  12724. sp_4096_cond_sub_142(a, a, m, ~((over - 1) >> 31));
  12725. sp_4096_norm_142(a);
  12726. }
  12727. /* Multiply two Montgomery form numbers mod the modulus (prime).
  12728. * (r = a * b mod m)
  12729. *
  12730. * r Result of multiplication.
  12731. * a First number to multiply in Montgomery form.
  12732. * b Second number to multiply in Montgomery form.
  12733. * m Modulus (prime).
  12734. * mp Montgomery mulitplier.
  12735. */
  12736. SP_NOINLINE static void sp_4096_mont_mul_142(sp_digit* r, const sp_digit* a,
  12737. const sp_digit* b, const sp_digit* m, sp_digit mp)
  12738. {
  12739. sp_4096_mul_142(r, a, b);
  12740. sp_4096_mont_reduce_142(r, m, mp);
  12741. }
  12742. /* Square the Montgomery form number. (r = a * a mod m)
  12743. *
  12744. * r Result of squaring.
  12745. * a Number to square in Montgomery form.
  12746. * m Modulus (prime).
  12747. * mp Montgomery mulitplier.
  12748. */
  12749. SP_NOINLINE static void sp_4096_mont_sqr_142(sp_digit* r, const sp_digit* a,
  12750. const sp_digit* m, sp_digit mp)
  12751. {
  12752. sp_4096_sqr_142(r, a);
  12753. sp_4096_mont_reduce_142(r, m, mp);
  12754. }
  12755. /* Multiply a by scalar b into r. (r = a * b)
  12756. *
  12757. * r A single precision integer.
  12758. * a A single precision integer.
  12759. * b A scalar.
  12760. */
  12761. SP_NOINLINE static void sp_4096_mul_d_284(sp_digit* r, const sp_digit* a,
  12762. sp_digit b)
  12763. {
  12764. sp_int64 tb = b;
  12765. sp_int64 t = 0;
  12766. int i;
  12767. for (i = 0; i < 284; i++) {
  12768. t += tb * a[i];
  12769. r[i] = (sp_digit)(t & 0x1fffffff);
  12770. t >>= 29;
  12771. }
  12772. r[284] = (sp_digit)t;
  12773. }
  12774. #ifdef WOLFSSL_SP_SMALL
  12775. /* Conditionally add a and b using the mask m.
  12776. * m is -1 to add and 0 when not.
  12777. *
  12778. * r A single precision number representing conditional add result.
  12779. * a A single precision number to add with.
  12780. * b A single precision number to add.
  12781. * m Mask value to apply.
  12782. */
  12783. static void sp_4096_cond_add_142(sp_digit* r, const sp_digit* a,
  12784. const sp_digit* b, const sp_digit m)
  12785. {
  12786. int i;
  12787. for (i = 0; i < 142; i++) {
  12788. r[i] = a[i] + (b[i] & m);
  12789. }
  12790. }
  12791. #endif /* WOLFSSL_SP_SMALL */
  12792. /* Add b to a into r. (r = a + b)
  12793. *
  12794. * r A single precision integer.
  12795. * a A single precision integer.
  12796. * b A single precision integer.
  12797. */
  12798. SP_NOINLINE static int sp_4096_add_142(sp_digit* r, const sp_digit* a,
  12799. const sp_digit* b)
  12800. {
  12801. int i;
  12802. for (i = 0; i < 142; i++) {
  12803. r[i] = a[i] + b[i];
  12804. }
  12805. return 0;
  12806. }
  12807. SP_NOINLINE static void sp_4096_rshift_142(sp_digit* r, const sp_digit* a,
  12808. byte n)
  12809. {
  12810. int i;
  12811. for (i=0; i<141; i++) {
  12812. r[i] = ((a[i] >> n) | (a[i + 1] << (29 - n))) & 0x1fffffff;
  12813. }
  12814. r[141] = a[141] >> n;
  12815. }
  12816. static WC_INLINE sp_digit sp_4096_div_word_142(sp_digit d1, sp_digit d0,
  12817. sp_digit div)
  12818. {
  12819. #ifdef SP_USE_DIVTI3
  12820. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  12821. return d / div;
  12822. #elif defined(__x86_64__) || defined(__i386__)
  12823. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  12824. sp_uint32 lo = (sp_uint32)d;
  12825. sp_digit hi = (sp_digit)(d >> 32);
  12826. __asm__ __volatile__ (
  12827. "idiv %2"
  12828. : "+a" (lo)
  12829. : "d" (hi), "r" (div)
  12830. : "cc"
  12831. );
  12832. return (sp_digit)lo;
  12833. #elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV)
  12834. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  12835. sp_digit dv = (div >> 1) + 1;
  12836. sp_digit t1 = (sp_digit)(d >> 29);
  12837. sp_digit t0 = (sp_digit)(d & 0x1fffffff);
  12838. sp_digit t2;
  12839. sp_digit sign;
  12840. sp_digit r;
  12841. int i;
  12842. sp_int64 m;
  12843. r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
  12844. t1 -= dv & (0 - r);
  12845. for (i = 27; i >= 1; i--) {
  12846. t1 += t1 + (((sp_uint32)t0 >> 28) & 1);
  12847. t0 <<= 1;
  12848. t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
  12849. r += r + t2;
  12850. t1 -= dv & (0 - t2);
  12851. t1 += t2;
  12852. }
  12853. r += r + 1;
  12854. m = d - ((sp_int64)r * div);
  12855. r += (sp_digit)(m >> 29);
  12856. m = d - ((sp_int64)r * div);
  12857. r += (sp_digit)(m >> 58) - (sp_digit)(d >> 58);
  12858. m = d - ((sp_int64)r * div);
  12859. sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
  12860. m *= sign;
  12861. t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
  12862. r += sign * t2;
  12863. m = d - ((sp_int64)r * div);
  12864. sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
  12865. m *= sign;
  12866. t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
  12867. r += sign * t2;
  12868. return r;
  12869. #else
  12870. sp_int64 d = ((sp_int64)d1 << 29) + d0;
  12871. sp_digit r = 0;
  12872. sp_digit t;
  12873. sp_digit dv = (div >> 14) + 1;
  12874. t = (sp_digit)(d >> 28);
  12875. t = (t / dv) << 14;
  12876. r += t;
  12877. d -= (sp_int64)t * div;
  12878. t = (sp_digit)(d >> 13);
  12879. t = t / (dv << 1);
  12880. r += t;
  12881. d -= (sp_int64)t * div;
  12882. t = (sp_digit)d;
  12883. t = t / div;
  12884. r += t;
  12885. d -= (sp_int64)t * div;
  12886. return r;
  12887. #endif
  12888. }
  12889. static WC_INLINE sp_digit sp_4096_word_div_word_142(sp_digit d, sp_digit div)
  12890. {
  12891. #if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
  12892. defined(SP_DIV_WORD_USE_DIV)
  12893. return d / div;
  12894. #else
  12895. return (sp_digit)((sp_uint32)(div - d) >> 31);
  12896. #endif
  12897. }
  12898. /* Divide d in a and put remainder into r (m*d + r = a)
  12899. * m is not calculated as it is not needed at this time.
  12900. *
  12901. * Full implementation.
  12902. *
  12903. * a Number to be divided.
  12904. * d Number to divide with.
  12905. * m Multiplier result.
  12906. * r Remainder from the division.
  12907. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  12908. */
  12909. static int sp_4096_div_142(const sp_digit* a, const sp_digit* d,
  12910. const sp_digit* m, sp_digit* r)
  12911. {
  12912. int i;
  12913. #ifndef WOLFSSL_SP_DIV_32
  12914. #endif
  12915. sp_digit dv;
  12916. sp_digit r1;
  12917. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  12918. sp_digit* t1 = NULL;
  12919. #else
  12920. sp_digit t1[4 * 142 + 3];
  12921. #endif
  12922. sp_digit* t2 = NULL;
  12923. sp_digit* sd = NULL;
  12924. int err = MP_OKAY;
  12925. (void)m;
  12926. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  12927. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 142 + 3), NULL,
  12928. DYNAMIC_TYPE_TMP_BUFFER);
  12929. if (t1 == NULL)
  12930. err = MEMORY_E;
  12931. #endif
  12932. (void)m;
  12933. if (err == MP_OKAY) {
  12934. t2 = t1 + 284 + 1;
  12935. sd = t2 + 142 + 1;
  12936. sp_4096_mul_d_142(sd, d, (sp_digit)1 << 22);
  12937. sp_4096_mul_d_284(t1, a, (sp_digit)1 << 22);
  12938. dv = sd[141];
  12939. t1[142 + 142] += t1[142 + 142 - 1] >> 29;
  12940. t1[142 + 142 - 1] &= 0x1fffffff;
  12941. for (i=142; i>=0; i--) {
  12942. r1 = sp_4096_div_word_142(t1[142 + i], t1[142 + i - 1], dv);
  12943. sp_4096_mul_d_142(t2, sd, r1);
  12944. (void)sp_4096_sub_142(&t1[i], &t1[i], t2);
  12945. sp_4096_norm_142(&t1[i]);
  12946. t1[142 + i] -= t2[142];
  12947. t1[142 + i] += t1[142 + i - 1] >> 29;
  12948. t1[142 + i - 1] &= 0x1fffffff;
  12949. r1 = sp_4096_div_word_142(-t1[142 + i], -t1[142 + i - 1], dv);
  12950. r1 -= t1[142 + i];
  12951. sp_4096_mul_d_142(t2, sd, r1);
  12952. (void)sp_4096_add_142(&t1[i], &t1[i], t2);
  12953. t1[142 + i] += t1[142 + i - 1] >> 29;
  12954. t1[142 + i - 1] &= 0x1fffffff;
  12955. }
  12956. t1[142 - 1] += t1[142 - 2] >> 29;
  12957. t1[142 - 2] &= 0x1fffffff;
  12958. r1 = sp_4096_word_div_word_142(t1[142 - 1], dv);
  12959. sp_4096_mul_d_142(t2, sd, r1);
  12960. sp_4096_sub_142(t1, t1, t2);
  12961. XMEMCPY(r, t1, sizeof(*r) * 284U);
  12962. for (i=0; i<141; i++) {
  12963. r[i+1] += r[i] >> 29;
  12964. r[i] &= 0x1fffffff;
  12965. }
  12966. sp_4096_cond_add_142(r, r, sd, r[141] >> 31);
  12967. sp_4096_norm_142(r);
  12968. sp_4096_rshift_142(r, r, 22);
  12969. }
  12970. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  12971. if (t1 != NULL)
  12972. XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  12973. #endif
  12974. return err;
  12975. }
  12976. /* Reduce a modulo m into r. (r = a mod m)
  12977. *
  12978. * r A single precision number that is the reduced result.
  12979. * a A single precision number that is to be reduced.
  12980. * m A single precision number that is the modulus to reduce with.
  12981. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  12982. */
  12983. static int sp_4096_mod_142(sp_digit* r, const sp_digit* a, const sp_digit* m)
  12984. {
  12985. return sp_4096_div_142(a, m, NULL, r);
  12986. }
  12987. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  12988. /* Modular exponentiate a to the e mod m. (r = a^e mod m)
  12989. *
  12990. * r A single precision number that is the result of the operation.
  12991. * a A single precision number being exponentiated.
  12992. * e A single precision number that is the exponent.
  12993. * bits The number of bits in the exponent.
  12994. * m A single precision number that is the modulus.
  12995. * returns 0 on success.
  12996. * returns MEMORY_E on dynamic memory allocation failure.
  12997. * returns MP_VAL when base is even or exponent is 0.
  12998. */
  12999. static int sp_4096_mod_exp_142(sp_digit* r, const sp_digit* a, const sp_digit* e,
  13000. int bits, const sp_digit* m, int reduceA)
  13001. {
  13002. #if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP)
  13003. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13004. sp_digit* td = NULL;
  13005. #else
  13006. sp_digit td[3 * 284];
  13007. #endif
  13008. sp_digit* t[3] = {0, 0, 0};
  13009. sp_digit* norm = NULL;
  13010. sp_digit mp = 1;
  13011. sp_digit n;
  13012. int i;
  13013. int c;
  13014. byte y;
  13015. int err = MP_OKAY;
  13016. if (bits == 0) {
  13017. err = MP_VAL;
  13018. }
  13019. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13020. if (err == MP_OKAY) {
  13021. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 142 * 2, NULL,
  13022. DYNAMIC_TYPE_TMP_BUFFER);
  13023. if (td == NULL)
  13024. err = MEMORY_E;
  13025. }
  13026. #endif
  13027. if (err == MP_OKAY) {
  13028. norm = td;
  13029. for (i=0; i<3; i++) {
  13030. t[i] = td + (i * 142 * 2);
  13031. XMEMSET(t[i], 0, sizeof(sp_digit) * 142U * 2U);
  13032. }
  13033. sp_4096_mont_setup(m, &mp);
  13034. sp_4096_mont_norm_142(norm, m);
  13035. if (reduceA != 0) {
  13036. err = sp_4096_mod_142(t[1], a, m);
  13037. }
  13038. else {
  13039. XMEMCPY(t[1], a, sizeof(sp_digit) * 142U);
  13040. }
  13041. }
  13042. if (err == MP_OKAY) {
  13043. sp_4096_mul_142(t[1], t[1], norm);
  13044. err = sp_4096_mod_142(t[1], t[1], m);
  13045. }
  13046. if (err == MP_OKAY) {
  13047. i = bits / 29;
  13048. c = bits % 29;
  13049. n = e[i--] << (29 - c);
  13050. for (; ; c--) {
  13051. if (c == 0) {
  13052. if (i == -1) {
  13053. break;
  13054. }
  13055. n = e[i--];
  13056. c = 29;
  13057. }
  13058. y = (int)((n >> 28) & 1);
  13059. n <<= 1;
  13060. sp_4096_mont_mul_142(t[y^1], t[0], t[1], m, mp);
  13061. XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
  13062. ((size_t)t[1] & addr_mask[y])),
  13063. sizeof(*t[2]) * 142 * 2);
  13064. sp_4096_mont_sqr_142(t[2], t[2], m, mp);
  13065. XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
  13066. ((size_t)t[1] & addr_mask[y])), t[2],
  13067. sizeof(*t[2]) * 142 * 2);
  13068. }
  13069. sp_4096_mont_reduce_142(t[0], m, mp);
  13070. n = sp_4096_cmp_142(t[0], m);
  13071. sp_4096_cond_sub_142(t[0], t[0], m, ~(n >> 31));
  13072. XMEMCPY(r, t[0], sizeof(*r) * 142 * 2);
  13073. }
  13074. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13075. if (td != NULL)
  13076. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  13077. #endif
  13078. return err;
  13079. #elif !defined(WC_NO_CACHE_RESISTANT)
  13080. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13081. sp_digit* td = NULL;
  13082. #else
  13083. sp_digit td[3 * 284];
  13084. #endif
  13085. sp_digit* t[3] = {0, 0, 0};
  13086. sp_digit* norm = NULL;
  13087. sp_digit mp = 1;
  13088. sp_digit n;
  13089. int i;
  13090. int c;
  13091. byte y;
  13092. int err = MP_OKAY;
  13093. if (bits == 0) {
  13094. err = MP_VAL;
  13095. }
  13096. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13097. if (err == MP_OKAY) {
  13098. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 142 * 2, NULL,
  13099. DYNAMIC_TYPE_TMP_BUFFER);
  13100. if (td == NULL)
  13101. err = MEMORY_E;
  13102. }
  13103. #endif
  13104. if (err == MP_OKAY) {
  13105. norm = td;
  13106. for (i=0; i<3; i++) {
  13107. t[i] = td + (i * 142 * 2);
  13108. }
  13109. sp_4096_mont_setup(m, &mp);
  13110. sp_4096_mont_norm_142(norm, m);
  13111. if (reduceA != 0) {
  13112. err = sp_4096_mod_142(t[1], a, m);
  13113. if (err == MP_OKAY) {
  13114. sp_4096_mul_142(t[1], t[1], norm);
  13115. err = sp_4096_mod_142(t[1], t[1], m);
  13116. }
  13117. }
  13118. else {
  13119. sp_4096_mul_142(t[1], a, norm);
  13120. err = sp_4096_mod_142(t[1], t[1], m);
  13121. }
  13122. }
  13123. if (err == MP_OKAY) {
  13124. i = bits / 29;
  13125. c = bits % 29;
  13126. n = e[i--] << (29 - c);
  13127. for (; ; c--) {
  13128. if (c == 0) {
  13129. if (i == -1) {
  13130. break;
  13131. }
  13132. n = e[i--];
  13133. c = 29;
  13134. }
  13135. y = (int)((n >> 28) & 1);
  13136. n <<= 1;
  13137. sp_4096_mont_mul_142(t[y^1], t[0], t[1], m, mp);
  13138. XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
  13139. ((size_t)t[1] & addr_mask[y])),
  13140. sizeof(*t[2]) * 142 * 2);
  13141. sp_4096_mont_sqr_142(t[2], t[2], m, mp);
  13142. XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
  13143. ((size_t)t[1] & addr_mask[y])), t[2],
  13144. sizeof(*t[2]) * 142 * 2);
  13145. }
  13146. sp_4096_mont_reduce_142(t[0], m, mp);
  13147. n = sp_4096_cmp_142(t[0], m);
  13148. sp_4096_cond_sub_142(t[0], t[0], m, ~(n >> 31));
  13149. XMEMCPY(r, t[0], sizeof(*r) * 142 * 2);
  13150. }
  13151. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13152. if (td != NULL)
  13153. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  13154. #endif
  13155. return err;
  13156. #else
  13157. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13158. sp_digit* td = NULL;
  13159. #else
  13160. sp_digit td[(16 * 284) + 284];
  13161. #endif
  13162. sp_digit* t[16];
  13163. sp_digit* rt = NULL;
  13164. sp_digit* norm = NULL;
  13165. sp_digit mp = 1;
  13166. sp_digit n;
  13167. int i;
  13168. int c;
  13169. byte y;
  13170. int err = MP_OKAY;
  13171. if (bits == 0) {
  13172. err = MP_VAL;
  13173. }
  13174. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13175. if (err == MP_OKAY) {
  13176. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((16 * 284) + 284), NULL,
  13177. DYNAMIC_TYPE_TMP_BUFFER);
  13178. if (td == NULL)
  13179. err = MEMORY_E;
  13180. }
  13181. #endif
  13182. if (err == MP_OKAY) {
  13183. norm = td;
  13184. for (i=0; i<16; i++)
  13185. t[i] = td + i * 284;
  13186. rt = td + 4544;
  13187. sp_4096_mont_setup(m, &mp);
  13188. sp_4096_mont_norm_142(norm, m);
  13189. if (reduceA != 0) {
  13190. err = sp_4096_mod_142(t[1], a, m);
  13191. if (err == MP_OKAY) {
  13192. sp_4096_mul_142(t[1], t[1], norm);
  13193. err = sp_4096_mod_142(t[1], t[1], m);
  13194. }
  13195. }
  13196. else {
  13197. sp_4096_mul_142(t[1], a, norm);
  13198. err = sp_4096_mod_142(t[1], t[1], m);
  13199. }
  13200. }
  13201. if (err == MP_OKAY) {
  13202. sp_4096_mont_sqr_142(t[ 2], t[ 1], m, mp);
  13203. sp_4096_mont_mul_142(t[ 3], t[ 2], t[ 1], m, mp);
  13204. sp_4096_mont_sqr_142(t[ 4], t[ 2], m, mp);
  13205. sp_4096_mont_mul_142(t[ 5], t[ 3], t[ 2], m, mp);
  13206. sp_4096_mont_sqr_142(t[ 6], t[ 3], m, mp);
  13207. sp_4096_mont_mul_142(t[ 7], t[ 4], t[ 3], m, mp);
  13208. sp_4096_mont_sqr_142(t[ 8], t[ 4], m, mp);
  13209. sp_4096_mont_mul_142(t[ 9], t[ 5], t[ 4], m, mp);
  13210. sp_4096_mont_sqr_142(t[10], t[ 5], m, mp);
  13211. sp_4096_mont_mul_142(t[11], t[ 6], t[ 5], m, mp);
  13212. sp_4096_mont_sqr_142(t[12], t[ 6], m, mp);
  13213. sp_4096_mont_mul_142(t[13], t[ 7], t[ 6], m, mp);
  13214. sp_4096_mont_sqr_142(t[14], t[ 7], m, mp);
  13215. sp_4096_mont_mul_142(t[15], t[ 8], t[ 7], m, mp);
  13216. bits = ((bits + 3) / 4) * 4;
  13217. i = ((bits + 28) / 29) - 1;
  13218. c = bits % 29;
  13219. if (c == 0) {
  13220. c = 29;
  13221. }
  13222. if (i < 142) {
  13223. n = e[i--] << (32 - c);
  13224. }
  13225. else {
  13226. n = 0;
  13227. i--;
  13228. }
  13229. if (c < 4) {
  13230. n |= e[i--] << (3 - c);
  13231. c += 29;
  13232. }
  13233. y = (int)((n >> 28) & 0xf);
  13234. n <<= 4;
  13235. c -= 4;
  13236. XMEMCPY(rt, t[y], sizeof(sp_digit) * 284);
  13237. while ((i >= 0) || (c >= 4)) {
  13238. if (c >= 4) {
  13239. y = (byte)((n >> 28) & 0xf);
  13240. n <<= 4;
  13241. c -= 4;
  13242. }
  13243. else if (c == 0) {
  13244. n = e[i--] << 3;
  13245. y = (byte)((n >> 28) & 0xf);
  13246. n <<= 4;
  13247. c = 25;
  13248. }
  13249. else {
  13250. y = (byte)((n >> 28) & 0xf);
  13251. n = e[i--] << 3;
  13252. c = 4 - c;
  13253. y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
  13254. n <<= c;
  13255. c = 29 - c;
  13256. }
  13257. sp_4096_mont_sqr_142(rt, rt, m, mp);
  13258. sp_4096_mont_sqr_142(rt, rt, m, mp);
  13259. sp_4096_mont_sqr_142(rt, rt, m, mp);
  13260. sp_4096_mont_sqr_142(rt, rt, m, mp);
  13261. sp_4096_mont_mul_142(rt, rt, t[y], m, mp);
  13262. }
  13263. sp_4096_mont_reduce_142(rt, m, mp);
  13264. n = sp_4096_cmp_142(rt, m);
  13265. sp_4096_cond_sub_142(rt, rt, m, ~(n >> 31));
  13266. XMEMCPY(r, rt, sizeof(sp_digit) * 284);
  13267. }
  13268. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13269. if (td != NULL)
  13270. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  13271. #endif
  13272. return err;
  13273. #endif
  13274. }
  13275. #endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
  13276. #ifdef WOLFSSL_HAVE_SP_RSA
  13277. /* RSA public key operation.
  13278. *
  13279. * in Array of bytes representing the number to exponentiate, base.
  13280. * inLen Number of bytes in base.
  13281. * em Public exponent.
  13282. * mm Modulus.
  13283. * out Buffer to hold big-endian bytes of exponentiation result.
  13284. * Must be at least 512 bytes long.
  13285. * outLen Number of bytes in result.
  13286. * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
  13287. * an array is too long and MEMORY_E when dynamic memory allocation fails.
  13288. */
  13289. int sp_RsaPublic_4096(const byte* in, word32 inLen, const mp_int* em,
  13290. const mp_int* mm, byte* out, word32* outLen)
  13291. {
  13292. #ifdef WOLFSSL_SP_SMALL
  13293. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13294. sp_digit* a = NULL;
  13295. #else
  13296. sp_digit a[142 * 5];
  13297. #endif
  13298. sp_digit* m = NULL;
  13299. sp_digit* r = NULL;
  13300. sp_digit* norm = NULL;
  13301. sp_digit e[1] = {0};
  13302. sp_digit mp = 0;
  13303. int i;
  13304. int err = MP_OKAY;
  13305. if (*outLen < 512U) {
  13306. err = MP_TO_E;
  13307. }
  13308. if (err == MP_OKAY) {
  13309. if (mp_count_bits(em) > 29) {
  13310. err = MP_READ_E;
  13311. }
  13312. else if (inLen > 512U) {
  13313. err = MP_READ_E;
  13314. }
  13315. else if (mp_count_bits(mm) != 4096) {
  13316. err = MP_READ_E;
  13317. }
  13318. else if (mp_iseven(mm)) {
  13319. err = MP_VAL;
  13320. }
  13321. }
  13322. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13323. if (err == MP_OKAY) {
  13324. a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 142 * 5, NULL,
  13325. DYNAMIC_TYPE_RSA);
  13326. if (a == NULL)
  13327. err = MEMORY_E;
  13328. }
  13329. #endif
  13330. if (err == MP_OKAY) {
  13331. r = a + 142 * 2;
  13332. m = r + 142 * 2;
  13333. norm = r;
  13334. sp_4096_from_bin(a, 142, in, inLen);
  13335. #if DIGIT_BIT >= 29
  13336. e[0] = (sp_digit)em->dp[0];
  13337. #else
  13338. e[0] = (sp_digit)em->dp[0];
  13339. if (em->used > 1) {
  13340. e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
  13341. }
  13342. #endif
  13343. if (e[0] == 0) {
  13344. err = MP_EXPTMOD_E;
  13345. }
  13346. }
  13347. if (err == MP_OKAY) {
  13348. sp_4096_from_mp(m, 142, mm);
  13349. sp_4096_mont_setup(m, &mp);
  13350. sp_4096_mont_norm_142(norm, m);
  13351. }
  13352. if (err == MP_OKAY) {
  13353. sp_4096_mul_142(a, a, norm);
  13354. err = sp_4096_mod_142(a, a, m);
  13355. }
  13356. if (err == MP_OKAY) {
  13357. for (i=28; i>=0; i--) {
  13358. if ((e[0] >> i) != 0) {
  13359. break;
  13360. }
  13361. }
  13362. XMEMCPY(r, a, sizeof(sp_digit) * 142 * 2);
  13363. for (i--; i>=0; i--) {
  13364. sp_4096_mont_sqr_142(r, r, m, mp);
  13365. if (((e[0] >> i) & 1) == 1) {
  13366. sp_4096_mont_mul_142(r, r, a, m, mp);
  13367. }
  13368. }
  13369. sp_4096_mont_reduce_142(r, m, mp);
  13370. mp = sp_4096_cmp_142(r, m);
  13371. sp_4096_cond_sub_142(r, r, m, ~(mp >> 31));
  13372. sp_4096_to_bin_142(r, out);
  13373. *outLen = 512;
  13374. }
  13375. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13376. if (a != NULL)
  13377. XFREE(a, NULL, DYNAMIC_TYPE_RSA);
  13378. #endif
  13379. return err;
  13380. #else
  13381. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13382. sp_digit* d = NULL;
  13383. #else
  13384. sp_digit d[142 * 5];
  13385. #endif
  13386. sp_digit* a = NULL;
  13387. sp_digit* m = NULL;
  13388. sp_digit* r = NULL;
  13389. sp_digit e[1] = {0};
  13390. int err = MP_OKAY;
  13391. if (*outLen < 512U) {
  13392. err = MP_TO_E;
  13393. }
  13394. if (err == MP_OKAY) {
  13395. if (mp_count_bits(em) > 29) {
  13396. err = MP_READ_E;
  13397. }
  13398. else if (inLen > 512U) {
  13399. err = MP_READ_E;
  13400. }
  13401. else if (mp_count_bits(mm) != 4096) {
  13402. err = MP_READ_E;
  13403. }
  13404. else if (mp_iseven(mm)) {
  13405. err = MP_VAL;
  13406. }
  13407. }
  13408. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13409. if (err == MP_OKAY) {
  13410. d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 142 * 5, NULL,
  13411. DYNAMIC_TYPE_RSA);
  13412. if (d == NULL)
  13413. err = MEMORY_E;
  13414. }
  13415. #endif
  13416. if (err == MP_OKAY) {
  13417. a = d;
  13418. r = a + 142 * 2;
  13419. m = r + 142 * 2;
  13420. sp_4096_from_bin(a, 142, in, inLen);
  13421. #if DIGIT_BIT >= 29
  13422. e[0] = (sp_digit)em->dp[0];
  13423. #else
  13424. e[0] = (sp_digit)em->dp[0];
  13425. if (em->used > 1) {
  13426. e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
  13427. }
  13428. #endif
  13429. if (e[0] == 0) {
  13430. err = MP_EXPTMOD_E;
  13431. }
  13432. }
  13433. if (err == MP_OKAY) {
  13434. sp_4096_from_mp(m, 142, mm);
  13435. if (e[0] == 0x3) {
  13436. sp_4096_sqr_142(r, a);
  13437. err = sp_4096_mod_142(r, r, m);
  13438. if (err == MP_OKAY) {
  13439. sp_4096_mul_142(r, a, r);
  13440. err = sp_4096_mod_142(r, r, m);
  13441. }
  13442. }
  13443. else {
  13444. sp_digit* norm = r;
  13445. int i;
  13446. sp_digit mp;
  13447. sp_4096_mont_setup(m, &mp);
  13448. sp_4096_mont_norm_142(norm, m);
  13449. sp_4096_mul_142(a, a, norm);
  13450. err = sp_4096_mod_142(a, a, m);
  13451. if (err == MP_OKAY) {
  13452. for (i=28; i>=0; i--) {
  13453. if ((e[0] >> i) != 0) {
  13454. break;
  13455. }
  13456. }
  13457. XMEMCPY(r, a, sizeof(sp_digit) * 284U);
  13458. for (i--; i>=0; i--) {
  13459. sp_4096_mont_sqr_142(r, r, m, mp);
  13460. if (((e[0] >> i) & 1) == 1) {
  13461. sp_4096_mont_mul_142(r, r, a, m, mp);
  13462. }
  13463. }
  13464. sp_4096_mont_reduce_142(r, m, mp);
  13465. mp = sp_4096_cmp_142(r, m);
  13466. sp_4096_cond_sub_142(r, r, m, ~(mp >> 31));
  13467. }
  13468. }
  13469. }
  13470. if (err == MP_OKAY) {
  13471. sp_4096_to_bin_142(r, out);
  13472. *outLen = 512;
  13473. }
  13474. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13475. if (d != NULL)
  13476. XFREE(d, NULL, DYNAMIC_TYPE_RSA);
  13477. #endif
  13478. return err;
  13479. #endif /* WOLFSSL_SP_SMALL */
  13480. }
  13481. #ifndef WOLFSSL_RSA_PUBLIC_ONLY
  13482. #if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM)
  13483. #endif /* !SP_RSA_PRIVATE_EXP_D & !RSA_LOW_MEM */
  13484. /* RSA private key operation.
  13485. *
  13486. * in Array of bytes representing the number to exponentiate, base.
  13487. * inLen Number of bytes in base.
  13488. * dm Private exponent.
  13489. * pm First prime.
  13490. * qm Second prime.
  13491. * dpm First prime's CRT exponent.
  13492. * dqm Second prime's CRT exponent.
  13493. * qim Inverse of second prime mod p.
  13494. * mm Modulus.
  13495. * out Buffer to hold big-endian bytes of exponentiation result.
  13496. * Must be at least 512 bytes long.
  13497. * outLen Number of bytes in result.
  13498. * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
  13499. * an array is too long and MEMORY_E when dynamic memory allocation fails.
  13500. */
  13501. int sp_RsaPrivate_4096(const byte* in, word32 inLen, const mp_int* dm,
  13502. const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
  13503. const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
  13504. {
  13505. #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
  13506. #if defined(WOLFSSL_SP_SMALL)
  13507. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13508. sp_digit* d = NULL;
  13509. #else
  13510. sp_digit d[142 * 4];
  13511. #endif
  13512. sp_digit* a = NULL;
  13513. sp_digit* m = NULL;
  13514. sp_digit* r = NULL;
  13515. int err = MP_OKAY;
  13516. (void)pm;
  13517. (void)qm;
  13518. (void)dpm;
  13519. (void)dqm;
  13520. (void)qim;
  13521. if (*outLen < 512U) {
  13522. err = MP_TO_E;
  13523. }
  13524. if (err == MP_OKAY) {
  13525. if (mp_count_bits(dm) > 4096) {
  13526. err = MP_READ_E;
  13527. }
  13528. else if (inLen > 512) {
  13529. err = MP_READ_E;
  13530. }
  13531. else if (mp_count_bits(mm) != 4096) {
  13532. err = MP_READ_E;
  13533. }
  13534. else if (mp_iseven(mm)) {
  13535. err = MP_VAL;
  13536. }
  13537. }
  13538. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13539. if (err == MP_OKAY) {
  13540. d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 142 * 4, NULL,
  13541. DYNAMIC_TYPE_RSA);
  13542. if (d == NULL)
  13543. err = MEMORY_E;
  13544. }
  13545. #endif
  13546. if (err == MP_OKAY) {
  13547. a = d + 142;
  13548. m = a + 284;
  13549. r = a;
  13550. sp_4096_from_bin(a, 142, in, inLen);
  13551. sp_4096_from_mp(d, 142, dm);
  13552. sp_4096_from_mp(m, 142, mm);
  13553. err = sp_4096_mod_exp_142(r, a, d, 4096, m, 0);
  13554. }
  13555. if (err == MP_OKAY) {
  13556. sp_4096_to_bin_142(r, out);
  13557. *outLen = 512;
  13558. }
  13559. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13560. if (d != NULL)
  13561. #endif
  13562. {
  13563. /* only "a" and "r" are sensitive and need zeroized (same pointer) */
  13564. if (a != NULL)
  13565. ForceZero(a, sizeof(sp_digit) * 142);
  13566. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13567. XFREE(d, NULL, DYNAMIC_TYPE_RSA);
  13568. #endif
  13569. }
  13570. return err;
  13571. #else
  13572. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13573. sp_digit* d = NULL;
  13574. #else
  13575. sp_digit d[142 * 4];
  13576. #endif
  13577. sp_digit* a = NULL;
  13578. sp_digit* m = NULL;
  13579. sp_digit* r = NULL;
  13580. int err = MP_OKAY;
  13581. (void)pm;
  13582. (void)qm;
  13583. (void)dpm;
  13584. (void)dqm;
  13585. (void)qim;
  13586. if (*outLen < 512U) {
  13587. err = MP_TO_E;
  13588. }
  13589. if (err == MP_OKAY) {
  13590. if (mp_count_bits(dm) > 4096) {
  13591. err = MP_READ_E;
  13592. }
  13593. else if (inLen > 512U) {
  13594. err = MP_READ_E;
  13595. }
  13596. else if (mp_count_bits(mm) != 4096) {
  13597. err = MP_READ_E;
  13598. }
  13599. else if (mp_iseven(mm)) {
  13600. err = MP_VAL;
  13601. }
  13602. }
  13603. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13604. if (err == MP_OKAY) {
  13605. d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 142 * 4, NULL,
  13606. DYNAMIC_TYPE_RSA);
  13607. if (d == NULL)
  13608. err = MEMORY_E;
  13609. }
  13610. #endif
  13611. if (err == MP_OKAY) {
  13612. a = d + 142;
  13613. m = a + 284;
  13614. r = a;
  13615. sp_4096_from_bin(a, 142, in, inLen);
  13616. sp_4096_from_mp(d, 142, dm);
  13617. sp_4096_from_mp(m, 142, mm);
  13618. err = sp_4096_mod_exp_142(r, a, d, 4096, m, 0);
  13619. }
  13620. if (err == MP_OKAY) {
  13621. sp_4096_to_bin_142(r, out);
  13622. *outLen = 512;
  13623. }
  13624. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13625. if (d != NULL)
  13626. #endif
  13627. {
  13628. /* only "a" and "r" are sensitive and need zeroized (same pointer) */
  13629. if (a != NULL)
  13630. ForceZero(a, sizeof(sp_digit) * 142);
  13631. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13632. XFREE(d, NULL, DYNAMIC_TYPE_RSA);
  13633. #endif
  13634. }
  13635. return err;
  13636. #endif /* WOLFSSL_SP_SMALL */
  13637. #else
  13638. #if defined(WOLFSSL_SP_SMALL)
  13639. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13640. sp_digit* a = NULL;
  13641. #else
  13642. sp_digit a[71 * 8];
  13643. #endif
  13644. sp_digit* p = NULL;
  13645. sp_digit* dp = NULL;
  13646. sp_digit* dq = NULL;
  13647. sp_digit* qi = NULL;
  13648. sp_digit* tmpa = NULL;
  13649. sp_digit* tmpb = NULL;
  13650. sp_digit* r = NULL;
  13651. int err = MP_OKAY;
  13652. (void)dm;
  13653. (void)mm;
  13654. if (*outLen < 512U) {
  13655. err = MP_TO_E;
  13656. }
  13657. if (err == MP_OKAY) {
  13658. if (inLen > 512) {
  13659. err = MP_READ_E;
  13660. }
  13661. else if (mp_count_bits(mm) != 4096) {
  13662. err = MP_READ_E;
  13663. }
  13664. else if (mp_iseven(mm)) {
  13665. err = MP_VAL;
  13666. }
  13667. else if (mp_iseven(pm)) {
  13668. err = MP_VAL;
  13669. }
  13670. else if (mp_iseven(qm)) {
  13671. err = MP_VAL;
  13672. }
  13673. }
  13674. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13675. if (err == MP_OKAY) {
  13676. a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 71 * 8, NULL,
  13677. DYNAMIC_TYPE_RSA);
  13678. if (a == NULL)
  13679. err = MEMORY_E;
  13680. }
  13681. #endif
  13682. if (err == MP_OKAY) {
  13683. p = a + 142;
  13684. qi = dq = dp = p + 71;
  13685. tmpa = qi + 71;
  13686. tmpb = tmpa + 142;
  13687. r = a;
  13688. sp_4096_from_bin(a, 142, in, inLen);
  13689. sp_4096_from_mp(p, 71, pm);
  13690. sp_4096_from_mp(dp, 71, dpm);
  13691. err = sp_4096_mod_exp_71(tmpa, a, dp, 2048, p, 1);
  13692. }
  13693. if (err == MP_OKAY) {
  13694. sp_4096_from_mp(p, 71, qm);
  13695. sp_4096_from_mp(dq, 71, dqm);
  13696. err = sp_4096_mod_exp_71(tmpb, a, dq, 2048, p, 1);
  13697. }
  13698. if (err == MP_OKAY) {
  13699. sp_4096_from_mp(p, 71, pm);
  13700. (void)sp_4096_sub_71(tmpa, tmpa, tmpb);
  13701. sp_4096_norm_71(tmpa);
  13702. sp_4096_cond_add_71(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[70] >> 31));
  13703. sp_4096_cond_add_71(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[70] >> 31));
  13704. sp_4096_norm_71(tmpa);
  13705. sp_4096_from_mp(qi, 71, qim);
  13706. sp_4096_mul_71(tmpa, tmpa, qi);
  13707. err = sp_4096_mod_71(tmpa, tmpa, p);
  13708. }
  13709. if (err == MP_OKAY) {
  13710. sp_4096_from_mp(p, 71, qm);
  13711. sp_4096_mul_71(tmpa, p, tmpa);
  13712. (void)sp_4096_add_142(r, tmpb, tmpa);
  13713. sp_4096_norm_142(r);
  13714. sp_4096_to_bin_142(r, out);
  13715. *outLen = 512;
  13716. }
  13717. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13718. if (a != NULL)
  13719. #endif
  13720. {
  13721. ForceZero(a, sizeof(sp_digit) * 71 * 8);
  13722. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13723. XFREE(a, NULL, DYNAMIC_TYPE_RSA);
  13724. #endif
  13725. }
  13726. return err;
  13727. #else
  13728. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13729. sp_digit* a = NULL;
  13730. #else
  13731. sp_digit a[71 * 13];
  13732. #endif
  13733. sp_digit* p = NULL;
  13734. sp_digit* q = NULL;
  13735. sp_digit* dp = NULL;
  13736. sp_digit* dq = NULL;
  13737. sp_digit* qi = NULL;
  13738. sp_digit* tmpa = NULL;
  13739. sp_digit* tmpb = NULL;
  13740. sp_digit* r = NULL;
  13741. int err = MP_OKAY;
  13742. (void)dm;
  13743. (void)mm;
  13744. if (*outLen < 512U) {
  13745. err = MP_TO_E;
  13746. }
  13747. if (err == MP_OKAY) {
  13748. if (inLen > 512U) {
  13749. err = MP_READ_E;
  13750. }
  13751. else if (mp_count_bits(mm) != 4096) {
  13752. err = MP_READ_E;
  13753. }
  13754. else if (mp_iseven(mm)) {
  13755. err = MP_VAL;
  13756. }
  13757. else if (mp_iseven(pm)) {
  13758. err = MP_VAL;
  13759. }
  13760. else if (mp_iseven(qm)) {
  13761. err = MP_VAL;
  13762. }
  13763. }
  13764. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13765. if (err == MP_OKAY) {
  13766. a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 71 * 13, NULL,
  13767. DYNAMIC_TYPE_RSA);
  13768. if (a == NULL)
  13769. err = MEMORY_E;
  13770. }
  13771. #endif
  13772. if (err == MP_OKAY) {
  13773. p = a + 142 * 2;
  13774. q = p + 71;
  13775. dp = q + 71;
  13776. dq = dp + 71;
  13777. qi = dq + 71;
  13778. tmpa = qi + 71;
  13779. tmpb = tmpa + 142;
  13780. r = a;
  13781. sp_4096_from_bin(a, 142, in, inLen);
  13782. sp_4096_from_mp(p, 71, pm);
  13783. sp_4096_from_mp(q, 71, qm);
  13784. sp_4096_from_mp(dp, 71, dpm);
  13785. sp_4096_from_mp(dq, 71, dqm);
  13786. sp_4096_from_mp(qi, 71, qim);
  13787. err = sp_4096_mod_exp_71(tmpa, a, dp, 2048, p, 1);
  13788. }
  13789. if (err == MP_OKAY) {
  13790. err = sp_4096_mod_exp_71(tmpb, a, dq, 2048, q, 1);
  13791. }
  13792. if (err == MP_OKAY) {
  13793. (void)sp_4096_sub_71(tmpa, tmpa, tmpb);
  13794. sp_4096_norm_71(tmpa);
  13795. sp_4096_cond_add_71(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[70] >> 31));
  13796. sp_4096_cond_add_71(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[70] >> 31));
  13797. sp_4096_norm_71(tmpa);
  13798. sp_4096_mul_71(tmpa, tmpa, qi);
  13799. err = sp_4096_mod_71(tmpa, tmpa, p);
  13800. }
  13801. if (err == MP_OKAY) {
  13802. sp_4096_mul_71(tmpa, tmpa, q);
  13803. (void)sp_4096_add_142(r, tmpb, tmpa);
  13804. sp_4096_norm_142(r);
  13805. sp_4096_to_bin_142(r, out);
  13806. *outLen = 512;
  13807. }
  13808. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13809. if (a != NULL)
  13810. #endif
  13811. {
  13812. ForceZero(a, sizeof(sp_digit) * 71 * 13);
  13813. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13814. XFREE(a, NULL, DYNAMIC_TYPE_RSA);
  13815. #endif
  13816. }
  13817. return err;
  13818. #endif /* WOLFSSL_SP_SMALL */
  13819. #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
  13820. }
  13821. #endif /* !WOLFSSL_RSA_PUBLIC_ONLY */
  13822. #endif /* WOLFSSL_HAVE_SP_RSA */
  13823. #if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \
  13824. !defined(WOLFSSL_RSA_PUBLIC_ONLY))
  13825. /* Convert an array of sp_digit to an mp_int.
  13826. *
  13827. * a A single precision integer.
  13828. * r A multi-precision integer.
  13829. */
  13830. static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
  13831. {
  13832. int err;
  13833. err = mp_grow(r, (4096 + DIGIT_BIT - 1) / DIGIT_BIT);
  13834. if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
  13835. #if DIGIT_BIT == 29
  13836. XMEMCPY(r->dp, a, sizeof(sp_digit) * 142);
  13837. r->used = 142;
  13838. mp_clamp(r);
  13839. #elif DIGIT_BIT < 29
  13840. int i;
  13841. int j = 0;
  13842. int s = 0;
  13843. r->dp[0] = 0;
  13844. for (i = 0; i < 142; i++) {
  13845. r->dp[j] |= (mp_digit)(a[i] << s);
  13846. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  13847. s = DIGIT_BIT - s;
  13848. r->dp[++j] = (mp_digit)(a[i] >> s);
  13849. while (s + DIGIT_BIT <= 29) {
  13850. s += DIGIT_BIT;
  13851. r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  13852. if (s == SP_WORD_SIZE) {
  13853. r->dp[j] = 0;
  13854. }
  13855. else {
  13856. r->dp[j] = (mp_digit)(a[i] >> s);
  13857. }
  13858. }
  13859. s = 29 - s;
  13860. }
  13861. r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT;
  13862. mp_clamp(r);
  13863. #else
  13864. int i;
  13865. int j = 0;
  13866. int s = 0;
  13867. r->dp[0] = 0;
  13868. for (i = 0; i < 142; i++) {
  13869. r->dp[j] |= ((mp_digit)a[i]) << s;
  13870. if (s + 29 >= DIGIT_BIT) {
  13871. #if DIGIT_BIT != 32 && DIGIT_BIT != 64
  13872. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  13873. #endif
  13874. s = DIGIT_BIT - s;
  13875. r->dp[++j] = a[i] >> s;
  13876. s = 29 - s;
  13877. }
  13878. else {
  13879. s += 29;
  13880. }
  13881. }
  13882. r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT;
  13883. mp_clamp(r);
  13884. #endif
  13885. }
  13886. return err;
  13887. }
  13888. /* Perform the modular exponentiation for Diffie-Hellman.
  13889. *
  13890. * base Base. MP integer.
  13891. * exp Exponent. MP integer.
  13892. * mod Modulus. MP integer.
  13893. * res Result. MP integer.
  13894. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  13895. * and MEMORY_E if memory allocation fails.
  13896. */
  13897. int sp_ModExp_4096(const mp_int* base, const mp_int* exp, const mp_int* mod,
  13898. mp_int* res)
  13899. {
  13900. #ifdef WOLFSSL_SP_SMALL
  13901. int err = MP_OKAY;
  13902. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13903. sp_digit* b = NULL;
  13904. #else
  13905. sp_digit b[142 * 4];
  13906. #endif
  13907. sp_digit* e = NULL;
  13908. sp_digit* m = NULL;
  13909. sp_digit* r = NULL;
  13910. int expBits = mp_count_bits(exp);
  13911. if (mp_count_bits(base) > 4096) {
  13912. err = MP_READ_E;
  13913. }
  13914. else if (expBits > 4096) {
  13915. err = MP_READ_E;
  13916. }
  13917. else if (mp_count_bits(mod) != 4096) {
  13918. err = MP_READ_E;
  13919. }
  13920. else if (mp_iseven(mod)) {
  13921. err = MP_VAL;
  13922. }
  13923. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13924. if (err == MP_OKAY) {
  13925. b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 142 * 4, NULL,
  13926. DYNAMIC_TYPE_DH);
  13927. if (b == NULL)
  13928. err = MEMORY_E;
  13929. }
  13930. #endif
  13931. if (err == MP_OKAY) {
  13932. e = b + 142 * 2;
  13933. m = e + 142;
  13934. r = b;
  13935. sp_4096_from_mp(b, 142, base);
  13936. sp_4096_from_mp(e, 142, exp);
  13937. sp_4096_from_mp(m, 142, mod);
  13938. err = sp_4096_mod_exp_142(r, b, e, mp_count_bits(exp), m, 0);
  13939. }
  13940. if (err == MP_OKAY) {
  13941. err = sp_4096_to_mp(r, res);
  13942. }
  13943. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13944. if (b != NULL)
  13945. #endif
  13946. {
  13947. /* only "e" is sensitive and needs zeroized */
  13948. if (e != NULL)
  13949. ForceZero(e, sizeof(sp_digit) * 142U);
  13950. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13951. XFREE(b, NULL, DYNAMIC_TYPE_DH);
  13952. #endif
  13953. }
  13954. return err;
  13955. #else
  13956. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13957. sp_digit* b = NULL;
  13958. #else
  13959. sp_digit b[142 * 4];
  13960. #endif
  13961. sp_digit* e = NULL;
  13962. sp_digit* m = NULL;
  13963. sp_digit* r = NULL;
  13964. int err = MP_OKAY;
  13965. int expBits = mp_count_bits(exp);
  13966. if (mp_count_bits(base) > 4096) {
  13967. err = MP_READ_E;
  13968. }
  13969. else if (expBits > 4096) {
  13970. err = MP_READ_E;
  13971. }
  13972. else if (mp_count_bits(mod) != 4096) {
  13973. err = MP_READ_E;
  13974. }
  13975. else if (mp_iseven(mod)) {
  13976. err = MP_VAL;
  13977. }
  13978. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13979. if (err == MP_OKAY) {
  13980. b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 142 * 4, NULL, DYNAMIC_TYPE_DH);
  13981. if (b == NULL)
  13982. err = MEMORY_E;
  13983. }
  13984. #endif
  13985. if (err == MP_OKAY) {
  13986. e = b + 142 * 2;
  13987. m = e + 142;
  13988. r = b;
  13989. sp_4096_from_mp(b, 142, base);
  13990. sp_4096_from_mp(e, 142, exp);
  13991. sp_4096_from_mp(m, 142, mod);
  13992. err = sp_4096_mod_exp_142(r, b, e, expBits, m, 0);
  13993. }
  13994. if (err == MP_OKAY) {
  13995. err = sp_4096_to_mp(r, res);
  13996. }
  13997. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  13998. if (b != NULL)
  13999. #endif
  14000. {
  14001. /* only "e" is sensitive and needs zeroized */
  14002. if (e != NULL)
  14003. ForceZero(e, sizeof(sp_digit) * 142U);
  14004. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  14005. XFREE(b, NULL, DYNAMIC_TYPE_DH);
  14006. #endif
  14007. }
  14008. return err;
  14009. #endif
  14010. }
  14011. #ifdef WOLFSSL_HAVE_SP_DH
  14012. #ifdef HAVE_FFDHE_4096
  14013. SP_NOINLINE static void sp_4096_lshift_142(sp_digit* r, const sp_digit* a,
  14014. byte n)
  14015. {
  14016. int i;
  14017. r[142] = a[141] >> (29 - n);
  14018. for (i=141; i>0; i--) {
  14019. r[i] = ((a[i] << n) | (a[i-1] >> (29 - n))) & 0x1fffffff;
  14020. }
  14021. r[0] = (a[0] << n) & 0x1fffffff;
  14022. }
  14023. /* Modular exponentiate 2 to the e mod m. (r = 2^e mod m)
  14024. *
  14025. * r A single precision number that is the result of the operation.
  14026. * e A single precision number that is the exponent.
  14027. * bits The number of bits in the exponent.
  14028. * m A single precision number that is the modulus.
  14029. * returns 0 on success.
  14030. * returns MEMORY_E on dynamic memory allocation failure.
  14031. * returns MP_VAL when base is even.
  14032. */
  14033. static int sp_4096_mod_exp_2_142(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m)
  14034. {
  14035. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  14036. sp_digit* td = NULL;
  14037. #else
  14038. sp_digit td[427];
  14039. #endif
  14040. sp_digit* norm = NULL;
  14041. sp_digit* tmp = NULL;
  14042. sp_digit mp = 1;
  14043. sp_digit n;
  14044. sp_digit o;
  14045. int i;
  14046. int c;
  14047. byte y;
  14048. int err = MP_OKAY;
  14049. if (bits == 0) {
  14050. err = MP_VAL;
  14051. }
  14052. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  14053. if (err == MP_OKAY) {
  14054. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 427, NULL,
  14055. DYNAMIC_TYPE_TMP_BUFFER);
  14056. if (td == NULL)
  14057. err = MEMORY_E;
  14058. }
  14059. #endif
  14060. if (err == MP_OKAY) {
  14061. norm = td;
  14062. tmp = td + 284;
  14063. XMEMSET(td, 0, sizeof(sp_digit) * 427);
  14064. sp_4096_mont_setup(m, &mp);
  14065. sp_4096_mont_norm_142(norm, m);
  14066. bits = ((bits + 3) / 4) * 4;
  14067. i = ((bits + 28) / 29) - 1;
  14068. c = bits % 29;
  14069. if (c == 0) {
  14070. c = 29;
  14071. }
  14072. if (i < 142) {
  14073. n = e[i--] << (32 - c);
  14074. }
  14075. else {
  14076. n = 0;
  14077. i--;
  14078. }
  14079. if (c < 4) {
  14080. n |= e[i--] << (3 - c);
  14081. c += 29;
  14082. }
  14083. y = (int)((n >> 28) & 0xf);
  14084. n <<= 4;
  14085. c -= 4;
  14086. sp_4096_lshift_142(r, norm, (byte)y);
  14087. while ((i >= 0) || (c >= 4)) {
  14088. if (c >= 4) {
  14089. y = (byte)((n >> 28) & 0xf);
  14090. n <<= 4;
  14091. c -= 4;
  14092. }
  14093. else if (c == 0) {
  14094. n = e[i--] << 3;
  14095. y = (byte)((n >> 28) & 0xf);
  14096. n <<= 4;
  14097. c = 25;
  14098. }
  14099. else {
  14100. y = (byte)((n >> 28) & 0xf);
  14101. n = e[i--] << 3;
  14102. c = 4 - c;
  14103. y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
  14104. n <<= c;
  14105. c = 29 - c;
  14106. }
  14107. sp_4096_mont_sqr_142(r, r, m, mp);
  14108. sp_4096_mont_sqr_142(r, r, m, mp);
  14109. sp_4096_mont_sqr_142(r, r, m, mp);
  14110. sp_4096_mont_sqr_142(r, r, m, mp);
  14111. sp_4096_lshift_142(r, r, (byte)y);
  14112. sp_4096_mul_d_142(tmp, norm, (r[142] << 22) + (r[141] >> 7));
  14113. r[142] = 0;
  14114. r[141] &= 0x7fL;
  14115. (void)sp_4096_add_142(r, r, tmp);
  14116. sp_4096_norm_142(r);
  14117. o = sp_4096_cmp_142(r, m);
  14118. sp_4096_cond_sub_142(r, r, m, ~(o >> 31));
  14119. }
  14120. sp_4096_mont_reduce_142(r, m, mp);
  14121. n = sp_4096_cmp_142(r, m);
  14122. sp_4096_cond_sub_142(r, r, m, ~(n >> 31));
  14123. }
  14124. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  14125. if (td != NULL)
  14126. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  14127. #endif
  14128. return err;
  14129. }
  14130. #endif /* HAVE_FFDHE_4096 */
  14131. /* Perform the modular exponentiation for Diffie-Hellman.
  14132. *
  14133. * base Base.
  14134. * exp Array of bytes that is the exponent.
  14135. * expLen Length of data, in bytes, in exponent.
  14136. * mod Modulus.
  14137. * out Buffer to hold big-endian bytes of exponentiation result.
  14138. * Must be at least 512 bytes long.
  14139. * outLen Length, in bytes, of exponentiation result.
  14140. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  14141. * and MEMORY_E if memory allocation fails.
  14142. */
  14143. int sp_DhExp_4096(const mp_int* base, const byte* exp, word32 expLen,
  14144. const mp_int* mod, byte* out, word32* outLen)
  14145. {
  14146. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  14147. sp_digit* b = NULL;
  14148. #else
  14149. sp_digit b[142 * 4];
  14150. #endif
  14151. sp_digit* e = NULL;
  14152. sp_digit* m = NULL;
  14153. sp_digit* r = NULL;
  14154. word32 i;
  14155. int err = MP_OKAY;
  14156. if (mp_count_bits(base) > 4096) {
  14157. err = MP_READ_E;
  14158. }
  14159. else if (expLen > 512U) {
  14160. err = MP_READ_E;
  14161. }
  14162. else if (mp_count_bits(mod) != 4096) {
  14163. err = MP_READ_E;
  14164. }
  14165. else if (mp_iseven(mod)) {
  14166. err = MP_VAL;
  14167. }
  14168. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  14169. if (err == MP_OKAY) {
  14170. b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 142 * 4, NULL,
  14171. DYNAMIC_TYPE_DH);
  14172. if (b == NULL)
  14173. err = MEMORY_E;
  14174. }
  14175. #endif
  14176. if (err == MP_OKAY) {
  14177. e = b + 142 * 2;
  14178. m = e + 142;
  14179. r = b;
  14180. sp_4096_from_mp(b, 142, base);
  14181. sp_4096_from_bin(e, 142, exp, expLen);
  14182. sp_4096_from_mp(m, 142, mod);
  14183. #ifdef HAVE_FFDHE_4096
  14184. if (base->used == 1 && base->dp[0] == 2U &&
  14185. ((m[141] << 9) | (m[140] >> 20)) == 0xffffL) {
  14186. err = sp_4096_mod_exp_2_142(r, e, expLen * 8U, m);
  14187. }
  14188. else {
  14189. #endif
  14190. err = sp_4096_mod_exp_142(r, b, e, expLen * 8U, m, 0);
  14191. #ifdef HAVE_FFDHE_4096
  14192. }
  14193. #endif
  14194. }
  14195. if (err == MP_OKAY) {
  14196. sp_4096_to_bin_142(r, out);
  14197. *outLen = 512;
  14198. for (i=0; i<512U && out[i] == 0U; i++) {
  14199. /* Search for first non-zero. */
  14200. }
  14201. *outLen -= i;
  14202. XMEMMOVE(out, out + i, *outLen);
  14203. }
  14204. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  14205. if (b != NULL)
  14206. #endif
  14207. {
  14208. /* only "e" is sensitive and needs zeroized */
  14209. if (e != NULL)
  14210. ForceZero(e, sizeof(sp_digit) * 142U);
  14211. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  14212. XFREE(b, NULL, DYNAMIC_TYPE_DH);
  14213. #endif
  14214. }
  14215. return err;
  14216. }
  14217. #endif /* WOLFSSL_HAVE_SP_DH */
  14218. #endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
  14219. #else
  14220. /* Read big endian unsigned byte array into r.
  14221. *
  14222. * r A single precision integer.
  14223. * size Maximum number of bytes to convert
  14224. * a Byte array.
  14225. * n Number of bytes in array to read.
  14226. */
  14227. static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n)
  14228. {
  14229. int i;
  14230. int j = 0;
  14231. word32 s = 0;
  14232. r[0] = 0;
  14233. for (i = n-1; i >= 0; i--) {
  14234. r[j] |= (((sp_digit)a[i]) << s);
  14235. if (s >= 18U) {
  14236. r[j] &= 0x3ffffff;
  14237. s = 26U - s;
  14238. if (j + 1 >= size) {
  14239. break;
  14240. }
  14241. r[++j] = (sp_digit)a[i] >> s;
  14242. s = 8U - s;
  14243. }
  14244. else {
  14245. s += 8U;
  14246. }
  14247. }
  14248. for (j++; j < size; j++) {
  14249. r[j] = 0;
  14250. }
  14251. }
  14252. /* Convert an mp_int to an array of sp_digit.
  14253. *
  14254. * r A single precision integer.
  14255. * size Maximum number of bytes to convert
  14256. * a A multi-precision integer.
  14257. */
  14258. static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
  14259. {
  14260. #if DIGIT_BIT == 26
  14261. int j;
  14262. XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
  14263. for (j = a->used; j < size; j++) {
  14264. r[j] = 0;
  14265. }
  14266. #elif DIGIT_BIT > 26
  14267. int i;
  14268. int j = 0;
  14269. word32 s = 0;
  14270. r[0] = 0;
  14271. for (i = 0; i < a->used && j < size; i++) {
  14272. r[j] |= ((sp_digit)a->dp[i] << s);
  14273. r[j] &= 0x3ffffff;
  14274. s = 26U - s;
  14275. if (j + 1 >= size) {
  14276. break;
  14277. }
  14278. /* lint allow cast of mismatch word32 and mp_digit */
  14279. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  14280. while ((s + 26U) <= (word32)DIGIT_BIT) {
  14281. s += 26U;
  14282. r[j] &= 0x3ffffff;
  14283. if (j + 1 >= size) {
  14284. break;
  14285. }
  14286. if (s < (word32)DIGIT_BIT) {
  14287. /* lint allow cast of mismatch word32 and mp_digit */
  14288. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  14289. }
  14290. else {
  14291. r[++j] = (sp_digit)0;
  14292. }
  14293. }
  14294. s = (word32)DIGIT_BIT - s;
  14295. }
  14296. for (j++; j < size; j++) {
  14297. r[j] = 0;
  14298. }
  14299. #else
  14300. int i;
  14301. int j = 0;
  14302. int s = 0;
  14303. r[0] = 0;
  14304. for (i = 0; i < a->used && j < size; i++) {
  14305. r[j] |= ((sp_digit)a->dp[i]) << s;
  14306. if (s + DIGIT_BIT >= 26) {
  14307. r[j] &= 0x3ffffff;
  14308. if (j + 1 >= size) {
  14309. break;
  14310. }
  14311. s = 26 - s;
  14312. if (s == DIGIT_BIT) {
  14313. r[++j] = 0;
  14314. s = 0;
  14315. }
  14316. else {
  14317. r[++j] = a->dp[i] >> s;
  14318. s = DIGIT_BIT - s;
  14319. }
  14320. }
  14321. else {
  14322. s += DIGIT_BIT;
  14323. }
  14324. }
  14325. for (j++; j < size; j++) {
  14326. r[j] = 0;
  14327. }
  14328. #endif
  14329. }
  14330. /* Write r as big endian to byte array.
  14331. * Fixed length number of bytes written: 512
  14332. *
  14333. * r A single precision integer.
  14334. * a Byte array.
  14335. */
  14336. static void sp_4096_to_bin_162(sp_digit* r, byte* a)
  14337. {
  14338. int i;
  14339. int j;
  14340. int s = 0;
  14341. int b;
  14342. for (i=0; i<161; i++) {
  14343. r[i+1] += r[i] >> 26;
  14344. r[i] &= 0x3ffffff;
  14345. }
  14346. j = 4103 / 8 - 1;
  14347. a[j] = 0;
  14348. for (i=0; i<162 && j>=0; i++) {
  14349. b = 0;
  14350. /* lint allow cast of mismatch sp_digit and int */
  14351. a[j--] |= (byte)(r[i] << s); /*lint !e9033*/
  14352. b += 8 - s;
  14353. if (j < 0) {
  14354. break;
  14355. }
  14356. while (b < 26) {
  14357. a[j--] = (byte)(r[i] >> b);
  14358. b += 8;
  14359. if (j < 0) {
  14360. break;
  14361. }
  14362. }
  14363. s = 8 - (b - 26);
  14364. if (j >= 0) {
  14365. a[j] = 0;
  14366. }
  14367. if (s != 0) {
  14368. j++;
  14369. }
  14370. }
  14371. }
  14372. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  14373. #if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D)
  14374. /* Normalize the values in each word to 26 bits.
  14375. *
  14376. * a Array of sp_digit to normalize.
  14377. */
  14378. static void sp_4096_norm_81(sp_digit* a)
  14379. {
  14380. int i;
  14381. for (i = 0; i < 80; i += 8) {
  14382. a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff;
  14383. a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff;
  14384. a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff;
  14385. a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff;
  14386. a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff;
  14387. a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff;
  14388. a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff;
  14389. a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff;
  14390. }
  14391. }
  14392. #endif /* WOLFSSL_HAVE_SP_RSA & !SP_RSA_PRIVATE_EXP_D */
  14393. #endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
  14394. /* Normalize the values in each word to 26 bits.
  14395. *
  14396. * a Array of sp_digit to normalize.
  14397. */
  14398. static void sp_4096_norm_79(sp_digit* a)
  14399. {
  14400. int i;
  14401. for (i = 0; i < 72; i += 8) {
  14402. a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff;
  14403. a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff;
  14404. a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff;
  14405. a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff;
  14406. a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff;
  14407. a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff;
  14408. a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff;
  14409. a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff;
  14410. }
  14411. a[73] += a[72] >> 26; a[72] &= 0x3ffffff;
  14412. a[74] += a[73] >> 26; a[73] &= 0x3ffffff;
  14413. a[75] += a[74] >> 26; a[74] &= 0x3ffffff;
  14414. a[76] += a[75] >> 26; a[75] &= 0x3ffffff;
  14415. a[77] += a[76] >> 26; a[76] &= 0x3ffffff;
  14416. a[78] += a[77] >> 26; a[77] &= 0x3ffffff;
  14417. }
  14418. /* Normalize the values in each word to 26 bits.
  14419. *
  14420. * a Array of sp_digit to normalize.
  14421. */
  14422. static void sp_4096_norm_162(sp_digit* a)
  14423. {
  14424. int i;
  14425. for (i = 0; i < 160; i += 8) {
  14426. a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff;
  14427. a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff;
  14428. a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff;
  14429. a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff;
  14430. a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff;
  14431. a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff;
  14432. a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff;
  14433. a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff;
  14434. }
  14435. a[161] += a[160] >> 26; a[160] &= 0x3ffffff;
  14436. }
  14437. /* Normalize the values in each word to 26 bits.
  14438. *
  14439. * a Array of sp_digit to normalize.
  14440. */
  14441. static void sp_4096_norm_158(sp_digit* a)
  14442. {
  14443. int i;
  14444. for (i = 0; i < 152; i += 8) {
  14445. a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff;
  14446. a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff;
  14447. a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff;
  14448. a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff;
  14449. a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff;
  14450. a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff;
  14451. a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff;
  14452. a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff;
  14453. }
  14454. a[153] += a[152] >> 26; a[152] &= 0x3ffffff;
  14455. a[154] += a[153] >> 26; a[153] &= 0x3ffffff;
  14456. a[155] += a[154] >> 26; a[154] &= 0x3ffffff;
  14457. a[156] += a[155] >> 26; a[155] &= 0x3ffffff;
  14458. a[157] += a[156] >> 26; a[156] &= 0x3ffffff;
  14459. }
  14460. #ifndef WOLFSSL_SP_SMALL
  14461. /* Multiply a and b into r. (r = a * b)
  14462. *
  14463. * r A single precision integer.
  14464. * a A single precision integer.
  14465. * b A single precision integer.
  14466. */
  14467. SP_NOINLINE static void sp_4096_mul_9(sp_digit* r, const sp_digit* a,
  14468. const sp_digit* b)
  14469. {
  14470. sp_uint64 t0 = ((sp_uint64)a[ 0]) * b[ 0];
  14471. sp_uint64 t1 = ((sp_uint64)a[ 0]) * b[ 1]
  14472. + ((sp_uint64)a[ 1]) * b[ 0];
  14473. sp_uint64 t2 = ((sp_uint64)a[ 0]) * b[ 2]
  14474. + ((sp_uint64)a[ 1]) * b[ 1]
  14475. + ((sp_uint64)a[ 2]) * b[ 0];
  14476. sp_uint64 t3 = ((sp_uint64)a[ 0]) * b[ 3]
  14477. + ((sp_uint64)a[ 1]) * b[ 2]
  14478. + ((sp_uint64)a[ 2]) * b[ 1]
  14479. + ((sp_uint64)a[ 3]) * b[ 0];
  14480. sp_uint64 t4 = ((sp_uint64)a[ 0]) * b[ 4]
  14481. + ((sp_uint64)a[ 1]) * b[ 3]
  14482. + ((sp_uint64)a[ 2]) * b[ 2]
  14483. + ((sp_uint64)a[ 3]) * b[ 1]
  14484. + ((sp_uint64)a[ 4]) * b[ 0];
  14485. sp_uint64 t5 = ((sp_uint64)a[ 0]) * b[ 5]
  14486. + ((sp_uint64)a[ 1]) * b[ 4]
  14487. + ((sp_uint64)a[ 2]) * b[ 3]
  14488. + ((sp_uint64)a[ 3]) * b[ 2]
  14489. + ((sp_uint64)a[ 4]) * b[ 1]
  14490. + ((sp_uint64)a[ 5]) * b[ 0];
  14491. sp_uint64 t6 = ((sp_uint64)a[ 0]) * b[ 6]
  14492. + ((sp_uint64)a[ 1]) * b[ 5]
  14493. + ((sp_uint64)a[ 2]) * b[ 4]
  14494. + ((sp_uint64)a[ 3]) * b[ 3]
  14495. + ((sp_uint64)a[ 4]) * b[ 2]
  14496. + ((sp_uint64)a[ 5]) * b[ 1]
  14497. + ((sp_uint64)a[ 6]) * b[ 0];
  14498. sp_uint64 t7 = ((sp_uint64)a[ 0]) * b[ 7]
  14499. + ((sp_uint64)a[ 1]) * b[ 6]
  14500. + ((sp_uint64)a[ 2]) * b[ 5]
  14501. + ((sp_uint64)a[ 3]) * b[ 4]
  14502. + ((sp_uint64)a[ 4]) * b[ 3]
  14503. + ((sp_uint64)a[ 5]) * b[ 2]
  14504. + ((sp_uint64)a[ 6]) * b[ 1]
  14505. + ((sp_uint64)a[ 7]) * b[ 0];
  14506. sp_uint64 t8 = ((sp_uint64)a[ 0]) * b[ 8]
  14507. + ((sp_uint64)a[ 1]) * b[ 7]
  14508. + ((sp_uint64)a[ 2]) * b[ 6]
  14509. + ((sp_uint64)a[ 3]) * b[ 5]
  14510. + ((sp_uint64)a[ 4]) * b[ 4]
  14511. + ((sp_uint64)a[ 5]) * b[ 3]
  14512. + ((sp_uint64)a[ 6]) * b[ 2]
  14513. + ((sp_uint64)a[ 7]) * b[ 1]
  14514. + ((sp_uint64)a[ 8]) * b[ 0];
  14515. sp_uint64 t9 = ((sp_uint64)a[ 1]) * b[ 8]
  14516. + ((sp_uint64)a[ 2]) * b[ 7]
  14517. + ((sp_uint64)a[ 3]) * b[ 6]
  14518. + ((sp_uint64)a[ 4]) * b[ 5]
  14519. + ((sp_uint64)a[ 5]) * b[ 4]
  14520. + ((sp_uint64)a[ 6]) * b[ 3]
  14521. + ((sp_uint64)a[ 7]) * b[ 2]
  14522. + ((sp_uint64)a[ 8]) * b[ 1];
  14523. sp_uint64 t10 = ((sp_uint64)a[ 2]) * b[ 8]
  14524. + ((sp_uint64)a[ 3]) * b[ 7]
  14525. + ((sp_uint64)a[ 4]) * b[ 6]
  14526. + ((sp_uint64)a[ 5]) * b[ 5]
  14527. + ((sp_uint64)a[ 6]) * b[ 4]
  14528. + ((sp_uint64)a[ 7]) * b[ 3]
  14529. + ((sp_uint64)a[ 8]) * b[ 2];
  14530. sp_uint64 t11 = ((sp_uint64)a[ 3]) * b[ 8]
  14531. + ((sp_uint64)a[ 4]) * b[ 7]
  14532. + ((sp_uint64)a[ 5]) * b[ 6]
  14533. + ((sp_uint64)a[ 6]) * b[ 5]
  14534. + ((sp_uint64)a[ 7]) * b[ 4]
  14535. + ((sp_uint64)a[ 8]) * b[ 3];
  14536. sp_uint64 t12 = ((sp_uint64)a[ 4]) * b[ 8]
  14537. + ((sp_uint64)a[ 5]) * b[ 7]
  14538. + ((sp_uint64)a[ 6]) * b[ 6]
  14539. + ((sp_uint64)a[ 7]) * b[ 5]
  14540. + ((sp_uint64)a[ 8]) * b[ 4];
  14541. sp_uint64 t13 = ((sp_uint64)a[ 5]) * b[ 8]
  14542. + ((sp_uint64)a[ 6]) * b[ 7]
  14543. + ((sp_uint64)a[ 7]) * b[ 6]
  14544. + ((sp_uint64)a[ 8]) * b[ 5];
  14545. sp_uint64 t14 = ((sp_uint64)a[ 6]) * b[ 8]
  14546. + ((sp_uint64)a[ 7]) * b[ 7]
  14547. + ((sp_uint64)a[ 8]) * b[ 6];
  14548. sp_uint64 t15 = ((sp_uint64)a[ 7]) * b[ 8]
  14549. + ((sp_uint64)a[ 8]) * b[ 7];
  14550. sp_uint64 t16 = ((sp_uint64)a[ 8]) * b[ 8];
  14551. t1 += t0 >> 26; r[ 0] = t0 & 0x3ffffff;
  14552. t2 += t1 >> 26; r[ 1] = t1 & 0x3ffffff;
  14553. t3 += t2 >> 26; r[ 2] = t2 & 0x3ffffff;
  14554. t4 += t3 >> 26; r[ 3] = t3 & 0x3ffffff;
  14555. t5 += t4 >> 26; r[ 4] = t4 & 0x3ffffff;
  14556. t6 += t5 >> 26; r[ 5] = t5 & 0x3ffffff;
  14557. t7 += t6 >> 26; r[ 6] = t6 & 0x3ffffff;
  14558. t8 += t7 >> 26; r[ 7] = t7 & 0x3ffffff;
  14559. t9 += t8 >> 26; r[ 8] = t8 & 0x3ffffff;
  14560. t10 += t9 >> 26; r[ 9] = t9 & 0x3ffffff;
  14561. t11 += t10 >> 26; r[10] = t10 & 0x3ffffff;
  14562. t12 += t11 >> 26; r[11] = t11 & 0x3ffffff;
  14563. t13 += t12 >> 26; r[12] = t12 & 0x3ffffff;
  14564. t14 += t13 >> 26; r[13] = t13 & 0x3ffffff;
  14565. t15 += t14 >> 26; r[14] = t14 & 0x3ffffff;
  14566. t16 += t15 >> 26; r[15] = t15 & 0x3ffffff;
  14567. r[17] = (sp_digit)(t16 >> 26);
  14568. r[16] = t16 & 0x3ffffff;
  14569. }
  14570. /* Add b to a into r. (r = a + b)
  14571. *
  14572. * r A single precision integer.
  14573. * a A single precision integer.
  14574. * b A single precision integer.
  14575. */
  14576. SP_NOINLINE static int sp_4096_add_9(sp_digit* r, const sp_digit* a,
  14577. const sp_digit* b)
  14578. {
  14579. r[ 0] = a[ 0] + b[ 0];
  14580. r[ 1] = a[ 1] + b[ 1];
  14581. r[ 2] = a[ 2] + b[ 2];
  14582. r[ 3] = a[ 3] + b[ 3];
  14583. r[ 4] = a[ 4] + b[ 4];
  14584. r[ 5] = a[ 5] + b[ 5];
  14585. r[ 6] = a[ 6] + b[ 6];
  14586. r[ 7] = a[ 7] + b[ 7];
  14587. r[ 8] = a[ 8] + b[ 8];
  14588. return 0;
  14589. }
  14590. /* Sub b from a into r. (r = a - b)
  14591. *
  14592. * r A single precision integer.
  14593. * a A single precision integer.
  14594. * b A single precision integer.
  14595. */
  14596. SP_NOINLINE static int sp_4096_sub_18(sp_digit* r, const sp_digit* a,
  14597. const sp_digit* b)
  14598. {
  14599. int i;
  14600. for (i = 0; i < 16; i += 8) {
  14601. r[i + 0] = a[i + 0] - b[i + 0];
  14602. r[i + 1] = a[i + 1] - b[i + 1];
  14603. r[i + 2] = a[i + 2] - b[i + 2];
  14604. r[i + 3] = a[i + 3] - b[i + 3];
  14605. r[i + 4] = a[i + 4] - b[i + 4];
  14606. r[i + 5] = a[i + 5] - b[i + 5];
  14607. r[i + 6] = a[i + 6] - b[i + 6];
  14608. r[i + 7] = a[i + 7] - b[i + 7];
  14609. }
  14610. r[16] = a[16] - b[16];
  14611. r[17] = a[17] - b[17];
  14612. return 0;
  14613. }
  14614. /* Add b to a into r. (r = a + b)
  14615. *
  14616. * r A single precision integer.
  14617. * a A single precision integer.
  14618. * b A single precision integer.
  14619. */
  14620. SP_NOINLINE static int sp_4096_add_18(sp_digit* r, const sp_digit* a,
  14621. const sp_digit* b)
  14622. {
  14623. int i;
  14624. for (i = 0; i < 16; i += 8) {
  14625. r[i + 0] = a[i + 0] + b[i + 0];
  14626. r[i + 1] = a[i + 1] + b[i + 1];
  14627. r[i + 2] = a[i + 2] + b[i + 2];
  14628. r[i + 3] = a[i + 3] + b[i + 3];
  14629. r[i + 4] = a[i + 4] + b[i + 4];
  14630. r[i + 5] = a[i + 5] + b[i + 5];
  14631. r[i + 6] = a[i + 6] + b[i + 6];
  14632. r[i + 7] = a[i + 7] + b[i + 7];
  14633. }
  14634. r[16] = a[16] + b[16];
  14635. r[17] = a[17] + b[17];
  14636. return 0;
  14637. }
  14638. /* Normalize the values in each word to 26 bits.
  14639. *
  14640. * a Array of sp_digit to normalize.
  14641. */
  14642. static void sp_4096_norm_9(sp_digit* a)
  14643. {
  14644. a[1] += a[0] >> 26; a[0] &= 0x3ffffff;
  14645. a[2] += a[1] >> 26; a[1] &= 0x3ffffff;
  14646. a[3] += a[2] >> 26; a[2] &= 0x3ffffff;
  14647. a[4] += a[3] >> 26; a[3] &= 0x3ffffff;
  14648. a[5] += a[4] >> 26; a[4] &= 0x3ffffff;
  14649. a[6] += a[5] >> 26; a[5] &= 0x3ffffff;
  14650. a[7] += a[6] >> 26; a[6] &= 0x3ffffff;
  14651. a[8] += a[7] >> 26; a[7] &= 0x3ffffff;
  14652. }
  14653. /* Normalize the values in each word to 26 bits.
  14654. *
  14655. * a Array of sp_digit to normalize.
  14656. */
  14657. static void sp_4096_norm_18(sp_digit* a)
  14658. {
  14659. int i;
  14660. for (i = 0; i < 16; i += 8) {
  14661. a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff;
  14662. a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff;
  14663. a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff;
  14664. a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff;
  14665. a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff;
  14666. a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff;
  14667. a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff;
  14668. a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff;
  14669. }
  14670. a[17] += a[16] >> 26; a[16] &= 0x3ffffff;
  14671. }
  14672. /* Normalize the values in each word to 26 bits.
  14673. *
  14674. * a Array of sp_digit to normalize.
  14675. */
  14676. static void sp_4096_norm_54(sp_digit* a)
  14677. {
  14678. int i;
  14679. for (i = 0; i < 48; i += 8) {
  14680. a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff;
  14681. a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff;
  14682. a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff;
  14683. a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff;
  14684. a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff;
  14685. a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff;
  14686. a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff;
  14687. a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff;
  14688. }
  14689. a[49] += a[48] >> 26; a[48] &= 0x3ffffff;
  14690. a[50] += a[49] >> 26; a[49] &= 0x3ffffff;
  14691. a[51] += a[50] >> 26; a[50] &= 0x3ffffff;
  14692. a[52] += a[51] >> 26; a[51] &= 0x3ffffff;
  14693. a[53] += a[52] >> 26; a[52] &= 0x3ffffff;
  14694. }
  14695. /* Multiply a and b into r. (r = a * b)
  14696. *
  14697. * r A single precision integer.
  14698. * a A single precision integer.
  14699. * b A single precision integer.
  14700. */
  14701. SP_NOINLINE static void sp_4096_mul_27(sp_digit* r, const sp_digit* a,
  14702. const sp_digit* b)
  14703. {
  14704. sp_digit p0[18];
  14705. sp_digit p1[18];
  14706. sp_digit p2[18];
  14707. sp_digit p3[18];
  14708. sp_digit p4[18];
  14709. sp_digit p5[18];
  14710. sp_digit t0[18];
  14711. sp_digit t1[18];
  14712. sp_digit t2[18];
  14713. sp_digit a0[9];
  14714. sp_digit a1[9];
  14715. sp_digit a2[9];
  14716. sp_digit b0[9];
  14717. sp_digit b1[9];
  14718. sp_digit b2[9];
  14719. (void)sp_4096_add_9(a0, a, &a[9]);
  14720. sp_4096_norm_9(a0);
  14721. (void)sp_4096_add_9(b0, b, &b[9]);
  14722. sp_4096_norm_9(b0);
  14723. (void)sp_4096_add_9(a1, &a[9], &a[18]);
  14724. sp_4096_norm_9(a1);
  14725. (void)sp_4096_add_9(b1, &b[9], &b[18]);
  14726. sp_4096_norm_9(b1);
  14727. (void)sp_4096_add_9(a2, a0, &a[18]);
  14728. sp_4096_norm_9(a1);
  14729. (void)sp_4096_add_9(b2, b0, &b[18]);
  14730. sp_4096_norm_9(b2);
  14731. sp_4096_mul_9(p0, a, b);
  14732. sp_4096_mul_9(p2, &a[9], &b[9]);
  14733. sp_4096_mul_9(p4, &a[18], &b[18]);
  14734. sp_4096_mul_9(p1, a0, b0);
  14735. sp_4096_mul_9(p3, a1, b1);
  14736. sp_4096_mul_9(p5, a2, b2);
  14737. XMEMSET(r, 0, sizeof(*r)*2U*27U);
  14738. (void)sp_4096_sub_18(t0, p3, p2);
  14739. (void)sp_4096_sub_18(t1, p1, p2);
  14740. (void)sp_4096_sub_18(t2, p5, t0);
  14741. (void)sp_4096_sub_18(t2, t2, t1);
  14742. sp_4096_norm_18(t2);
  14743. (void)sp_4096_sub_18(t0, t0, p4);
  14744. sp_4096_norm_18(t0);
  14745. (void)sp_4096_sub_18(t1, t1, p0);
  14746. sp_4096_norm_18(t1);
  14747. (void)sp_4096_add_18(r, r, p0);
  14748. (void)sp_4096_add_18(&r[9], &r[9], t1);
  14749. (void)sp_4096_add_18(&r[18], &r[18], t2);
  14750. (void)sp_4096_add_18(&r[27], &r[27], t0);
  14751. (void)sp_4096_add_18(&r[36], &r[36], p4);
  14752. sp_4096_norm_54(r);
  14753. }
  14754. /* Add b to a into r. (r = a + b)
  14755. *
  14756. * r A single precision integer.
  14757. * a A single precision integer.
  14758. * b A single precision integer.
  14759. */
  14760. SP_NOINLINE static int sp_4096_add_27(sp_digit* r, const sp_digit* a,
  14761. const sp_digit* b)
  14762. {
  14763. int i;
  14764. for (i = 0; i < 24; i += 8) {
  14765. r[i + 0] = a[i + 0] + b[i + 0];
  14766. r[i + 1] = a[i + 1] + b[i + 1];
  14767. r[i + 2] = a[i + 2] + b[i + 2];
  14768. r[i + 3] = a[i + 3] + b[i + 3];
  14769. r[i + 4] = a[i + 4] + b[i + 4];
  14770. r[i + 5] = a[i + 5] + b[i + 5];
  14771. r[i + 6] = a[i + 6] + b[i + 6];
  14772. r[i + 7] = a[i + 7] + b[i + 7];
  14773. }
  14774. r[24] = a[24] + b[24];
  14775. r[25] = a[25] + b[25];
  14776. r[26] = a[26] + b[26];
  14777. return 0;
  14778. }
  14779. /* Sub b from a into r. (r = a - b)
  14780. *
  14781. * r A single precision integer.
  14782. * a A single precision integer.
  14783. * b A single precision integer.
  14784. */
  14785. SP_NOINLINE static int sp_4096_sub_54(sp_digit* r, const sp_digit* a,
  14786. const sp_digit* b)
  14787. {
  14788. int i;
  14789. for (i = 0; i < 48; i += 8) {
  14790. r[i + 0] = a[i + 0] - b[i + 0];
  14791. r[i + 1] = a[i + 1] - b[i + 1];
  14792. r[i + 2] = a[i + 2] - b[i + 2];
  14793. r[i + 3] = a[i + 3] - b[i + 3];
  14794. r[i + 4] = a[i + 4] - b[i + 4];
  14795. r[i + 5] = a[i + 5] - b[i + 5];
  14796. r[i + 6] = a[i + 6] - b[i + 6];
  14797. r[i + 7] = a[i + 7] - b[i + 7];
  14798. }
  14799. r[48] = a[48] - b[48];
  14800. r[49] = a[49] - b[49];
  14801. r[50] = a[50] - b[50];
  14802. r[51] = a[51] - b[51];
  14803. r[52] = a[52] - b[52];
  14804. r[53] = a[53] - b[53];
  14805. return 0;
  14806. }
  14807. /* Add b to a into r. (r = a + b)
  14808. *
  14809. * r A single precision integer.
  14810. * a A single precision integer.
  14811. * b A single precision integer.
  14812. */
  14813. SP_NOINLINE static int sp_4096_add_54(sp_digit* r, const sp_digit* a,
  14814. const sp_digit* b)
  14815. {
  14816. int i;
  14817. for (i = 0; i < 48; i += 8) {
  14818. r[i + 0] = a[i + 0] + b[i + 0];
  14819. r[i + 1] = a[i + 1] + b[i + 1];
  14820. r[i + 2] = a[i + 2] + b[i + 2];
  14821. r[i + 3] = a[i + 3] + b[i + 3];
  14822. r[i + 4] = a[i + 4] + b[i + 4];
  14823. r[i + 5] = a[i + 5] + b[i + 5];
  14824. r[i + 6] = a[i + 6] + b[i + 6];
  14825. r[i + 7] = a[i + 7] + b[i + 7];
  14826. }
  14827. r[48] = a[48] + b[48];
  14828. r[49] = a[49] + b[49];
  14829. r[50] = a[50] + b[50];
  14830. r[51] = a[51] + b[51];
  14831. r[52] = a[52] + b[52];
  14832. r[53] = a[53] + b[53];
  14833. return 0;
  14834. }
  14835. /* Normalize the values in each word to 26 bits.
  14836. *
  14837. * a Array of sp_digit to normalize.
  14838. */
  14839. static void sp_4096_norm_27(sp_digit* a)
  14840. {
  14841. int i;
  14842. for (i = 0; i < 24; i += 8) {
  14843. a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff;
  14844. a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff;
  14845. a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff;
  14846. a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff;
  14847. a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff;
  14848. a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff;
  14849. a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff;
  14850. a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff;
  14851. }
  14852. a[25] += a[24] >> 26; a[24] &= 0x3ffffff;
  14853. a[26] += a[25] >> 26; a[25] &= 0x3ffffff;
  14854. }
  14855. /* Multiply a and b into r. (r = a * b)
  14856. *
  14857. * r A single precision integer.
  14858. * a A single precision integer.
  14859. * b A single precision integer.
  14860. */
  14861. SP_NOINLINE static void sp_4096_mul_81(sp_digit* r, const sp_digit* a,
  14862. const sp_digit* b)
  14863. {
  14864. sp_digit p0[54];
  14865. sp_digit p1[54];
  14866. sp_digit p2[54];
  14867. sp_digit p3[54];
  14868. sp_digit p4[54];
  14869. sp_digit p5[54];
  14870. sp_digit t0[54];
  14871. sp_digit t1[54];
  14872. sp_digit t2[54];
  14873. sp_digit a0[27];
  14874. sp_digit a1[27];
  14875. sp_digit a2[27];
  14876. sp_digit b0[27];
  14877. sp_digit b1[27];
  14878. sp_digit b2[27];
  14879. (void)sp_4096_add_27(a0, a, &a[27]);
  14880. sp_4096_norm_27(a0);
  14881. (void)sp_4096_add_27(b0, b, &b[27]);
  14882. sp_4096_norm_27(b0);
  14883. (void)sp_4096_add_27(a1, &a[27], &a[54]);
  14884. sp_4096_norm_27(a1);
  14885. (void)sp_4096_add_27(b1, &b[27], &b[54]);
  14886. sp_4096_norm_27(b1);
  14887. (void)sp_4096_add_27(a2, a0, &a[54]);
  14888. sp_4096_norm_27(a1);
  14889. (void)sp_4096_add_27(b2, b0, &b[54]);
  14890. sp_4096_norm_27(b2);
  14891. sp_4096_mul_27(p0, a, b);
  14892. sp_4096_mul_27(p2, &a[27], &b[27]);
  14893. sp_4096_mul_27(p4, &a[54], &b[54]);
  14894. sp_4096_mul_27(p1, a0, b0);
  14895. sp_4096_mul_27(p3, a1, b1);
  14896. sp_4096_mul_27(p5, a2, b2);
  14897. XMEMSET(r, 0, sizeof(*r)*2U*81U);
  14898. (void)sp_4096_sub_54(t0, p3, p2);
  14899. (void)sp_4096_sub_54(t1, p1, p2);
  14900. (void)sp_4096_sub_54(t2, p5, t0);
  14901. (void)sp_4096_sub_54(t2, t2, t1);
  14902. sp_4096_norm_54(t2);
  14903. (void)sp_4096_sub_54(t0, t0, p4);
  14904. sp_4096_norm_54(t0);
  14905. (void)sp_4096_sub_54(t1, t1, p0);
  14906. sp_4096_norm_54(t1);
  14907. (void)sp_4096_add_54(r, r, p0);
  14908. (void)sp_4096_add_54(&r[27], &r[27], t1);
  14909. (void)sp_4096_add_54(&r[54], &r[54], t2);
  14910. (void)sp_4096_add_54(&r[81], &r[81], t0);
  14911. (void)sp_4096_add_54(&r[108], &r[108], p4);
  14912. sp_4096_norm_162(r);
  14913. }
  14914. /* Add b to a into r. (r = a + b)
  14915. *
  14916. * r A single precision integer.
  14917. * a A single precision integer.
  14918. * b A single precision integer.
  14919. */
  14920. SP_NOINLINE static int sp_4096_add_81(sp_digit* r, const sp_digit* a,
  14921. const sp_digit* b)
  14922. {
  14923. int i;
  14924. for (i = 0; i < 80; i += 8) {
  14925. r[i + 0] = a[i + 0] + b[i + 0];
  14926. r[i + 1] = a[i + 1] + b[i + 1];
  14927. r[i + 2] = a[i + 2] + b[i + 2];
  14928. r[i + 3] = a[i + 3] + b[i + 3];
  14929. r[i + 4] = a[i + 4] + b[i + 4];
  14930. r[i + 5] = a[i + 5] + b[i + 5];
  14931. r[i + 6] = a[i + 6] + b[i + 6];
  14932. r[i + 7] = a[i + 7] + b[i + 7];
  14933. }
  14934. r[80] = a[80] + b[80];
  14935. return 0;
  14936. }
  14937. /* Add b to a into r. (r = a + b)
  14938. *
  14939. * r A single precision integer.
  14940. * a A single precision integer.
  14941. * b A single precision integer.
  14942. */
  14943. SP_NOINLINE static int sp_4096_add_162(sp_digit* r, const sp_digit* a,
  14944. const sp_digit* b)
  14945. {
  14946. int i;
  14947. for (i = 0; i < 160; i += 8) {
  14948. r[i + 0] = a[i + 0] + b[i + 0];
  14949. r[i + 1] = a[i + 1] + b[i + 1];
  14950. r[i + 2] = a[i + 2] + b[i + 2];
  14951. r[i + 3] = a[i + 3] + b[i + 3];
  14952. r[i + 4] = a[i + 4] + b[i + 4];
  14953. r[i + 5] = a[i + 5] + b[i + 5];
  14954. r[i + 6] = a[i + 6] + b[i + 6];
  14955. r[i + 7] = a[i + 7] + b[i + 7];
  14956. }
  14957. r[160] = a[160] + b[160];
  14958. r[161] = a[161] + b[161];
  14959. return 0;
  14960. }
  14961. /* Sub b from a into r. (r = a - b)
  14962. *
  14963. * r A single precision integer.
  14964. * a A single precision integer.
  14965. * b A single precision integer.
  14966. */
  14967. SP_NOINLINE static int sp_4096_sub_162(sp_digit* r, const sp_digit* a,
  14968. const sp_digit* b)
  14969. {
  14970. int i;
  14971. for (i = 0; i < 160; i += 8) {
  14972. r[i + 0] = a[i + 0] - b[i + 0];
  14973. r[i + 1] = a[i + 1] - b[i + 1];
  14974. r[i + 2] = a[i + 2] - b[i + 2];
  14975. r[i + 3] = a[i + 3] - b[i + 3];
  14976. r[i + 4] = a[i + 4] - b[i + 4];
  14977. r[i + 5] = a[i + 5] - b[i + 5];
  14978. r[i + 6] = a[i + 6] - b[i + 6];
  14979. r[i + 7] = a[i + 7] - b[i + 7];
  14980. }
  14981. r[160] = a[160] - b[160];
  14982. r[161] = a[161] - b[161];
  14983. return 0;
  14984. }
  14985. /* Normalize the values in each word to 26 bits.
  14986. *
  14987. * a Array of sp_digit to normalize.
  14988. */
  14989. static void sp_4096_norm_324(sp_digit* a)
  14990. {
  14991. int i;
  14992. for (i = 0; i < 320; i += 8) {
  14993. a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff;
  14994. a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff;
  14995. a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff;
  14996. a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff;
  14997. a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff;
  14998. a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff;
  14999. a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff;
  15000. a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff;
  15001. }
  15002. a[321] += a[320] >> 26; a[320] &= 0x3ffffff;
  15003. a[322] += a[321] >> 26; a[321] &= 0x3ffffff;
  15004. a[323] += a[322] >> 26; a[322] &= 0x3ffffff;
  15005. }
  15006. /* Multiply a and b into r. (r = a * b)
  15007. *
  15008. * r A single precision integer.
  15009. * a A single precision integer.
  15010. * b A single precision integer.
  15011. */
  15012. SP_NOINLINE static void sp_4096_mul_162(sp_digit* r, const sp_digit* a,
  15013. const sp_digit* b)
  15014. {
  15015. sp_digit* z0 = r;
  15016. sp_digit z1[162];
  15017. sp_digit* a1 = z1;
  15018. sp_digit b1[81];
  15019. sp_digit* z2 = r + 162;
  15020. (void)sp_4096_add_81(a1, a, &a[81]);
  15021. sp_4096_norm_81(a1);
  15022. (void)sp_4096_add_81(b1, b, &b[81]);
  15023. sp_4096_norm_81(b1);
  15024. sp_4096_mul_81(z2, &a[81], &b[81]);
  15025. sp_4096_mul_81(z0, a, b);
  15026. sp_4096_mul_81(z1, a1, b1);
  15027. (void)sp_4096_sub_162(z1, z1, z2);
  15028. (void)sp_4096_sub_162(z1, z1, z0);
  15029. (void)sp_4096_add_162(r + 81, r + 81, z1);
  15030. sp_4096_norm_324(r);
  15031. }
  15032. /* Square a and put result in r. (r = a * a)
  15033. *
  15034. * r A single precision integer.
  15035. * a A single precision integer.
  15036. */
  15037. SP_NOINLINE static void sp_4096_sqr_9(sp_digit* r, const sp_digit* a)
  15038. {
  15039. sp_uint64 t0 = ((sp_uint64)a[ 0]) * a[ 0];
  15040. sp_uint64 t1 = (((sp_uint64)a[ 0]) * a[ 1]) * 2;
  15041. sp_uint64 t2 = (((sp_uint64)a[ 0]) * a[ 2]) * 2
  15042. + ((sp_uint64)a[ 1]) * a[ 1];
  15043. sp_uint64 t3 = (((sp_uint64)a[ 0]) * a[ 3]
  15044. + ((sp_uint64)a[ 1]) * a[ 2]) * 2;
  15045. sp_uint64 t4 = (((sp_uint64)a[ 0]) * a[ 4]
  15046. + ((sp_uint64)a[ 1]) * a[ 3]) * 2
  15047. + ((sp_uint64)a[ 2]) * a[ 2];
  15048. sp_uint64 t5 = (((sp_uint64)a[ 0]) * a[ 5]
  15049. + ((sp_uint64)a[ 1]) * a[ 4]
  15050. + ((sp_uint64)a[ 2]) * a[ 3]) * 2;
  15051. sp_uint64 t6 = (((sp_uint64)a[ 0]) * a[ 6]
  15052. + ((sp_uint64)a[ 1]) * a[ 5]
  15053. + ((sp_uint64)a[ 2]) * a[ 4]) * 2
  15054. + ((sp_uint64)a[ 3]) * a[ 3];
  15055. sp_uint64 t7 = (((sp_uint64)a[ 0]) * a[ 7]
  15056. + ((sp_uint64)a[ 1]) * a[ 6]
  15057. + ((sp_uint64)a[ 2]) * a[ 5]
  15058. + ((sp_uint64)a[ 3]) * a[ 4]) * 2;
  15059. sp_uint64 t8 = (((sp_uint64)a[ 0]) * a[ 8]
  15060. + ((sp_uint64)a[ 1]) * a[ 7]
  15061. + ((sp_uint64)a[ 2]) * a[ 6]
  15062. + ((sp_uint64)a[ 3]) * a[ 5]) * 2
  15063. + ((sp_uint64)a[ 4]) * a[ 4];
  15064. sp_uint64 t9 = (((sp_uint64)a[ 1]) * a[ 8]
  15065. + ((sp_uint64)a[ 2]) * a[ 7]
  15066. + ((sp_uint64)a[ 3]) * a[ 6]
  15067. + ((sp_uint64)a[ 4]) * a[ 5]) * 2;
  15068. sp_uint64 t10 = (((sp_uint64)a[ 2]) * a[ 8]
  15069. + ((sp_uint64)a[ 3]) * a[ 7]
  15070. + ((sp_uint64)a[ 4]) * a[ 6]) * 2
  15071. + ((sp_uint64)a[ 5]) * a[ 5];
  15072. sp_uint64 t11 = (((sp_uint64)a[ 3]) * a[ 8]
  15073. + ((sp_uint64)a[ 4]) * a[ 7]
  15074. + ((sp_uint64)a[ 5]) * a[ 6]) * 2;
  15075. sp_uint64 t12 = (((sp_uint64)a[ 4]) * a[ 8]
  15076. + ((sp_uint64)a[ 5]) * a[ 7]) * 2
  15077. + ((sp_uint64)a[ 6]) * a[ 6];
  15078. sp_uint64 t13 = (((sp_uint64)a[ 5]) * a[ 8]
  15079. + ((sp_uint64)a[ 6]) * a[ 7]) * 2;
  15080. sp_uint64 t14 = (((sp_uint64)a[ 6]) * a[ 8]) * 2
  15081. + ((sp_uint64)a[ 7]) * a[ 7];
  15082. sp_uint64 t15 = (((sp_uint64)a[ 7]) * a[ 8]) * 2;
  15083. sp_uint64 t16 = ((sp_uint64)a[ 8]) * a[ 8];
  15084. t1 += t0 >> 26; r[ 0] = t0 & 0x3ffffff;
  15085. t2 += t1 >> 26; r[ 1] = t1 & 0x3ffffff;
  15086. t3 += t2 >> 26; r[ 2] = t2 & 0x3ffffff;
  15087. t4 += t3 >> 26; r[ 3] = t3 & 0x3ffffff;
  15088. t5 += t4 >> 26; r[ 4] = t4 & 0x3ffffff;
  15089. t6 += t5 >> 26; r[ 5] = t5 & 0x3ffffff;
  15090. t7 += t6 >> 26; r[ 6] = t6 & 0x3ffffff;
  15091. t8 += t7 >> 26; r[ 7] = t7 & 0x3ffffff;
  15092. t9 += t8 >> 26; r[ 8] = t8 & 0x3ffffff;
  15093. t10 += t9 >> 26; r[ 9] = t9 & 0x3ffffff;
  15094. t11 += t10 >> 26; r[10] = t10 & 0x3ffffff;
  15095. t12 += t11 >> 26; r[11] = t11 & 0x3ffffff;
  15096. t13 += t12 >> 26; r[12] = t12 & 0x3ffffff;
  15097. t14 += t13 >> 26; r[13] = t13 & 0x3ffffff;
  15098. t15 += t14 >> 26; r[14] = t14 & 0x3ffffff;
  15099. t16 += t15 >> 26; r[15] = t15 & 0x3ffffff;
  15100. r[17] = (sp_digit)(t16 >> 26);
  15101. r[16] = t16 & 0x3ffffff;
  15102. }
  15103. /* Square a into r. (r = a * a)
  15104. *
  15105. * r A single precision integer.
  15106. * a A single precision integer.
  15107. */
  15108. SP_NOINLINE static void sp_4096_sqr_27(sp_digit* r, const sp_digit* a)
  15109. {
  15110. sp_digit p0[18];
  15111. sp_digit p1[18];
  15112. sp_digit p2[18];
  15113. sp_digit p3[18];
  15114. sp_digit p4[18];
  15115. sp_digit p5[18];
  15116. sp_digit t0[18];
  15117. sp_digit t1[18];
  15118. sp_digit t2[18];
  15119. sp_digit a0[9];
  15120. sp_digit a1[9];
  15121. sp_digit a2[9];
  15122. (void)sp_4096_add_9(a0, a, &a[9]);
  15123. sp_4096_norm_9(a0);
  15124. (void)sp_4096_add_9(a1, &a[9], &a[18]);
  15125. sp_4096_norm_9(a1);
  15126. (void)sp_4096_add_9(a2, a0, &a[18]);
  15127. sp_4096_norm_9(a2);
  15128. sp_4096_sqr_9(p0, a);
  15129. sp_4096_sqr_9(p2, &a[9]);
  15130. sp_4096_sqr_9(p4, &a[18]);
  15131. sp_4096_sqr_9(p1, a0);
  15132. sp_4096_sqr_9(p3, a1);
  15133. sp_4096_sqr_9(p5, a2);
  15134. XMEMSET(r, 0, sizeof(*r)*2U*27U);
  15135. (void)sp_4096_sub_18(t0, p3, p2);
  15136. (void)sp_4096_sub_18(t1, p1, p2);
  15137. (void)sp_4096_sub_18(t2, p5, t0);
  15138. (void)sp_4096_sub_18(t2, t2, t1);
  15139. sp_4096_norm_18(t2);
  15140. (void)sp_4096_sub_18(t0, t0, p4);
  15141. sp_4096_norm_18(t0);
  15142. (void)sp_4096_sub_18(t1, t1, p0);
  15143. sp_4096_norm_18(t1);
  15144. (void)sp_4096_add_18(r, r, p0);
  15145. (void)sp_4096_add_18(&r[9], &r[9], t1);
  15146. (void)sp_4096_add_18(&r[18], &r[18], t2);
  15147. (void)sp_4096_add_18(&r[27], &r[27], t0);
  15148. (void)sp_4096_add_18(&r[36], &r[36], p4);
  15149. sp_4096_norm_54(r);
  15150. }
  15151. /* Square a into r. (r = a * a)
  15152. *
  15153. * r A single precision integer.
  15154. * a A single precision integer.
  15155. */
  15156. SP_NOINLINE static void sp_4096_sqr_81(sp_digit* r, const sp_digit* a)
  15157. {
  15158. sp_digit p0[54];
  15159. sp_digit p1[54];
  15160. sp_digit p2[54];
  15161. sp_digit p3[54];
  15162. sp_digit p4[54];
  15163. sp_digit p5[54];
  15164. sp_digit t0[54];
  15165. sp_digit t1[54];
  15166. sp_digit t2[54];
  15167. sp_digit a0[27];
  15168. sp_digit a1[27];
  15169. sp_digit a2[27];
  15170. (void)sp_4096_add_27(a0, a, &a[27]);
  15171. sp_4096_norm_27(a0);
  15172. (void)sp_4096_add_27(a1, &a[27], &a[54]);
  15173. sp_4096_norm_27(a1);
  15174. (void)sp_4096_add_27(a2, a0, &a[54]);
  15175. sp_4096_norm_27(a2);
  15176. sp_4096_sqr_27(p0, a);
  15177. sp_4096_sqr_27(p2, &a[27]);
  15178. sp_4096_sqr_27(p4, &a[54]);
  15179. sp_4096_sqr_27(p1, a0);
  15180. sp_4096_sqr_27(p3, a1);
  15181. sp_4096_sqr_27(p5, a2);
  15182. XMEMSET(r, 0, sizeof(*r)*2U*81U);
  15183. (void)sp_4096_sub_54(t0, p3, p2);
  15184. (void)sp_4096_sub_54(t1, p1, p2);
  15185. (void)sp_4096_sub_54(t2, p5, t0);
  15186. (void)sp_4096_sub_54(t2, t2, t1);
  15187. sp_4096_norm_54(t2);
  15188. (void)sp_4096_sub_54(t0, t0, p4);
  15189. sp_4096_norm_54(t0);
  15190. (void)sp_4096_sub_54(t1, t1, p0);
  15191. sp_4096_norm_54(t1);
  15192. (void)sp_4096_add_54(r, r, p0);
  15193. (void)sp_4096_add_54(&r[27], &r[27], t1);
  15194. (void)sp_4096_add_54(&r[54], &r[54], t2);
  15195. (void)sp_4096_add_54(&r[81], &r[81], t0);
  15196. (void)sp_4096_add_54(&r[108], &r[108], p4);
  15197. sp_4096_norm_162(r);
  15198. }
  15199. /* Square a and put result in r. (r = a * a)
  15200. *
  15201. * r A single precision integer.
  15202. * a A single precision integer.
  15203. */
  15204. SP_NOINLINE static void sp_4096_sqr_162(sp_digit* r, const sp_digit* a)
  15205. {
  15206. sp_digit* z0 = r;
  15207. sp_digit z1[162];
  15208. sp_digit* a1 = z1;
  15209. sp_digit* z2 = r + 162;
  15210. (void)sp_4096_add_81(a1, a, &a[81]);
  15211. sp_4096_norm_81(a1);
  15212. sp_4096_sqr_81(z2, &a[81]);
  15213. sp_4096_sqr_81(z0, a);
  15214. sp_4096_sqr_81(z1, a1);
  15215. (void)sp_4096_sub_162(z1, z1, z2);
  15216. (void)sp_4096_sub_162(z1, z1, z0);
  15217. (void)sp_4096_add_162(r + 81, r + 81, z1);
  15218. sp_4096_norm_324(r);
  15219. }
  15220. #endif /* !WOLFSSL_SP_SMALL */
  15221. /* Caclulate the bottom digit of -1/a mod 2^n.
  15222. *
  15223. * a A single precision number.
  15224. * rho Bottom word of inverse.
  15225. */
  15226. static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho)
  15227. {
  15228. sp_digit x;
  15229. sp_digit b;
  15230. b = a[0];
  15231. x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
  15232. x *= 2 - b * x; /* here x*a==1 mod 2**8 */
  15233. x *= 2 - b * x; /* here x*a==1 mod 2**16 */
  15234. x *= 2 - b * x; /* here x*a==1 mod 2**32 */
  15235. x &= 0x3ffffff;
  15236. /* rho = -1/m mod b */
  15237. *rho = ((sp_digit)1 << 26) - x;
  15238. }
  15239. /* Multiply a by scalar b into r. (r = a * b)
  15240. *
  15241. * r A single precision integer.
  15242. * a A single precision integer.
  15243. * b A scalar.
  15244. */
  15245. SP_NOINLINE static void sp_4096_mul_d_162(sp_digit* r, const sp_digit* a,
  15246. sp_digit b)
  15247. {
  15248. sp_int64 tb = b;
  15249. sp_int64 t = 0;
  15250. sp_digit t2;
  15251. sp_int64 p[4];
  15252. int i;
  15253. for (i = 0; i < 160; i += 4) {
  15254. p[0] = tb * a[i + 0];
  15255. p[1] = tb * a[i + 1];
  15256. p[2] = tb * a[i + 2];
  15257. p[3] = tb * a[i + 3];
  15258. t += p[0];
  15259. t2 = (sp_digit)(t & 0x3ffffff);
  15260. t >>= 26;
  15261. r[i + 0] = (sp_digit)t2;
  15262. t += p[1];
  15263. t2 = (sp_digit)(t & 0x3ffffff);
  15264. t >>= 26;
  15265. r[i + 1] = (sp_digit)t2;
  15266. t += p[2];
  15267. t2 = (sp_digit)(t & 0x3ffffff);
  15268. t >>= 26;
  15269. r[i + 2] = (sp_digit)t2;
  15270. t += p[3];
  15271. t2 = (sp_digit)(t & 0x3ffffff);
  15272. t >>= 26;
  15273. r[i + 3] = (sp_digit)t2;
  15274. }
  15275. t += tb * a[160];
  15276. r[160] = (sp_digit)(t & 0x3ffffff);
  15277. t >>= 26;
  15278. t += tb * a[161];
  15279. r[161] = (sp_digit)(t & 0x3ffffff);
  15280. t >>= 26;
  15281. r[162] = (sp_digit)(t & 0x3ffffff);
  15282. }
  15283. #if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)
  15284. #if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D)
  15285. /* Sub b from a into r. (r = a - b)
  15286. *
  15287. * r A single precision integer.
  15288. * a A single precision integer.
  15289. * b A single precision integer.
  15290. */
  15291. SP_NOINLINE static int sp_4096_sub_81(sp_digit* r, const sp_digit* a,
  15292. const sp_digit* b)
  15293. {
  15294. int i;
  15295. for (i = 0; i < 80; i += 8) {
  15296. r[i + 0] = a[i + 0] - b[i + 0];
  15297. r[i + 1] = a[i + 1] - b[i + 1];
  15298. r[i + 2] = a[i + 2] - b[i + 2];
  15299. r[i + 3] = a[i + 3] - b[i + 3];
  15300. r[i + 4] = a[i + 4] - b[i + 4];
  15301. r[i + 5] = a[i + 5] - b[i + 5];
  15302. r[i + 6] = a[i + 6] - b[i + 6];
  15303. r[i + 7] = a[i + 7] - b[i + 7];
  15304. }
  15305. r[80] = a[80] - b[80];
  15306. return 0;
  15307. }
  15308. /* r = 2^n mod m where n is the number of bits to reduce by.
  15309. * Given m must be 4096 bits, just need to subtract.
  15310. *
  15311. * r A single precision number.
  15312. * m A single precision number.
  15313. */
  15314. static void sp_4096_mont_norm_81(sp_digit* r, const sp_digit* m)
  15315. {
  15316. /* Set r = 2^n - 1. */
  15317. int i;
  15318. for (i = 0; i < 72; i += 8) {
  15319. r[i + 0] = 0x3ffffff;
  15320. r[i + 1] = 0x3ffffff;
  15321. r[i + 2] = 0x3ffffff;
  15322. r[i + 3] = 0x3ffffff;
  15323. r[i + 4] = 0x3ffffff;
  15324. r[i + 5] = 0x3ffffff;
  15325. r[i + 6] = 0x3ffffff;
  15326. r[i + 7] = 0x3ffffff;
  15327. }
  15328. r[72] = 0x3ffffff;
  15329. r[73] = 0x3ffffff;
  15330. r[74] = 0x3ffffff;
  15331. r[75] = 0x3ffffff;
  15332. r[76] = 0x3ffffff;
  15333. r[77] = 0x3ffffff;
  15334. r[78] = 0xfffffL;
  15335. r[79] = 0;
  15336. r[80] = 0;
  15337. /* r = (2^n - 1) mod n */
  15338. (void)sp_4096_sub_81(r, r, m);
  15339. /* Add one so r = 2^n mod m */
  15340. r[0] += 1;
  15341. }
  15342. /* Compare a with b in constant time.
  15343. *
  15344. * a A single precision integer.
  15345. * b A single precision integer.
  15346. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  15347. * respectively.
  15348. */
  15349. static sp_digit sp_4096_cmp_81(const sp_digit* a, const sp_digit* b)
  15350. {
  15351. sp_digit r = 0;
  15352. int i;
  15353. r |= (a[80] - b[80]) & (0 - (sp_digit)1);
  15354. for (i = 72; i >= 0; i -= 8) {
  15355. r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 25);
  15356. r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 25);
  15357. r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 25);
  15358. r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 25);
  15359. r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 25);
  15360. r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 25);
  15361. r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 25);
  15362. r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 25);
  15363. }
  15364. return r;
  15365. }
  15366. /* Conditionally subtract b from a using the mask m.
  15367. * m is -1 to subtract and 0 when not.
  15368. *
  15369. * r A single precision number representing condition subtract result.
  15370. * a A single precision number to subtract from.
  15371. * b A single precision number to subtract.
  15372. * m Mask value to apply.
  15373. */
  15374. static void sp_4096_cond_sub_81(sp_digit* r, const sp_digit* a,
  15375. const sp_digit* b, const sp_digit m)
  15376. {
  15377. int i;
  15378. for (i = 0; i < 80; i += 8) {
  15379. r[i + 0] = a[i + 0] - (b[i + 0] & m);
  15380. r[i + 1] = a[i + 1] - (b[i + 1] & m);
  15381. r[i + 2] = a[i + 2] - (b[i + 2] & m);
  15382. r[i + 3] = a[i + 3] - (b[i + 3] & m);
  15383. r[i + 4] = a[i + 4] - (b[i + 4] & m);
  15384. r[i + 5] = a[i + 5] - (b[i + 5] & m);
  15385. r[i + 6] = a[i + 6] - (b[i + 6] & m);
  15386. r[i + 7] = a[i + 7] - (b[i + 7] & m);
  15387. }
  15388. r[80] = a[80] - (b[80] & m);
  15389. }
  15390. /* Mul a by scalar b and add into r. (r += a * b)
  15391. *
  15392. * r A single precision integer.
  15393. * a A single precision integer.
  15394. * b A scalar.
  15395. */
  15396. SP_NOINLINE static void sp_4096_mul_add_81(sp_digit* r, const sp_digit* a,
  15397. const sp_digit b)
  15398. {
  15399. #ifndef WOLFSSL_SP_LARGE_CODE
  15400. sp_int64 tb = b;
  15401. sp_int64 t = 0;
  15402. int i;
  15403. for (i = 0; i < 81; i++) {
  15404. t += r[i];
  15405. t += tb * a[i];
  15406. r[i] = ((sp_digit)t) & 0x3ffffff;
  15407. t >>= 26;
  15408. }
  15409. r[81] += (sp_digit)t;
  15410. #else
  15411. sp_int64 tb = b;
  15412. sp_int64 t[8];
  15413. int i;
  15414. t[0] = 0;
  15415. for (i = 0; i < 80; i += 8) {
  15416. t[0] += (tb * a[i+0]) + r[i+0];
  15417. t[1] = (tb * a[i+1]) + r[i+1];
  15418. t[2] = (tb * a[i+2]) + r[i+2];
  15419. t[3] = (tb * a[i+3]) + r[i+3];
  15420. t[4] = (tb * a[i+4]) + r[i+4];
  15421. t[5] = (tb * a[i+5]) + r[i+5];
  15422. t[6] = (tb * a[i+6]) + r[i+6];
  15423. t[7] = (tb * a[i+7]) + r[i+7];
  15424. r[i+0] = t[0] & 0x3ffffff;
  15425. t[1] += t[0] >> 26;
  15426. r[i+1] = t[1] & 0x3ffffff;
  15427. t[2] += t[1] >> 26;
  15428. r[i+2] = t[2] & 0x3ffffff;
  15429. t[3] += t[2] >> 26;
  15430. r[i+3] = t[3] & 0x3ffffff;
  15431. t[4] += t[3] >> 26;
  15432. r[i+4] = t[4] & 0x3ffffff;
  15433. t[5] += t[4] >> 26;
  15434. r[i+5] = t[5] & 0x3ffffff;
  15435. t[6] += t[5] >> 26;
  15436. r[i+6] = t[6] & 0x3ffffff;
  15437. t[7] += t[6] >> 26;
  15438. r[i+7] = t[7] & 0x3ffffff;
  15439. t[0] = t[7] >> 26;
  15440. }
  15441. t[0] += (tb * a[80]) + r[80];
  15442. r[80] = t[0] & 0x3ffffff;
  15443. r[81] += (sp_digit)(t[0] >> 26);
  15444. #endif /* !WOLFSSL_SP_LARGE_CODE */
  15445. }
  15446. /* Shift the result in the high 2048 bits down to the bottom.
  15447. *
  15448. * r A single precision number.
  15449. * a A single precision number.
  15450. */
  15451. static void sp_4096_mont_shift_81(sp_digit* r, const sp_digit* a)
  15452. {
  15453. int i;
  15454. sp_int64 n = a[78] >> 20;
  15455. n += ((sp_int64)a[79]) << 6;
  15456. for (i = 0; i < 72; i += 8) {
  15457. r[i + 0] = n & 0x3ffffff;
  15458. n >>= 26; n += ((sp_int64)a[i + 80]) << 6;
  15459. r[i + 1] = n & 0x3ffffff;
  15460. n >>= 26; n += ((sp_int64)a[i + 81]) << 6;
  15461. r[i + 2] = n & 0x3ffffff;
  15462. n >>= 26; n += ((sp_int64)a[i + 82]) << 6;
  15463. r[i + 3] = n & 0x3ffffff;
  15464. n >>= 26; n += ((sp_int64)a[i + 83]) << 6;
  15465. r[i + 4] = n & 0x3ffffff;
  15466. n >>= 26; n += ((sp_int64)a[i + 84]) << 6;
  15467. r[i + 5] = n & 0x3ffffff;
  15468. n >>= 26; n += ((sp_int64)a[i + 85]) << 6;
  15469. r[i + 6] = n & 0x3ffffff;
  15470. n >>= 26; n += ((sp_int64)a[i + 86]) << 6;
  15471. r[i + 7] = n & 0x3ffffff;
  15472. n >>= 26; n += ((sp_int64)a[i + 87]) << 6;
  15473. }
  15474. r[72] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[152]) << 6;
  15475. r[73] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[153]) << 6;
  15476. r[74] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[154]) << 6;
  15477. r[75] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[155]) << 6;
  15478. r[76] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[156]) << 6;
  15479. r[77] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[157]) << 6;
  15480. r[78] = (sp_digit)n;
  15481. XMEMSET(&r[79], 0, sizeof(*r) * 79U);
  15482. }
  15483. /* Reduce the number back to 4096 bits using Montgomery reduction.
  15484. *
  15485. * a A single precision number to reduce in place.
  15486. * m The single precision number representing the modulus.
  15487. * mp The digit representing the negative inverse of m mod 2^n.
  15488. */
  15489. static void sp_4096_mont_reduce_81(sp_digit* a, const sp_digit* m, sp_digit mp)
  15490. {
  15491. int i;
  15492. sp_digit mu;
  15493. sp_digit over;
  15494. sp_4096_norm_81(a + 79);
  15495. for (i=0; i<78; i++) {
  15496. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x3ffffff;
  15497. sp_4096_mul_add_81(a+i, m, mu);
  15498. a[i+1] += a[i] >> 26;
  15499. }
  15500. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffL;
  15501. sp_4096_mul_add_81(a+i, m, mu);
  15502. a[i+1] += a[i] >> 26;
  15503. a[i] &= 0x3ffffff;
  15504. sp_4096_mont_shift_81(a, a);
  15505. over = a[78] - m[78];
  15506. sp_4096_cond_sub_81(a, a, m, ~((over - 1) >> 31));
  15507. sp_4096_norm_81(a);
  15508. }
  15509. /* Multiply two Montgomery form numbers mod the modulus (prime).
  15510. * (r = a * b mod m)
  15511. *
  15512. * r Result of multiplication.
  15513. * a First number to multiply in Montgomery form.
  15514. * b Second number to multiply in Montgomery form.
  15515. * m Modulus (prime).
  15516. * mp Montgomery mulitplier.
  15517. */
  15518. SP_NOINLINE static void sp_4096_mont_mul_81(sp_digit* r, const sp_digit* a,
  15519. const sp_digit* b, const sp_digit* m, sp_digit mp)
  15520. {
  15521. sp_4096_mul_81(r, a, b);
  15522. sp_4096_mont_reduce_81(r, m, mp);
  15523. }
  15524. /* Square the Montgomery form number. (r = a * a mod m)
  15525. *
  15526. * r Result of squaring.
  15527. * a Number to square in Montgomery form.
  15528. * m Modulus (prime).
  15529. * mp Montgomery mulitplier.
  15530. */
  15531. SP_NOINLINE static void sp_4096_mont_sqr_81(sp_digit* r, const sp_digit* a,
  15532. const sp_digit* m, sp_digit mp)
  15533. {
  15534. sp_4096_sqr_81(r, a);
  15535. sp_4096_mont_reduce_81(r, m, mp);
  15536. }
  15537. /* Multiply a by scalar b into r. (r = a * b)
  15538. *
  15539. * r A single precision integer.
  15540. * a A single precision integer.
  15541. * b A scalar.
  15542. */
  15543. SP_NOINLINE static void sp_4096_mul_d_81(sp_digit* r, const sp_digit* a,
  15544. sp_digit b)
  15545. {
  15546. sp_int64 tb = b;
  15547. sp_int64 t = 0;
  15548. sp_digit t2;
  15549. sp_int64 p[4];
  15550. int i;
  15551. for (i = 0; i < 80; i += 4) {
  15552. p[0] = tb * a[i + 0];
  15553. p[1] = tb * a[i + 1];
  15554. p[2] = tb * a[i + 2];
  15555. p[3] = tb * a[i + 3];
  15556. t += p[0];
  15557. t2 = (sp_digit)(t & 0x3ffffff);
  15558. t >>= 26;
  15559. r[i + 0] = (sp_digit)t2;
  15560. t += p[1];
  15561. t2 = (sp_digit)(t & 0x3ffffff);
  15562. t >>= 26;
  15563. r[i + 1] = (sp_digit)t2;
  15564. t += p[2];
  15565. t2 = (sp_digit)(t & 0x3ffffff);
  15566. t >>= 26;
  15567. r[i + 2] = (sp_digit)t2;
  15568. t += p[3];
  15569. t2 = (sp_digit)(t & 0x3ffffff);
  15570. t >>= 26;
  15571. r[i + 3] = (sp_digit)t2;
  15572. }
  15573. t += tb * a[80];
  15574. r[80] = (sp_digit)(t & 0x3ffffff);
  15575. t >>= 26;
  15576. r[81] = (sp_digit)(t & 0x3ffffff);
  15577. }
  15578. #ifndef WOLFSSL_SP_SMALL
  15579. /* Conditionally add a and b using the mask m.
  15580. * m is -1 to add and 0 when not.
  15581. *
  15582. * r A single precision number representing conditional add result.
  15583. * a A single precision number to add with.
  15584. * b A single precision number to add.
  15585. * m Mask value to apply.
  15586. */
  15587. static void sp_4096_cond_add_81(sp_digit* r, const sp_digit* a,
  15588. const sp_digit* b, const sp_digit m)
  15589. {
  15590. int i;
  15591. for (i = 0; i < 80; i += 8) {
  15592. r[i + 0] = a[i + 0] + (b[i + 0] & m);
  15593. r[i + 1] = a[i + 1] + (b[i + 1] & m);
  15594. r[i + 2] = a[i + 2] + (b[i + 2] & m);
  15595. r[i + 3] = a[i + 3] + (b[i + 3] & m);
  15596. r[i + 4] = a[i + 4] + (b[i + 4] & m);
  15597. r[i + 5] = a[i + 5] + (b[i + 5] & m);
  15598. r[i + 6] = a[i + 6] + (b[i + 6] & m);
  15599. r[i + 7] = a[i + 7] + (b[i + 7] & m);
  15600. }
  15601. r[80] = a[80] + (b[80] & m);
  15602. }
  15603. #endif /* !WOLFSSL_SP_SMALL */
  15604. SP_NOINLINE static void sp_4096_rshift_81(sp_digit* r, const sp_digit* a,
  15605. byte n)
  15606. {
  15607. int i;
  15608. for (i=0; i<80; i += 8) {
  15609. r[i+0] = (a[i+0] >> n) | ((a[i+1] << (26 - n)) & 0x3ffffff);
  15610. r[i+1] = (a[i+1] >> n) | ((a[i+2] << (26 - n)) & 0x3ffffff);
  15611. r[i+2] = (a[i+2] >> n) | ((a[i+3] << (26 - n)) & 0x3ffffff);
  15612. r[i+3] = (a[i+3] >> n) | ((a[i+4] << (26 - n)) & 0x3ffffff);
  15613. r[i+4] = (a[i+4] >> n) | ((a[i+5] << (26 - n)) & 0x3ffffff);
  15614. r[i+5] = (a[i+5] >> n) | ((a[i+6] << (26 - n)) & 0x3ffffff);
  15615. r[i+6] = (a[i+6] >> n) | ((a[i+7] << (26 - n)) & 0x3ffffff);
  15616. r[i+7] = (a[i+7] >> n) | ((a[i+8] << (26 - n)) & 0x3ffffff);
  15617. }
  15618. r[80] = a[80] >> n;
  15619. }
  15620. static WC_INLINE sp_digit sp_4096_div_word_81(sp_digit d1, sp_digit d0,
  15621. sp_digit div)
  15622. {
  15623. #ifdef SP_USE_DIVTI3
  15624. sp_int64 d = ((sp_int64)d1 << 26) + d0;
  15625. return d / div;
  15626. #elif defined(__x86_64__) || defined(__i386__)
  15627. sp_int64 d = ((sp_int64)d1 << 26) + d0;
  15628. sp_uint32 lo = (sp_uint32)d;
  15629. sp_digit hi = (sp_digit)(d >> 32);
  15630. __asm__ __volatile__ (
  15631. "idiv %2"
  15632. : "+a" (lo)
  15633. : "d" (hi), "r" (div)
  15634. : "cc"
  15635. );
  15636. return (sp_digit)lo;
  15637. #elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV)
  15638. sp_int64 d = ((sp_int64)d1 << 26) + d0;
  15639. sp_digit dv = (div >> 1) + 1;
  15640. sp_digit t1 = (sp_digit)(d >> 26);
  15641. sp_digit t0 = (sp_digit)(d & 0x3ffffff);
  15642. sp_digit t2;
  15643. sp_digit sign;
  15644. sp_digit r;
  15645. int i;
  15646. sp_int64 m;
  15647. r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
  15648. t1 -= dv & (0 - r);
  15649. for (i = 24; i >= 1; i--) {
  15650. t1 += t1 + (((sp_uint32)t0 >> 25) & 1);
  15651. t0 <<= 1;
  15652. t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
  15653. r += r + t2;
  15654. t1 -= dv & (0 - t2);
  15655. t1 += t2;
  15656. }
  15657. r += r + 1;
  15658. m = d - ((sp_int64)r * div);
  15659. r += (sp_digit)(m >> 26);
  15660. m = d - ((sp_int64)r * div);
  15661. r += (sp_digit)(m >> 52) - (sp_digit)(d >> 52);
  15662. m = d - ((sp_int64)r * div);
  15663. sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
  15664. m *= sign;
  15665. t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
  15666. r += sign * t2;
  15667. m = d - ((sp_int64)r * div);
  15668. sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
  15669. m *= sign;
  15670. t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
  15671. r += sign * t2;
  15672. return r;
  15673. #else
  15674. sp_int64 d = ((sp_int64)d1 << 26) + d0;
  15675. sp_digit r = 0;
  15676. sp_digit t;
  15677. sp_digit dv = (div >> 11) + 1;
  15678. t = (sp_digit)(d >> 22);
  15679. t = (t / dv) << 11;
  15680. r += t;
  15681. d -= (sp_int64)t * div;
  15682. t = (sp_digit)(d >> 7);
  15683. t = t / (dv << 4);
  15684. r += t;
  15685. d -= (sp_int64)t * div;
  15686. t = (sp_digit)d;
  15687. t = t / div;
  15688. r += t;
  15689. d -= (sp_int64)t * div;
  15690. return r;
  15691. #endif
  15692. }
  15693. static WC_INLINE sp_digit sp_4096_word_div_word_81(sp_digit d, sp_digit div)
  15694. {
  15695. #if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
  15696. defined(SP_DIV_WORD_USE_DIV)
  15697. return d / div;
  15698. #else
  15699. return (sp_digit)((sp_uint32)(div - d) >> 31);
  15700. #endif
  15701. }
  15702. /* Divide d in a and put remainder into r (m*d + r = a)
  15703. * m is not calculated as it is not needed at this time.
  15704. *
  15705. * Full implementation.
  15706. *
  15707. * a Number to be divided.
  15708. * d Number to divide with.
  15709. * m Multiplier result.
  15710. * r Remainder from the division.
  15711. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  15712. */
  15713. static int sp_4096_div_81(const sp_digit* a, const sp_digit* d,
  15714. const sp_digit* m, sp_digit* r)
  15715. {
  15716. int i;
  15717. #ifndef WOLFSSL_SP_DIV_32
  15718. #endif
  15719. sp_digit dv;
  15720. sp_digit r1;
  15721. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  15722. sp_digit* t1 = NULL;
  15723. #else
  15724. sp_digit t1[4 * 81 + 3];
  15725. #endif
  15726. sp_digit* t2 = NULL;
  15727. sp_digit* sd = NULL;
  15728. int err = MP_OKAY;
  15729. (void)m;
  15730. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  15731. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 81 + 3), NULL,
  15732. DYNAMIC_TYPE_TMP_BUFFER);
  15733. if (t1 == NULL)
  15734. err = MEMORY_E;
  15735. #endif
  15736. (void)m;
  15737. if (err == MP_OKAY) {
  15738. t2 = t1 + 162 + 1;
  15739. sd = t2 + 81 + 1;
  15740. sp_4096_mul_d_81(sd, d, (sp_digit)1 << 6);
  15741. sp_4096_mul_d_162(t1, a, (sp_digit)1 << 6);
  15742. dv = sd[78];
  15743. t1[79 + 79] += t1[79 + 79 - 1] >> 26;
  15744. t1[79 + 79 - 1] &= 0x3ffffff;
  15745. for (i=79; i>=0; i--) {
  15746. r1 = sp_4096_div_word_81(t1[79 + i], t1[79 + i - 1], dv);
  15747. sp_4096_mul_d_81(t2, sd, r1);
  15748. (void)sp_4096_sub_81(&t1[i], &t1[i], t2);
  15749. sp_4096_norm_79(&t1[i]);
  15750. t1[79 + i] += t1[79 + i - 1] >> 26;
  15751. t1[79 + i - 1] &= 0x3ffffff;
  15752. r1 = sp_4096_div_word_81(-t1[79 + i], -t1[79 + i - 1], dv);
  15753. r1 -= t1[79 + i];
  15754. sp_4096_mul_d_81(t2, sd, r1);
  15755. (void)sp_4096_add_81(&t1[i], &t1[i], t2);
  15756. t1[79 + i] += t1[79 + i - 1] >> 26;
  15757. t1[79 + i - 1] &= 0x3ffffff;
  15758. }
  15759. t1[79 - 1] += t1[79 - 2] >> 26;
  15760. t1[79 - 2] &= 0x3ffffff;
  15761. r1 = sp_4096_word_div_word_81(t1[79 - 1], dv);
  15762. sp_4096_mul_d_81(t2, sd, r1);
  15763. sp_4096_sub_81(t1, t1, t2);
  15764. XMEMCPY(r, t1, sizeof(*r) * 162U);
  15765. for (i=0; i<78; i++) {
  15766. r[i+1] += r[i] >> 26;
  15767. r[i] &= 0x3ffffff;
  15768. }
  15769. sp_4096_cond_add_81(r, r, sd, r[78] >> 31);
  15770. sp_4096_norm_79(r);
  15771. sp_4096_rshift_81(r, r, 6);
  15772. r[79] = 0;
  15773. r[80] = 0;
  15774. }
  15775. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  15776. if (t1 != NULL)
  15777. XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  15778. #endif
  15779. return err;
  15780. }
  15781. /* Reduce a modulo m into r. (r = a mod m)
  15782. *
  15783. * r A single precision number that is the reduced result.
  15784. * a A single precision number that is to be reduced.
  15785. * m A single precision number that is the modulus to reduce with.
  15786. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  15787. */
  15788. static int sp_4096_mod_81(sp_digit* r, const sp_digit* a, const sp_digit* m)
  15789. {
  15790. return sp_4096_div_81(a, m, NULL, r);
  15791. }
  15792. /* Modular exponentiate a to the e mod m. (r = a^e mod m)
  15793. *
  15794. * r A single precision number that is the result of the operation.
  15795. * a A single precision number being exponentiated.
  15796. * e A single precision number that is the exponent.
  15797. * bits The number of bits in the exponent.
  15798. * m A single precision number that is the modulus.
  15799. * returns 0 on success.
  15800. * returns MEMORY_E on dynamic memory allocation failure.
  15801. * returns MP_VAL when base is even or exponent is 0.
  15802. */
  15803. static int sp_4096_mod_exp_81(sp_digit* r, const sp_digit* a, const sp_digit* e,
  15804. int bits, const sp_digit* m, int reduceA)
  15805. {
  15806. #if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP)
  15807. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  15808. sp_digit* td = NULL;
  15809. #else
  15810. sp_digit td[3 * 162];
  15811. #endif
  15812. sp_digit* t[3] = {0, 0, 0};
  15813. sp_digit* norm = NULL;
  15814. sp_digit mp = 1;
  15815. sp_digit n;
  15816. int i;
  15817. int c;
  15818. byte y;
  15819. int err = MP_OKAY;
  15820. if (bits == 0) {
  15821. err = MP_VAL;
  15822. }
  15823. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  15824. if (err == MP_OKAY) {
  15825. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 81 * 2, NULL,
  15826. DYNAMIC_TYPE_TMP_BUFFER);
  15827. if (td == NULL)
  15828. err = MEMORY_E;
  15829. }
  15830. #endif
  15831. if (err == MP_OKAY) {
  15832. norm = td;
  15833. for (i=0; i<3; i++) {
  15834. t[i] = td + (i * 81 * 2);
  15835. XMEMSET(t[i], 0, sizeof(sp_digit) * 81U * 2U);
  15836. }
  15837. sp_4096_mont_setup(m, &mp);
  15838. sp_4096_mont_norm_81(norm, m);
  15839. if (reduceA != 0) {
  15840. err = sp_4096_mod_81(t[1], a, m);
  15841. }
  15842. else {
  15843. XMEMCPY(t[1], a, sizeof(sp_digit) * 81U);
  15844. }
  15845. }
  15846. if (err == MP_OKAY) {
  15847. sp_4096_mul_81(t[1], t[1], norm);
  15848. err = sp_4096_mod_81(t[1], t[1], m);
  15849. }
  15850. if (err == MP_OKAY) {
  15851. i = bits / 26;
  15852. c = bits % 26;
  15853. n = e[i--] << (26 - c);
  15854. for (; ; c--) {
  15855. if (c == 0) {
  15856. if (i == -1) {
  15857. break;
  15858. }
  15859. n = e[i--];
  15860. c = 26;
  15861. }
  15862. y = (int)((n >> 25) & 1);
  15863. n <<= 1;
  15864. sp_4096_mont_mul_81(t[y^1], t[0], t[1], m, mp);
  15865. XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
  15866. ((size_t)t[1] & addr_mask[y])),
  15867. sizeof(*t[2]) * 81 * 2);
  15868. sp_4096_mont_sqr_81(t[2], t[2], m, mp);
  15869. XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
  15870. ((size_t)t[1] & addr_mask[y])), t[2],
  15871. sizeof(*t[2]) * 81 * 2);
  15872. }
  15873. sp_4096_mont_reduce_81(t[0], m, mp);
  15874. n = sp_4096_cmp_81(t[0], m);
  15875. sp_4096_cond_sub_81(t[0], t[0], m, ~(n >> 31));
  15876. XMEMCPY(r, t[0], sizeof(*r) * 81 * 2);
  15877. }
  15878. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  15879. if (td != NULL)
  15880. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  15881. #endif
  15882. return err;
  15883. #elif !defined(WC_NO_CACHE_RESISTANT)
  15884. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  15885. sp_digit* td = NULL;
  15886. #else
  15887. sp_digit td[3 * 162];
  15888. #endif
  15889. sp_digit* t[3] = {0, 0, 0};
  15890. sp_digit* norm = NULL;
  15891. sp_digit mp = 1;
  15892. sp_digit n;
  15893. int i;
  15894. int c;
  15895. byte y;
  15896. int err = MP_OKAY;
  15897. if (bits == 0) {
  15898. err = MP_VAL;
  15899. }
  15900. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  15901. if (err == MP_OKAY) {
  15902. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 81 * 2, NULL,
  15903. DYNAMIC_TYPE_TMP_BUFFER);
  15904. if (td == NULL)
  15905. err = MEMORY_E;
  15906. }
  15907. #endif
  15908. if (err == MP_OKAY) {
  15909. norm = td;
  15910. for (i=0; i<3; i++) {
  15911. t[i] = td + (i * 81 * 2);
  15912. }
  15913. sp_4096_mont_setup(m, &mp);
  15914. sp_4096_mont_norm_81(norm, m);
  15915. if (reduceA != 0) {
  15916. err = sp_4096_mod_81(t[1], a, m);
  15917. if (err == MP_OKAY) {
  15918. sp_4096_mul_81(t[1], t[1], norm);
  15919. err = sp_4096_mod_81(t[1], t[1], m);
  15920. }
  15921. }
  15922. else {
  15923. sp_4096_mul_81(t[1], a, norm);
  15924. err = sp_4096_mod_81(t[1], t[1], m);
  15925. }
  15926. }
  15927. if (err == MP_OKAY) {
  15928. i = bits / 26;
  15929. c = bits % 26;
  15930. n = e[i--] << (26 - c);
  15931. for (; ; c--) {
  15932. if (c == 0) {
  15933. if (i == -1) {
  15934. break;
  15935. }
  15936. n = e[i--];
  15937. c = 26;
  15938. }
  15939. y = (int)((n >> 25) & 1);
  15940. n <<= 1;
  15941. sp_4096_mont_mul_81(t[y^1], t[0], t[1], m, mp);
  15942. XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
  15943. ((size_t)t[1] & addr_mask[y])),
  15944. sizeof(*t[2]) * 81 * 2);
  15945. sp_4096_mont_sqr_81(t[2], t[2], m, mp);
  15946. XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
  15947. ((size_t)t[1] & addr_mask[y])), t[2],
  15948. sizeof(*t[2]) * 81 * 2);
  15949. }
  15950. sp_4096_mont_reduce_81(t[0], m, mp);
  15951. n = sp_4096_cmp_81(t[0], m);
  15952. sp_4096_cond_sub_81(t[0], t[0], m, ~(n >> 31));
  15953. XMEMCPY(r, t[0], sizeof(*r) * 81 * 2);
  15954. }
  15955. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  15956. if (td != NULL)
  15957. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  15958. #endif
  15959. return err;
  15960. #else
  15961. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  15962. sp_digit* td = NULL;
  15963. #else
  15964. sp_digit td[(32 * 162) + 162];
  15965. #endif
  15966. sp_digit* t[32];
  15967. sp_digit* rt = NULL;
  15968. sp_digit* norm = NULL;
  15969. sp_digit mp = 1;
  15970. sp_digit n;
  15971. int i;
  15972. int c;
  15973. byte y;
  15974. int err = MP_OKAY;
  15975. if (bits == 0) {
  15976. err = MP_VAL;
  15977. }
  15978. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  15979. if (err == MP_OKAY) {
  15980. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((32 * 162) + 162), NULL,
  15981. DYNAMIC_TYPE_TMP_BUFFER);
  15982. if (td == NULL)
  15983. err = MEMORY_E;
  15984. }
  15985. #endif
  15986. if (err == MP_OKAY) {
  15987. norm = td;
  15988. for (i=0; i<32; i++)
  15989. t[i] = td + i * 162;
  15990. rt = td + 5184;
  15991. sp_4096_mont_setup(m, &mp);
  15992. sp_4096_mont_norm_81(norm, m);
  15993. if (reduceA != 0) {
  15994. err = sp_4096_mod_81(t[1], a, m);
  15995. if (err == MP_OKAY) {
  15996. sp_4096_mul_81(t[1], t[1], norm);
  15997. err = sp_4096_mod_81(t[1], t[1], m);
  15998. }
  15999. }
  16000. else {
  16001. sp_4096_mul_81(t[1], a, norm);
  16002. err = sp_4096_mod_81(t[1], t[1], m);
  16003. }
  16004. }
  16005. if (err == MP_OKAY) {
  16006. sp_4096_mont_sqr_81(t[ 2], t[ 1], m, mp);
  16007. sp_4096_mont_mul_81(t[ 3], t[ 2], t[ 1], m, mp);
  16008. sp_4096_mont_sqr_81(t[ 4], t[ 2], m, mp);
  16009. sp_4096_mont_mul_81(t[ 5], t[ 3], t[ 2], m, mp);
  16010. sp_4096_mont_sqr_81(t[ 6], t[ 3], m, mp);
  16011. sp_4096_mont_mul_81(t[ 7], t[ 4], t[ 3], m, mp);
  16012. sp_4096_mont_sqr_81(t[ 8], t[ 4], m, mp);
  16013. sp_4096_mont_mul_81(t[ 9], t[ 5], t[ 4], m, mp);
  16014. sp_4096_mont_sqr_81(t[10], t[ 5], m, mp);
  16015. sp_4096_mont_mul_81(t[11], t[ 6], t[ 5], m, mp);
  16016. sp_4096_mont_sqr_81(t[12], t[ 6], m, mp);
  16017. sp_4096_mont_mul_81(t[13], t[ 7], t[ 6], m, mp);
  16018. sp_4096_mont_sqr_81(t[14], t[ 7], m, mp);
  16019. sp_4096_mont_mul_81(t[15], t[ 8], t[ 7], m, mp);
  16020. sp_4096_mont_sqr_81(t[16], t[ 8], m, mp);
  16021. sp_4096_mont_mul_81(t[17], t[ 9], t[ 8], m, mp);
  16022. sp_4096_mont_sqr_81(t[18], t[ 9], m, mp);
  16023. sp_4096_mont_mul_81(t[19], t[10], t[ 9], m, mp);
  16024. sp_4096_mont_sqr_81(t[20], t[10], m, mp);
  16025. sp_4096_mont_mul_81(t[21], t[11], t[10], m, mp);
  16026. sp_4096_mont_sqr_81(t[22], t[11], m, mp);
  16027. sp_4096_mont_mul_81(t[23], t[12], t[11], m, mp);
  16028. sp_4096_mont_sqr_81(t[24], t[12], m, mp);
  16029. sp_4096_mont_mul_81(t[25], t[13], t[12], m, mp);
  16030. sp_4096_mont_sqr_81(t[26], t[13], m, mp);
  16031. sp_4096_mont_mul_81(t[27], t[14], t[13], m, mp);
  16032. sp_4096_mont_sqr_81(t[28], t[14], m, mp);
  16033. sp_4096_mont_mul_81(t[29], t[15], t[14], m, mp);
  16034. sp_4096_mont_sqr_81(t[30], t[15], m, mp);
  16035. sp_4096_mont_mul_81(t[31], t[16], t[15], m, mp);
  16036. bits = ((bits + 4) / 5) * 5;
  16037. i = ((bits + 25) / 26) - 1;
  16038. c = bits % 26;
  16039. if (c == 0) {
  16040. c = 26;
  16041. }
  16042. if (i < 81) {
  16043. n = e[i--] << (32 - c);
  16044. }
  16045. else {
  16046. n = 0;
  16047. i--;
  16048. }
  16049. if (c < 5) {
  16050. n |= e[i--] << (6 - c);
  16051. c += 26;
  16052. }
  16053. y = (int)((n >> 27) & 0x1f);
  16054. n <<= 5;
  16055. c -= 5;
  16056. XMEMCPY(rt, t[y], sizeof(sp_digit) * 162);
  16057. while ((i >= 0) || (c >= 5)) {
  16058. if (c >= 5) {
  16059. y = (byte)((n >> 27) & 0x1f);
  16060. n <<= 5;
  16061. c -= 5;
  16062. }
  16063. else if (c == 0) {
  16064. n = e[i--] << 6;
  16065. y = (byte)((n >> 27) & 0x1f);
  16066. n <<= 5;
  16067. c = 21;
  16068. }
  16069. else {
  16070. y = (byte)((n >> 27) & 0x1f);
  16071. n = e[i--] << 6;
  16072. c = 5 - c;
  16073. y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
  16074. n <<= c;
  16075. c = 26 - c;
  16076. }
  16077. sp_4096_mont_sqr_81(rt, rt, m, mp);
  16078. sp_4096_mont_sqr_81(rt, rt, m, mp);
  16079. sp_4096_mont_sqr_81(rt, rt, m, mp);
  16080. sp_4096_mont_sqr_81(rt, rt, m, mp);
  16081. sp_4096_mont_sqr_81(rt, rt, m, mp);
  16082. sp_4096_mont_mul_81(rt, rt, t[y], m, mp);
  16083. }
  16084. sp_4096_mont_reduce_81(rt, m, mp);
  16085. n = sp_4096_cmp_81(rt, m);
  16086. sp_4096_cond_sub_81(rt, rt, m, ~(n >> 31));
  16087. XMEMCPY(r, rt, sizeof(sp_digit) * 162);
  16088. }
  16089. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  16090. if (td != NULL)
  16091. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  16092. #endif
  16093. return err;
  16094. #endif
  16095. }
  16096. #endif /* WOLFSSL_HAVE_SP_RSA & !SP_RSA_PRIVATE_EXP_D */
  16097. #endif /* (WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH) & !WOLFSSL_RSA_PUBLIC_ONLY */
  16098. /* r = 2^n mod m where n is the number of bits to reduce by.
  16099. * Given m must be 4096 bits, just need to subtract.
  16100. *
  16101. * r A single precision number.
  16102. * m A single precision number.
  16103. */
  16104. static void sp_4096_mont_norm_162(sp_digit* r, const sp_digit* m)
  16105. {
  16106. /* Set r = 2^n - 1. */
  16107. int i;
  16108. for (i = 0; i < 152; i += 8) {
  16109. r[i + 0] = 0x3ffffff;
  16110. r[i + 1] = 0x3ffffff;
  16111. r[i + 2] = 0x3ffffff;
  16112. r[i + 3] = 0x3ffffff;
  16113. r[i + 4] = 0x3ffffff;
  16114. r[i + 5] = 0x3ffffff;
  16115. r[i + 6] = 0x3ffffff;
  16116. r[i + 7] = 0x3ffffff;
  16117. }
  16118. r[152] = 0x3ffffff;
  16119. r[153] = 0x3ffffff;
  16120. r[154] = 0x3ffffff;
  16121. r[155] = 0x3ffffff;
  16122. r[156] = 0x3ffffff;
  16123. r[157] = 0x3fffL;
  16124. r[158] = 0;
  16125. r[159] = 0;
  16126. r[160] = 0;
  16127. r[161] = 0;
  16128. /* r = (2^n - 1) mod n */
  16129. (void)sp_4096_sub_162(r, r, m);
  16130. /* Add one so r = 2^n mod m */
  16131. r[0] += 1;
  16132. }
  16133. /* Compare a with b in constant time.
  16134. *
  16135. * a A single precision integer.
  16136. * b A single precision integer.
  16137. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  16138. * respectively.
  16139. */
  16140. static sp_digit sp_4096_cmp_162(const sp_digit* a, const sp_digit* b)
  16141. {
  16142. sp_digit r = 0;
  16143. int i;
  16144. r |= (a[161] - b[161]) & (0 - (sp_digit)1);
  16145. r |= (a[160] - b[160]) & ~(((sp_digit)0 - r) >> 25);
  16146. for (i = 152; i >= 0; i -= 8) {
  16147. r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 25);
  16148. r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 25);
  16149. r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 25);
  16150. r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 25);
  16151. r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 25);
  16152. r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 25);
  16153. r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 25);
  16154. r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 25);
  16155. }
  16156. return r;
  16157. }
  16158. /* Conditionally subtract b from a using the mask m.
  16159. * m is -1 to subtract and 0 when not.
  16160. *
  16161. * r A single precision number representing condition subtract result.
  16162. * a A single precision number to subtract from.
  16163. * b A single precision number to subtract.
  16164. * m Mask value to apply.
  16165. */
  16166. static void sp_4096_cond_sub_162(sp_digit* r, const sp_digit* a,
  16167. const sp_digit* b, const sp_digit m)
  16168. {
  16169. int i;
  16170. for (i = 0; i < 160; i += 8) {
  16171. r[i + 0] = a[i + 0] - (b[i + 0] & m);
  16172. r[i + 1] = a[i + 1] - (b[i + 1] & m);
  16173. r[i + 2] = a[i + 2] - (b[i + 2] & m);
  16174. r[i + 3] = a[i + 3] - (b[i + 3] & m);
  16175. r[i + 4] = a[i + 4] - (b[i + 4] & m);
  16176. r[i + 5] = a[i + 5] - (b[i + 5] & m);
  16177. r[i + 6] = a[i + 6] - (b[i + 6] & m);
  16178. r[i + 7] = a[i + 7] - (b[i + 7] & m);
  16179. }
  16180. r[160] = a[160] - (b[160] & m);
  16181. r[161] = a[161] - (b[161] & m);
  16182. }
  16183. /* Mul a by scalar b and add into r. (r += a * b)
  16184. *
  16185. * r A single precision integer.
  16186. * a A single precision integer.
  16187. * b A scalar.
  16188. */
  16189. SP_NOINLINE static void sp_4096_mul_add_162(sp_digit* r, const sp_digit* a,
  16190. const sp_digit b)
  16191. {
  16192. #ifndef WOLFSSL_SP_LARGE_CODE
  16193. sp_int64 tb = b;
  16194. sp_int64 t = 0;
  16195. int i;
  16196. for (i = 0; i < 162; i++) {
  16197. t += r[i];
  16198. t += tb * a[i];
  16199. r[i] = ((sp_digit)t) & 0x3ffffff;
  16200. t >>= 26;
  16201. }
  16202. r[162] += (sp_digit)t;
  16203. #else
  16204. sp_int64 tb = b;
  16205. sp_int64 t[8];
  16206. int i;
  16207. t[0] = 0;
  16208. for (i = 0; i < 160; i += 8) {
  16209. t[0] += (tb * a[i+0]) + r[i+0];
  16210. t[1] = (tb * a[i+1]) + r[i+1];
  16211. t[2] = (tb * a[i+2]) + r[i+2];
  16212. t[3] = (tb * a[i+3]) + r[i+3];
  16213. t[4] = (tb * a[i+4]) + r[i+4];
  16214. t[5] = (tb * a[i+5]) + r[i+5];
  16215. t[6] = (tb * a[i+6]) + r[i+6];
  16216. t[7] = (tb * a[i+7]) + r[i+7];
  16217. r[i+0] = t[0] & 0x3ffffff;
  16218. t[1] += t[0] >> 26;
  16219. r[i+1] = t[1] & 0x3ffffff;
  16220. t[2] += t[1] >> 26;
  16221. r[i+2] = t[2] & 0x3ffffff;
  16222. t[3] += t[2] >> 26;
  16223. r[i+3] = t[3] & 0x3ffffff;
  16224. t[4] += t[3] >> 26;
  16225. r[i+4] = t[4] & 0x3ffffff;
  16226. t[5] += t[4] >> 26;
  16227. r[i+5] = t[5] & 0x3ffffff;
  16228. t[6] += t[5] >> 26;
  16229. r[i+6] = t[6] & 0x3ffffff;
  16230. t[7] += t[6] >> 26;
  16231. r[i+7] = t[7] & 0x3ffffff;
  16232. t[0] = t[7] >> 26;
  16233. }
  16234. t[0] += (tb * a[160]) + r[160];
  16235. t[1] = (tb * a[161]) + r[161];
  16236. r[160] = t[0] & 0x3ffffff;
  16237. t[1] += t[0] >> 26;
  16238. r[161] = t[1] & 0x3ffffff;
  16239. r[162] += (sp_digit)(t[1] >> 26);
  16240. #endif /* !WOLFSSL_SP_LARGE_CODE */
  16241. }
  16242. /* Shift the result in the high 4096 bits down to the bottom.
  16243. *
  16244. * r A single precision number.
  16245. * a A single precision number.
  16246. */
  16247. static void sp_4096_mont_shift_162(sp_digit* r, const sp_digit* a)
  16248. {
  16249. int i;
  16250. sp_int64 n = a[157] >> 14;
  16251. n += ((sp_int64)a[158]) << 12;
  16252. for (i = 0; i < 152; i += 8) {
  16253. r[i + 0] = n & 0x3ffffff;
  16254. n >>= 26; n += ((sp_int64)a[i + 159]) << 12;
  16255. r[i + 1] = n & 0x3ffffff;
  16256. n >>= 26; n += ((sp_int64)a[i + 160]) << 12;
  16257. r[i + 2] = n & 0x3ffffff;
  16258. n >>= 26; n += ((sp_int64)a[i + 161]) << 12;
  16259. r[i + 3] = n & 0x3ffffff;
  16260. n >>= 26; n += ((sp_int64)a[i + 162]) << 12;
  16261. r[i + 4] = n & 0x3ffffff;
  16262. n >>= 26; n += ((sp_int64)a[i + 163]) << 12;
  16263. r[i + 5] = n & 0x3ffffff;
  16264. n >>= 26; n += ((sp_int64)a[i + 164]) << 12;
  16265. r[i + 6] = n & 0x3ffffff;
  16266. n >>= 26; n += ((sp_int64)a[i + 165]) << 12;
  16267. r[i + 7] = n & 0x3ffffff;
  16268. n >>= 26; n += ((sp_int64)a[i + 166]) << 12;
  16269. }
  16270. r[152] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[311]) << 12;
  16271. r[153] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[312]) << 12;
  16272. r[154] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[313]) << 12;
  16273. r[155] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[314]) << 12;
  16274. r[156] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[315]) << 12;
  16275. r[157] = (sp_digit)n;
  16276. XMEMSET(&r[158], 0, sizeof(*r) * 158U);
  16277. }
  16278. /* Reduce the number back to 4096 bits using Montgomery reduction.
  16279. *
  16280. * a A single precision number to reduce in place.
  16281. * m The single precision number representing the modulus.
  16282. * mp The digit representing the negative inverse of m mod 2^n.
  16283. */
  16284. static void sp_4096_mont_reduce_162(sp_digit* a, const sp_digit* m, sp_digit mp)
  16285. {
  16286. int i;
  16287. sp_digit mu;
  16288. sp_digit over;
  16289. sp_4096_norm_162(a + 158);
  16290. #ifdef WOLFSSL_SP_DH
  16291. if (mp != 1) {
  16292. for (i=0; i<157; i++) {
  16293. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x3ffffff;
  16294. sp_4096_mul_add_162(a+i, m, mu);
  16295. a[i+1] += a[i] >> 26;
  16296. }
  16297. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x3fffL;
  16298. sp_4096_mul_add_162(a+i, m, mu);
  16299. a[i+1] += a[i] >> 26;
  16300. a[i] &= 0x3ffffff;
  16301. }
  16302. else {
  16303. for (i=0; i<157; i++) {
  16304. mu = a[i] & 0x3ffffff;
  16305. sp_4096_mul_add_162(a+i, m, mu);
  16306. a[i+1] += a[i] >> 26;
  16307. }
  16308. mu = a[i] & 0x3fffL;
  16309. sp_4096_mul_add_162(a+i, m, mu);
  16310. a[i+1] += a[i] >> 26;
  16311. a[i] &= 0x3ffffff;
  16312. }
  16313. #else
  16314. for (i=0; i<157; i++) {
  16315. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x3ffffff;
  16316. sp_4096_mul_add_162(a+i, m, mu);
  16317. a[i+1] += a[i] >> 26;
  16318. }
  16319. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x3fffL;
  16320. sp_4096_mul_add_162(a+i, m, mu);
  16321. a[i+1] += a[i] >> 26;
  16322. a[i] &= 0x3ffffff;
  16323. #endif
  16324. sp_4096_mont_shift_162(a, a);
  16325. over = a[157] - m[157];
  16326. sp_4096_cond_sub_162(a, a, m, ~((over - 1) >> 31));
  16327. sp_4096_norm_162(a);
  16328. }
  16329. /* Multiply two Montgomery form numbers mod the modulus (prime).
  16330. * (r = a * b mod m)
  16331. *
  16332. * r Result of multiplication.
  16333. * a First number to multiply in Montgomery form.
  16334. * b Second number to multiply in Montgomery form.
  16335. * m Modulus (prime).
  16336. * mp Montgomery mulitplier.
  16337. */
  16338. SP_NOINLINE static void sp_4096_mont_mul_162(sp_digit* r, const sp_digit* a,
  16339. const sp_digit* b, const sp_digit* m, sp_digit mp)
  16340. {
  16341. sp_4096_mul_162(r, a, b);
  16342. sp_4096_mont_reduce_162(r, m, mp);
  16343. }
  16344. /* Square the Montgomery form number. (r = a * a mod m)
  16345. *
  16346. * r Result of squaring.
  16347. * a Number to square in Montgomery form.
  16348. * m Modulus (prime).
  16349. * mp Montgomery mulitplier.
  16350. */
  16351. SP_NOINLINE static void sp_4096_mont_sqr_162(sp_digit* r, const sp_digit* a,
  16352. const sp_digit* m, sp_digit mp)
  16353. {
  16354. sp_4096_sqr_162(r, a);
  16355. sp_4096_mont_reduce_162(r, m, mp);
  16356. }
  16357. /* Multiply a by scalar b into r. (r = a * b)
  16358. *
  16359. * r A single precision integer.
  16360. * a A single precision integer.
  16361. * b A scalar.
  16362. */
  16363. SP_NOINLINE static void sp_4096_mul_d_324(sp_digit* r, const sp_digit* a,
  16364. sp_digit b)
  16365. {
  16366. sp_int64 tb = b;
  16367. sp_int64 t = 0;
  16368. sp_digit t2;
  16369. sp_int64 p[4];
  16370. int i;
  16371. for (i = 0; i < 324; i += 4) {
  16372. p[0] = tb * a[i + 0];
  16373. p[1] = tb * a[i + 1];
  16374. p[2] = tb * a[i + 2];
  16375. p[3] = tb * a[i + 3];
  16376. t += p[0];
  16377. t2 = (sp_digit)(t & 0x3ffffff);
  16378. t >>= 26;
  16379. r[i + 0] = (sp_digit)t2;
  16380. t += p[1];
  16381. t2 = (sp_digit)(t & 0x3ffffff);
  16382. t >>= 26;
  16383. r[i + 1] = (sp_digit)t2;
  16384. t += p[2];
  16385. t2 = (sp_digit)(t & 0x3ffffff);
  16386. t >>= 26;
  16387. r[i + 2] = (sp_digit)t2;
  16388. t += p[3];
  16389. t2 = (sp_digit)(t & 0x3ffffff);
  16390. t >>= 26;
  16391. r[i + 3] = (sp_digit)t2;
  16392. }
  16393. r[324] = (sp_digit)(t & 0x3ffffff);
  16394. }
  16395. #ifndef WOLFSSL_SP_SMALL
  16396. /* Conditionally add a and b using the mask m.
  16397. * m is -1 to add and 0 when not.
  16398. *
  16399. * r A single precision number representing conditional add result.
  16400. * a A single precision number to add with.
  16401. * b A single precision number to add.
  16402. * m Mask value to apply.
  16403. */
  16404. static void sp_4096_cond_add_162(sp_digit* r, const sp_digit* a,
  16405. const sp_digit* b, const sp_digit m)
  16406. {
  16407. int i;
  16408. for (i = 0; i < 160; i += 8) {
  16409. r[i + 0] = a[i + 0] + (b[i + 0] & m);
  16410. r[i + 1] = a[i + 1] + (b[i + 1] & m);
  16411. r[i + 2] = a[i + 2] + (b[i + 2] & m);
  16412. r[i + 3] = a[i + 3] + (b[i + 3] & m);
  16413. r[i + 4] = a[i + 4] + (b[i + 4] & m);
  16414. r[i + 5] = a[i + 5] + (b[i + 5] & m);
  16415. r[i + 6] = a[i + 6] + (b[i + 6] & m);
  16416. r[i + 7] = a[i + 7] + (b[i + 7] & m);
  16417. }
  16418. r[160] = a[160] + (b[160] & m);
  16419. r[161] = a[161] + (b[161] & m);
  16420. }
  16421. #endif /* !WOLFSSL_SP_SMALL */
  16422. SP_NOINLINE static void sp_4096_rshift_162(sp_digit* r, const sp_digit* a,
  16423. byte n)
  16424. {
  16425. int i;
  16426. for (i=0; i<160; i += 8) {
  16427. r[i+0] = (a[i+0] >> n) | ((a[i+1] << (26 - n)) & 0x3ffffff);
  16428. r[i+1] = (a[i+1] >> n) | ((a[i+2] << (26 - n)) & 0x3ffffff);
  16429. r[i+2] = (a[i+2] >> n) | ((a[i+3] << (26 - n)) & 0x3ffffff);
  16430. r[i+3] = (a[i+3] >> n) | ((a[i+4] << (26 - n)) & 0x3ffffff);
  16431. r[i+4] = (a[i+4] >> n) | ((a[i+5] << (26 - n)) & 0x3ffffff);
  16432. r[i+5] = (a[i+5] >> n) | ((a[i+6] << (26 - n)) & 0x3ffffff);
  16433. r[i+6] = (a[i+6] >> n) | ((a[i+7] << (26 - n)) & 0x3ffffff);
  16434. r[i+7] = (a[i+7] >> n) | ((a[i+8] << (26 - n)) & 0x3ffffff);
  16435. }
  16436. r[160] = (a[160] >> n) | ((a[161] << (26 - n)) & 0x3ffffff);
  16437. r[161] = a[161] >> n;
  16438. }
  16439. static WC_INLINE sp_digit sp_4096_div_word_162(sp_digit d1, sp_digit d0,
  16440. sp_digit div)
  16441. {
  16442. #ifdef SP_USE_DIVTI3
  16443. sp_int64 d = ((sp_int64)d1 << 26) + d0;
  16444. return d / div;
  16445. #elif defined(__x86_64__) || defined(__i386__)
  16446. sp_int64 d = ((sp_int64)d1 << 26) + d0;
  16447. sp_uint32 lo = (sp_uint32)d;
  16448. sp_digit hi = (sp_digit)(d >> 32);
  16449. __asm__ __volatile__ (
  16450. "idiv %2"
  16451. : "+a" (lo)
  16452. : "d" (hi), "r" (div)
  16453. : "cc"
  16454. );
  16455. return (sp_digit)lo;
  16456. #elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV)
  16457. sp_int64 d = ((sp_int64)d1 << 26) + d0;
  16458. sp_digit dv = (div >> 1) + 1;
  16459. sp_digit t1 = (sp_digit)(d >> 26);
  16460. sp_digit t0 = (sp_digit)(d & 0x3ffffff);
  16461. sp_digit t2;
  16462. sp_digit sign;
  16463. sp_digit r;
  16464. int i;
  16465. sp_int64 m;
  16466. r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
  16467. t1 -= dv & (0 - r);
  16468. for (i = 24; i >= 1; i--) {
  16469. t1 += t1 + (((sp_uint32)t0 >> 25) & 1);
  16470. t0 <<= 1;
  16471. t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
  16472. r += r + t2;
  16473. t1 -= dv & (0 - t2);
  16474. t1 += t2;
  16475. }
  16476. r += r + 1;
  16477. m = d - ((sp_int64)r * div);
  16478. r += (sp_digit)(m >> 26);
  16479. m = d - ((sp_int64)r * div);
  16480. r += (sp_digit)(m >> 52) - (sp_digit)(d >> 52);
  16481. m = d - ((sp_int64)r * div);
  16482. sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
  16483. m *= sign;
  16484. t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
  16485. r += sign * t2;
  16486. m = d - ((sp_int64)r * div);
  16487. sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
  16488. m *= sign;
  16489. t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
  16490. r += sign * t2;
  16491. return r;
  16492. #else
  16493. sp_int64 d = ((sp_int64)d1 << 26) + d0;
  16494. sp_digit r = 0;
  16495. sp_digit t;
  16496. sp_digit dv = (div >> 11) + 1;
  16497. t = (sp_digit)(d >> 22);
  16498. t = (t / dv) << 11;
  16499. r += t;
  16500. d -= (sp_int64)t * div;
  16501. t = (sp_digit)(d >> 7);
  16502. t = t / (dv << 4);
  16503. r += t;
  16504. d -= (sp_int64)t * div;
  16505. t = (sp_digit)d;
  16506. t = t / div;
  16507. r += t;
  16508. d -= (sp_int64)t * div;
  16509. return r;
  16510. #endif
  16511. }
  16512. static WC_INLINE sp_digit sp_4096_word_div_word_162(sp_digit d, sp_digit div)
  16513. {
  16514. #if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
  16515. defined(SP_DIV_WORD_USE_DIV)
  16516. return d / div;
  16517. #else
  16518. return (sp_digit)((sp_uint32)(div - d) >> 31);
  16519. #endif
  16520. }
  16521. /* Divide d in a and put remainder into r (m*d + r = a)
  16522. * m is not calculated as it is not needed at this time.
  16523. *
  16524. * Full implementation.
  16525. *
  16526. * a Number to be divided.
  16527. * d Number to divide with.
  16528. * m Multiplier result.
  16529. * r Remainder from the division.
  16530. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  16531. */
  16532. static int sp_4096_div_162(const sp_digit* a, const sp_digit* d,
  16533. const sp_digit* m, sp_digit* r)
  16534. {
  16535. int i;
  16536. #ifndef WOLFSSL_SP_DIV_32
  16537. #endif
  16538. sp_digit dv;
  16539. sp_digit r1;
  16540. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  16541. sp_digit* t1 = NULL;
  16542. #else
  16543. sp_digit t1[4 * 162 + 3];
  16544. #endif
  16545. sp_digit* t2 = NULL;
  16546. sp_digit* sd = NULL;
  16547. int err = MP_OKAY;
  16548. (void)m;
  16549. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  16550. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 162 + 3), NULL,
  16551. DYNAMIC_TYPE_TMP_BUFFER);
  16552. if (t1 == NULL)
  16553. err = MEMORY_E;
  16554. #endif
  16555. (void)m;
  16556. if (err == MP_OKAY) {
  16557. t2 = t1 + 324 + 1;
  16558. sd = t2 + 162 + 1;
  16559. sp_4096_mul_d_162(sd, d, (sp_digit)1 << 12);
  16560. sp_4096_mul_d_324(t1, a, (sp_digit)1 << 12);
  16561. dv = sd[157];
  16562. t1[158 + 158] += t1[158 + 158 - 1] >> 26;
  16563. t1[158 + 158 - 1] &= 0x3ffffff;
  16564. for (i=158; i>=0; i--) {
  16565. r1 = sp_4096_div_word_162(t1[158 + i], t1[158 + i - 1], dv);
  16566. sp_4096_mul_d_162(t2, sd, r1);
  16567. (void)sp_4096_sub_162(&t1[i], &t1[i], t2);
  16568. sp_4096_norm_158(&t1[i]);
  16569. t1[158 + i] += t1[158 + i - 1] >> 26;
  16570. t1[158 + i - 1] &= 0x3ffffff;
  16571. r1 = sp_4096_div_word_162(-t1[158 + i], -t1[158 + i - 1], dv);
  16572. r1 -= t1[158 + i];
  16573. sp_4096_mul_d_162(t2, sd, r1);
  16574. (void)sp_4096_add_162(&t1[i], &t1[i], t2);
  16575. t1[158 + i] += t1[158 + i - 1] >> 26;
  16576. t1[158 + i - 1] &= 0x3ffffff;
  16577. }
  16578. t1[158 - 1] += t1[158 - 2] >> 26;
  16579. t1[158 - 2] &= 0x3ffffff;
  16580. r1 = sp_4096_word_div_word_162(t1[158 - 1], dv);
  16581. sp_4096_mul_d_162(t2, sd, r1);
  16582. sp_4096_sub_162(t1, t1, t2);
  16583. XMEMCPY(r, t1, sizeof(*r) * 324U);
  16584. for (i=0; i<157; i++) {
  16585. r[i+1] += r[i] >> 26;
  16586. r[i] &= 0x3ffffff;
  16587. }
  16588. sp_4096_cond_add_162(r, r, sd, r[157] >> 31);
  16589. sp_4096_norm_158(r);
  16590. sp_4096_rshift_162(r, r, 12);
  16591. r[158] = 0;
  16592. r[159] = 0;
  16593. r[160] = 0;
  16594. r[161] = 0;
  16595. }
  16596. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  16597. if (t1 != NULL)
  16598. XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  16599. #endif
  16600. return err;
  16601. }
  16602. /* Reduce a modulo m into r. (r = a mod m)
  16603. *
  16604. * r A single precision number that is the reduced result.
  16605. * a A single precision number that is to be reduced.
  16606. * m A single precision number that is the modulus to reduce with.
  16607. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  16608. */
  16609. static int sp_4096_mod_162(sp_digit* r, const sp_digit* a, const sp_digit* m)
  16610. {
  16611. return sp_4096_div_162(a, m, NULL, r);
  16612. }
  16613. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
  16614. #if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \
  16615. defined(WOLFSSL_HAVE_SP_DH)
  16616. /* Modular exponentiate a to the e mod m. (r = a^e mod m)
  16617. *
  16618. * r A single precision number that is the result of the operation.
  16619. * a A single precision number being exponentiated.
  16620. * e A single precision number that is the exponent.
  16621. * bits The number of bits in the exponent.
  16622. * m A single precision number that is the modulus.
  16623. * returns 0 on success.
  16624. * returns MEMORY_E on dynamic memory allocation failure.
  16625. * returns MP_VAL when base is even or exponent is 0.
  16626. */
  16627. static int sp_4096_mod_exp_162(sp_digit* r, const sp_digit* a, const sp_digit* e,
  16628. int bits, const sp_digit* m, int reduceA)
  16629. {
  16630. #if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP)
  16631. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  16632. sp_digit* td = NULL;
  16633. #else
  16634. sp_digit td[3 * 324];
  16635. #endif
  16636. sp_digit* t[3] = {0, 0, 0};
  16637. sp_digit* norm = NULL;
  16638. sp_digit mp = 1;
  16639. sp_digit n;
  16640. int i;
  16641. int c;
  16642. byte y;
  16643. int err = MP_OKAY;
  16644. if (bits == 0) {
  16645. err = MP_VAL;
  16646. }
  16647. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  16648. if (err == MP_OKAY) {
  16649. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 162 * 2, NULL,
  16650. DYNAMIC_TYPE_TMP_BUFFER);
  16651. if (td == NULL)
  16652. err = MEMORY_E;
  16653. }
  16654. #endif
  16655. if (err == MP_OKAY) {
  16656. norm = td;
  16657. for (i=0; i<3; i++) {
  16658. t[i] = td + (i * 162 * 2);
  16659. XMEMSET(t[i], 0, sizeof(sp_digit) * 162U * 2U);
  16660. }
  16661. sp_4096_mont_setup(m, &mp);
  16662. sp_4096_mont_norm_162(norm, m);
  16663. if (reduceA != 0) {
  16664. err = sp_4096_mod_162(t[1], a, m);
  16665. }
  16666. else {
  16667. XMEMCPY(t[1], a, sizeof(sp_digit) * 162U);
  16668. }
  16669. }
  16670. if (err == MP_OKAY) {
  16671. sp_4096_mul_162(t[1], t[1], norm);
  16672. err = sp_4096_mod_162(t[1], t[1], m);
  16673. }
  16674. if (err == MP_OKAY) {
  16675. i = bits / 26;
  16676. c = bits % 26;
  16677. n = e[i--] << (26 - c);
  16678. for (; ; c--) {
  16679. if (c == 0) {
  16680. if (i == -1) {
  16681. break;
  16682. }
  16683. n = e[i--];
  16684. c = 26;
  16685. }
  16686. y = (int)((n >> 25) & 1);
  16687. n <<= 1;
  16688. sp_4096_mont_mul_162(t[y^1], t[0], t[1], m, mp);
  16689. XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
  16690. ((size_t)t[1] & addr_mask[y])),
  16691. sizeof(*t[2]) * 162 * 2);
  16692. sp_4096_mont_sqr_162(t[2], t[2], m, mp);
  16693. XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
  16694. ((size_t)t[1] & addr_mask[y])), t[2],
  16695. sizeof(*t[2]) * 162 * 2);
  16696. }
  16697. sp_4096_mont_reduce_162(t[0], m, mp);
  16698. n = sp_4096_cmp_162(t[0], m);
  16699. sp_4096_cond_sub_162(t[0], t[0], m, ~(n >> 31));
  16700. XMEMCPY(r, t[0], sizeof(*r) * 162 * 2);
  16701. }
  16702. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  16703. if (td != NULL)
  16704. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  16705. #endif
  16706. return err;
  16707. #elif !defined(WC_NO_CACHE_RESISTANT)
  16708. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  16709. sp_digit* td = NULL;
  16710. #else
  16711. sp_digit td[3 * 324];
  16712. #endif
  16713. sp_digit* t[3] = {0, 0, 0};
  16714. sp_digit* norm = NULL;
  16715. sp_digit mp = 1;
  16716. sp_digit n;
  16717. int i;
  16718. int c;
  16719. byte y;
  16720. int err = MP_OKAY;
  16721. if (bits == 0) {
  16722. err = MP_VAL;
  16723. }
  16724. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  16725. if (err == MP_OKAY) {
  16726. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 162 * 2, NULL,
  16727. DYNAMIC_TYPE_TMP_BUFFER);
  16728. if (td == NULL)
  16729. err = MEMORY_E;
  16730. }
  16731. #endif
  16732. if (err == MP_OKAY) {
  16733. norm = td;
  16734. for (i=0; i<3; i++) {
  16735. t[i] = td + (i * 162 * 2);
  16736. }
  16737. sp_4096_mont_setup(m, &mp);
  16738. sp_4096_mont_norm_162(norm, m);
  16739. if (reduceA != 0) {
  16740. err = sp_4096_mod_162(t[1], a, m);
  16741. if (err == MP_OKAY) {
  16742. sp_4096_mul_162(t[1], t[1], norm);
  16743. err = sp_4096_mod_162(t[1], t[1], m);
  16744. }
  16745. }
  16746. else {
  16747. sp_4096_mul_162(t[1], a, norm);
  16748. err = sp_4096_mod_162(t[1], t[1], m);
  16749. }
  16750. }
  16751. if (err == MP_OKAY) {
  16752. i = bits / 26;
  16753. c = bits % 26;
  16754. n = e[i--] << (26 - c);
  16755. for (; ; c--) {
  16756. if (c == 0) {
  16757. if (i == -1) {
  16758. break;
  16759. }
  16760. n = e[i--];
  16761. c = 26;
  16762. }
  16763. y = (int)((n >> 25) & 1);
  16764. n <<= 1;
  16765. sp_4096_mont_mul_162(t[y^1], t[0], t[1], m, mp);
  16766. XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
  16767. ((size_t)t[1] & addr_mask[y])),
  16768. sizeof(*t[2]) * 162 * 2);
  16769. sp_4096_mont_sqr_162(t[2], t[2], m, mp);
  16770. XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
  16771. ((size_t)t[1] & addr_mask[y])), t[2],
  16772. sizeof(*t[2]) * 162 * 2);
  16773. }
  16774. sp_4096_mont_reduce_162(t[0], m, mp);
  16775. n = sp_4096_cmp_162(t[0], m);
  16776. sp_4096_cond_sub_162(t[0], t[0], m, ~(n >> 31));
  16777. XMEMCPY(r, t[0], sizeof(*r) * 162 * 2);
  16778. }
  16779. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  16780. if (td != NULL)
  16781. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  16782. #endif
  16783. return err;
  16784. #else
  16785. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  16786. sp_digit* td = NULL;
  16787. #else
  16788. sp_digit td[(16 * 324) + 324];
  16789. #endif
  16790. sp_digit* t[16];
  16791. sp_digit* rt = NULL;
  16792. sp_digit* norm = NULL;
  16793. sp_digit mp = 1;
  16794. sp_digit n;
  16795. int i;
  16796. int c;
  16797. byte y;
  16798. int err = MP_OKAY;
  16799. if (bits == 0) {
  16800. err = MP_VAL;
  16801. }
  16802. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  16803. if (err == MP_OKAY) {
  16804. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((16 * 324) + 324), NULL,
  16805. DYNAMIC_TYPE_TMP_BUFFER);
  16806. if (td == NULL)
  16807. err = MEMORY_E;
  16808. }
  16809. #endif
  16810. if (err == MP_OKAY) {
  16811. norm = td;
  16812. for (i=0; i<16; i++)
  16813. t[i] = td + i * 324;
  16814. rt = td + 5184;
  16815. sp_4096_mont_setup(m, &mp);
  16816. sp_4096_mont_norm_162(norm, m);
  16817. if (reduceA != 0) {
  16818. err = sp_4096_mod_162(t[1], a, m);
  16819. if (err == MP_OKAY) {
  16820. sp_4096_mul_162(t[1], t[1], norm);
  16821. err = sp_4096_mod_162(t[1], t[1], m);
  16822. }
  16823. }
  16824. else {
  16825. sp_4096_mul_162(t[1], a, norm);
  16826. err = sp_4096_mod_162(t[1], t[1], m);
  16827. }
  16828. }
  16829. if (err == MP_OKAY) {
  16830. sp_4096_mont_sqr_162(t[ 2], t[ 1], m, mp);
  16831. sp_4096_mont_mul_162(t[ 3], t[ 2], t[ 1], m, mp);
  16832. sp_4096_mont_sqr_162(t[ 4], t[ 2], m, mp);
  16833. sp_4096_mont_mul_162(t[ 5], t[ 3], t[ 2], m, mp);
  16834. sp_4096_mont_sqr_162(t[ 6], t[ 3], m, mp);
  16835. sp_4096_mont_mul_162(t[ 7], t[ 4], t[ 3], m, mp);
  16836. sp_4096_mont_sqr_162(t[ 8], t[ 4], m, mp);
  16837. sp_4096_mont_mul_162(t[ 9], t[ 5], t[ 4], m, mp);
  16838. sp_4096_mont_sqr_162(t[10], t[ 5], m, mp);
  16839. sp_4096_mont_mul_162(t[11], t[ 6], t[ 5], m, mp);
  16840. sp_4096_mont_sqr_162(t[12], t[ 6], m, mp);
  16841. sp_4096_mont_mul_162(t[13], t[ 7], t[ 6], m, mp);
  16842. sp_4096_mont_sqr_162(t[14], t[ 7], m, mp);
  16843. sp_4096_mont_mul_162(t[15], t[ 8], t[ 7], m, mp);
  16844. bits = ((bits + 3) / 4) * 4;
  16845. i = ((bits + 25) / 26) - 1;
  16846. c = bits % 26;
  16847. if (c == 0) {
  16848. c = 26;
  16849. }
  16850. if (i < 162) {
  16851. n = e[i--] << (32 - c);
  16852. }
  16853. else {
  16854. n = 0;
  16855. i--;
  16856. }
  16857. if (c < 4) {
  16858. n |= e[i--] << (6 - c);
  16859. c += 26;
  16860. }
  16861. y = (int)((n >> 28) & 0xf);
  16862. n <<= 4;
  16863. c -= 4;
  16864. XMEMCPY(rt, t[y], sizeof(sp_digit) * 324);
  16865. while ((i >= 0) || (c >= 4)) {
  16866. if (c >= 4) {
  16867. y = (byte)((n >> 28) & 0xf);
  16868. n <<= 4;
  16869. c -= 4;
  16870. }
  16871. else if (c == 0) {
  16872. n = e[i--] << 6;
  16873. y = (byte)((n >> 28) & 0xf);
  16874. n <<= 4;
  16875. c = 22;
  16876. }
  16877. else {
  16878. y = (byte)((n >> 28) & 0xf);
  16879. n = e[i--] << 6;
  16880. c = 4 - c;
  16881. y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
  16882. n <<= c;
  16883. c = 26 - c;
  16884. }
  16885. sp_4096_mont_sqr_162(rt, rt, m, mp);
  16886. sp_4096_mont_sqr_162(rt, rt, m, mp);
  16887. sp_4096_mont_sqr_162(rt, rt, m, mp);
  16888. sp_4096_mont_sqr_162(rt, rt, m, mp);
  16889. sp_4096_mont_mul_162(rt, rt, t[y], m, mp);
  16890. }
  16891. sp_4096_mont_reduce_162(rt, m, mp);
  16892. n = sp_4096_cmp_162(rt, m);
  16893. sp_4096_cond_sub_162(rt, rt, m, ~(n >> 31));
  16894. XMEMCPY(r, rt, sizeof(sp_digit) * 324);
  16895. }
  16896. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  16897. if (td != NULL)
  16898. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  16899. #endif
  16900. return err;
  16901. #endif
  16902. }
  16903. #endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) || */
  16904. /* WOLFSSL_HAVE_SP_DH */
  16905. #endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
  16906. #ifdef WOLFSSL_HAVE_SP_RSA
  16907. /* RSA public key operation.
  16908. *
  16909. * in Array of bytes representing the number to exponentiate, base.
  16910. * inLen Number of bytes in base.
  16911. * em Public exponent.
  16912. * mm Modulus.
  16913. * out Buffer to hold big-endian bytes of exponentiation result.
  16914. * Must be at least 512 bytes long.
  16915. * outLen Number of bytes in result.
  16916. * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
  16917. * an array is too long and MEMORY_E when dynamic memory allocation fails.
  16918. */
  16919. int sp_RsaPublic_4096(const byte* in, word32 inLen, const mp_int* em,
  16920. const mp_int* mm, byte* out, word32* outLen)
  16921. {
  16922. #ifdef WOLFSSL_SP_SMALL
  16923. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  16924. sp_digit* a = NULL;
  16925. #else
  16926. sp_digit a[162 * 5];
  16927. #endif
  16928. sp_digit* m = NULL;
  16929. sp_digit* r = NULL;
  16930. sp_digit* norm = NULL;
  16931. sp_digit e[1] = {0};
  16932. sp_digit mp = 0;
  16933. int i;
  16934. int err = MP_OKAY;
  16935. if (*outLen < 512U) {
  16936. err = MP_TO_E;
  16937. }
  16938. if (err == MP_OKAY) {
  16939. if (mp_count_bits(em) > 26) {
  16940. err = MP_READ_E;
  16941. }
  16942. else if (inLen > 512U) {
  16943. err = MP_READ_E;
  16944. }
  16945. else if (mp_count_bits(mm) != 4096) {
  16946. err = MP_READ_E;
  16947. }
  16948. else if (mp_iseven(mm)) {
  16949. err = MP_VAL;
  16950. }
  16951. }
  16952. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  16953. if (err == MP_OKAY) {
  16954. a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 162 * 5, NULL,
  16955. DYNAMIC_TYPE_RSA);
  16956. if (a == NULL)
  16957. err = MEMORY_E;
  16958. }
  16959. #endif
  16960. if (err == MP_OKAY) {
  16961. r = a + 162 * 2;
  16962. m = r + 162 * 2;
  16963. norm = r;
  16964. sp_4096_from_bin(a, 162, in, inLen);
  16965. #if DIGIT_BIT >= 26
  16966. e[0] = (sp_digit)em->dp[0];
  16967. #else
  16968. e[0] = (sp_digit)em->dp[0];
  16969. if (em->used > 1) {
  16970. e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
  16971. }
  16972. #endif
  16973. if (e[0] == 0) {
  16974. err = MP_EXPTMOD_E;
  16975. }
  16976. }
  16977. if (err == MP_OKAY) {
  16978. sp_4096_from_mp(m, 162, mm);
  16979. sp_4096_mont_setup(m, &mp);
  16980. sp_4096_mont_norm_162(norm, m);
  16981. }
  16982. if (err == MP_OKAY) {
  16983. sp_4096_mul_162(a, a, norm);
  16984. err = sp_4096_mod_162(a, a, m);
  16985. }
  16986. if (err == MP_OKAY) {
  16987. for (i=25; i>=0; i--) {
  16988. if ((e[0] >> i) != 0) {
  16989. break;
  16990. }
  16991. }
  16992. XMEMCPY(r, a, sizeof(sp_digit) * 162 * 2);
  16993. for (i--; i>=0; i--) {
  16994. sp_4096_mont_sqr_162(r, r, m, mp);
  16995. if (((e[0] >> i) & 1) == 1) {
  16996. sp_4096_mont_mul_162(r, r, a, m, mp);
  16997. }
  16998. }
  16999. sp_4096_mont_reduce_162(r, m, mp);
  17000. mp = sp_4096_cmp_162(r, m);
  17001. sp_4096_cond_sub_162(r, r, m, ~(mp >> 31));
  17002. sp_4096_to_bin_162(r, out);
  17003. *outLen = 512;
  17004. }
  17005. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17006. if (a != NULL)
  17007. XFREE(a, NULL, DYNAMIC_TYPE_RSA);
  17008. #endif
  17009. return err;
  17010. #else
  17011. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17012. sp_digit* d = NULL;
  17013. #else
  17014. sp_digit d[162 * 5];
  17015. #endif
  17016. sp_digit* a = NULL;
  17017. sp_digit* m = NULL;
  17018. sp_digit* r = NULL;
  17019. sp_digit e[1] = {0};
  17020. int err = MP_OKAY;
  17021. if (*outLen < 512U) {
  17022. err = MP_TO_E;
  17023. }
  17024. if (err == MP_OKAY) {
  17025. if (mp_count_bits(em) > 26) {
  17026. err = MP_READ_E;
  17027. }
  17028. else if (inLen > 512U) {
  17029. err = MP_READ_E;
  17030. }
  17031. else if (mp_count_bits(mm) != 4096) {
  17032. err = MP_READ_E;
  17033. }
  17034. else if (mp_iseven(mm)) {
  17035. err = MP_VAL;
  17036. }
  17037. }
  17038. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17039. if (err == MP_OKAY) {
  17040. d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 162 * 5, NULL,
  17041. DYNAMIC_TYPE_RSA);
  17042. if (d == NULL)
  17043. err = MEMORY_E;
  17044. }
  17045. #endif
  17046. if (err == MP_OKAY) {
  17047. a = d;
  17048. r = a + 162 * 2;
  17049. m = r + 162 * 2;
  17050. sp_4096_from_bin(a, 162, in, inLen);
  17051. #if DIGIT_BIT >= 26
  17052. e[0] = (sp_digit)em->dp[0];
  17053. #else
  17054. e[0] = (sp_digit)em->dp[0];
  17055. if (em->used > 1) {
  17056. e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
  17057. }
  17058. #endif
  17059. if (e[0] == 0) {
  17060. err = MP_EXPTMOD_E;
  17061. }
  17062. }
  17063. if (err == MP_OKAY) {
  17064. sp_4096_from_mp(m, 162, mm);
  17065. if (e[0] == 0x3) {
  17066. sp_4096_sqr_162(r, a);
  17067. err = sp_4096_mod_162(r, r, m);
  17068. if (err == MP_OKAY) {
  17069. sp_4096_mul_162(r, a, r);
  17070. err = sp_4096_mod_162(r, r, m);
  17071. }
  17072. }
  17073. else {
  17074. sp_digit* norm = r;
  17075. int i;
  17076. sp_digit mp;
  17077. sp_4096_mont_setup(m, &mp);
  17078. sp_4096_mont_norm_162(norm, m);
  17079. sp_4096_mul_162(a, a, norm);
  17080. err = sp_4096_mod_162(a, a, m);
  17081. if (err == MP_OKAY) {
  17082. for (i=25; i>=0; i--) {
  17083. if ((e[0] >> i) != 0) {
  17084. break;
  17085. }
  17086. }
  17087. XMEMCPY(r, a, sizeof(sp_digit) * 324U);
  17088. for (i--; i>=0; i--) {
  17089. sp_4096_mont_sqr_162(r, r, m, mp);
  17090. if (((e[0] >> i) & 1) == 1) {
  17091. sp_4096_mont_mul_162(r, r, a, m, mp);
  17092. }
  17093. }
  17094. sp_4096_mont_reduce_162(r, m, mp);
  17095. mp = sp_4096_cmp_162(r, m);
  17096. sp_4096_cond_sub_162(r, r, m, ~(mp >> 31));
  17097. }
  17098. }
  17099. }
  17100. if (err == MP_OKAY) {
  17101. sp_4096_to_bin_162(r, out);
  17102. *outLen = 512;
  17103. }
  17104. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17105. if (d != NULL)
  17106. XFREE(d, NULL, DYNAMIC_TYPE_RSA);
  17107. #endif
  17108. return err;
  17109. #endif /* WOLFSSL_SP_SMALL */
  17110. }
  17111. #ifndef WOLFSSL_RSA_PUBLIC_ONLY
  17112. #if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM)
  17113. #endif /* !SP_RSA_PRIVATE_EXP_D & !RSA_LOW_MEM */
  17114. /* RSA private key operation.
  17115. *
  17116. * in Array of bytes representing the number to exponentiate, base.
  17117. * inLen Number of bytes in base.
  17118. * dm Private exponent.
  17119. * pm First prime.
  17120. * qm Second prime.
  17121. * dpm First prime's CRT exponent.
  17122. * dqm Second prime's CRT exponent.
  17123. * qim Inverse of second prime mod p.
  17124. * mm Modulus.
  17125. * out Buffer to hold big-endian bytes of exponentiation result.
  17126. * Must be at least 512 bytes long.
  17127. * outLen Number of bytes in result.
  17128. * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
  17129. * an array is too long and MEMORY_E when dynamic memory allocation fails.
  17130. */
  17131. int sp_RsaPrivate_4096(const byte* in, word32 inLen, const mp_int* dm,
  17132. const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
  17133. const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
  17134. {
  17135. #if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
  17136. #if defined(WOLFSSL_SP_SMALL)
  17137. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17138. sp_digit* d = NULL;
  17139. #else
  17140. sp_digit d[162 * 4];
  17141. #endif
  17142. sp_digit* a = NULL;
  17143. sp_digit* m = NULL;
  17144. sp_digit* r = NULL;
  17145. int err = MP_OKAY;
  17146. (void)pm;
  17147. (void)qm;
  17148. (void)dpm;
  17149. (void)dqm;
  17150. (void)qim;
  17151. if (*outLen < 512U) {
  17152. err = MP_TO_E;
  17153. }
  17154. if (err == MP_OKAY) {
  17155. if (mp_count_bits(dm) > 4096) {
  17156. err = MP_READ_E;
  17157. }
  17158. else if (inLen > 512) {
  17159. err = MP_READ_E;
  17160. }
  17161. else if (mp_count_bits(mm) != 4096) {
  17162. err = MP_READ_E;
  17163. }
  17164. else if (mp_iseven(mm)) {
  17165. err = MP_VAL;
  17166. }
  17167. }
  17168. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17169. if (err == MP_OKAY) {
  17170. d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 162 * 4, NULL,
  17171. DYNAMIC_TYPE_RSA);
  17172. if (d == NULL)
  17173. err = MEMORY_E;
  17174. }
  17175. #endif
  17176. if (err == MP_OKAY) {
  17177. a = d + 162;
  17178. m = a + 324;
  17179. r = a;
  17180. sp_4096_from_bin(a, 162, in, inLen);
  17181. sp_4096_from_mp(d, 162, dm);
  17182. sp_4096_from_mp(m, 162, mm);
  17183. err = sp_4096_mod_exp_162(r, a, d, 4096, m, 0);
  17184. }
  17185. if (err == MP_OKAY) {
  17186. sp_4096_to_bin_162(r, out);
  17187. *outLen = 512;
  17188. }
  17189. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17190. if (d != NULL)
  17191. #endif
  17192. {
  17193. /* only "a" and "r" are sensitive and need zeroized (same pointer) */
  17194. if (a != NULL)
  17195. ForceZero(a, sizeof(sp_digit) * 162);
  17196. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17197. XFREE(d, NULL, DYNAMIC_TYPE_RSA);
  17198. #endif
  17199. }
  17200. return err;
  17201. #else
  17202. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17203. sp_digit* d = NULL;
  17204. #else
  17205. sp_digit d[162 * 4];
  17206. #endif
  17207. sp_digit* a = NULL;
  17208. sp_digit* m = NULL;
  17209. sp_digit* r = NULL;
  17210. int err = MP_OKAY;
  17211. (void)pm;
  17212. (void)qm;
  17213. (void)dpm;
  17214. (void)dqm;
  17215. (void)qim;
  17216. if (*outLen < 512U) {
  17217. err = MP_TO_E;
  17218. }
  17219. if (err == MP_OKAY) {
  17220. if (mp_count_bits(dm) > 4096) {
  17221. err = MP_READ_E;
  17222. }
  17223. else if (inLen > 512U) {
  17224. err = MP_READ_E;
  17225. }
  17226. else if (mp_count_bits(mm) != 4096) {
  17227. err = MP_READ_E;
  17228. }
  17229. else if (mp_iseven(mm)) {
  17230. err = MP_VAL;
  17231. }
  17232. }
  17233. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17234. if (err == MP_OKAY) {
  17235. d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 162 * 4, NULL,
  17236. DYNAMIC_TYPE_RSA);
  17237. if (d == NULL)
  17238. err = MEMORY_E;
  17239. }
  17240. #endif
  17241. if (err == MP_OKAY) {
  17242. a = d + 162;
  17243. m = a + 324;
  17244. r = a;
  17245. sp_4096_from_bin(a, 162, in, inLen);
  17246. sp_4096_from_mp(d, 162, dm);
  17247. sp_4096_from_mp(m, 162, mm);
  17248. err = sp_4096_mod_exp_162(r, a, d, 4096, m, 0);
  17249. }
  17250. if (err == MP_OKAY) {
  17251. sp_4096_to_bin_162(r, out);
  17252. *outLen = 512;
  17253. }
  17254. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17255. if (d != NULL)
  17256. #endif
  17257. {
  17258. /* only "a" and "r" are sensitive and need zeroized (same pointer) */
  17259. if (a != NULL)
  17260. ForceZero(a, sizeof(sp_digit) * 162);
  17261. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17262. XFREE(d, NULL, DYNAMIC_TYPE_RSA);
  17263. #endif
  17264. }
  17265. return err;
  17266. #endif /* WOLFSSL_SP_SMALL */
  17267. #else
  17268. #if defined(WOLFSSL_SP_SMALL)
  17269. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17270. sp_digit* a = NULL;
  17271. #else
  17272. sp_digit a[81 * 8];
  17273. #endif
  17274. sp_digit* p = NULL;
  17275. sp_digit* dp = NULL;
  17276. sp_digit* dq = NULL;
  17277. sp_digit* qi = NULL;
  17278. sp_digit* tmpa = NULL;
  17279. sp_digit* tmpb = NULL;
  17280. sp_digit* r = NULL;
  17281. int err = MP_OKAY;
  17282. (void)dm;
  17283. (void)mm;
  17284. if (*outLen < 512U) {
  17285. err = MP_TO_E;
  17286. }
  17287. if (err == MP_OKAY) {
  17288. if (inLen > 512) {
  17289. err = MP_READ_E;
  17290. }
  17291. else if (mp_count_bits(mm) != 4096) {
  17292. err = MP_READ_E;
  17293. }
  17294. else if (mp_iseven(mm)) {
  17295. err = MP_VAL;
  17296. }
  17297. else if (mp_iseven(pm)) {
  17298. err = MP_VAL;
  17299. }
  17300. else if (mp_iseven(qm)) {
  17301. err = MP_VAL;
  17302. }
  17303. }
  17304. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17305. if (err == MP_OKAY) {
  17306. a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 81 * 8, NULL,
  17307. DYNAMIC_TYPE_RSA);
  17308. if (a == NULL)
  17309. err = MEMORY_E;
  17310. }
  17311. #endif
  17312. if (err == MP_OKAY) {
  17313. p = a + 162;
  17314. qi = dq = dp = p + 81;
  17315. tmpa = qi + 81;
  17316. tmpb = tmpa + 162;
  17317. r = a;
  17318. sp_4096_from_bin(a, 162, in, inLen);
  17319. sp_4096_from_mp(p, 81, pm);
  17320. sp_4096_from_mp(dp, 81, dpm);
  17321. err = sp_4096_mod_exp_81(tmpa, a, dp, 2048, p, 1);
  17322. }
  17323. if (err == MP_OKAY) {
  17324. sp_4096_from_mp(p, 81, qm);
  17325. sp_4096_from_mp(dq, 81, dqm);
  17326. err = sp_4096_mod_exp_81(tmpb, a, dq, 2048, p, 1);
  17327. }
  17328. if (err == MP_OKAY) {
  17329. sp_4096_from_mp(p, 81, pm);
  17330. (void)sp_4096_sub_81(tmpa, tmpa, tmpb);
  17331. sp_4096_norm_79(tmpa);
  17332. sp_4096_cond_add_81(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[78] >> 31));
  17333. sp_4096_cond_add_81(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[78] >> 31));
  17334. sp_4096_norm_81(tmpa);
  17335. sp_4096_from_mp(qi, 81, qim);
  17336. sp_4096_mul_81(tmpa, tmpa, qi);
  17337. err = sp_4096_mod_81(tmpa, tmpa, p);
  17338. }
  17339. if (err == MP_OKAY) {
  17340. sp_4096_from_mp(p, 81, qm);
  17341. sp_4096_mul_81(tmpa, p, tmpa);
  17342. (void)sp_4096_add_162(r, tmpb, tmpa);
  17343. sp_4096_norm_162(r);
  17344. sp_4096_to_bin_162(r, out);
  17345. *outLen = 512;
  17346. }
  17347. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17348. if (a != NULL)
  17349. #endif
  17350. {
  17351. ForceZero(a, sizeof(sp_digit) * 81 * 8);
  17352. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17353. XFREE(a, NULL, DYNAMIC_TYPE_RSA);
  17354. #endif
  17355. }
  17356. return err;
  17357. #else
  17358. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17359. sp_digit* a = NULL;
  17360. #else
  17361. sp_digit a[81 * 13];
  17362. #endif
  17363. sp_digit* p = NULL;
  17364. sp_digit* q = NULL;
  17365. sp_digit* dp = NULL;
  17366. sp_digit* dq = NULL;
  17367. sp_digit* qi = NULL;
  17368. sp_digit* tmpa = NULL;
  17369. sp_digit* tmpb = NULL;
  17370. sp_digit* r = NULL;
  17371. int err = MP_OKAY;
  17372. (void)dm;
  17373. (void)mm;
  17374. if (*outLen < 512U) {
  17375. err = MP_TO_E;
  17376. }
  17377. if (err == MP_OKAY) {
  17378. if (inLen > 512U) {
  17379. err = MP_READ_E;
  17380. }
  17381. else if (mp_count_bits(mm) != 4096) {
  17382. err = MP_READ_E;
  17383. }
  17384. else if (mp_iseven(mm)) {
  17385. err = MP_VAL;
  17386. }
  17387. else if (mp_iseven(pm)) {
  17388. err = MP_VAL;
  17389. }
  17390. else if (mp_iseven(qm)) {
  17391. err = MP_VAL;
  17392. }
  17393. }
  17394. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17395. if (err == MP_OKAY) {
  17396. a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 81 * 13, NULL,
  17397. DYNAMIC_TYPE_RSA);
  17398. if (a == NULL)
  17399. err = MEMORY_E;
  17400. }
  17401. #endif
  17402. if (err == MP_OKAY) {
  17403. p = a + 162 * 2;
  17404. q = p + 81;
  17405. dp = q + 81;
  17406. dq = dp + 81;
  17407. qi = dq + 81;
  17408. tmpa = qi + 81;
  17409. tmpb = tmpa + 162;
  17410. r = a;
  17411. sp_4096_from_bin(a, 162, in, inLen);
  17412. sp_4096_from_mp(p, 81, pm);
  17413. sp_4096_from_mp(q, 81, qm);
  17414. sp_4096_from_mp(dp, 81, dpm);
  17415. sp_4096_from_mp(dq, 81, dqm);
  17416. sp_4096_from_mp(qi, 81, qim);
  17417. err = sp_4096_mod_exp_81(tmpa, a, dp, 2048, p, 1);
  17418. }
  17419. if (err == MP_OKAY) {
  17420. err = sp_4096_mod_exp_81(tmpb, a, dq, 2048, q, 1);
  17421. }
  17422. if (err == MP_OKAY) {
  17423. (void)sp_4096_sub_81(tmpa, tmpa, tmpb);
  17424. sp_4096_norm_79(tmpa);
  17425. sp_4096_cond_add_81(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[78] >> 31));
  17426. sp_4096_cond_add_81(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[78] >> 31));
  17427. sp_4096_norm_81(tmpa);
  17428. sp_4096_mul_81(tmpa, tmpa, qi);
  17429. err = sp_4096_mod_81(tmpa, tmpa, p);
  17430. }
  17431. if (err == MP_OKAY) {
  17432. sp_4096_mul_81(tmpa, tmpa, q);
  17433. (void)sp_4096_add_162(r, tmpb, tmpa);
  17434. sp_4096_norm_162(r);
  17435. sp_4096_to_bin_162(r, out);
  17436. *outLen = 512;
  17437. }
  17438. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17439. if (a != NULL)
  17440. #endif
  17441. {
  17442. ForceZero(a, sizeof(sp_digit) * 81 * 13);
  17443. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17444. XFREE(a, NULL, DYNAMIC_TYPE_RSA);
  17445. #endif
  17446. }
  17447. return err;
  17448. #endif /* WOLFSSL_SP_SMALL */
  17449. #endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
  17450. }
  17451. #endif /* !WOLFSSL_RSA_PUBLIC_ONLY */
  17452. #endif /* WOLFSSL_HAVE_SP_RSA */
  17453. #if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \
  17454. !defined(WOLFSSL_RSA_PUBLIC_ONLY))
  17455. /* Convert an array of sp_digit to an mp_int.
  17456. *
  17457. * a A single precision integer.
  17458. * r A multi-precision integer.
  17459. */
  17460. static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
  17461. {
  17462. int err;
  17463. err = mp_grow(r, (4096 + DIGIT_BIT - 1) / DIGIT_BIT);
  17464. if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
  17465. #if DIGIT_BIT == 26
  17466. XMEMCPY(r->dp, a, sizeof(sp_digit) * 162);
  17467. r->used = 162;
  17468. mp_clamp(r);
  17469. #elif DIGIT_BIT < 26
  17470. int i;
  17471. int j = 0;
  17472. int s = 0;
  17473. r->dp[0] = 0;
  17474. for (i = 0; i < 162; i++) {
  17475. r->dp[j] |= (mp_digit)(a[i] << s);
  17476. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  17477. s = DIGIT_BIT - s;
  17478. r->dp[++j] = (mp_digit)(a[i] >> s);
  17479. while (s + DIGIT_BIT <= 26) {
  17480. s += DIGIT_BIT;
  17481. r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  17482. if (s == SP_WORD_SIZE) {
  17483. r->dp[j] = 0;
  17484. }
  17485. else {
  17486. r->dp[j] = (mp_digit)(a[i] >> s);
  17487. }
  17488. }
  17489. s = 26 - s;
  17490. }
  17491. r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT;
  17492. mp_clamp(r);
  17493. #else
  17494. int i;
  17495. int j = 0;
  17496. int s = 0;
  17497. r->dp[0] = 0;
  17498. for (i = 0; i < 162; i++) {
  17499. r->dp[j] |= ((mp_digit)a[i]) << s;
  17500. if (s + 26 >= DIGIT_BIT) {
  17501. #if DIGIT_BIT != 32 && DIGIT_BIT != 64
  17502. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  17503. #endif
  17504. s = DIGIT_BIT - s;
  17505. r->dp[++j] = a[i] >> s;
  17506. s = 26 - s;
  17507. }
  17508. else {
  17509. s += 26;
  17510. }
  17511. }
  17512. r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT;
  17513. mp_clamp(r);
  17514. #endif
  17515. }
  17516. return err;
  17517. }
  17518. /* Perform the modular exponentiation for Diffie-Hellman.
  17519. *
  17520. * base Base. MP integer.
  17521. * exp Exponent. MP integer.
  17522. * mod Modulus. MP integer.
  17523. * res Result. MP integer.
  17524. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  17525. * and MEMORY_E if memory allocation fails.
  17526. */
  17527. int sp_ModExp_4096(const mp_int* base, const mp_int* exp, const mp_int* mod,
  17528. mp_int* res)
  17529. {
  17530. #ifdef WOLFSSL_SP_SMALL
  17531. int err = MP_OKAY;
  17532. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17533. sp_digit* b = NULL;
  17534. #else
  17535. sp_digit b[162 * 4];
  17536. #endif
  17537. sp_digit* e = NULL;
  17538. sp_digit* m = NULL;
  17539. sp_digit* r = NULL;
  17540. int expBits = mp_count_bits(exp);
  17541. if (mp_count_bits(base) > 4096) {
  17542. err = MP_READ_E;
  17543. }
  17544. else if (expBits > 4096) {
  17545. err = MP_READ_E;
  17546. }
  17547. else if (mp_count_bits(mod) != 4096) {
  17548. err = MP_READ_E;
  17549. }
  17550. else if (mp_iseven(mod)) {
  17551. err = MP_VAL;
  17552. }
  17553. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17554. if (err == MP_OKAY) {
  17555. b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 162 * 4, NULL,
  17556. DYNAMIC_TYPE_DH);
  17557. if (b == NULL)
  17558. err = MEMORY_E;
  17559. }
  17560. #endif
  17561. if (err == MP_OKAY) {
  17562. e = b + 162 * 2;
  17563. m = e + 162;
  17564. r = b;
  17565. sp_4096_from_mp(b, 162, base);
  17566. sp_4096_from_mp(e, 162, exp);
  17567. sp_4096_from_mp(m, 162, mod);
  17568. err = sp_4096_mod_exp_162(r, b, e, mp_count_bits(exp), m, 0);
  17569. }
  17570. if (err == MP_OKAY) {
  17571. err = sp_4096_to_mp(r, res);
  17572. }
  17573. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17574. if (b != NULL)
  17575. #endif
  17576. {
  17577. /* only "e" is sensitive and needs zeroized */
  17578. if (e != NULL)
  17579. ForceZero(e, sizeof(sp_digit) * 162U);
  17580. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17581. XFREE(b, NULL, DYNAMIC_TYPE_DH);
  17582. #endif
  17583. }
  17584. return err;
  17585. #else
  17586. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17587. sp_digit* b = NULL;
  17588. #else
  17589. sp_digit b[162 * 4];
  17590. #endif
  17591. sp_digit* e = NULL;
  17592. sp_digit* m = NULL;
  17593. sp_digit* r = NULL;
  17594. int err = MP_OKAY;
  17595. int expBits = mp_count_bits(exp);
  17596. if (mp_count_bits(base) > 4096) {
  17597. err = MP_READ_E;
  17598. }
  17599. else if (expBits > 4096) {
  17600. err = MP_READ_E;
  17601. }
  17602. else if (mp_count_bits(mod) != 4096) {
  17603. err = MP_READ_E;
  17604. }
  17605. else if (mp_iseven(mod)) {
  17606. err = MP_VAL;
  17607. }
  17608. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17609. if (err == MP_OKAY) {
  17610. b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 162 * 4, NULL, DYNAMIC_TYPE_DH);
  17611. if (b == NULL)
  17612. err = MEMORY_E;
  17613. }
  17614. #endif
  17615. if (err == MP_OKAY) {
  17616. e = b + 162 * 2;
  17617. m = e + 162;
  17618. r = b;
  17619. sp_4096_from_mp(b, 162, base);
  17620. sp_4096_from_mp(e, 162, exp);
  17621. sp_4096_from_mp(m, 162, mod);
  17622. err = sp_4096_mod_exp_162(r, b, e, expBits, m, 0);
  17623. }
  17624. if (err == MP_OKAY) {
  17625. err = sp_4096_to_mp(r, res);
  17626. }
  17627. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17628. if (b != NULL)
  17629. #endif
  17630. {
  17631. /* only "e" is sensitive and needs zeroized */
  17632. if (e != NULL)
  17633. ForceZero(e, sizeof(sp_digit) * 162U);
  17634. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17635. XFREE(b, NULL, DYNAMIC_TYPE_DH);
  17636. #endif
  17637. }
  17638. return err;
  17639. #endif
  17640. }
  17641. #ifdef WOLFSSL_HAVE_SP_DH
  17642. #ifdef HAVE_FFDHE_4096
  17643. SP_NOINLINE static void sp_4096_lshift_162(sp_digit* r, const sp_digit* a,
  17644. byte n)
  17645. {
  17646. sp_int_digit s;
  17647. sp_int_digit t;
  17648. s = (sp_int_digit)a[161];
  17649. r[162] = s >> (26U - n);
  17650. s = (sp_int_digit)(a[161]); t = (sp_int_digit)(a[160]);
  17651. r[161] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17652. s = (sp_int_digit)(a[160]); t = (sp_int_digit)(a[159]);
  17653. r[160] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17654. s = (sp_int_digit)(a[159]); t = (sp_int_digit)(a[158]);
  17655. r[159] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17656. s = (sp_int_digit)(a[158]); t = (sp_int_digit)(a[157]);
  17657. r[158] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17658. s = (sp_int_digit)(a[157]); t = (sp_int_digit)(a[156]);
  17659. r[157] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17660. s = (sp_int_digit)(a[156]); t = (sp_int_digit)(a[155]);
  17661. r[156] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17662. s = (sp_int_digit)(a[155]); t = (sp_int_digit)(a[154]);
  17663. r[155] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17664. s = (sp_int_digit)(a[154]); t = (sp_int_digit)(a[153]);
  17665. r[154] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17666. s = (sp_int_digit)(a[153]); t = (sp_int_digit)(a[152]);
  17667. r[153] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17668. s = (sp_int_digit)(a[152]); t = (sp_int_digit)(a[151]);
  17669. r[152] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17670. s = (sp_int_digit)(a[151]); t = (sp_int_digit)(a[150]);
  17671. r[151] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17672. s = (sp_int_digit)(a[150]); t = (sp_int_digit)(a[149]);
  17673. r[150] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17674. s = (sp_int_digit)(a[149]); t = (sp_int_digit)(a[148]);
  17675. r[149] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17676. s = (sp_int_digit)(a[148]); t = (sp_int_digit)(a[147]);
  17677. r[148] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17678. s = (sp_int_digit)(a[147]); t = (sp_int_digit)(a[146]);
  17679. r[147] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17680. s = (sp_int_digit)(a[146]); t = (sp_int_digit)(a[145]);
  17681. r[146] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17682. s = (sp_int_digit)(a[145]); t = (sp_int_digit)(a[144]);
  17683. r[145] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17684. s = (sp_int_digit)(a[144]); t = (sp_int_digit)(a[143]);
  17685. r[144] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17686. s = (sp_int_digit)(a[143]); t = (sp_int_digit)(a[142]);
  17687. r[143] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17688. s = (sp_int_digit)(a[142]); t = (sp_int_digit)(a[141]);
  17689. r[142] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17690. s = (sp_int_digit)(a[141]); t = (sp_int_digit)(a[140]);
  17691. r[141] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17692. s = (sp_int_digit)(a[140]); t = (sp_int_digit)(a[139]);
  17693. r[140] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17694. s = (sp_int_digit)(a[139]); t = (sp_int_digit)(a[138]);
  17695. r[139] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17696. s = (sp_int_digit)(a[138]); t = (sp_int_digit)(a[137]);
  17697. r[138] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17698. s = (sp_int_digit)(a[137]); t = (sp_int_digit)(a[136]);
  17699. r[137] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17700. s = (sp_int_digit)(a[136]); t = (sp_int_digit)(a[135]);
  17701. r[136] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17702. s = (sp_int_digit)(a[135]); t = (sp_int_digit)(a[134]);
  17703. r[135] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17704. s = (sp_int_digit)(a[134]); t = (sp_int_digit)(a[133]);
  17705. r[134] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17706. s = (sp_int_digit)(a[133]); t = (sp_int_digit)(a[132]);
  17707. r[133] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17708. s = (sp_int_digit)(a[132]); t = (sp_int_digit)(a[131]);
  17709. r[132] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17710. s = (sp_int_digit)(a[131]); t = (sp_int_digit)(a[130]);
  17711. r[131] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17712. s = (sp_int_digit)(a[130]); t = (sp_int_digit)(a[129]);
  17713. r[130] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17714. s = (sp_int_digit)(a[129]); t = (sp_int_digit)(a[128]);
  17715. r[129] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17716. s = (sp_int_digit)(a[128]); t = (sp_int_digit)(a[127]);
  17717. r[128] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17718. s = (sp_int_digit)(a[127]); t = (sp_int_digit)(a[126]);
  17719. r[127] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17720. s = (sp_int_digit)(a[126]); t = (sp_int_digit)(a[125]);
  17721. r[126] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17722. s = (sp_int_digit)(a[125]); t = (sp_int_digit)(a[124]);
  17723. r[125] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17724. s = (sp_int_digit)(a[124]); t = (sp_int_digit)(a[123]);
  17725. r[124] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17726. s = (sp_int_digit)(a[123]); t = (sp_int_digit)(a[122]);
  17727. r[123] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17728. s = (sp_int_digit)(a[122]); t = (sp_int_digit)(a[121]);
  17729. r[122] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17730. s = (sp_int_digit)(a[121]); t = (sp_int_digit)(a[120]);
  17731. r[121] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17732. s = (sp_int_digit)(a[120]); t = (sp_int_digit)(a[119]);
  17733. r[120] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17734. s = (sp_int_digit)(a[119]); t = (sp_int_digit)(a[118]);
  17735. r[119] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17736. s = (sp_int_digit)(a[118]); t = (sp_int_digit)(a[117]);
  17737. r[118] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17738. s = (sp_int_digit)(a[117]); t = (sp_int_digit)(a[116]);
  17739. r[117] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17740. s = (sp_int_digit)(a[116]); t = (sp_int_digit)(a[115]);
  17741. r[116] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17742. s = (sp_int_digit)(a[115]); t = (sp_int_digit)(a[114]);
  17743. r[115] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17744. s = (sp_int_digit)(a[114]); t = (sp_int_digit)(a[113]);
  17745. r[114] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17746. s = (sp_int_digit)(a[113]); t = (sp_int_digit)(a[112]);
  17747. r[113] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17748. s = (sp_int_digit)(a[112]); t = (sp_int_digit)(a[111]);
  17749. r[112] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17750. s = (sp_int_digit)(a[111]); t = (sp_int_digit)(a[110]);
  17751. r[111] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17752. s = (sp_int_digit)(a[110]); t = (sp_int_digit)(a[109]);
  17753. r[110] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17754. s = (sp_int_digit)(a[109]); t = (sp_int_digit)(a[108]);
  17755. r[109] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17756. s = (sp_int_digit)(a[108]); t = (sp_int_digit)(a[107]);
  17757. r[108] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17758. s = (sp_int_digit)(a[107]); t = (sp_int_digit)(a[106]);
  17759. r[107] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17760. s = (sp_int_digit)(a[106]); t = (sp_int_digit)(a[105]);
  17761. r[106] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17762. s = (sp_int_digit)(a[105]); t = (sp_int_digit)(a[104]);
  17763. r[105] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17764. s = (sp_int_digit)(a[104]); t = (sp_int_digit)(a[103]);
  17765. r[104] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17766. s = (sp_int_digit)(a[103]); t = (sp_int_digit)(a[102]);
  17767. r[103] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17768. s = (sp_int_digit)(a[102]); t = (sp_int_digit)(a[101]);
  17769. r[102] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17770. s = (sp_int_digit)(a[101]); t = (sp_int_digit)(a[100]);
  17771. r[101] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17772. s = (sp_int_digit)(a[100]); t = (sp_int_digit)(a[99]);
  17773. r[100] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17774. s = (sp_int_digit)(a[99]); t = (sp_int_digit)(a[98]);
  17775. r[99] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17776. s = (sp_int_digit)(a[98]); t = (sp_int_digit)(a[97]);
  17777. r[98] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17778. s = (sp_int_digit)(a[97]); t = (sp_int_digit)(a[96]);
  17779. r[97] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17780. s = (sp_int_digit)(a[96]); t = (sp_int_digit)(a[95]);
  17781. r[96] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17782. s = (sp_int_digit)(a[95]); t = (sp_int_digit)(a[94]);
  17783. r[95] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17784. s = (sp_int_digit)(a[94]); t = (sp_int_digit)(a[93]);
  17785. r[94] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17786. s = (sp_int_digit)(a[93]); t = (sp_int_digit)(a[92]);
  17787. r[93] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17788. s = (sp_int_digit)(a[92]); t = (sp_int_digit)(a[91]);
  17789. r[92] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17790. s = (sp_int_digit)(a[91]); t = (sp_int_digit)(a[90]);
  17791. r[91] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17792. s = (sp_int_digit)(a[90]); t = (sp_int_digit)(a[89]);
  17793. r[90] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17794. s = (sp_int_digit)(a[89]); t = (sp_int_digit)(a[88]);
  17795. r[89] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17796. s = (sp_int_digit)(a[88]); t = (sp_int_digit)(a[87]);
  17797. r[88] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17798. s = (sp_int_digit)(a[87]); t = (sp_int_digit)(a[86]);
  17799. r[87] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17800. s = (sp_int_digit)(a[86]); t = (sp_int_digit)(a[85]);
  17801. r[86] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17802. s = (sp_int_digit)(a[85]); t = (sp_int_digit)(a[84]);
  17803. r[85] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17804. s = (sp_int_digit)(a[84]); t = (sp_int_digit)(a[83]);
  17805. r[84] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17806. s = (sp_int_digit)(a[83]); t = (sp_int_digit)(a[82]);
  17807. r[83] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17808. s = (sp_int_digit)(a[82]); t = (sp_int_digit)(a[81]);
  17809. r[82] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17810. s = (sp_int_digit)(a[81]); t = (sp_int_digit)(a[80]);
  17811. r[81] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17812. s = (sp_int_digit)(a[80]); t = (sp_int_digit)(a[79]);
  17813. r[80] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17814. s = (sp_int_digit)(a[79]); t = (sp_int_digit)(a[78]);
  17815. r[79] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17816. s = (sp_int_digit)(a[78]); t = (sp_int_digit)(a[77]);
  17817. r[78] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17818. s = (sp_int_digit)(a[77]); t = (sp_int_digit)(a[76]);
  17819. r[77] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17820. s = (sp_int_digit)(a[76]); t = (sp_int_digit)(a[75]);
  17821. r[76] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17822. s = (sp_int_digit)(a[75]); t = (sp_int_digit)(a[74]);
  17823. r[75] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17824. s = (sp_int_digit)(a[74]); t = (sp_int_digit)(a[73]);
  17825. r[74] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17826. s = (sp_int_digit)(a[73]); t = (sp_int_digit)(a[72]);
  17827. r[73] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17828. s = (sp_int_digit)(a[72]); t = (sp_int_digit)(a[71]);
  17829. r[72] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17830. s = (sp_int_digit)(a[71]); t = (sp_int_digit)(a[70]);
  17831. r[71] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17832. s = (sp_int_digit)(a[70]); t = (sp_int_digit)(a[69]);
  17833. r[70] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17834. s = (sp_int_digit)(a[69]); t = (sp_int_digit)(a[68]);
  17835. r[69] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17836. s = (sp_int_digit)(a[68]); t = (sp_int_digit)(a[67]);
  17837. r[68] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17838. s = (sp_int_digit)(a[67]); t = (sp_int_digit)(a[66]);
  17839. r[67] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17840. s = (sp_int_digit)(a[66]); t = (sp_int_digit)(a[65]);
  17841. r[66] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17842. s = (sp_int_digit)(a[65]); t = (sp_int_digit)(a[64]);
  17843. r[65] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17844. s = (sp_int_digit)(a[64]); t = (sp_int_digit)(a[63]);
  17845. r[64] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17846. s = (sp_int_digit)(a[63]); t = (sp_int_digit)(a[62]);
  17847. r[63] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17848. s = (sp_int_digit)(a[62]); t = (sp_int_digit)(a[61]);
  17849. r[62] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17850. s = (sp_int_digit)(a[61]); t = (sp_int_digit)(a[60]);
  17851. r[61] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17852. s = (sp_int_digit)(a[60]); t = (sp_int_digit)(a[59]);
  17853. r[60] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17854. s = (sp_int_digit)(a[59]); t = (sp_int_digit)(a[58]);
  17855. r[59] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17856. s = (sp_int_digit)(a[58]); t = (sp_int_digit)(a[57]);
  17857. r[58] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17858. s = (sp_int_digit)(a[57]); t = (sp_int_digit)(a[56]);
  17859. r[57] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17860. s = (sp_int_digit)(a[56]); t = (sp_int_digit)(a[55]);
  17861. r[56] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17862. s = (sp_int_digit)(a[55]); t = (sp_int_digit)(a[54]);
  17863. r[55] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17864. s = (sp_int_digit)(a[54]); t = (sp_int_digit)(a[53]);
  17865. r[54] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17866. s = (sp_int_digit)(a[53]); t = (sp_int_digit)(a[52]);
  17867. r[53] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17868. s = (sp_int_digit)(a[52]); t = (sp_int_digit)(a[51]);
  17869. r[52] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17870. s = (sp_int_digit)(a[51]); t = (sp_int_digit)(a[50]);
  17871. r[51] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17872. s = (sp_int_digit)(a[50]); t = (sp_int_digit)(a[49]);
  17873. r[50] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17874. s = (sp_int_digit)(a[49]); t = (sp_int_digit)(a[48]);
  17875. r[49] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17876. s = (sp_int_digit)(a[48]); t = (sp_int_digit)(a[47]);
  17877. r[48] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17878. s = (sp_int_digit)(a[47]); t = (sp_int_digit)(a[46]);
  17879. r[47] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17880. s = (sp_int_digit)(a[46]); t = (sp_int_digit)(a[45]);
  17881. r[46] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17882. s = (sp_int_digit)(a[45]); t = (sp_int_digit)(a[44]);
  17883. r[45] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17884. s = (sp_int_digit)(a[44]); t = (sp_int_digit)(a[43]);
  17885. r[44] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17886. s = (sp_int_digit)(a[43]); t = (sp_int_digit)(a[42]);
  17887. r[43] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17888. s = (sp_int_digit)(a[42]); t = (sp_int_digit)(a[41]);
  17889. r[42] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17890. s = (sp_int_digit)(a[41]); t = (sp_int_digit)(a[40]);
  17891. r[41] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17892. s = (sp_int_digit)(a[40]); t = (sp_int_digit)(a[39]);
  17893. r[40] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17894. s = (sp_int_digit)(a[39]); t = (sp_int_digit)(a[38]);
  17895. r[39] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17896. s = (sp_int_digit)(a[38]); t = (sp_int_digit)(a[37]);
  17897. r[38] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17898. s = (sp_int_digit)(a[37]); t = (sp_int_digit)(a[36]);
  17899. r[37] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17900. s = (sp_int_digit)(a[36]); t = (sp_int_digit)(a[35]);
  17901. r[36] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17902. s = (sp_int_digit)(a[35]); t = (sp_int_digit)(a[34]);
  17903. r[35] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17904. s = (sp_int_digit)(a[34]); t = (sp_int_digit)(a[33]);
  17905. r[34] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17906. s = (sp_int_digit)(a[33]); t = (sp_int_digit)(a[32]);
  17907. r[33] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17908. s = (sp_int_digit)(a[32]); t = (sp_int_digit)(a[31]);
  17909. r[32] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17910. s = (sp_int_digit)(a[31]); t = (sp_int_digit)(a[30]);
  17911. r[31] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17912. s = (sp_int_digit)(a[30]); t = (sp_int_digit)(a[29]);
  17913. r[30] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17914. s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]);
  17915. r[29] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17916. s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]);
  17917. r[28] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17918. s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]);
  17919. r[27] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17920. s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]);
  17921. r[26] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17922. s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]);
  17923. r[25] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17924. s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]);
  17925. r[24] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17926. s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]);
  17927. r[23] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17928. s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]);
  17929. r[22] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17930. s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]);
  17931. r[21] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17932. s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]);
  17933. r[20] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17934. s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]);
  17935. r[19] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17936. s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]);
  17937. r[18] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17938. s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]);
  17939. r[17] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17940. s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]);
  17941. r[16] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17942. s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]);
  17943. r[15] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17944. s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]);
  17945. r[14] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17946. s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]);
  17947. r[13] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17948. s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]);
  17949. r[12] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17950. s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]);
  17951. r[11] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17952. s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]);
  17953. r[10] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17954. s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]);
  17955. r[9] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17956. s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]);
  17957. r[8] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17958. s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]);
  17959. r[7] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17960. s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]);
  17961. r[6] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17962. s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]);
  17963. r[5] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17964. s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]);
  17965. r[4] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17966. s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]);
  17967. r[3] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17968. s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]);
  17969. r[2] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17970. s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]);
  17971. r[1] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  17972. r[0] = (a[0] << n) & 0x3ffffff;
  17973. }
  17974. /* Modular exponentiate 2 to the e mod m. (r = 2^e mod m)
  17975. *
  17976. * r A single precision number that is the result of the operation.
  17977. * e A single precision number that is the exponent.
  17978. * bits The number of bits in the exponent.
  17979. * m A single precision number that is the modulus.
  17980. * returns 0 on success.
  17981. * returns MEMORY_E on dynamic memory allocation failure.
  17982. * returns MP_VAL when base is even.
  17983. */
  17984. static int sp_4096_mod_exp_2_162(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m)
  17985. {
  17986. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  17987. sp_digit* td = NULL;
  17988. #else
  17989. sp_digit td[487];
  17990. #endif
  17991. sp_digit* norm = NULL;
  17992. sp_digit* tmp = NULL;
  17993. sp_digit mp = 1;
  17994. sp_digit n;
  17995. sp_digit o;
  17996. int i;
  17997. int c;
  17998. byte y;
  17999. int err = MP_OKAY;
  18000. if (bits == 0) {
  18001. err = MP_VAL;
  18002. }
  18003. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  18004. if (err == MP_OKAY) {
  18005. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 487, NULL,
  18006. DYNAMIC_TYPE_TMP_BUFFER);
  18007. if (td == NULL)
  18008. err = MEMORY_E;
  18009. }
  18010. #endif
  18011. if (err == MP_OKAY) {
  18012. norm = td;
  18013. tmp = td + 324;
  18014. XMEMSET(td, 0, sizeof(sp_digit) * 487);
  18015. sp_4096_mont_setup(m, &mp);
  18016. sp_4096_mont_norm_162(norm, m);
  18017. bits = ((bits + 3) / 4) * 4;
  18018. i = ((bits + 25) / 26) - 1;
  18019. c = bits % 26;
  18020. if (c == 0) {
  18021. c = 26;
  18022. }
  18023. if (i < 162) {
  18024. n = e[i--] << (32 - c);
  18025. }
  18026. else {
  18027. n = 0;
  18028. i--;
  18029. }
  18030. if (c < 4) {
  18031. n |= e[i--] << (6 - c);
  18032. c += 26;
  18033. }
  18034. y = (int)((n >> 28) & 0xf);
  18035. n <<= 4;
  18036. c -= 4;
  18037. sp_4096_lshift_162(r, norm, (byte)y);
  18038. while ((i >= 0) || (c >= 4)) {
  18039. if (c >= 4) {
  18040. y = (byte)((n >> 28) & 0xf);
  18041. n <<= 4;
  18042. c -= 4;
  18043. }
  18044. else if (c == 0) {
  18045. n = e[i--] << 6;
  18046. y = (byte)((n >> 28) & 0xf);
  18047. n <<= 4;
  18048. c = 22;
  18049. }
  18050. else {
  18051. y = (byte)((n >> 28) & 0xf);
  18052. n = e[i--] << 6;
  18053. c = 4 - c;
  18054. y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
  18055. n <<= c;
  18056. c = 26 - c;
  18057. }
  18058. sp_4096_mont_sqr_162(r, r, m, mp);
  18059. sp_4096_mont_sqr_162(r, r, m, mp);
  18060. sp_4096_mont_sqr_162(r, r, m, mp);
  18061. sp_4096_mont_sqr_162(r, r, m, mp);
  18062. sp_4096_lshift_162(r, r, (byte)y);
  18063. sp_4096_mul_d_162(tmp, norm, (r[158] << 12) + (r[157] >> 14));
  18064. r[158] = 0;
  18065. r[157] &= 0x3fffL;
  18066. (void)sp_4096_add_162(r, r, tmp);
  18067. sp_4096_norm_162(r);
  18068. o = sp_4096_cmp_162(r, m);
  18069. sp_4096_cond_sub_162(r, r, m, ~(o >> 31));
  18070. }
  18071. sp_4096_mont_reduce_162(r, m, mp);
  18072. n = sp_4096_cmp_162(r, m);
  18073. sp_4096_cond_sub_162(r, r, m, ~(n >> 31));
  18074. }
  18075. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  18076. if (td != NULL)
  18077. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  18078. #endif
  18079. return err;
  18080. }
  18081. #endif /* HAVE_FFDHE_4096 */
  18082. /* Perform the modular exponentiation for Diffie-Hellman.
  18083. *
  18084. * base Base.
  18085. * exp Array of bytes that is the exponent.
  18086. * expLen Length of data, in bytes, in exponent.
  18087. * mod Modulus.
  18088. * out Buffer to hold big-endian bytes of exponentiation result.
  18089. * Must be at least 512 bytes long.
  18090. * outLen Length, in bytes, of exponentiation result.
  18091. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  18092. * and MEMORY_E if memory allocation fails.
  18093. */
  18094. int sp_DhExp_4096(const mp_int* base, const byte* exp, word32 expLen,
  18095. const mp_int* mod, byte* out, word32* outLen)
  18096. {
  18097. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  18098. sp_digit* b = NULL;
  18099. #else
  18100. sp_digit b[162 * 4];
  18101. #endif
  18102. sp_digit* e = NULL;
  18103. sp_digit* m = NULL;
  18104. sp_digit* r = NULL;
  18105. word32 i;
  18106. int err = MP_OKAY;
  18107. if (mp_count_bits(base) > 4096) {
  18108. err = MP_READ_E;
  18109. }
  18110. else if (expLen > 512U) {
  18111. err = MP_READ_E;
  18112. }
  18113. else if (mp_count_bits(mod) != 4096) {
  18114. err = MP_READ_E;
  18115. }
  18116. else if (mp_iseven(mod)) {
  18117. err = MP_VAL;
  18118. }
  18119. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  18120. if (err == MP_OKAY) {
  18121. b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 162 * 4, NULL,
  18122. DYNAMIC_TYPE_DH);
  18123. if (b == NULL)
  18124. err = MEMORY_E;
  18125. }
  18126. #endif
  18127. if (err == MP_OKAY) {
  18128. e = b + 162 * 2;
  18129. m = e + 162;
  18130. r = b;
  18131. sp_4096_from_mp(b, 162, base);
  18132. sp_4096_from_bin(e, 162, exp, expLen);
  18133. sp_4096_from_mp(m, 162, mod);
  18134. #ifdef HAVE_FFDHE_4096
  18135. if (base->used == 1 && base->dp[0] == 2U &&
  18136. ((m[157] << 2) | (m[156] >> 24)) == 0xffffL) {
  18137. err = sp_4096_mod_exp_2_162(r, e, expLen * 8U, m);
  18138. }
  18139. else {
  18140. #endif
  18141. err = sp_4096_mod_exp_162(r, b, e, expLen * 8U, m, 0);
  18142. #ifdef HAVE_FFDHE_4096
  18143. }
  18144. #endif
  18145. }
  18146. if (err == MP_OKAY) {
  18147. sp_4096_to_bin_162(r, out);
  18148. *outLen = 512;
  18149. for (i=0; i<512U && out[i] == 0U; i++) {
  18150. /* Search for first non-zero. */
  18151. }
  18152. *outLen -= i;
  18153. XMEMMOVE(out, out + i, *outLen);
  18154. }
  18155. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  18156. if (b != NULL)
  18157. #endif
  18158. {
  18159. /* only "e" is sensitive and needs zeroized */
  18160. if (e != NULL)
  18161. ForceZero(e, sizeof(sp_digit) * 162U);
  18162. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  18163. XFREE(b, NULL, DYNAMIC_TYPE_DH);
  18164. #endif
  18165. }
  18166. return err;
  18167. }
  18168. #endif /* WOLFSSL_HAVE_SP_DH */
  18169. #endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
  18170. #endif /* WOLFSSL_SP_SMALL */
  18171. #endif /* WOLFSSL_SP_4096 */
  18172. #endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
  18173. #ifdef WOLFSSL_HAVE_SP_ECC
  18174. #ifndef WOLFSSL_SP_NO_256
  18175. /* Point structure to use. */
  18176. typedef struct sp_point_256 {
  18177. /* X ordinate of point. */
  18178. sp_digit x[2 * 9];
  18179. /* Y ordinate of point. */
  18180. sp_digit y[2 * 9];
  18181. /* Z ordinate of point. */
  18182. sp_digit z[2 * 9];
  18183. /* Indicates point is at infinity. */
  18184. int infinity;
  18185. } sp_point_256;
  18186. /* The modulus (prime) of the curve P256. */
  18187. static const sp_digit p256_mod[9] = {
  18188. 0x1fffffff,0x1fffffff,0x1fffffff,0x000001ff,0x00000000,0x00000000,
  18189. 0x00040000,0x1fe00000,0x00ffffff
  18190. };
  18191. /* The Montgomery normalizer for modulus of the curve P256. */
  18192. static const sp_digit p256_norm_mod[9] = {
  18193. 0x00000001,0x00000000,0x00000000,0x1ffffe00,0x1fffffff,0x1fffffff,
  18194. 0x1ffbffff,0x001fffff,0x00000000
  18195. };
  18196. /* The Montgomery multiplier for modulus of the curve P256. */
  18197. static const sp_digit p256_mp_mod = 0x0000001;
  18198. #if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
  18199. defined(HAVE_ECC_VERIFY)
  18200. /* The order of the curve P256. */
  18201. static const sp_digit p256_order[9] = {
  18202. 0x1c632551,0x1dce5617,0x05e7a13c,0x0df55b4e,0x1ffffbce,0x1fffffff,
  18203. 0x0003ffff,0x1fe00000,0x00ffffff
  18204. };
  18205. #endif
  18206. /* The order of the curve P256 minus 2. */
  18207. static const sp_digit p256_order2[9] = {
  18208. 0x1c63254f,0x1dce5617,0x05e7a13c,0x0df55b4e,0x1ffffbce,0x1fffffff,
  18209. 0x0003ffff,0x1fe00000,0x00ffffff
  18210. };
  18211. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  18212. /* The Montgomery normalizer for order of the curve P256. */
  18213. static const sp_digit p256_norm_order[9] = {
  18214. 0x039cdaaf,0x0231a9e8,0x1a185ec3,0x120aa4b1,0x00000431,0x00000000,
  18215. 0x1ffc0000,0x001fffff,0x00000000
  18216. };
  18217. #endif
  18218. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  18219. /* The Montgomery multiplier for order of the curve P256. */
  18220. static const sp_digit p256_mp_order = 0xe00bc4f;
  18221. #endif
  18222. /* The base point of curve P256. */
  18223. static const sp_point_256 p256_base = {
  18224. /* X ordinate */
  18225. {
  18226. 0x1898c296,0x0509ca2e,0x1acce83d,0x06fb025b,0x040f2770,0x1372b1d2,
  18227. 0x091fe2f3,0x1e5c2588,0x006b17d1,
  18228. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  18229. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0
  18230. },
  18231. /* Y ordinate */
  18232. {
  18233. 0x17bf51f5,0x1db20341,0x0c57b3b2,0x1c66aed6,0x19e162bc,0x15a53e07,
  18234. 0x1e6e3b9f,0x1c5fc34f,0x004fe342,
  18235. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  18236. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0
  18237. },
  18238. /* Z ordinate */
  18239. {
  18240. 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
  18241. 0x00000000,0x00000000,0x00000000,
  18242. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  18243. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0
  18244. },
  18245. /* infinity */
  18246. 0
  18247. };
  18248. #if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY)
  18249. static const sp_digit p256_b[9] = {
  18250. 0x07d2604b,0x1e71e1f1,0x14ec3d8e,0x1a0d6198,0x086bc651,0x1eaabb4c,
  18251. 0x0f9ecfae,0x1b154752,0x005ac635
  18252. };
  18253. #endif
  18254. #ifdef WOLFSSL_SP_SMALL
  18255. /* Multiply a and b into r. (r = a * b)
  18256. *
  18257. * r A single precision integer.
  18258. * a A single precision integer.
  18259. * b A single precision integer.
  18260. */
  18261. SP_NOINLINE static void sp_256_mul_9(sp_digit* r, const sp_digit* a,
  18262. const sp_digit* b)
  18263. {
  18264. int i;
  18265. int imax;
  18266. int k;
  18267. sp_uint64 c;
  18268. sp_uint64 lo;
  18269. c = ((sp_uint64)a[8]) * b[8];
  18270. r[17] = (sp_digit)(c >> 29);
  18271. c &= 0x1fffffff;
  18272. for (k = 15; k >= 0; k--) {
  18273. if (k >= 9) {
  18274. i = k - 8;
  18275. imax = 8;
  18276. }
  18277. else {
  18278. i = 0;
  18279. imax = k;
  18280. }
  18281. lo = 0;
  18282. for (; i <= imax; i++) {
  18283. lo += ((sp_uint64)a[i]) * b[k - i];
  18284. }
  18285. c += lo >> 29;
  18286. r[k + 2] += (sp_digit)(c >> 29);
  18287. r[k + 1] = (sp_digit)(c & 0x1fffffff);
  18288. c = lo & 0x1fffffff;
  18289. }
  18290. r[0] = (sp_digit)c;
  18291. }
  18292. #else
  18293. /* Multiply a and b into r. (r = a * b)
  18294. *
  18295. * r A single precision integer.
  18296. * a A single precision integer.
  18297. * b A single precision integer.
  18298. */
  18299. SP_NOINLINE static void sp_256_mul_9(sp_digit* r, const sp_digit* a,
  18300. const sp_digit* b)
  18301. {
  18302. sp_int64 t0 = ((sp_int64)a[ 0]) * b[ 0];
  18303. sp_int64 t1 = ((sp_int64)a[ 0]) * b[ 1]
  18304. + ((sp_int64)a[ 1]) * b[ 0];
  18305. sp_int64 t2 = ((sp_int64)a[ 0]) * b[ 2]
  18306. + ((sp_int64)a[ 1]) * b[ 1]
  18307. + ((sp_int64)a[ 2]) * b[ 0];
  18308. sp_int64 t3 = ((sp_int64)a[ 0]) * b[ 3]
  18309. + ((sp_int64)a[ 1]) * b[ 2]
  18310. + ((sp_int64)a[ 2]) * b[ 1]
  18311. + ((sp_int64)a[ 3]) * b[ 0];
  18312. sp_int64 t4 = ((sp_int64)a[ 0]) * b[ 4]
  18313. + ((sp_int64)a[ 1]) * b[ 3]
  18314. + ((sp_int64)a[ 2]) * b[ 2]
  18315. + ((sp_int64)a[ 3]) * b[ 1]
  18316. + ((sp_int64)a[ 4]) * b[ 0];
  18317. sp_int64 t5 = ((sp_int64)a[ 0]) * b[ 5]
  18318. + ((sp_int64)a[ 1]) * b[ 4]
  18319. + ((sp_int64)a[ 2]) * b[ 3]
  18320. + ((sp_int64)a[ 3]) * b[ 2]
  18321. + ((sp_int64)a[ 4]) * b[ 1]
  18322. + ((sp_int64)a[ 5]) * b[ 0];
  18323. sp_int64 t6 = ((sp_int64)a[ 0]) * b[ 6]
  18324. + ((sp_int64)a[ 1]) * b[ 5]
  18325. + ((sp_int64)a[ 2]) * b[ 4]
  18326. + ((sp_int64)a[ 3]) * b[ 3]
  18327. + ((sp_int64)a[ 4]) * b[ 2]
  18328. + ((sp_int64)a[ 5]) * b[ 1]
  18329. + ((sp_int64)a[ 6]) * b[ 0];
  18330. sp_int64 t7 = ((sp_int64)a[ 0]) * b[ 7]
  18331. + ((sp_int64)a[ 1]) * b[ 6]
  18332. + ((sp_int64)a[ 2]) * b[ 5]
  18333. + ((sp_int64)a[ 3]) * b[ 4]
  18334. + ((sp_int64)a[ 4]) * b[ 3]
  18335. + ((sp_int64)a[ 5]) * b[ 2]
  18336. + ((sp_int64)a[ 6]) * b[ 1]
  18337. + ((sp_int64)a[ 7]) * b[ 0];
  18338. sp_int64 t8 = ((sp_int64)a[ 0]) * b[ 8]
  18339. + ((sp_int64)a[ 1]) * b[ 7]
  18340. + ((sp_int64)a[ 2]) * b[ 6]
  18341. + ((sp_int64)a[ 3]) * b[ 5]
  18342. + ((sp_int64)a[ 4]) * b[ 4]
  18343. + ((sp_int64)a[ 5]) * b[ 3]
  18344. + ((sp_int64)a[ 6]) * b[ 2]
  18345. + ((sp_int64)a[ 7]) * b[ 1]
  18346. + ((sp_int64)a[ 8]) * b[ 0];
  18347. sp_int64 t9 = ((sp_int64)a[ 1]) * b[ 8]
  18348. + ((sp_int64)a[ 2]) * b[ 7]
  18349. + ((sp_int64)a[ 3]) * b[ 6]
  18350. + ((sp_int64)a[ 4]) * b[ 5]
  18351. + ((sp_int64)a[ 5]) * b[ 4]
  18352. + ((sp_int64)a[ 6]) * b[ 3]
  18353. + ((sp_int64)a[ 7]) * b[ 2]
  18354. + ((sp_int64)a[ 8]) * b[ 1];
  18355. sp_int64 t10 = ((sp_int64)a[ 2]) * b[ 8]
  18356. + ((sp_int64)a[ 3]) * b[ 7]
  18357. + ((sp_int64)a[ 4]) * b[ 6]
  18358. + ((sp_int64)a[ 5]) * b[ 5]
  18359. + ((sp_int64)a[ 6]) * b[ 4]
  18360. + ((sp_int64)a[ 7]) * b[ 3]
  18361. + ((sp_int64)a[ 8]) * b[ 2];
  18362. sp_int64 t11 = ((sp_int64)a[ 3]) * b[ 8]
  18363. + ((sp_int64)a[ 4]) * b[ 7]
  18364. + ((sp_int64)a[ 5]) * b[ 6]
  18365. + ((sp_int64)a[ 6]) * b[ 5]
  18366. + ((sp_int64)a[ 7]) * b[ 4]
  18367. + ((sp_int64)a[ 8]) * b[ 3];
  18368. sp_int64 t12 = ((sp_int64)a[ 4]) * b[ 8]
  18369. + ((sp_int64)a[ 5]) * b[ 7]
  18370. + ((sp_int64)a[ 6]) * b[ 6]
  18371. + ((sp_int64)a[ 7]) * b[ 5]
  18372. + ((sp_int64)a[ 8]) * b[ 4];
  18373. sp_int64 t13 = ((sp_int64)a[ 5]) * b[ 8]
  18374. + ((sp_int64)a[ 6]) * b[ 7]
  18375. + ((sp_int64)a[ 7]) * b[ 6]
  18376. + ((sp_int64)a[ 8]) * b[ 5];
  18377. sp_int64 t14 = ((sp_int64)a[ 6]) * b[ 8]
  18378. + ((sp_int64)a[ 7]) * b[ 7]
  18379. + ((sp_int64)a[ 8]) * b[ 6];
  18380. sp_int64 t15 = ((sp_int64)a[ 7]) * b[ 8]
  18381. + ((sp_int64)a[ 8]) * b[ 7];
  18382. sp_int64 t16 = ((sp_int64)a[ 8]) * b[ 8];
  18383. t1 += t0 >> 29; r[ 0] = t0 & 0x1fffffff;
  18384. t2 += t1 >> 29; r[ 1] = t1 & 0x1fffffff;
  18385. t3 += t2 >> 29; r[ 2] = t2 & 0x1fffffff;
  18386. t4 += t3 >> 29; r[ 3] = t3 & 0x1fffffff;
  18387. t5 += t4 >> 29; r[ 4] = t4 & 0x1fffffff;
  18388. t6 += t5 >> 29; r[ 5] = t5 & 0x1fffffff;
  18389. t7 += t6 >> 29; r[ 6] = t6 & 0x1fffffff;
  18390. t8 += t7 >> 29; r[ 7] = t7 & 0x1fffffff;
  18391. t9 += t8 >> 29; r[ 8] = t8 & 0x1fffffff;
  18392. t10 += t9 >> 29; r[ 9] = t9 & 0x1fffffff;
  18393. t11 += t10 >> 29; r[10] = t10 & 0x1fffffff;
  18394. t12 += t11 >> 29; r[11] = t11 & 0x1fffffff;
  18395. t13 += t12 >> 29; r[12] = t12 & 0x1fffffff;
  18396. t14 += t13 >> 29; r[13] = t13 & 0x1fffffff;
  18397. t15 += t14 >> 29; r[14] = t14 & 0x1fffffff;
  18398. t16 += t15 >> 29; r[15] = t15 & 0x1fffffff;
  18399. r[17] = (sp_digit)(t16 >> 29);
  18400. r[16] = t16 & 0x1fffffff;
  18401. }
  18402. #endif /* WOLFSSL_SP_SMALL */
  18403. #ifdef WOLFSSL_SP_SMALL
  18404. /* Square a and put result in r. (r = a * a)
  18405. *
  18406. * r A single precision integer.
  18407. * a A single precision integer.
  18408. */
  18409. SP_NOINLINE static void sp_256_sqr_9(sp_digit* r, const sp_digit* a)
  18410. {
  18411. int i;
  18412. int imax;
  18413. int k;
  18414. sp_uint64 c;
  18415. sp_uint64 t;
  18416. c = ((sp_uint64)a[8]) * a[8];
  18417. r[17] = (sp_digit)(c >> 29);
  18418. c = (c & 0x1fffffff) << 29;
  18419. for (k = 15; k >= 0; k--) {
  18420. i = (k + 1) / 2;
  18421. if ((k & 1) == 0) {
  18422. c += ((sp_uint64)a[i]) * a[i];
  18423. i++;
  18424. }
  18425. if (k < 8) {
  18426. imax = k;
  18427. }
  18428. else {
  18429. imax = 8;
  18430. }
  18431. t = 0;
  18432. for (; i <= imax; i++) {
  18433. t += ((sp_uint64)a[i]) * a[k - i];
  18434. }
  18435. c += t * 2;
  18436. r[k + 2] += (sp_digit) (c >> 58);
  18437. r[k + 1] = (sp_digit)((c >> 29) & 0x1fffffff);
  18438. c = (c & 0x1fffffff) << 29;
  18439. }
  18440. r[0] = (sp_digit)(c >> 29);
  18441. }
  18442. #else
  18443. /* Square a and put result in r. (r = a * a)
  18444. *
  18445. * r A single precision integer.
  18446. * a A single precision integer.
  18447. */
  18448. SP_NOINLINE static void sp_256_sqr_9(sp_digit* r, const sp_digit* a)
  18449. {
  18450. sp_int64 t0 = ((sp_int64)a[ 0]) * a[ 0];
  18451. sp_int64 t1 = (((sp_int64)a[ 0]) * a[ 1]) * 2;
  18452. sp_int64 t2 = (((sp_int64)a[ 0]) * a[ 2]) * 2
  18453. + ((sp_int64)a[ 1]) * a[ 1];
  18454. sp_int64 t3 = (((sp_int64)a[ 0]) * a[ 3]
  18455. + ((sp_int64)a[ 1]) * a[ 2]) * 2;
  18456. sp_int64 t4 = (((sp_int64)a[ 0]) * a[ 4]
  18457. + ((sp_int64)a[ 1]) * a[ 3]) * 2
  18458. + ((sp_int64)a[ 2]) * a[ 2];
  18459. sp_int64 t5 = (((sp_int64)a[ 0]) * a[ 5]
  18460. + ((sp_int64)a[ 1]) * a[ 4]
  18461. + ((sp_int64)a[ 2]) * a[ 3]) * 2;
  18462. sp_int64 t6 = (((sp_int64)a[ 0]) * a[ 6]
  18463. + ((sp_int64)a[ 1]) * a[ 5]
  18464. + ((sp_int64)a[ 2]) * a[ 4]) * 2
  18465. + ((sp_int64)a[ 3]) * a[ 3];
  18466. sp_int64 t7 = (((sp_int64)a[ 0]) * a[ 7]
  18467. + ((sp_int64)a[ 1]) * a[ 6]
  18468. + ((sp_int64)a[ 2]) * a[ 5]
  18469. + ((sp_int64)a[ 3]) * a[ 4]) * 2;
  18470. sp_int64 t8 = (((sp_int64)a[ 0]) * a[ 8]
  18471. + ((sp_int64)a[ 1]) * a[ 7]
  18472. + ((sp_int64)a[ 2]) * a[ 6]
  18473. + ((sp_int64)a[ 3]) * a[ 5]) * 2
  18474. + ((sp_int64)a[ 4]) * a[ 4];
  18475. sp_int64 t9 = (((sp_int64)a[ 1]) * a[ 8]
  18476. + ((sp_int64)a[ 2]) * a[ 7]
  18477. + ((sp_int64)a[ 3]) * a[ 6]
  18478. + ((sp_int64)a[ 4]) * a[ 5]) * 2;
  18479. sp_int64 t10 = (((sp_int64)a[ 2]) * a[ 8]
  18480. + ((sp_int64)a[ 3]) * a[ 7]
  18481. + ((sp_int64)a[ 4]) * a[ 6]) * 2
  18482. + ((sp_int64)a[ 5]) * a[ 5];
  18483. sp_int64 t11 = (((sp_int64)a[ 3]) * a[ 8]
  18484. + ((sp_int64)a[ 4]) * a[ 7]
  18485. + ((sp_int64)a[ 5]) * a[ 6]) * 2;
  18486. sp_int64 t12 = (((sp_int64)a[ 4]) * a[ 8]
  18487. + ((sp_int64)a[ 5]) * a[ 7]) * 2
  18488. + ((sp_int64)a[ 6]) * a[ 6];
  18489. sp_int64 t13 = (((sp_int64)a[ 5]) * a[ 8]
  18490. + ((sp_int64)a[ 6]) * a[ 7]) * 2;
  18491. sp_int64 t14 = (((sp_int64)a[ 6]) * a[ 8]) * 2
  18492. + ((sp_int64)a[ 7]) * a[ 7];
  18493. sp_int64 t15 = (((sp_int64)a[ 7]) * a[ 8]) * 2;
  18494. sp_int64 t16 = ((sp_int64)a[ 8]) * a[ 8];
  18495. t1 += t0 >> 29; r[ 0] = t0 & 0x1fffffff;
  18496. t2 += t1 >> 29; r[ 1] = t1 & 0x1fffffff;
  18497. t3 += t2 >> 29; r[ 2] = t2 & 0x1fffffff;
  18498. t4 += t3 >> 29; r[ 3] = t3 & 0x1fffffff;
  18499. t5 += t4 >> 29; r[ 4] = t4 & 0x1fffffff;
  18500. t6 += t5 >> 29; r[ 5] = t5 & 0x1fffffff;
  18501. t7 += t6 >> 29; r[ 6] = t6 & 0x1fffffff;
  18502. t8 += t7 >> 29; r[ 7] = t7 & 0x1fffffff;
  18503. t9 += t8 >> 29; r[ 8] = t8 & 0x1fffffff;
  18504. t10 += t9 >> 29; r[ 9] = t9 & 0x1fffffff;
  18505. t11 += t10 >> 29; r[10] = t10 & 0x1fffffff;
  18506. t12 += t11 >> 29; r[11] = t11 & 0x1fffffff;
  18507. t13 += t12 >> 29; r[12] = t12 & 0x1fffffff;
  18508. t14 += t13 >> 29; r[13] = t13 & 0x1fffffff;
  18509. t15 += t14 >> 29; r[14] = t14 & 0x1fffffff;
  18510. t16 += t15 >> 29; r[15] = t15 & 0x1fffffff;
  18511. r[17] = (sp_digit)(t16 >> 29);
  18512. r[16] = t16 & 0x1fffffff;
  18513. }
  18514. #endif /* WOLFSSL_SP_SMALL */
  18515. #ifdef WOLFSSL_SP_SMALL
  18516. /* Add b to a into r. (r = a + b)
  18517. *
  18518. * r A single precision integer.
  18519. * a A single precision integer.
  18520. * b A single precision integer.
  18521. */
  18522. SP_NOINLINE static int sp_256_add_9(sp_digit* r, const sp_digit* a,
  18523. const sp_digit* b)
  18524. {
  18525. int i;
  18526. for (i = 0; i < 9; i++) {
  18527. r[i] = a[i] + b[i];
  18528. }
  18529. return 0;
  18530. }
  18531. #else
  18532. /* Add b to a into r. (r = a + b)
  18533. *
  18534. * r A single precision integer.
  18535. * a A single precision integer.
  18536. * b A single precision integer.
  18537. */
  18538. SP_NOINLINE static int sp_256_add_9(sp_digit* r, const sp_digit* a,
  18539. const sp_digit* b)
  18540. {
  18541. r[ 0] = a[ 0] + b[ 0];
  18542. r[ 1] = a[ 1] + b[ 1];
  18543. r[ 2] = a[ 2] + b[ 2];
  18544. r[ 3] = a[ 3] + b[ 3];
  18545. r[ 4] = a[ 4] + b[ 4];
  18546. r[ 5] = a[ 5] + b[ 5];
  18547. r[ 6] = a[ 6] + b[ 6];
  18548. r[ 7] = a[ 7] + b[ 7];
  18549. r[ 8] = a[ 8] + b[ 8];
  18550. return 0;
  18551. }
  18552. #endif /* WOLFSSL_SP_SMALL */
  18553. #ifdef WOLFSSL_SP_SMALL
  18554. /* Sub b from a into r. (r = a - b)
  18555. *
  18556. * r A single precision integer.
  18557. * a A single precision integer.
  18558. * b A single precision integer.
  18559. */
  18560. SP_NOINLINE static int sp_256_sub_9(sp_digit* r, const sp_digit* a,
  18561. const sp_digit* b)
  18562. {
  18563. int i;
  18564. for (i = 0; i < 9; i++) {
  18565. r[i] = a[i] - b[i];
  18566. }
  18567. return 0;
  18568. }
  18569. #else
  18570. /* Sub b from a into r. (r = a - b)
  18571. *
  18572. * r A single precision integer.
  18573. * a A single precision integer.
  18574. * b A single precision integer.
  18575. */
  18576. SP_NOINLINE static int sp_256_sub_9(sp_digit* r, const sp_digit* a,
  18577. const sp_digit* b)
  18578. {
  18579. r[ 0] = a[ 0] - b[ 0];
  18580. r[ 1] = a[ 1] - b[ 1];
  18581. r[ 2] = a[ 2] - b[ 2];
  18582. r[ 3] = a[ 3] - b[ 3];
  18583. r[ 4] = a[ 4] - b[ 4];
  18584. r[ 5] = a[ 5] - b[ 5];
  18585. r[ 6] = a[ 6] - b[ 6];
  18586. r[ 7] = a[ 7] - b[ 7];
  18587. r[ 8] = a[ 8] - b[ 8];
  18588. return 0;
  18589. }
  18590. #endif /* WOLFSSL_SP_SMALL */
  18591. /* Convert an mp_int to an array of sp_digit.
  18592. *
  18593. * r A single precision integer.
  18594. * size Maximum number of bytes to convert
  18595. * a A multi-precision integer.
  18596. */
  18597. static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
  18598. {
  18599. #if DIGIT_BIT == 29
  18600. int j;
  18601. XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
  18602. for (j = a->used; j < size; j++) {
  18603. r[j] = 0;
  18604. }
  18605. #elif DIGIT_BIT > 29
  18606. int i;
  18607. int j = 0;
  18608. word32 s = 0;
  18609. r[0] = 0;
  18610. for (i = 0; i < a->used && j < size; i++) {
  18611. r[j] |= ((sp_digit)a->dp[i] << s);
  18612. r[j] &= 0x1fffffff;
  18613. s = 29U - s;
  18614. if (j + 1 >= size) {
  18615. break;
  18616. }
  18617. /* lint allow cast of mismatch word32 and mp_digit */
  18618. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  18619. while ((s + 29U) <= (word32)DIGIT_BIT) {
  18620. s += 29U;
  18621. r[j] &= 0x1fffffff;
  18622. if (j + 1 >= size) {
  18623. break;
  18624. }
  18625. if (s < (word32)DIGIT_BIT) {
  18626. /* lint allow cast of mismatch word32 and mp_digit */
  18627. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  18628. }
  18629. else {
  18630. r[++j] = (sp_digit)0;
  18631. }
  18632. }
  18633. s = (word32)DIGIT_BIT - s;
  18634. }
  18635. for (j++; j < size; j++) {
  18636. r[j] = 0;
  18637. }
  18638. #else
  18639. int i;
  18640. int j = 0;
  18641. int s = 0;
  18642. r[0] = 0;
  18643. for (i = 0; i < a->used && j < size; i++) {
  18644. r[j] |= ((sp_digit)a->dp[i]) << s;
  18645. if (s + DIGIT_BIT >= 29) {
  18646. r[j] &= 0x1fffffff;
  18647. if (j + 1 >= size) {
  18648. break;
  18649. }
  18650. s = 29 - s;
  18651. if (s == DIGIT_BIT) {
  18652. r[++j] = 0;
  18653. s = 0;
  18654. }
  18655. else {
  18656. r[++j] = a->dp[i] >> s;
  18657. s = DIGIT_BIT - s;
  18658. }
  18659. }
  18660. else {
  18661. s += DIGIT_BIT;
  18662. }
  18663. }
  18664. for (j++; j < size; j++) {
  18665. r[j] = 0;
  18666. }
  18667. #endif
  18668. }
  18669. /* Convert a point of type ecc_point to type sp_point_256.
  18670. *
  18671. * p Point of type sp_point_256 (result).
  18672. * pm Point of type ecc_point.
  18673. */
  18674. static void sp_256_point_from_ecc_point_9(sp_point_256* p,
  18675. const ecc_point* pm)
  18676. {
  18677. XMEMSET(p->x, 0, sizeof(p->x));
  18678. XMEMSET(p->y, 0, sizeof(p->y));
  18679. XMEMSET(p->z, 0, sizeof(p->z));
  18680. sp_256_from_mp(p->x, 9, pm->x);
  18681. sp_256_from_mp(p->y, 9, pm->y);
  18682. sp_256_from_mp(p->z, 9, pm->z);
  18683. p->infinity = 0;
  18684. }
  18685. /* Convert an array of sp_digit to an mp_int.
  18686. *
  18687. * a A single precision integer.
  18688. * r A multi-precision integer.
  18689. */
  18690. static int sp_256_to_mp(const sp_digit* a, mp_int* r)
  18691. {
  18692. int err;
  18693. err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT);
  18694. if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
  18695. #if DIGIT_BIT == 29
  18696. XMEMCPY(r->dp, a, sizeof(sp_digit) * 9);
  18697. r->used = 9;
  18698. mp_clamp(r);
  18699. #elif DIGIT_BIT < 29
  18700. int i;
  18701. int j = 0;
  18702. int s = 0;
  18703. r->dp[0] = 0;
  18704. for (i = 0; i < 9; i++) {
  18705. r->dp[j] |= (mp_digit)(a[i] << s);
  18706. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  18707. s = DIGIT_BIT - s;
  18708. r->dp[++j] = (mp_digit)(a[i] >> s);
  18709. while (s + DIGIT_BIT <= 29) {
  18710. s += DIGIT_BIT;
  18711. r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  18712. if (s == SP_WORD_SIZE) {
  18713. r->dp[j] = 0;
  18714. }
  18715. else {
  18716. r->dp[j] = (mp_digit)(a[i] >> s);
  18717. }
  18718. }
  18719. s = 29 - s;
  18720. }
  18721. r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
  18722. mp_clamp(r);
  18723. #else
  18724. int i;
  18725. int j = 0;
  18726. int s = 0;
  18727. r->dp[0] = 0;
  18728. for (i = 0; i < 9; i++) {
  18729. r->dp[j] |= ((mp_digit)a[i]) << s;
  18730. if (s + 29 >= DIGIT_BIT) {
  18731. #if DIGIT_BIT != 32 && DIGIT_BIT != 64
  18732. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  18733. #endif
  18734. s = DIGIT_BIT - s;
  18735. r->dp[++j] = a[i] >> s;
  18736. s = 29 - s;
  18737. }
  18738. else {
  18739. s += 29;
  18740. }
  18741. }
  18742. r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
  18743. mp_clamp(r);
  18744. #endif
  18745. }
  18746. return err;
  18747. }
  18748. /* Convert a point of type sp_point_256 to type ecc_point.
  18749. *
  18750. * p Point of type sp_point_256.
  18751. * pm Point of type ecc_point (result).
  18752. * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
  18753. * MP_OKAY.
  18754. */
  18755. static int sp_256_point_to_ecc_point_9(const sp_point_256* p, ecc_point* pm)
  18756. {
  18757. int err;
  18758. err = sp_256_to_mp(p->x, pm->x);
  18759. if (err == MP_OKAY) {
  18760. err = sp_256_to_mp(p->y, pm->y);
  18761. }
  18762. if (err == MP_OKAY) {
  18763. err = sp_256_to_mp(p->z, pm->z);
  18764. }
  18765. return err;
  18766. }
  18767. /* Compare a with b in constant time.
  18768. *
  18769. * a A single precision integer.
  18770. * b A single precision integer.
  18771. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  18772. * respectively.
  18773. */
  18774. static sp_digit sp_256_cmp_9(const sp_digit* a, const sp_digit* b)
  18775. {
  18776. sp_digit r = 0;
  18777. #ifdef WOLFSSL_SP_SMALL
  18778. int i;
  18779. for (i=8; i>=0; i--) {
  18780. r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 28);
  18781. }
  18782. #else
  18783. r |= (a[ 8] - b[ 8]) & (0 - (sp_digit)1);
  18784. r |= (a[ 7] - b[ 7]) & ~(((sp_digit)0 - r) >> 28);
  18785. r |= (a[ 6] - b[ 6]) & ~(((sp_digit)0 - r) >> 28);
  18786. r |= (a[ 5] - b[ 5]) & ~(((sp_digit)0 - r) >> 28);
  18787. r |= (a[ 4] - b[ 4]) & ~(((sp_digit)0 - r) >> 28);
  18788. r |= (a[ 3] - b[ 3]) & ~(((sp_digit)0 - r) >> 28);
  18789. r |= (a[ 2] - b[ 2]) & ~(((sp_digit)0 - r) >> 28);
  18790. r |= (a[ 1] - b[ 1]) & ~(((sp_digit)0 - r) >> 28);
  18791. r |= (a[ 0] - b[ 0]) & ~(((sp_digit)0 - r) >> 28);
  18792. #endif /* WOLFSSL_SP_SMALL */
  18793. return r;
  18794. }
  18795. /* Conditionally subtract b from a using the mask m.
  18796. * m is -1 to subtract and 0 when not.
  18797. *
  18798. * r A single precision number representing condition subtract result.
  18799. * a A single precision number to subtract from.
  18800. * b A single precision number to subtract.
  18801. * m Mask value to apply.
  18802. */
  18803. static void sp_256_cond_sub_9(sp_digit* r, const sp_digit* a,
  18804. const sp_digit* b, const sp_digit m)
  18805. {
  18806. #ifdef WOLFSSL_SP_SMALL
  18807. int i;
  18808. for (i = 0; i < 9; i++) {
  18809. r[i] = a[i] - (b[i] & m);
  18810. }
  18811. #else
  18812. r[ 0] = a[ 0] - (b[ 0] & m);
  18813. r[ 1] = a[ 1] - (b[ 1] & m);
  18814. r[ 2] = a[ 2] - (b[ 2] & m);
  18815. r[ 3] = a[ 3] - (b[ 3] & m);
  18816. r[ 4] = a[ 4] - (b[ 4] & m);
  18817. r[ 5] = a[ 5] - (b[ 5] & m);
  18818. r[ 6] = a[ 6] - (b[ 6] & m);
  18819. r[ 7] = a[ 7] - (b[ 7] & m);
  18820. r[ 8] = a[ 8] - (b[ 8] & m);
  18821. #endif /* WOLFSSL_SP_SMALL */
  18822. }
  18823. /* Mul a by scalar b and add into r. (r += a * b)
  18824. *
  18825. * r A single precision integer.
  18826. * a A single precision integer.
  18827. * b A scalar.
  18828. */
  18829. SP_NOINLINE static void sp_256_mul_add_9(sp_digit* r, const sp_digit* a,
  18830. const sp_digit b)
  18831. {
  18832. #ifndef WOLFSSL_SP_LARGE_CODE
  18833. sp_int64 tb = b;
  18834. sp_int64 t = 0;
  18835. int i;
  18836. for (i = 0; i < 9; i++) {
  18837. t += r[i];
  18838. t += tb * a[i];
  18839. r[i] = ((sp_digit)t) & 0x1fffffff;
  18840. t >>= 29;
  18841. }
  18842. r[9] += (sp_digit)t;
  18843. #else
  18844. #ifdef WOLFSSL_SP_SMALL
  18845. sp_int64 tb = b;
  18846. sp_int64 t[4];
  18847. int i;
  18848. t[0] = 0;
  18849. for (i = 0; i < 8; i += 4) {
  18850. t[0] += (tb * a[i+0]) + r[i+0];
  18851. t[1] = (tb * a[i+1]) + r[i+1];
  18852. t[2] = (tb * a[i+2]) + r[i+2];
  18853. t[3] = (tb * a[i+3]) + r[i+3];
  18854. r[i+0] = t[0] & 0x1fffffff;
  18855. t[1] += t[0] >> 29;
  18856. r[i+1] = t[1] & 0x1fffffff;
  18857. t[2] += t[1] >> 29;
  18858. r[i+2] = t[2] & 0x1fffffff;
  18859. t[3] += t[2] >> 29;
  18860. r[i+3] = t[3] & 0x1fffffff;
  18861. t[0] = t[3] >> 29;
  18862. }
  18863. t[0] += (tb * a[8]) + r[8];
  18864. r[8] = t[0] & 0x1fffffff;
  18865. r[9] += (sp_digit)(t[0] >> 29);
  18866. #else
  18867. sp_int64 tb = b;
  18868. sp_int64 t[8];
  18869. int i;
  18870. t[0] = 0;
  18871. for (i = 0; i < 8; i += 8) {
  18872. t[0] += (tb * a[i+0]) + r[i+0];
  18873. t[1] = (tb * a[i+1]) + r[i+1];
  18874. t[2] = (tb * a[i+2]) + r[i+2];
  18875. t[3] = (tb * a[i+3]) + r[i+3];
  18876. t[4] = (tb * a[i+4]) + r[i+4];
  18877. t[5] = (tb * a[i+5]) + r[i+5];
  18878. t[6] = (tb * a[i+6]) + r[i+6];
  18879. t[7] = (tb * a[i+7]) + r[i+7];
  18880. r[i+0] = t[0] & 0x1fffffff;
  18881. t[1] += t[0] >> 29;
  18882. r[i+1] = t[1] & 0x1fffffff;
  18883. t[2] += t[1] >> 29;
  18884. r[i+2] = t[2] & 0x1fffffff;
  18885. t[3] += t[2] >> 29;
  18886. r[i+3] = t[3] & 0x1fffffff;
  18887. t[4] += t[3] >> 29;
  18888. r[i+4] = t[4] & 0x1fffffff;
  18889. t[5] += t[4] >> 29;
  18890. r[i+5] = t[5] & 0x1fffffff;
  18891. t[6] += t[5] >> 29;
  18892. r[i+6] = t[6] & 0x1fffffff;
  18893. t[7] += t[6] >> 29;
  18894. r[i+7] = t[7] & 0x1fffffff;
  18895. t[0] = t[7] >> 29;
  18896. }
  18897. t[0] += (tb * a[8]) + r[8];
  18898. r[8] = t[0] & 0x1fffffff;
  18899. r[9] += (sp_digit)(t[0] >> 29);
  18900. #endif /* WOLFSSL_SP_SMALL */
  18901. #endif /* !WOLFSSL_SP_LARGE_CODE */
  18902. }
  18903. /* Normalize the values in each word to 29 bits.
  18904. *
  18905. * a Array of sp_digit to normalize.
  18906. */
  18907. static void sp_256_norm_9(sp_digit* a)
  18908. {
  18909. #ifdef WOLFSSL_SP_SMALL
  18910. int i;
  18911. for (i = 0; i < 8; i++) {
  18912. a[i+1] += a[i] >> 29;
  18913. a[i] &= 0x1fffffff;
  18914. }
  18915. #else
  18916. a[1] += a[0] >> 29; a[0] &= 0x1fffffff;
  18917. a[2] += a[1] >> 29; a[1] &= 0x1fffffff;
  18918. a[3] += a[2] >> 29; a[2] &= 0x1fffffff;
  18919. a[4] += a[3] >> 29; a[3] &= 0x1fffffff;
  18920. a[5] += a[4] >> 29; a[4] &= 0x1fffffff;
  18921. a[6] += a[5] >> 29; a[5] &= 0x1fffffff;
  18922. a[7] += a[6] >> 29; a[6] &= 0x1fffffff;
  18923. a[8] += a[7] >> 29; a[7] &= 0x1fffffff;
  18924. #endif /* WOLFSSL_SP_SMALL */
  18925. }
  18926. /* Shift the result in the high 256 bits down to the bottom.
  18927. *
  18928. * r A single precision number.
  18929. * a A single precision number.
  18930. */
  18931. static void sp_256_mont_shift_9(sp_digit* r, const sp_digit* a)
  18932. {
  18933. #ifdef WOLFSSL_SP_SMALL
  18934. int i;
  18935. sp_int64 n = a[8] >> 24;
  18936. n += ((sp_int64)a[9]) << 5;
  18937. for (i = 0; i < 8; i++) {
  18938. r[i] = n & 0x1fffffff;
  18939. n >>= 29;
  18940. n += ((sp_int64)a[10 + i]) << 5;
  18941. }
  18942. r[8] = (sp_digit)n;
  18943. #else
  18944. sp_int64 n = a[8] >> 24;
  18945. n += ((sp_int64)a[9]) << 5;
  18946. r[ 0] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[10]) << 5;
  18947. r[ 1] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[11]) << 5;
  18948. r[ 2] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[12]) << 5;
  18949. r[ 3] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[13]) << 5;
  18950. r[ 4] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[14]) << 5;
  18951. r[ 5] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[15]) << 5;
  18952. r[ 6] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[16]) << 5;
  18953. r[ 7] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[17]) << 5;
  18954. r[8] = (sp_digit)n;
  18955. #endif /* WOLFSSL_SP_SMALL */
  18956. XMEMSET(&r[9], 0, sizeof(*r) * 9U);
  18957. }
  18958. /* Reduce the number back to 256 bits using Montgomery reduction.
  18959. *
  18960. * a A single precision number to reduce in place.
  18961. * m The single precision number representing the modulus.
  18962. * mp The digit representing the negative inverse of m mod 2^n.
  18963. */
  18964. static void sp_256_mont_reduce_order_9(sp_digit* a, const sp_digit* m, sp_digit mp)
  18965. {
  18966. int i;
  18967. sp_digit mu;
  18968. sp_digit over;
  18969. sp_256_norm_9(a + 9);
  18970. for (i=0; i<8; i++) {
  18971. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff;
  18972. sp_256_mul_add_9(a+i, m, mu);
  18973. a[i+1] += a[i] >> 29;
  18974. }
  18975. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0xffffffL;
  18976. sp_256_mul_add_9(a+i, m, mu);
  18977. a[i+1] += a[i] >> 29;
  18978. a[i] &= 0x1fffffff;
  18979. sp_256_mont_shift_9(a, a);
  18980. over = a[8] >> 24;
  18981. sp_256_cond_sub_9(a, a, m, ~((over - 1) >> 31));
  18982. sp_256_norm_9(a);
  18983. }
  18984. /* Reduce the number back to 256 bits using Montgomery reduction.
  18985. *
  18986. * a A single precision number to reduce in place.
  18987. * m The single precision number representing the modulus.
  18988. * mp The digit representing the negative inverse of m mod 2^n.
  18989. */
  18990. static void sp_256_mont_reduce_9(sp_digit* a, const sp_digit* m, sp_digit mp)
  18991. {
  18992. int i;
  18993. sp_digit am;
  18994. (void)m;
  18995. (void)mp;
  18996. for (i = 0; i < 8; i++) {
  18997. am = a[i] & 0x1fffffff;
  18998. a[i + 3] += (am << 9) & 0x1fffffff;
  18999. a[i + 4] += am >> 20;
  19000. a[i + 6] += (am << 18) & 0x1fffffff;
  19001. a[i + 7] += (am >> 11) - ((am << 21) & 0x1fffffff);
  19002. a[i + 8] += -(am >> 8) + ((am << 24) & 0x1fffffff);
  19003. a[i + 9] += am >> 5;
  19004. a[i + 1] += a[i] >> 29;
  19005. }
  19006. am = a[8] & 0xffffff;
  19007. a[8 + 3] += (am << 9) & 0x1fffffff;
  19008. a[8 + 4] += am >> 20;
  19009. a[8 + 6] += (am << 18) & 0x1fffffff;
  19010. a[8 + 7] += (am >> 11) - ((am << 21) & 0x1fffffff);
  19011. a[8 + 8] += -(am >> 8) + ((am << 24) & 0x1fffffff);
  19012. a[8 + 9] += am >> 5;
  19013. a[0] = (a[ 8] >> 24) + ((a[ 9] << 5) & 0x1fffffff);
  19014. a[1] = (a[ 9] >> 24) + ((a[10] << 5) & 0x1fffffff);
  19015. a[2] = (a[10] >> 24) + ((a[11] << 5) & 0x1fffffff);
  19016. a[3] = (a[11] >> 24) + ((a[12] << 5) & 0x1fffffff);
  19017. a[4] = (a[12] >> 24) + ((a[13] << 5) & 0x1fffffff);
  19018. a[5] = (a[13] >> 24) + ((a[14] << 5) & 0x1fffffff);
  19019. a[6] = (a[14] >> 24) + ((a[15] << 5) & 0x1fffffff);
  19020. a[7] = (a[15] >> 24) + ((a[16] << 5) & 0x1fffffff);
  19021. a[8] = (a[16] >> 24) + (a[17] << 5);
  19022. a[1] += a[0] >> 29; a[0] &= 0x1fffffff;
  19023. a[2] += a[1] >> 29; a[1] &= 0x1fffffff;
  19024. a[3] += a[2] >> 29; a[2] &= 0x1fffffff;
  19025. a[4] += a[3] >> 29; a[3] &= 0x1fffffff;
  19026. a[5] += a[4] >> 29; a[4] &= 0x1fffffff;
  19027. a[6] += a[5] >> 29; a[5] &= 0x1fffffff;
  19028. a[7] += a[6] >> 29; a[6] &= 0x1fffffff;
  19029. a[8] += a[7] >> 29; a[7] &= 0x1fffffff;
  19030. /* Get the bit over, if any. */
  19031. am = a[8] >> 24;
  19032. /* Create mask. */
  19033. am = 0 - am;
  19034. a[0] -= 0x1fffffff & am;
  19035. a[1] -= 0x1fffffff & am;
  19036. a[2] -= 0x1fffffff & am;
  19037. a[3] -= 0x000001ff & am;
  19038. /* p256_mod[4] is zero */
  19039. /* p256_mod[5] is zero */
  19040. a[6] -= 0x00040000 & am;
  19041. a[7] -= 0x1fe00000 & am;
  19042. a[8] -= 0x00ffffff & am;
  19043. a[1] += a[0] >> 29; a[0] &= 0x1fffffff;
  19044. a[2] += a[1] >> 29; a[1] &= 0x1fffffff;
  19045. a[3] += a[2] >> 29; a[2] &= 0x1fffffff;
  19046. a[4] += a[3] >> 29; a[3] &= 0x1fffffff;
  19047. a[5] += a[4] >> 29; a[4] &= 0x1fffffff;
  19048. a[6] += a[5] >> 29; a[5] &= 0x1fffffff;
  19049. a[7] += a[6] >> 29; a[6] &= 0x1fffffff;
  19050. a[8] += a[7] >> 29; a[7] &= 0x1fffffff;
  19051. }
  19052. /* Multiply two Montgomery form numbers mod the modulus (prime).
  19053. * (r = a * b mod m)
  19054. *
  19055. * r Result of multiplication.
  19056. * a First number to multiply in Montgomery form.
  19057. * b Second number to multiply in Montgomery form.
  19058. * m Modulus (prime).
  19059. * mp Montgomery mulitplier.
  19060. */
  19061. SP_NOINLINE static void sp_256_mont_mul_9(sp_digit* r, const sp_digit* a,
  19062. const sp_digit* b, const sp_digit* m, sp_digit mp)
  19063. {
  19064. sp_256_mul_9(r, a, b);
  19065. sp_256_mont_reduce_9(r, m, mp);
  19066. }
  19067. /* Square the Montgomery form number. (r = a * a mod m)
  19068. *
  19069. * r Result of squaring.
  19070. * a Number to square in Montgomery form.
  19071. * m Modulus (prime).
  19072. * mp Montgomery mulitplier.
  19073. */
  19074. SP_NOINLINE static void sp_256_mont_sqr_9(sp_digit* r, const sp_digit* a,
  19075. const sp_digit* m, sp_digit mp)
  19076. {
  19077. sp_256_sqr_9(r, a);
  19078. sp_256_mont_reduce_9(r, m, mp);
  19079. }
  19080. #if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY)
  19081. /* Square the Montgomery form number a number of times. (r = a ^ n mod m)
  19082. *
  19083. * r Result of squaring.
  19084. * a Number to square in Montgomery form.
  19085. * n Number of times to square.
  19086. * m Modulus (prime).
  19087. * mp Montgomery mulitplier.
  19088. */
  19089. static void sp_256_mont_sqr_n_9(sp_digit* r, const sp_digit* a, int n,
  19090. const sp_digit* m, sp_digit mp)
  19091. {
  19092. sp_256_mont_sqr_9(r, a, m, mp);
  19093. for (; n > 1; n--) {
  19094. sp_256_mont_sqr_9(r, r, m, mp);
  19095. }
  19096. }
  19097. #endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */
  19098. #ifdef WOLFSSL_SP_SMALL
  19099. /* Mod-2 for the P256 curve. */
  19100. static const uint32_t p256_mod_minus_2[8] = {
  19101. 0xfffffffdU,0xffffffffU,0xffffffffU,0x00000000U,0x00000000U,0x00000000U,
  19102. 0x00000001U,0xffffffffU
  19103. };
  19104. #endif /* !WOLFSSL_SP_SMALL */
  19105. /* Invert the number, in Montgomery form, modulo the modulus (prime) of the
  19106. * P256 curve. (r = 1 / a mod m)
  19107. *
  19108. * r Inverse result.
  19109. * a Number to invert.
  19110. * td Temporary data.
  19111. */
  19112. static void sp_256_mont_inv_9(sp_digit* r, const sp_digit* a, sp_digit* td)
  19113. {
  19114. #ifdef WOLFSSL_SP_SMALL
  19115. sp_digit* t = td;
  19116. int i;
  19117. XMEMCPY(t, a, sizeof(sp_digit) * 9);
  19118. for (i=254; i>=0; i--) {
  19119. sp_256_mont_sqr_9(t, t, p256_mod, p256_mp_mod);
  19120. if (p256_mod_minus_2[i / 32] & ((sp_digit)1 << (i % 32)))
  19121. sp_256_mont_mul_9(t, t, a, p256_mod, p256_mp_mod);
  19122. }
  19123. XMEMCPY(r, t, sizeof(sp_digit) * 9);
  19124. #else
  19125. sp_digit* t1 = td;
  19126. sp_digit* t2 = td + 2 * 9;
  19127. sp_digit* t3 = td + 4 * 9;
  19128. /* 0x2 */
  19129. sp_256_mont_sqr_9(t1, a, p256_mod, p256_mp_mod);
  19130. /* 0x3 */
  19131. sp_256_mont_mul_9(t2, t1, a, p256_mod, p256_mp_mod);
  19132. /* 0xc */
  19133. sp_256_mont_sqr_n_9(t1, t2, 2, p256_mod, p256_mp_mod);
  19134. /* 0xd */
  19135. sp_256_mont_mul_9(t3, t1, a, p256_mod, p256_mp_mod);
  19136. /* 0xf */
  19137. sp_256_mont_mul_9(t2, t2, t1, p256_mod, p256_mp_mod);
  19138. /* 0xf0 */
  19139. sp_256_mont_sqr_n_9(t1, t2, 4, p256_mod, p256_mp_mod);
  19140. /* 0xfd */
  19141. sp_256_mont_mul_9(t3, t3, t1, p256_mod, p256_mp_mod);
  19142. /* 0xff */
  19143. sp_256_mont_mul_9(t2, t2, t1, p256_mod, p256_mp_mod);
  19144. /* 0xff00 */
  19145. sp_256_mont_sqr_n_9(t1, t2, 8, p256_mod, p256_mp_mod);
  19146. /* 0xfffd */
  19147. sp_256_mont_mul_9(t3, t3, t1, p256_mod, p256_mp_mod);
  19148. /* 0xffff */
  19149. sp_256_mont_mul_9(t2, t2, t1, p256_mod, p256_mp_mod);
  19150. /* 0xffff0000 */
  19151. sp_256_mont_sqr_n_9(t1, t2, 16, p256_mod, p256_mp_mod);
  19152. /* 0xfffffffd */
  19153. sp_256_mont_mul_9(t3, t3, t1, p256_mod, p256_mp_mod);
  19154. /* 0xffffffff */
  19155. sp_256_mont_mul_9(t2, t2, t1, p256_mod, p256_mp_mod);
  19156. /* 0xffffffff00000000 */
  19157. sp_256_mont_sqr_n_9(t1, t2, 32, p256_mod, p256_mp_mod);
  19158. /* 0xffffffffffffffff */
  19159. sp_256_mont_mul_9(t2, t2, t1, p256_mod, p256_mp_mod);
  19160. /* 0xffffffff00000001 */
  19161. sp_256_mont_mul_9(r, t1, a, p256_mod, p256_mp_mod);
  19162. /* 0xffffffff000000010000000000000000000000000000000000000000 */
  19163. sp_256_mont_sqr_n_9(r, r, 160, p256_mod, p256_mp_mod);
  19164. /* 0xffffffff00000001000000000000000000000000ffffffffffffffff */
  19165. sp_256_mont_mul_9(r, r, t2, p256_mod, p256_mp_mod);
  19166. /* 0xffffffff00000001000000000000000000000000ffffffffffffffff00000000 */
  19167. sp_256_mont_sqr_n_9(r, r, 32, p256_mod, p256_mp_mod);
  19168. /* 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffd */
  19169. sp_256_mont_mul_9(r, r, t3, p256_mod, p256_mp_mod);
  19170. #endif /* WOLFSSL_SP_SMALL */
  19171. }
  19172. /* Map the Montgomery form projective coordinate point to an affine point.
  19173. *
  19174. * r Resulting affine coordinate point.
  19175. * p Montgomery form projective coordinate point.
  19176. * t Temporary ordinate data.
  19177. */
  19178. static void sp_256_map_9(sp_point_256* r, const sp_point_256* p,
  19179. sp_digit* t)
  19180. {
  19181. sp_digit* t1 = t;
  19182. sp_digit* t2 = t + 2*9;
  19183. sp_int32 n;
  19184. sp_256_mont_inv_9(t1, p->z, t + 2*9);
  19185. sp_256_mont_sqr_9(t2, t1, p256_mod, p256_mp_mod);
  19186. sp_256_mont_mul_9(t1, t2, t1, p256_mod, p256_mp_mod);
  19187. /* x /= z^2 */
  19188. sp_256_mont_mul_9(r->x, p->x, t2, p256_mod, p256_mp_mod);
  19189. XMEMSET(r->x + 9, 0, sizeof(r->x) / 2U);
  19190. sp_256_mont_reduce_9(r->x, p256_mod, p256_mp_mod);
  19191. /* Reduce x to less than modulus */
  19192. n = sp_256_cmp_9(r->x, p256_mod);
  19193. sp_256_cond_sub_9(r->x, r->x, p256_mod, ~(n >> 28));
  19194. sp_256_norm_9(r->x);
  19195. /* y /= z^3 */
  19196. sp_256_mont_mul_9(r->y, p->y, t1, p256_mod, p256_mp_mod);
  19197. XMEMSET(r->y + 9, 0, sizeof(r->y) / 2U);
  19198. sp_256_mont_reduce_9(r->y, p256_mod, p256_mp_mod);
  19199. /* Reduce y to less than modulus */
  19200. n = sp_256_cmp_9(r->y, p256_mod);
  19201. sp_256_cond_sub_9(r->y, r->y, p256_mod, ~(n >> 28));
  19202. sp_256_norm_9(r->y);
  19203. XMEMSET(r->z, 0, sizeof(r->z) / 2);
  19204. r->z[0] = 1;
  19205. }
  19206. /* Add two Montgomery form numbers (r = a + b % m).
  19207. *
  19208. * r Result of addition.
  19209. * a First number to add in Montgomery form.
  19210. * b Second number to add in Montgomery form.
  19211. * m Modulus (prime).
  19212. */
  19213. static void sp_256_mont_add_9(sp_digit* r, const sp_digit* a, const sp_digit* b,
  19214. const sp_digit* m)
  19215. {
  19216. sp_digit over;
  19217. (void)sp_256_add_9(r, a, b);
  19218. sp_256_norm_9(r);
  19219. over = r[8] >> 24;
  19220. sp_256_cond_sub_9(r, r, m, ~((over - 1) >> 31));
  19221. sp_256_norm_9(r);
  19222. }
  19223. /* Double a Montgomery form number (r = a + a % m).
  19224. *
  19225. * r Result of doubling.
  19226. * a Number to double in Montgomery form.
  19227. * m Modulus (prime).
  19228. */
  19229. static void sp_256_mont_dbl_9(sp_digit* r, const sp_digit* a, const sp_digit* m)
  19230. {
  19231. sp_digit over;
  19232. (void)sp_256_add_9(r, a, a);
  19233. sp_256_norm_9(r);
  19234. over = r[8] >> 24;
  19235. sp_256_cond_sub_9(r, r, m, ~((over - 1) >> 31));
  19236. sp_256_norm_9(r);
  19237. }
  19238. /* Triple a Montgomery form number (r = a + a + a % m).
  19239. *
  19240. * r Result of Tripling.
  19241. * a Number to triple in Montgomery form.
  19242. * m Modulus (prime).
  19243. */
  19244. static void sp_256_mont_tpl_9(sp_digit* r, const sp_digit* a, const sp_digit* m)
  19245. {
  19246. sp_digit over;
  19247. (void)sp_256_add_9(r, a, a);
  19248. sp_256_norm_9(r);
  19249. over = r[8] >> 24;
  19250. sp_256_cond_sub_9(r, r, m, ~((over - 1) >> 31));
  19251. sp_256_norm_9(r);
  19252. (void)sp_256_add_9(r, r, a);
  19253. sp_256_norm_9(r);
  19254. over = r[8] >> 24;
  19255. sp_256_cond_sub_9(r, r, m, ~((over - 1) >> 31));
  19256. sp_256_norm_9(r);
  19257. }
  19258. #ifdef WOLFSSL_SP_SMALL
  19259. /* Conditionally add a and b using the mask m.
  19260. * m is -1 to add and 0 when not.
  19261. *
  19262. * r A single precision number representing conditional add result.
  19263. * a A single precision number to add with.
  19264. * b A single precision number to add.
  19265. * m Mask value to apply.
  19266. */
  19267. static void sp_256_cond_add_9(sp_digit* r, const sp_digit* a,
  19268. const sp_digit* b, const sp_digit m)
  19269. {
  19270. int i;
  19271. for (i = 0; i < 9; i++) {
  19272. r[i] = a[i] + (b[i] & m);
  19273. }
  19274. }
  19275. #endif /* WOLFSSL_SP_SMALL */
  19276. #ifndef WOLFSSL_SP_SMALL
  19277. /* Conditionally add a and b using the mask m.
  19278. * m is -1 to add and 0 when not.
  19279. *
  19280. * r A single precision number representing conditional add result.
  19281. * a A single precision number to add with.
  19282. * b A single precision number to add.
  19283. * m Mask value to apply.
  19284. */
  19285. static void sp_256_cond_add_9(sp_digit* r, const sp_digit* a,
  19286. const sp_digit* b, const sp_digit m)
  19287. {
  19288. r[ 0] = a[ 0] + (b[ 0] & m);
  19289. r[ 1] = a[ 1] + (b[ 1] & m);
  19290. r[ 2] = a[ 2] + (b[ 2] & m);
  19291. r[ 3] = a[ 3] + (b[ 3] & m);
  19292. r[ 4] = a[ 4] + (b[ 4] & m);
  19293. r[ 5] = a[ 5] + (b[ 5] & m);
  19294. r[ 6] = a[ 6] + (b[ 6] & m);
  19295. r[ 7] = a[ 7] + (b[ 7] & m);
  19296. r[ 8] = a[ 8] + (b[ 8] & m);
  19297. }
  19298. #endif /* !WOLFSSL_SP_SMALL */
  19299. /* Subtract two Montgomery form numbers (r = a - b % m).
  19300. *
  19301. * r Result of subtration.
  19302. * a Number to subtract from in Montgomery form.
  19303. * b Number to subtract with in Montgomery form.
  19304. * m Modulus (prime).
  19305. */
  19306. static void sp_256_mont_sub_9(sp_digit* r, const sp_digit* a, const sp_digit* b,
  19307. const sp_digit* m)
  19308. {
  19309. (void)sp_256_sub_9(r, a, b);
  19310. sp_256_norm_9(r);
  19311. sp_256_cond_add_9(r, r, m, r[8] >> 24);
  19312. sp_256_norm_9(r);
  19313. }
  19314. #define sp_256_mont_sub_lower_9 sp_256_mont_sub_9
  19315. /* Shift number left one bit.
  19316. * Bottom bit is lost.
  19317. *
  19318. * r Result of shift.
  19319. * a Number to shift.
  19320. */
  19321. SP_NOINLINE static void sp_256_rshift1_9(sp_digit* r, const sp_digit* a)
  19322. {
  19323. #ifdef WOLFSSL_SP_SMALL
  19324. int i;
  19325. for (i=0; i<8; i++) {
  19326. r[i] = (a[i] >> 1) + ((a[i + 1] << 28) & 0x1fffffff);
  19327. }
  19328. #else
  19329. r[0] = (a[0] >> 1) + ((a[1] << 28) & 0x1fffffff);
  19330. r[1] = (a[1] >> 1) + ((a[2] << 28) & 0x1fffffff);
  19331. r[2] = (a[2] >> 1) + ((a[3] << 28) & 0x1fffffff);
  19332. r[3] = (a[3] >> 1) + ((a[4] << 28) & 0x1fffffff);
  19333. r[4] = (a[4] >> 1) + ((a[5] << 28) & 0x1fffffff);
  19334. r[5] = (a[5] >> 1) + ((a[6] << 28) & 0x1fffffff);
  19335. r[6] = (a[6] >> 1) + ((a[7] << 28) & 0x1fffffff);
  19336. r[7] = (a[7] >> 1) + ((a[8] << 28) & 0x1fffffff);
  19337. #endif
  19338. r[8] = a[8] >> 1;
  19339. }
  19340. /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
  19341. *
  19342. * r Result of division by 2.
  19343. * a Number to divide.
  19344. * m Modulus (prime).
  19345. */
  19346. static void sp_256_div2_9(sp_digit* r, const sp_digit* a, const sp_digit* m)
  19347. {
  19348. sp_256_cond_add_9(r, a, m, 0 - (a[0] & 1));
  19349. sp_256_norm_9(r);
  19350. sp_256_rshift1_9(r, r);
  19351. }
  19352. /* Double the Montgomery form projective point p.
  19353. *
  19354. * r Result of doubling point.
  19355. * p Point to double.
  19356. * t Temporary ordinate data.
  19357. */
  19358. #ifdef WOLFSSL_SP_NONBLOCK
  19359. typedef struct sp_256_proj_point_dbl_9_ctx {
  19360. int state;
  19361. sp_digit* t1;
  19362. sp_digit* t2;
  19363. sp_digit* x;
  19364. sp_digit* y;
  19365. sp_digit* z;
  19366. } sp_256_proj_point_dbl_9_ctx;
  19367. static int sp_256_proj_point_dbl_9_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* p, sp_digit* t)
  19368. {
  19369. int err = FP_WOULDBLOCK;
  19370. sp_256_proj_point_dbl_9_ctx* ctx = (sp_256_proj_point_dbl_9_ctx*)sp_ctx->data;
  19371. typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_9_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  19372. (void)sizeof(ctx_size_test);
  19373. switch (ctx->state) {
  19374. case 0:
  19375. ctx->t1 = t;
  19376. ctx->t2 = t + 2*9;
  19377. ctx->x = r->x;
  19378. ctx->y = r->y;
  19379. ctx->z = r->z;
  19380. /* Put infinity into result. */
  19381. if (r != p) {
  19382. r->infinity = p->infinity;
  19383. }
  19384. ctx->state = 1;
  19385. break;
  19386. case 1:
  19387. /* T1 = Z * Z */
  19388. sp_256_mont_sqr_9(ctx->t1, p->z, p256_mod, p256_mp_mod);
  19389. ctx->state = 2;
  19390. break;
  19391. case 2:
  19392. /* Z = Y * Z */
  19393. sp_256_mont_mul_9(ctx->z, p->y, p->z, p256_mod, p256_mp_mod);
  19394. ctx->state = 3;
  19395. break;
  19396. case 3:
  19397. /* Z = 2Z */
  19398. sp_256_mont_dbl_9(ctx->z, ctx->z, p256_mod);
  19399. ctx->state = 4;
  19400. break;
  19401. case 4:
  19402. /* T2 = X - T1 */
  19403. sp_256_mont_sub_9(ctx->t2, p->x, ctx->t1, p256_mod);
  19404. ctx->state = 5;
  19405. break;
  19406. case 5:
  19407. /* T1 = X + T1 */
  19408. sp_256_mont_add_9(ctx->t1, p->x, ctx->t1, p256_mod);
  19409. ctx->state = 6;
  19410. break;
  19411. case 6:
  19412. /* T2 = T1 * T2 */
  19413. sp_256_mont_mul_9(ctx->t2, ctx->t1, ctx->t2, p256_mod, p256_mp_mod);
  19414. ctx->state = 7;
  19415. break;
  19416. case 7:
  19417. /* T1 = 3T2 */
  19418. sp_256_mont_tpl_9(ctx->t1, ctx->t2, p256_mod);
  19419. ctx->state = 8;
  19420. break;
  19421. case 8:
  19422. /* Y = 2Y */
  19423. sp_256_mont_dbl_9(ctx->y, p->y, p256_mod);
  19424. ctx->state = 9;
  19425. break;
  19426. case 9:
  19427. /* Y = Y * Y */
  19428. sp_256_mont_sqr_9(ctx->y, ctx->y, p256_mod, p256_mp_mod);
  19429. ctx->state = 10;
  19430. break;
  19431. case 10:
  19432. /* T2 = Y * Y */
  19433. sp_256_mont_sqr_9(ctx->t2, ctx->y, p256_mod, p256_mp_mod);
  19434. ctx->state = 11;
  19435. break;
  19436. case 11:
  19437. /* T2 = T2/2 */
  19438. sp_256_div2_9(ctx->t2, ctx->t2, p256_mod);
  19439. ctx->state = 12;
  19440. break;
  19441. case 12:
  19442. /* Y = Y * X */
  19443. sp_256_mont_mul_9(ctx->y, ctx->y, p->x, p256_mod, p256_mp_mod);
  19444. ctx->state = 13;
  19445. break;
  19446. case 13:
  19447. /* X = T1 * T1 */
  19448. sp_256_mont_sqr_9(ctx->x, ctx->t1, p256_mod, p256_mp_mod);
  19449. ctx->state = 14;
  19450. break;
  19451. case 14:
  19452. /* X = X - Y */
  19453. sp_256_mont_sub_9(ctx->x, ctx->x, ctx->y, p256_mod);
  19454. ctx->state = 15;
  19455. break;
  19456. case 15:
  19457. /* X = X - Y */
  19458. sp_256_mont_sub_9(ctx->x, ctx->x, ctx->y, p256_mod);
  19459. ctx->state = 16;
  19460. break;
  19461. case 16:
  19462. /* Y = Y - X */
  19463. sp_256_mont_sub_lower_9(ctx->y, ctx->y, ctx->x, p256_mod);
  19464. ctx->state = 17;
  19465. break;
  19466. case 17:
  19467. /* Y = Y * T1 */
  19468. sp_256_mont_mul_9(ctx->y, ctx->y, ctx->t1, p256_mod, p256_mp_mod);
  19469. ctx->state = 18;
  19470. break;
  19471. case 18:
  19472. /* Y = Y - T2 */
  19473. sp_256_mont_sub_9(ctx->y, ctx->y, ctx->t2, p256_mod);
  19474. ctx->state = 19;
  19475. /* fall-through */
  19476. case 19:
  19477. err = MP_OKAY;
  19478. break;
  19479. }
  19480. if (err == MP_OKAY && ctx->state != 19) {
  19481. err = FP_WOULDBLOCK;
  19482. }
  19483. return err;
  19484. }
  19485. #endif /* WOLFSSL_SP_NONBLOCK */
  19486. static void sp_256_proj_point_dbl_9(sp_point_256* r, const sp_point_256* p,
  19487. sp_digit* t)
  19488. {
  19489. sp_digit* t1 = t;
  19490. sp_digit* t2 = t + 2*9;
  19491. sp_digit* x;
  19492. sp_digit* y;
  19493. sp_digit* z;
  19494. x = r->x;
  19495. y = r->y;
  19496. z = r->z;
  19497. /* Put infinity into result. */
  19498. if (r != p) {
  19499. r->infinity = p->infinity;
  19500. }
  19501. /* T1 = Z * Z */
  19502. sp_256_mont_sqr_9(t1, p->z, p256_mod, p256_mp_mod);
  19503. /* Z = Y * Z */
  19504. sp_256_mont_mul_9(z, p->y, p->z, p256_mod, p256_mp_mod);
  19505. /* Z = 2Z */
  19506. sp_256_mont_dbl_9(z, z, p256_mod);
  19507. /* T2 = X - T1 */
  19508. sp_256_mont_sub_9(t2, p->x, t1, p256_mod);
  19509. /* T1 = X + T1 */
  19510. sp_256_mont_add_9(t1, p->x, t1, p256_mod);
  19511. /* T2 = T1 * T2 */
  19512. sp_256_mont_mul_9(t2, t1, t2, p256_mod, p256_mp_mod);
  19513. /* T1 = 3T2 */
  19514. sp_256_mont_tpl_9(t1, t2, p256_mod);
  19515. /* Y = 2Y */
  19516. sp_256_mont_dbl_9(y, p->y, p256_mod);
  19517. /* Y = Y * Y */
  19518. sp_256_mont_sqr_9(y, y, p256_mod, p256_mp_mod);
  19519. /* T2 = Y * Y */
  19520. sp_256_mont_sqr_9(t2, y, p256_mod, p256_mp_mod);
  19521. /* T2 = T2/2 */
  19522. sp_256_div2_9(t2, t2, p256_mod);
  19523. /* Y = Y * X */
  19524. sp_256_mont_mul_9(y, y, p->x, p256_mod, p256_mp_mod);
  19525. /* X = T1 * T1 */
  19526. sp_256_mont_sqr_9(x, t1, p256_mod, p256_mp_mod);
  19527. /* X = X - Y */
  19528. sp_256_mont_sub_9(x, x, y, p256_mod);
  19529. /* X = X - Y */
  19530. sp_256_mont_sub_9(x, x, y, p256_mod);
  19531. /* Y = Y - X */
  19532. sp_256_mont_sub_lower_9(y, y, x, p256_mod);
  19533. /* Y = Y * T1 */
  19534. sp_256_mont_mul_9(y, y, t1, p256_mod, p256_mp_mod);
  19535. /* Y = Y - T2 */
  19536. sp_256_mont_sub_9(y, y, t2, p256_mod);
  19537. }
  19538. /* Compare two numbers to determine if they are equal.
  19539. * Constant time implementation.
  19540. *
  19541. * a First number to compare.
  19542. * b Second number to compare.
  19543. * returns 1 when equal and 0 otherwise.
  19544. */
  19545. static int sp_256_cmp_equal_9(const sp_digit* a, const sp_digit* b)
  19546. {
  19547. return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) |
  19548. (a[3] ^ b[3]) | (a[4] ^ b[4]) | (a[5] ^ b[5]) |
  19549. (a[6] ^ b[6]) | (a[7] ^ b[7]) | (a[8] ^ b[8])) == 0;
  19550. }
  19551. /* Returns 1 if the number of zero.
  19552. * Implementation is constant time.
  19553. *
  19554. * a Number to check.
  19555. * returns 1 if the number is zero and 0 otherwise.
  19556. */
  19557. static int sp_256_iszero_9(const sp_digit* a)
  19558. {
  19559. return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] |
  19560. a[8]) == 0;
  19561. }
  19562. /* Add two Montgomery form projective points.
  19563. *
  19564. * r Result of addition.
  19565. * p First point to add.
  19566. * q Second point to add.
  19567. * t Temporary ordinate data.
  19568. */
  19569. #ifdef WOLFSSL_SP_NONBLOCK
  19570. typedef struct sp_256_proj_point_add_9_ctx {
  19571. int state;
  19572. sp_256_proj_point_dbl_9_ctx dbl_ctx;
  19573. const sp_point_256* ap[2];
  19574. sp_point_256* rp[2];
  19575. sp_digit* t1;
  19576. sp_digit* t2;
  19577. sp_digit* t3;
  19578. sp_digit* t4;
  19579. sp_digit* t5;
  19580. sp_digit* t6;
  19581. sp_digit* x;
  19582. sp_digit* y;
  19583. sp_digit* z;
  19584. } sp_256_proj_point_add_9_ctx;
  19585. static int sp_256_proj_point_add_9_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r,
  19586. const sp_point_256* p, const sp_point_256* q, sp_digit* t)
  19587. {
  19588. int err = FP_WOULDBLOCK;
  19589. sp_256_proj_point_add_9_ctx* ctx = (sp_256_proj_point_add_9_ctx*)sp_ctx->data;
  19590. /* Ensure only the first point is the same as the result. */
  19591. if (q == r) {
  19592. const sp_point_256* a = p;
  19593. p = q;
  19594. q = a;
  19595. }
  19596. typedef char ctx_size_test[sizeof(sp_256_proj_point_add_9_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  19597. (void)sizeof(ctx_size_test);
  19598. switch (ctx->state) {
  19599. case 0: /* INIT */
  19600. ctx->t1 = t;
  19601. ctx->t2 = t + 2*9;
  19602. ctx->t3 = t + 4*9;
  19603. ctx->t4 = t + 6*9;
  19604. ctx->t5 = t + 8*9;
  19605. ctx->t6 = t + 10*9;
  19606. ctx->x = ctx->t6;
  19607. ctx->y = ctx->t1;
  19608. ctx->z = ctx->t2;
  19609. ctx->state = 1;
  19610. break;
  19611. case 1:
  19612. /* Check double */
  19613. (void)sp_256_sub_9(ctx->t1, p256_mod, q->y);
  19614. sp_256_norm_9(ctx->t1);
  19615. if ((~p->infinity & ~q->infinity &
  19616. sp_256_cmp_equal_9(p->x, q->x) & sp_256_cmp_equal_9(p->z, q->z) &
  19617. (sp_256_cmp_equal_9(p->y, q->y) | sp_256_cmp_equal_9(p->y, ctx->t1))) != 0)
  19618. {
  19619. XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
  19620. ctx->state = 2;
  19621. }
  19622. else {
  19623. ctx->state = 3;
  19624. }
  19625. break;
  19626. case 2:
  19627. err = sp_256_proj_point_dbl_9_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t);
  19628. if (err == MP_OKAY)
  19629. ctx->state = 27; /* done */
  19630. break;
  19631. case 3:
  19632. {
  19633. ctx->state = 4;
  19634. break;
  19635. }
  19636. case 4:
  19637. /* U1 = X1*Z2^2 */
  19638. sp_256_mont_sqr_9(ctx->t1, q->z, p256_mod, p256_mp_mod);
  19639. ctx->state = 5;
  19640. break;
  19641. case 5:
  19642. sp_256_mont_mul_9(ctx->t3, ctx->t1, q->z, p256_mod, p256_mp_mod);
  19643. ctx->state = 6;
  19644. break;
  19645. case 6:
  19646. sp_256_mont_mul_9(ctx->t1, ctx->t1, p->x, p256_mod, p256_mp_mod);
  19647. ctx->state = 7;
  19648. break;
  19649. case 7:
  19650. /* U2 = X2*Z1^2 */
  19651. sp_256_mont_sqr_9(ctx->t2, p->z, p256_mod, p256_mp_mod);
  19652. ctx->state = 8;
  19653. break;
  19654. case 8:
  19655. sp_256_mont_mul_9(ctx->t4, ctx->t2, p->z, p256_mod, p256_mp_mod);
  19656. ctx->state = 9;
  19657. break;
  19658. case 9:
  19659. sp_256_mont_mul_9(ctx->t2, ctx->t2, q->x, p256_mod, p256_mp_mod);
  19660. ctx->state = 10;
  19661. break;
  19662. case 10:
  19663. /* S1 = Y1*Z2^3 */
  19664. sp_256_mont_mul_9(ctx->t3, ctx->t3, p->y, p256_mod, p256_mp_mod);
  19665. ctx->state = 11;
  19666. break;
  19667. case 11:
  19668. /* S2 = Y2*Z1^3 */
  19669. sp_256_mont_mul_9(ctx->t4, ctx->t4, q->y, p256_mod, p256_mp_mod);
  19670. ctx->state = 12;
  19671. break;
  19672. case 12:
  19673. /* H = U2 - U1 */
  19674. sp_256_mont_sub_9(ctx->t2, ctx->t2, ctx->t1, p256_mod);
  19675. ctx->state = 13;
  19676. break;
  19677. case 13:
  19678. /* R = S2 - S1 */
  19679. sp_256_mont_sub_9(ctx->t4, ctx->t4, ctx->t3, p256_mod);
  19680. ctx->state = 14;
  19681. break;
  19682. case 14:
  19683. /* X3 = R^2 - H^3 - 2*U1*H^2 */
  19684. sp_256_mont_sqr_9(ctx->t5, ctx->t2, p256_mod, p256_mp_mod);
  19685. ctx->state = 15;
  19686. break;
  19687. case 15:
  19688. sp_256_mont_mul_9(ctx->y, ctx->t1, ctx->t5, p256_mod, p256_mp_mod);
  19689. ctx->state = 16;
  19690. break;
  19691. case 16:
  19692. sp_256_mont_mul_9(ctx->t5, ctx->t5, ctx->t2, p256_mod, p256_mp_mod);
  19693. ctx->state = 17;
  19694. break;
  19695. case 17:
  19696. /* Z3 = H*Z1*Z2 */
  19697. sp_256_mont_mul_9(ctx->z, p->z, ctx->t2, p256_mod, p256_mp_mod);
  19698. ctx->state = 18;
  19699. break;
  19700. case 18:
  19701. sp_256_mont_mul_9(ctx->z, ctx->z, q->z, p256_mod, p256_mp_mod);
  19702. ctx->state = 19;
  19703. break;
  19704. case 19:
  19705. sp_256_mont_sqr_9(ctx->x, ctx->t4, p256_mod, p256_mp_mod);
  19706. ctx->state = 20;
  19707. break;
  19708. case 20:
  19709. sp_256_mont_sub_9(ctx->x, ctx->x, ctx->t5, p256_mod);
  19710. ctx->state = 21;
  19711. break;
  19712. case 21:
  19713. sp_256_mont_mul_9(ctx->t5, ctx->t5, ctx->t3, p256_mod, p256_mp_mod);
  19714. ctx->state = 22;
  19715. break;
  19716. case 22:
  19717. sp_256_mont_dbl_9(ctx->t3, ctx->y, p256_mod);
  19718. ctx->state = 23;
  19719. break;
  19720. case 23:
  19721. sp_256_mont_sub_9(ctx->x, ctx->x, ctx->t3, p256_mod);
  19722. ctx->state = 24;
  19723. break;
  19724. case 24:
  19725. /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
  19726. sp_256_mont_sub_lower_9(ctx->y, ctx->y, ctx->x, p256_mod);
  19727. ctx->state = 25;
  19728. break;
  19729. case 25:
  19730. sp_256_mont_mul_9(ctx->y, ctx->y, ctx->t4, p256_mod, p256_mp_mod);
  19731. ctx->state = 26;
  19732. break;
  19733. case 26:
  19734. sp_256_mont_sub_9(ctx->y, ctx->y, ctx->t5, p256_mod);
  19735. ctx->state = 27;
  19736. /* fall-through */
  19737. case 27:
  19738. {
  19739. int i;
  19740. sp_digit maskp = 0 - (q->infinity & (!p->infinity));
  19741. sp_digit maskq = 0 - (p->infinity & (!q->infinity));
  19742. sp_digit maskt = ~(maskp | maskq);
  19743. for (i = 0; i < 9; i++) {
  19744. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) |
  19745. (ctx->x[i] & maskt);
  19746. }
  19747. for (i = 0; i < 9; i++) {
  19748. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) |
  19749. (ctx->y[i] & maskt);
  19750. }
  19751. for (i = 0; i < 9; i++) {
  19752. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) |
  19753. (ctx->z[i] & maskt);
  19754. }
  19755. r->z[0] |= p->infinity & q->infinity;
  19756. r->infinity = p->infinity & q->infinity;
  19757. err = MP_OKAY;
  19758. break;
  19759. }
  19760. }
  19761. if (err == MP_OKAY && ctx->state != 27) {
  19762. err = FP_WOULDBLOCK;
  19763. }
  19764. return err;
  19765. }
  19766. #endif /* WOLFSSL_SP_NONBLOCK */
  19767. static void sp_256_proj_point_add_9(sp_point_256* r,
  19768. const sp_point_256* p, const sp_point_256* q, sp_digit* t)
  19769. {
  19770. sp_digit* t1 = t;
  19771. sp_digit* t2 = t + 2*9;
  19772. sp_digit* t3 = t + 4*9;
  19773. sp_digit* t4 = t + 6*9;
  19774. sp_digit* t5 = t + 8*9;
  19775. sp_digit* t6 = t + 10*9;
  19776. /* Check double */
  19777. (void)sp_256_sub_9(t1, p256_mod, q->y);
  19778. sp_256_norm_9(t1);
  19779. if ((~p->infinity & ~q->infinity &
  19780. sp_256_cmp_equal_9(p->x, q->x) & sp_256_cmp_equal_9(p->z, q->z) &
  19781. (sp_256_cmp_equal_9(p->y, q->y) | sp_256_cmp_equal_9(p->y, t1))) != 0) {
  19782. sp_256_proj_point_dbl_9(r, p, t);
  19783. }
  19784. else {
  19785. sp_digit maskp;
  19786. sp_digit maskq;
  19787. sp_digit maskt;
  19788. sp_digit* x = t6;
  19789. sp_digit* y = t1;
  19790. sp_digit* z = t2;
  19791. int i;
  19792. maskp = 0 - (q->infinity & (!p->infinity));
  19793. maskq = 0 - (p->infinity & (!q->infinity));
  19794. maskt = ~(maskp | maskq);
  19795. /* U1 = X1*Z2^2 */
  19796. sp_256_mont_sqr_9(t1, q->z, p256_mod, p256_mp_mod);
  19797. sp_256_mont_mul_9(t3, t1, q->z, p256_mod, p256_mp_mod);
  19798. sp_256_mont_mul_9(t1, t1, p->x, p256_mod, p256_mp_mod);
  19799. /* U2 = X2*Z1^2 */
  19800. sp_256_mont_sqr_9(t2, p->z, p256_mod, p256_mp_mod);
  19801. sp_256_mont_mul_9(t4, t2, p->z, p256_mod, p256_mp_mod);
  19802. sp_256_mont_mul_9(t2, t2, q->x, p256_mod, p256_mp_mod);
  19803. /* S1 = Y1*Z2^3 */
  19804. sp_256_mont_mul_9(t3, t3, p->y, p256_mod, p256_mp_mod);
  19805. /* S2 = Y2*Z1^3 */
  19806. sp_256_mont_mul_9(t4, t4, q->y, p256_mod, p256_mp_mod);
  19807. /* H = U2 - U1 */
  19808. sp_256_mont_sub_9(t2, t2, t1, p256_mod);
  19809. /* R = S2 - S1 */
  19810. sp_256_mont_sub_9(t4, t4, t3, p256_mod);
  19811. if (~p->infinity & ~q->infinity &
  19812. sp_256_iszero_9(t2) & sp_256_iszero_9(t4) & maskt) {
  19813. sp_256_proj_point_dbl_9(r, p, t);
  19814. }
  19815. else {
  19816. /* X3 = R^2 - H^3 - 2*U1*H^2 */
  19817. sp_256_mont_sqr_9(t5, t2, p256_mod, p256_mp_mod);
  19818. sp_256_mont_mul_9(y, t1, t5, p256_mod, p256_mp_mod);
  19819. sp_256_mont_mul_9(t5, t5, t2, p256_mod, p256_mp_mod);
  19820. /* Z3 = H*Z1*Z2 */
  19821. sp_256_mont_mul_9(z, p->z, t2, p256_mod, p256_mp_mod);
  19822. sp_256_mont_mul_9(z, z, q->z, p256_mod, p256_mp_mod);
  19823. sp_256_mont_sqr_9(x, t4, p256_mod, p256_mp_mod);
  19824. sp_256_mont_sub_9(x, x, t5, p256_mod);
  19825. sp_256_mont_mul_9(t5, t5, t3, p256_mod, p256_mp_mod);
  19826. sp_256_mont_dbl_9(t3, y, p256_mod);
  19827. sp_256_mont_sub_9(x, x, t3, p256_mod);
  19828. /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
  19829. sp_256_mont_sub_lower_9(y, y, x, p256_mod);
  19830. sp_256_mont_mul_9(y, y, t4, p256_mod, p256_mp_mod);
  19831. sp_256_mont_sub_9(y, y, t5, p256_mod);
  19832. for (i = 0; i < 9; i++) {
  19833. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) |
  19834. (x[i] & maskt);
  19835. }
  19836. for (i = 0; i < 9; i++) {
  19837. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) |
  19838. (y[i] & maskt);
  19839. }
  19840. for (i = 0; i < 9; i++) {
  19841. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) |
  19842. (z[i] & maskt);
  19843. }
  19844. r->z[0] |= p->infinity & q->infinity;
  19845. r->infinity = p->infinity & q->infinity;
  19846. }
  19847. }
  19848. }
  19849. /* Multiply a number by Montgomery normalizer mod modulus (prime).
  19850. *
  19851. * r The resulting Montgomery form number.
  19852. * a The number to convert.
  19853. * m The modulus (prime).
  19854. * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
  19855. */
  19856. static int sp_256_mod_mul_norm_9(sp_digit* r, const sp_digit* a, const sp_digit* m)
  19857. {
  19858. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  19859. int64_t* t = NULL;
  19860. #else
  19861. int64_t t[2 * 8];
  19862. #endif
  19863. int64_t* a32 = NULL;
  19864. int64_t o;
  19865. int err = MP_OKAY;
  19866. (void)m;
  19867. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  19868. t = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 8, NULL, DYNAMIC_TYPE_ECC);
  19869. if (t == NULL)
  19870. return MEMORY_E;
  19871. #endif
  19872. if (err == MP_OKAY) {
  19873. a32 = t + 8;
  19874. a32[0] = a[0];
  19875. a32[0] |= a[1] << 29U;
  19876. a32[0] &= 0xffffffffL;
  19877. a32[1] = (a[1] >> 3);
  19878. a32[1] |= a[2] << 26U;
  19879. a32[1] &= 0xffffffffL;
  19880. a32[2] = (a[2] >> 6);
  19881. a32[2] |= a[3] << 23U;
  19882. a32[2] &= 0xffffffffL;
  19883. a32[3] = (a[3] >> 9);
  19884. a32[3] |= a[4] << 20U;
  19885. a32[3] &= 0xffffffffL;
  19886. a32[4] = (a[4] >> 12);
  19887. a32[4] |= a[5] << 17U;
  19888. a32[4] &= 0xffffffffL;
  19889. a32[5] = (a[5] >> 15);
  19890. a32[5] |= a[6] << 14U;
  19891. a32[5] &= 0xffffffffL;
  19892. a32[6] = (a[6] >> 18);
  19893. a32[6] |= a[7] << 11U;
  19894. a32[6] &= 0xffffffffL;
  19895. a32[7] = (a[7] >> 21);
  19896. a32[7] |= a[8] << 8U;
  19897. a32[7] &= 0xffffffffL;
  19898. /* 1 1 0 -1 -1 -1 -1 0 */
  19899. t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6];
  19900. /* 0 1 1 0 -1 -1 -1 -1 */
  19901. t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7];
  19902. /* 0 0 1 1 0 -1 -1 -1 */
  19903. t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7];
  19904. /* -1 -1 0 2 2 1 0 -1 */
  19905. t[3] = 0 - a32[0] - a32[1] + 2 * a32[3] + 2 * a32[4] + a32[5] - a32[7];
  19906. /* 0 -1 -1 0 2 2 1 0 */
  19907. t[4] = 0 - a32[1] - a32[2] + 2 * a32[4] + 2 * a32[5] + a32[6];
  19908. /* 0 0 -1 -1 0 2 2 1 */
  19909. t[5] = 0 - a32[2] - a32[3] + 2 * a32[5] + 2 * a32[6] + a32[7];
  19910. /* -1 -1 0 0 0 1 3 2 */
  19911. t[6] = 0 - a32[0] - a32[1] + a32[5] + 3 * a32[6] + 2 * a32[7];
  19912. /* 1 0 -1 -1 -1 -1 0 3 */
  19913. t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3 * a32[7];
  19914. t[1] += t[0] >> 32U; t[0] &= 0xffffffffL;
  19915. t[2] += t[1] >> 32U; t[1] &= 0xffffffffL;
  19916. t[3] += t[2] >> 32U; t[2] &= 0xffffffffL;
  19917. t[4] += t[3] >> 32U; t[3] &= 0xffffffffL;
  19918. t[5] += t[4] >> 32U; t[4] &= 0xffffffffL;
  19919. t[6] += t[5] >> 32U; t[5] &= 0xffffffffL;
  19920. t[7] += t[6] >> 32U; t[6] &= 0xffffffffL;
  19921. o = t[7] >> 32U; t[7] &= 0xffffffffL;
  19922. t[0] += o;
  19923. t[3] -= o;
  19924. t[6] -= o;
  19925. t[7] += o;
  19926. t[1] += t[0] >> 32U; t[0] &= 0xffffffffL;
  19927. t[2] += t[1] >> 32U; t[1] &= 0xffffffffL;
  19928. t[3] += t[2] >> 32U; t[2] &= 0xffffffffL;
  19929. t[4] += t[3] >> 32U; t[3] &= 0xffffffffL;
  19930. t[5] += t[4] >> 32U; t[4] &= 0xffffffffL;
  19931. t[6] += t[5] >> 32U; t[5] &= 0xffffffffL;
  19932. t[7] += t[6] >> 32U; t[6] &= 0xffffffffL;
  19933. r[0] = (sp_digit)(t[0]) & 0x1fffffffL;
  19934. r[1] = (sp_digit)(t[0] >> 29U);
  19935. r[1] |= (sp_digit)(t[1] << 3U);
  19936. r[1] &= 0x1fffffffL;
  19937. r[2] = (sp_digit)(t[1] >> 26U);
  19938. r[2] |= (sp_digit)(t[2] << 6U);
  19939. r[2] &= 0x1fffffffL;
  19940. r[3] = (sp_digit)(t[2] >> 23U);
  19941. r[3] |= (sp_digit)(t[3] << 9U);
  19942. r[3] &= 0x1fffffffL;
  19943. r[4] = (sp_digit)(t[3] >> 20U);
  19944. r[4] |= (sp_digit)(t[4] << 12U);
  19945. r[4] &= 0x1fffffffL;
  19946. r[5] = (sp_digit)(t[4] >> 17U);
  19947. r[5] |= (sp_digit)(t[5] << 15U);
  19948. r[5] &= 0x1fffffffL;
  19949. r[6] = (sp_digit)(t[5] >> 14U);
  19950. r[6] |= (sp_digit)(t[6] << 18U);
  19951. r[6] &= 0x1fffffffL;
  19952. r[7] = (sp_digit)(t[6] >> 11U);
  19953. r[7] |= (sp_digit)(t[7] << 21U);
  19954. r[7] &= 0x1fffffffL;
  19955. r[8] = (sp_digit)(t[7] >> 8U);
  19956. }
  19957. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  19958. if (t != NULL)
  19959. XFREE(t, NULL, DYNAMIC_TYPE_ECC);
  19960. #endif
  19961. return err;
  19962. }
  19963. #ifdef WOLFSSL_SP_SMALL
  19964. /* Multiply the point by the scalar and return the result.
  19965. * If map is true then convert result to affine coordinates.
  19966. *
  19967. * Small implementation using add and double that is cache attack resistant but
  19968. * allocates memory rather than use large stacks.
  19969. * 256 adds and doubles.
  19970. *
  19971. * r Resulting point.
  19972. * g Point to multiply.
  19973. * k Scalar to multiply by.
  19974. * map Indicates whether to convert result to affine.
  19975. * ct Constant time required.
  19976. * heap Heap to use for allocation.
  19977. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  19978. */
  19979. #ifdef WOLFSSL_SP_NONBLOCK
  19980. typedef struct sp_256_ecc_mulmod_9_ctx {
  19981. int state;
  19982. union {
  19983. sp_256_proj_point_dbl_9_ctx dbl_ctx;
  19984. sp_256_proj_point_add_9_ctx add_ctx;
  19985. };
  19986. sp_point_256 t[3];
  19987. sp_digit tmp[2 * 9 * 6];
  19988. sp_digit n;
  19989. int i;
  19990. int c;
  19991. int y;
  19992. } sp_256_ecc_mulmod_9_ctx;
  19993. static int sp_256_ecc_mulmod_9_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r,
  19994. const sp_point_256* g, const sp_digit* k, int map, int ct, void* heap)
  19995. {
  19996. int err = FP_WOULDBLOCK;
  19997. sp_256_ecc_mulmod_9_ctx* ctx = (sp_256_ecc_mulmod_9_ctx*)sp_ctx->data;
  19998. typedef char ctx_size_test[sizeof(sp_256_ecc_mulmod_9_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  19999. (void)sizeof(ctx_size_test);
  20000. /* Implementation is constant time. */
  20001. (void)ct;
  20002. switch (ctx->state) {
  20003. case 0: /* INIT */
  20004. XMEMSET(ctx->t, 0, sizeof(sp_point_256) * 3);
  20005. ctx->i = 8;
  20006. ctx->c = 24;
  20007. ctx->n = k[ctx->i--] << (29 - ctx->c);
  20008. /* t[0] = {0, 0, 1} * norm */
  20009. ctx->t[0].infinity = 1;
  20010. ctx->state = 1;
  20011. break;
  20012. case 1: /* T1X */
  20013. /* t[1] = {g->x, g->y, g->z} * norm */
  20014. err = sp_256_mod_mul_norm_9(ctx->t[1].x, g->x, p256_mod);
  20015. ctx->state = 2;
  20016. break;
  20017. case 2: /* T1Y */
  20018. err = sp_256_mod_mul_norm_9(ctx->t[1].y, g->y, p256_mod);
  20019. ctx->state = 3;
  20020. break;
  20021. case 3: /* T1Z */
  20022. err = sp_256_mod_mul_norm_9(ctx->t[1].z, g->z, p256_mod);
  20023. ctx->state = 4;
  20024. break;
  20025. case 4: /* ADDPREP */
  20026. if (ctx->c == 0) {
  20027. if (ctx->i == -1) {
  20028. ctx->state = 7;
  20029. break;
  20030. }
  20031. ctx->n = k[ctx->i--];
  20032. ctx->c = 29;
  20033. }
  20034. ctx->y = (ctx->n >> 28) & 1;
  20035. ctx->n <<= 1;
  20036. XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx));
  20037. ctx->state = 5;
  20038. break;
  20039. case 5: /* ADD */
  20040. err = sp_256_proj_point_add_9_nb((sp_ecc_ctx_t*)&ctx->add_ctx,
  20041. &ctx->t[ctx->y^1], &ctx->t[0], &ctx->t[1], ctx->tmp);
  20042. if (err == MP_OKAY) {
  20043. XMEMCPY(&ctx->t[2], (void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) +
  20044. ((size_t)&ctx->t[1] & addr_mask[ctx->y])),
  20045. sizeof(sp_point_256));
  20046. XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
  20047. ctx->state = 6;
  20048. }
  20049. break;
  20050. case 6: /* DBL */
  20051. err = sp_256_proj_point_dbl_9_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->t[2],
  20052. &ctx->t[2], ctx->tmp);
  20053. if (err == MP_OKAY) {
  20054. XMEMCPY((void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) +
  20055. ((size_t)&ctx->t[1] & addr_mask[ctx->y])), &ctx->t[2],
  20056. sizeof(sp_point_256));
  20057. ctx->state = 4;
  20058. ctx->c--;
  20059. }
  20060. break;
  20061. case 7: /* MAP */
  20062. if (map != 0) {
  20063. sp_256_map_9(r, &ctx->t[0], ctx->tmp);
  20064. }
  20065. else {
  20066. XMEMCPY(r, &ctx->t[0], sizeof(sp_point_256));
  20067. }
  20068. err = MP_OKAY;
  20069. break;
  20070. }
  20071. if (err == MP_OKAY && ctx->state != 7) {
  20072. err = FP_WOULDBLOCK;
  20073. }
  20074. if (err != FP_WOULDBLOCK) {
  20075. ForceZero(ctx->tmp, sizeof(ctx->tmp));
  20076. ForceZero(ctx->t, sizeof(ctx->t));
  20077. }
  20078. (void)heap;
  20079. return err;
  20080. }
  20081. #endif /* WOLFSSL_SP_NONBLOCK */
  20082. static int sp_256_ecc_mulmod_9(sp_point_256* r, const sp_point_256* g,
  20083. const sp_digit* k, int map, int ct, void* heap)
  20084. {
  20085. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  20086. sp_point_256* t = NULL;
  20087. sp_digit* tmp = NULL;
  20088. #else
  20089. sp_point_256 t[3];
  20090. sp_digit tmp[2 * 9 * 6];
  20091. #endif
  20092. sp_digit n;
  20093. int i;
  20094. int c;
  20095. int y;
  20096. int err = MP_OKAY;
  20097. /* Implementation is constant time. */
  20098. (void)ct;
  20099. (void)heap;
  20100. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  20101. t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap,
  20102. DYNAMIC_TYPE_ECC);
  20103. if (t == NULL)
  20104. err = MEMORY_E;
  20105. if (err == MP_OKAY) {
  20106. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 9 * 6, heap,
  20107. DYNAMIC_TYPE_ECC);
  20108. if (tmp == NULL)
  20109. err = MEMORY_E;
  20110. }
  20111. #endif
  20112. if (err == MP_OKAY) {
  20113. XMEMSET(t, 0, sizeof(sp_point_256) * 3);
  20114. /* t[0] = {0, 0, 1} * norm */
  20115. t[0].infinity = 1;
  20116. /* t[1] = {g->x, g->y, g->z} * norm */
  20117. err = sp_256_mod_mul_norm_9(t[1].x, g->x, p256_mod);
  20118. }
  20119. if (err == MP_OKAY)
  20120. err = sp_256_mod_mul_norm_9(t[1].y, g->y, p256_mod);
  20121. if (err == MP_OKAY)
  20122. err = sp_256_mod_mul_norm_9(t[1].z, g->z, p256_mod);
  20123. if (err == MP_OKAY) {
  20124. i = 8;
  20125. c = 24;
  20126. n = k[i--] << (29 - c);
  20127. for (; ; c--) {
  20128. if (c == 0) {
  20129. if (i == -1)
  20130. break;
  20131. n = k[i--];
  20132. c = 29;
  20133. }
  20134. y = (n >> 28) & 1;
  20135. n <<= 1;
  20136. sp_256_proj_point_add_9(&t[y^1], &t[0], &t[1], tmp);
  20137. XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) +
  20138. ((size_t)&t[1] & addr_mask[y])),
  20139. sizeof(sp_point_256));
  20140. sp_256_proj_point_dbl_9(&t[2], &t[2], tmp);
  20141. XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) +
  20142. ((size_t)&t[1] & addr_mask[y])), &t[2],
  20143. sizeof(sp_point_256));
  20144. }
  20145. if (map != 0) {
  20146. sp_256_map_9(r, &t[0], tmp);
  20147. }
  20148. else {
  20149. XMEMCPY(r, &t[0], sizeof(sp_point_256));
  20150. }
  20151. }
  20152. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  20153. if (tmp != NULL)
  20154. #endif
  20155. {
  20156. ForceZero(tmp, sizeof(sp_digit) * 2 * 9 * 6);
  20157. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  20158. XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
  20159. #endif
  20160. }
  20161. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  20162. if (t != NULL)
  20163. #endif
  20164. {
  20165. ForceZero(t, sizeof(sp_point_256) * 3);
  20166. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  20167. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  20168. #endif
  20169. }
  20170. return err;
  20171. }
  20172. #else
  20173. /* A table entry for pre-computed points. */
  20174. typedef struct sp_table_entry_256 {
  20175. sp_digit x[9];
  20176. sp_digit y[9];
  20177. } sp_table_entry_256;
  20178. /* Conditionally copy a into r using the mask m.
  20179. * m is -1 to copy and 0 when not.
  20180. *
  20181. * r A single precision number to copy over.
  20182. * a A single precision number to copy.
  20183. * m Mask value to apply.
  20184. */
  20185. static void sp_256_cond_copy_9(sp_digit* r, const sp_digit* a, const sp_digit m)
  20186. {
  20187. sp_digit t[9];
  20188. #ifdef WOLFSSL_SP_SMALL
  20189. int i;
  20190. for (i = 0; i < 9; i++) {
  20191. t[i] = r[i] ^ a[i];
  20192. }
  20193. for (i = 0; i < 9; i++) {
  20194. r[i] ^= t[i] & m;
  20195. }
  20196. #else
  20197. t[ 0] = r[ 0] ^ a[ 0];
  20198. t[ 1] = r[ 1] ^ a[ 1];
  20199. t[ 2] = r[ 2] ^ a[ 2];
  20200. t[ 3] = r[ 3] ^ a[ 3];
  20201. t[ 4] = r[ 4] ^ a[ 4];
  20202. t[ 5] = r[ 5] ^ a[ 5];
  20203. t[ 6] = r[ 6] ^ a[ 6];
  20204. t[ 7] = r[ 7] ^ a[ 7];
  20205. t[ 8] = r[ 8] ^ a[ 8];
  20206. r[ 0] ^= t[ 0] & m;
  20207. r[ 1] ^= t[ 1] & m;
  20208. r[ 2] ^= t[ 2] & m;
  20209. r[ 3] ^= t[ 3] & m;
  20210. r[ 4] ^= t[ 4] & m;
  20211. r[ 5] ^= t[ 5] & m;
  20212. r[ 6] ^= t[ 6] & m;
  20213. r[ 7] ^= t[ 7] & m;
  20214. r[ 8] ^= t[ 8] & m;
  20215. #endif /* WOLFSSL_SP_SMALL */
  20216. }
  20217. #define sp_256_mont_dbl_lower_9 sp_256_mont_dbl_9
  20218. #define sp_256_mont_tpl_lower_9 sp_256_mont_tpl_9
  20219. /* Double the Montgomery form projective point p a number of times.
  20220. *
  20221. * r Result of repeated doubling of point.
  20222. * p Point to double.
  20223. * n Number of times to double
  20224. * t Temporary ordinate data.
  20225. */
  20226. static void sp_256_proj_point_dbl_n_9(sp_point_256* p, int i,
  20227. sp_digit* t)
  20228. {
  20229. sp_digit* w = t;
  20230. sp_digit* a = t + 2*9;
  20231. sp_digit* b = t + 4*9;
  20232. sp_digit* t1 = t + 6*9;
  20233. sp_digit* t2 = t + 8*9;
  20234. sp_digit* x;
  20235. sp_digit* y;
  20236. sp_digit* z;
  20237. volatile int n = i;
  20238. x = p->x;
  20239. y = p->y;
  20240. z = p->z;
  20241. /* Y = 2*Y */
  20242. sp_256_mont_dbl_9(y, y, p256_mod);
  20243. /* W = Z^4 */
  20244. sp_256_mont_sqr_9(w, z, p256_mod, p256_mp_mod);
  20245. sp_256_mont_sqr_9(w, w, p256_mod, p256_mp_mod);
  20246. #ifndef WOLFSSL_SP_SMALL
  20247. while (--n > 0)
  20248. #else
  20249. while (--n >= 0)
  20250. #endif
  20251. {
  20252. /* A = 3*(X^2 - W) */
  20253. sp_256_mont_sqr_9(t1, x, p256_mod, p256_mp_mod);
  20254. sp_256_mont_sub_9(t1, t1, w, p256_mod);
  20255. sp_256_mont_tpl_lower_9(a, t1, p256_mod);
  20256. /* B = X*Y^2 */
  20257. sp_256_mont_sqr_9(t1, y, p256_mod, p256_mp_mod);
  20258. sp_256_mont_mul_9(b, t1, x, p256_mod, p256_mp_mod);
  20259. /* X = A^2 - 2B */
  20260. sp_256_mont_sqr_9(x, a, p256_mod, p256_mp_mod);
  20261. sp_256_mont_dbl_9(t2, b, p256_mod);
  20262. sp_256_mont_sub_9(x, x, t2, p256_mod);
  20263. /* b = 2.(B - X) */
  20264. sp_256_mont_sub_lower_9(t2, b, x, p256_mod);
  20265. sp_256_mont_dbl_lower_9(b, t2, p256_mod);
  20266. /* Z = Z*Y */
  20267. sp_256_mont_mul_9(z, z, y, p256_mod, p256_mp_mod);
  20268. /* t1 = Y^4 */
  20269. sp_256_mont_sqr_9(t1, t1, p256_mod, p256_mp_mod);
  20270. #ifdef WOLFSSL_SP_SMALL
  20271. if (n != 0)
  20272. #endif
  20273. {
  20274. /* W = W*Y^4 */
  20275. sp_256_mont_mul_9(w, w, t1, p256_mod, p256_mp_mod);
  20276. }
  20277. /* y = 2*A*(B - X) - Y^4 */
  20278. sp_256_mont_mul_9(y, b, a, p256_mod, p256_mp_mod);
  20279. sp_256_mont_sub_9(y, y, t1, p256_mod);
  20280. }
  20281. #ifndef WOLFSSL_SP_SMALL
  20282. /* A = 3*(X^2 - W) */
  20283. sp_256_mont_sqr_9(t1, x, p256_mod, p256_mp_mod);
  20284. sp_256_mont_sub_9(t1, t1, w, p256_mod);
  20285. sp_256_mont_tpl_lower_9(a, t1, p256_mod);
  20286. /* B = X*Y^2 */
  20287. sp_256_mont_sqr_9(t1, y, p256_mod, p256_mp_mod);
  20288. sp_256_mont_mul_9(b, t1, x, p256_mod, p256_mp_mod);
  20289. /* X = A^2 - 2B */
  20290. sp_256_mont_sqr_9(x, a, p256_mod, p256_mp_mod);
  20291. sp_256_mont_dbl_9(t2, b, p256_mod);
  20292. sp_256_mont_sub_9(x, x, t2, p256_mod);
  20293. /* b = 2.(B - X) */
  20294. sp_256_mont_sub_lower_9(t2, b, x, p256_mod);
  20295. sp_256_mont_dbl_lower_9(b, t2, p256_mod);
  20296. /* Z = Z*Y */
  20297. sp_256_mont_mul_9(z, z, y, p256_mod, p256_mp_mod);
  20298. /* t1 = Y^4 */
  20299. sp_256_mont_sqr_9(t1, t1, p256_mod, p256_mp_mod);
  20300. /* y = 2*A*(B - X) - Y^4 */
  20301. sp_256_mont_mul_9(y, b, a, p256_mod, p256_mp_mod);
  20302. sp_256_mont_sub_9(y, y, t1, p256_mod);
  20303. #endif
  20304. /* Y = Y/2 */
  20305. sp_256_div2_9(y, y, p256_mod);
  20306. }
  20307. /* Double the Montgomery form projective point p a number of times.
  20308. *
  20309. * r Result of repeated doubling of point.
  20310. * p Point to double.
  20311. * n Number of times to double
  20312. * t Temporary ordinate data.
  20313. */
  20314. static void sp_256_proj_point_dbl_n_store_9(sp_point_256* r,
  20315. const sp_point_256* p, int n, int m, sp_digit* t)
  20316. {
  20317. sp_digit* w = t;
  20318. sp_digit* a = t + 2*9;
  20319. sp_digit* b = t + 4*9;
  20320. sp_digit* t1 = t + 6*9;
  20321. sp_digit* t2 = t + 8*9;
  20322. sp_digit* x = r[2*m].x;
  20323. sp_digit* y = r[(1<<n)*m].y;
  20324. sp_digit* z = r[2*m].z;
  20325. int i;
  20326. int j;
  20327. for (i=0; i<9; i++) {
  20328. x[i] = p->x[i];
  20329. }
  20330. for (i=0; i<9; i++) {
  20331. y[i] = p->y[i];
  20332. }
  20333. for (i=0; i<9; i++) {
  20334. z[i] = p->z[i];
  20335. }
  20336. /* Y = 2*Y */
  20337. sp_256_mont_dbl_9(y, y, p256_mod);
  20338. /* W = Z^4 */
  20339. sp_256_mont_sqr_9(w, z, p256_mod, p256_mp_mod);
  20340. sp_256_mont_sqr_9(w, w, p256_mod, p256_mp_mod);
  20341. j = m;
  20342. for (i=1; i<=n; i++) {
  20343. j *= 2;
  20344. /* A = 3*(X^2 - W) */
  20345. sp_256_mont_sqr_9(t1, x, p256_mod, p256_mp_mod);
  20346. sp_256_mont_sub_9(t1, t1, w, p256_mod);
  20347. sp_256_mont_tpl_lower_9(a, t1, p256_mod);
  20348. /* B = X*Y^2 */
  20349. sp_256_mont_sqr_9(t1, y, p256_mod, p256_mp_mod);
  20350. sp_256_mont_mul_9(b, t1, x, p256_mod, p256_mp_mod);
  20351. x = r[j].x;
  20352. /* X = A^2 - 2B */
  20353. sp_256_mont_sqr_9(x, a, p256_mod, p256_mp_mod);
  20354. sp_256_mont_dbl_9(t2, b, p256_mod);
  20355. sp_256_mont_sub_9(x, x, t2, p256_mod);
  20356. /* b = 2.(B - X) */
  20357. sp_256_mont_sub_lower_9(t2, b, x, p256_mod);
  20358. sp_256_mont_dbl_lower_9(b, t2, p256_mod);
  20359. /* Z = Z*Y */
  20360. sp_256_mont_mul_9(r[j].z, z, y, p256_mod, p256_mp_mod);
  20361. z = r[j].z;
  20362. /* t1 = Y^4 */
  20363. sp_256_mont_sqr_9(t1, t1, p256_mod, p256_mp_mod);
  20364. if (i != n) {
  20365. /* W = W*Y^4 */
  20366. sp_256_mont_mul_9(w, w, t1, p256_mod, p256_mp_mod);
  20367. }
  20368. /* y = 2*A*(B - X) - Y^4 */
  20369. sp_256_mont_mul_9(y, b, a, p256_mod, p256_mp_mod);
  20370. sp_256_mont_sub_9(y, y, t1, p256_mod);
  20371. /* Y = Y/2 */
  20372. sp_256_div2_9(r[j].y, y, p256_mod);
  20373. r[j].infinity = 0;
  20374. }
  20375. }
  20376. /* Add two Montgomery form projective points.
  20377. *
  20378. * ra Result of addition.
  20379. * rs Result of subtraction.
  20380. * p First point to add.
  20381. * q Second point to add.
  20382. * t Temporary ordinate data.
  20383. */
  20384. static void sp_256_proj_point_add_sub_9(sp_point_256* ra,
  20385. sp_point_256* rs, const sp_point_256* p, const sp_point_256* q,
  20386. sp_digit* t)
  20387. {
  20388. sp_digit* t1 = t;
  20389. sp_digit* t2 = t + 2*9;
  20390. sp_digit* t3 = t + 4*9;
  20391. sp_digit* t4 = t + 6*9;
  20392. sp_digit* t5 = t + 8*9;
  20393. sp_digit* t6 = t + 10*9;
  20394. sp_digit* xa = ra->x;
  20395. sp_digit* ya = ra->y;
  20396. sp_digit* za = ra->z;
  20397. sp_digit* xs = rs->x;
  20398. sp_digit* ys = rs->y;
  20399. sp_digit* zs = rs->z;
  20400. XMEMCPY(xa, p->x, sizeof(p->x) / 2);
  20401. XMEMCPY(ya, p->y, sizeof(p->y) / 2);
  20402. XMEMCPY(za, p->z, sizeof(p->z) / 2);
  20403. ra->infinity = 0;
  20404. rs->infinity = 0;
  20405. /* U1 = X1*Z2^2 */
  20406. sp_256_mont_sqr_9(t1, q->z, p256_mod, p256_mp_mod);
  20407. sp_256_mont_mul_9(t3, t1, q->z, p256_mod, p256_mp_mod);
  20408. sp_256_mont_mul_9(t1, t1, xa, p256_mod, p256_mp_mod);
  20409. /* U2 = X2*Z1^2 */
  20410. sp_256_mont_sqr_9(t2, za, p256_mod, p256_mp_mod);
  20411. sp_256_mont_mul_9(t4, t2, za, p256_mod, p256_mp_mod);
  20412. sp_256_mont_mul_9(t2, t2, q->x, p256_mod, p256_mp_mod);
  20413. /* S1 = Y1*Z2^3 */
  20414. sp_256_mont_mul_9(t3, t3, ya, p256_mod, p256_mp_mod);
  20415. /* S2 = Y2*Z1^3 */
  20416. sp_256_mont_mul_9(t4, t4, q->y, p256_mod, p256_mp_mod);
  20417. /* H = U2 - U1 */
  20418. sp_256_mont_sub_9(t2, t2, t1, p256_mod);
  20419. /* RS = S2 + S1 */
  20420. sp_256_mont_add_9(t6, t4, t3, p256_mod);
  20421. /* R = S2 - S1 */
  20422. sp_256_mont_sub_9(t4, t4, t3, p256_mod);
  20423. /* Z3 = H*Z1*Z2 */
  20424. /* ZS = H*Z1*Z2 */
  20425. sp_256_mont_mul_9(za, za, q->z, p256_mod, p256_mp_mod);
  20426. sp_256_mont_mul_9(za, za, t2, p256_mod, p256_mp_mod);
  20427. XMEMCPY(zs, za, sizeof(p->z)/2);
  20428. /* X3 = R^2 - H^3 - 2*U1*H^2 */
  20429. /* XS = RS^2 - H^3 - 2*U1*H^2 */
  20430. sp_256_mont_sqr_9(xa, t4, p256_mod, p256_mp_mod);
  20431. sp_256_mont_sqr_9(xs, t6, p256_mod, p256_mp_mod);
  20432. sp_256_mont_sqr_9(t5, t2, p256_mod, p256_mp_mod);
  20433. sp_256_mont_mul_9(ya, t1, t5, p256_mod, p256_mp_mod);
  20434. sp_256_mont_mul_9(t5, t5, t2, p256_mod, p256_mp_mod);
  20435. sp_256_mont_sub_9(xa, xa, t5, p256_mod);
  20436. sp_256_mont_sub_9(xs, xs, t5, p256_mod);
  20437. sp_256_mont_dbl_9(t1, ya, p256_mod);
  20438. sp_256_mont_sub_9(xa, xa, t1, p256_mod);
  20439. sp_256_mont_sub_9(xs, xs, t1, p256_mod);
  20440. /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
  20441. /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */
  20442. sp_256_mont_sub_lower_9(ys, ya, xs, p256_mod);
  20443. sp_256_mont_sub_lower_9(ya, ya, xa, p256_mod);
  20444. sp_256_mont_mul_9(ya, ya, t4, p256_mod, p256_mp_mod);
  20445. sp_256_sub_9(t6, p256_mod, t6);
  20446. sp_256_mont_mul_9(ys, ys, t6, p256_mod, p256_mp_mod);
  20447. sp_256_mont_mul_9(t5, t5, t3, p256_mod, p256_mp_mod);
  20448. sp_256_mont_sub_9(ya, ya, t5, p256_mod);
  20449. sp_256_mont_sub_9(ys, ys, t5, p256_mod);
  20450. }
  20451. /* Structure used to describe recoding of scalar multiplication. */
  20452. typedef struct ecc_recode_256 {
  20453. /* Index into pre-computation table. */
  20454. uint8_t i;
  20455. /* Use the negative of the point. */
  20456. uint8_t neg;
  20457. } ecc_recode_256;
  20458. /* The index into pre-computation table to use. */
  20459. static const uint8_t recode_index_9_6[66] = {
  20460. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
  20461. 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
  20462. 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
  20463. 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
  20464. 0, 1,
  20465. };
  20466. /* Whether to negate y-ordinate. */
  20467. static const uint8_t recode_neg_9_6[66] = {
  20468. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  20469. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  20470. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  20471. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  20472. 0, 0,
  20473. };
  20474. /* Recode the scalar for multiplication using pre-computed values and
  20475. * subtraction.
  20476. *
  20477. * k Scalar to multiply by.
  20478. * v Vector of operations to perform.
  20479. */
  20480. static void sp_256_ecc_recode_6_9(const sp_digit* k, ecc_recode_256* v)
  20481. {
  20482. int i;
  20483. int j;
  20484. uint8_t y;
  20485. int carry = 0;
  20486. int o;
  20487. sp_digit n;
  20488. j = 0;
  20489. n = k[j];
  20490. o = 0;
  20491. for (i=0; i<43; i++) {
  20492. y = (int8_t)n;
  20493. if (o + 6 < 29) {
  20494. y &= 0x3f;
  20495. n >>= 6;
  20496. o += 6;
  20497. }
  20498. else if (o + 6 == 29) {
  20499. n >>= 6;
  20500. if (++j < 9)
  20501. n = k[j];
  20502. o = 0;
  20503. }
  20504. else if (++j < 9) {
  20505. n = k[j];
  20506. y |= (uint8_t)((n << (29 - o)) & 0x3f);
  20507. o -= 23;
  20508. n >>= o;
  20509. }
  20510. y += (uint8_t)carry;
  20511. v[i].i = recode_index_9_6[y];
  20512. v[i].neg = recode_neg_9_6[y];
  20513. carry = (y >> 6) + v[i].neg;
  20514. }
  20515. }
  20516. #ifndef WC_NO_CACHE_RESISTANT
  20517. /* Touch each possible point that could be being copied.
  20518. *
  20519. * r Point to copy into.
  20520. * table Table - start of the entires to access
  20521. * idx Index of entry to retrieve.
  20522. */
  20523. static void sp_256_get_point_33_9(sp_point_256* r, const sp_point_256* table,
  20524. int idx)
  20525. {
  20526. int i;
  20527. sp_digit mask;
  20528. r->x[0] = 0;
  20529. r->x[1] = 0;
  20530. r->x[2] = 0;
  20531. r->x[3] = 0;
  20532. r->x[4] = 0;
  20533. r->x[5] = 0;
  20534. r->x[6] = 0;
  20535. r->x[7] = 0;
  20536. r->x[8] = 0;
  20537. r->y[0] = 0;
  20538. r->y[1] = 0;
  20539. r->y[2] = 0;
  20540. r->y[3] = 0;
  20541. r->y[4] = 0;
  20542. r->y[5] = 0;
  20543. r->y[6] = 0;
  20544. r->y[7] = 0;
  20545. r->y[8] = 0;
  20546. r->z[0] = 0;
  20547. r->z[1] = 0;
  20548. r->z[2] = 0;
  20549. r->z[3] = 0;
  20550. r->z[4] = 0;
  20551. r->z[5] = 0;
  20552. r->z[6] = 0;
  20553. r->z[7] = 0;
  20554. r->z[8] = 0;
  20555. for (i = 1; i < 33; i++) {
  20556. mask = 0 - (i == idx);
  20557. r->x[0] |= mask & table[i].x[0];
  20558. r->x[1] |= mask & table[i].x[1];
  20559. r->x[2] |= mask & table[i].x[2];
  20560. r->x[3] |= mask & table[i].x[3];
  20561. r->x[4] |= mask & table[i].x[4];
  20562. r->x[5] |= mask & table[i].x[5];
  20563. r->x[6] |= mask & table[i].x[6];
  20564. r->x[7] |= mask & table[i].x[7];
  20565. r->x[8] |= mask & table[i].x[8];
  20566. r->y[0] |= mask & table[i].y[0];
  20567. r->y[1] |= mask & table[i].y[1];
  20568. r->y[2] |= mask & table[i].y[2];
  20569. r->y[3] |= mask & table[i].y[3];
  20570. r->y[4] |= mask & table[i].y[4];
  20571. r->y[5] |= mask & table[i].y[5];
  20572. r->y[6] |= mask & table[i].y[6];
  20573. r->y[7] |= mask & table[i].y[7];
  20574. r->y[8] |= mask & table[i].y[8];
  20575. r->z[0] |= mask & table[i].z[0];
  20576. r->z[1] |= mask & table[i].z[1];
  20577. r->z[2] |= mask & table[i].z[2];
  20578. r->z[3] |= mask & table[i].z[3];
  20579. r->z[4] |= mask & table[i].z[4];
  20580. r->z[5] |= mask & table[i].z[5];
  20581. r->z[6] |= mask & table[i].z[6];
  20582. r->z[7] |= mask & table[i].z[7];
  20583. r->z[8] |= mask & table[i].z[8];
  20584. }
  20585. }
  20586. #endif /* !WC_NO_CACHE_RESISTANT */
  20587. /* Multiply the point by the scalar and return the result.
  20588. * If map is true then convert result to affine coordinates.
  20589. *
  20590. * Window technique of 6 bits. (Add-Sub variation.)
  20591. * Calculate 0..32 times the point. Use function that adds and
  20592. * subtracts the same two points.
  20593. * Recode to add or subtract one of the computed points.
  20594. * Double to push up.
  20595. * NOT a sliding window.
  20596. *
  20597. * r Resulting point.
  20598. * g Point to multiply.
  20599. * k Scalar to multiply by.
  20600. * map Indicates whether to convert result to affine.
  20601. * ct Constant time required.
  20602. * heap Heap to use for allocation.
  20603. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  20604. */
  20605. static int sp_256_ecc_mulmod_win_add_sub_9(sp_point_256* r, const sp_point_256* g,
  20606. const sp_digit* k, int map, int ct, void* heap)
  20607. {
  20608. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  20609. sp_point_256* t = NULL;
  20610. sp_digit* tmp = NULL;
  20611. #else
  20612. sp_point_256 t[33+2];
  20613. sp_digit tmp[2 * 9 * 6];
  20614. #endif
  20615. sp_point_256* rt = NULL;
  20616. sp_point_256* p = NULL;
  20617. sp_digit* negy;
  20618. int i;
  20619. ecc_recode_256 v[43];
  20620. int err = MP_OKAY;
  20621. /* Constant time used for cache attack resistance implementation. */
  20622. (void)ct;
  20623. (void)heap;
  20624. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  20625. t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) *
  20626. (33+2), heap, DYNAMIC_TYPE_ECC);
  20627. if (t == NULL)
  20628. err = MEMORY_E;
  20629. if (err == MP_OKAY) {
  20630. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 9 * 6,
  20631. heap, DYNAMIC_TYPE_ECC);
  20632. if (tmp == NULL)
  20633. err = MEMORY_E;
  20634. }
  20635. #endif
  20636. if (err == MP_OKAY) {
  20637. rt = t + 33;
  20638. p = t + 33+1;
  20639. /* t[0] = {0, 0, 1} * norm */
  20640. XMEMSET(&t[0], 0, sizeof(t[0]));
  20641. t[0].infinity = 1;
  20642. /* t[1] = {g->x, g->y, g->z} * norm */
  20643. err = sp_256_mod_mul_norm_9(t[1].x, g->x, p256_mod);
  20644. }
  20645. if (err == MP_OKAY) {
  20646. err = sp_256_mod_mul_norm_9(t[1].y, g->y, p256_mod);
  20647. }
  20648. if (err == MP_OKAY) {
  20649. err = sp_256_mod_mul_norm_9(t[1].z, g->z, p256_mod);
  20650. }
  20651. if (err == MP_OKAY) {
  20652. t[1].infinity = 0;
  20653. /* t[2] ... t[32] */
  20654. sp_256_proj_point_dbl_n_store_9(t, &t[ 1], 5, 1, tmp);
  20655. sp_256_proj_point_add_9(&t[ 3], &t[ 2], &t[ 1], tmp);
  20656. sp_256_proj_point_dbl_9(&t[ 6], &t[ 3], tmp);
  20657. sp_256_proj_point_add_sub_9(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp);
  20658. sp_256_proj_point_dbl_9(&t[10], &t[ 5], tmp);
  20659. sp_256_proj_point_add_sub_9(&t[11], &t[ 9], &t[10], &t[ 1], tmp);
  20660. sp_256_proj_point_dbl_9(&t[12], &t[ 6], tmp);
  20661. sp_256_proj_point_dbl_9(&t[14], &t[ 7], tmp);
  20662. sp_256_proj_point_add_sub_9(&t[15], &t[13], &t[14], &t[ 1], tmp);
  20663. sp_256_proj_point_dbl_9(&t[18], &t[ 9], tmp);
  20664. sp_256_proj_point_add_sub_9(&t[19], &t[17], &t[18], &t[ 1], tmp);
  20665. sp_256_proj_point_dbl_9(&t[20], &t[10], tmp);
  20666. sp_256_proj_point_dbl_9(&t[22], &t[11], tmp);
  20667. sp_256_proj_point_add_sub_9(&t[23], &t[21], &t[22], &t[ 1], tmp);
  20668. sp_256_proj_point_dbl_9(&t[24], &t[12], tmp);
  20669. sp_256_proj_point_dbl_9(&t[26], &t[13], tmp);
  20670. sp_256_proj_point_add_sub_9(&t[27], &t[25], &t[26], &t[ 1], tmp);
  20671. sp_256_proj_point_dbl_9(&t[28], &t[14], tmp);
  20672. sp_256_proj_point_dbl_9(&t[30], &t[15], tmp);
  20673. sp_256_proj_point_add_sub_9(&t[31], &t[29], &t[30], &t[ 1], tmp);
  20674. negy = t[0].y;
  20675. sp_256_ecc_recode_6_9(k, v);
  20676. i = 42;
  20677. #ifndef WC_NO_CACHE_RESISTANT
  20678. if (ct) {
  20679. sp_256_get_point_33_9(rt, t, v[i].i);
  20680. rt->infinity = !v[i].i;
  20681. }
  20682. else
  20683. #endif
  20684. {
  20685. XMEMCPY(rt, &t[v[i].i], sizeof(sp_point_256));
  20686. }
  20687. for (--i; i>=0; i--) {
  20688. sp_256_proj_point_dbl_n_9(rt, 6, tmp);
  20689. #ifndef WC_NO_CACHE_RESISTANT
  20690. if (ct) {
  20691. sp_256_get_point_33_9(p, t, v[i].i);
  20692. p->infinity = !v[i].i;
  20693. }
  20694. else
  20695. #endif
  20696. {
  20697. XMEMCPY(p, &t[v[i].i], sizeof(sp_point_256));
  20698. }
  20699. sp_256_sub_9(negy, p256_mod, p->y);
  20700. sp_256_norm_9(negy);
  20701. sp_256_cond_copy_9(p->y, negy, (sp_digit)0 - v[i].neg);
  20702. sp_256_proj_point_add_9(rt, rt, p, tmp);
  20703. }
  20704. if (map != 0) {
  20705. sp_256_map_9(r, rt, tmp);
  20706. }
  20707. else {
  20708. XMEMCPY(r, rt, sizeof(sp_point_256));
  20709. }
  20710. }
  20711. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  20712. if (t != NULL)
  20713. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  20714. if (tmp != NULL)
  20715. XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
  20716. #endif
  20717. return err;
  20718. }
  20719. #ifdef FP_ECC
  20720. #endif /* FP_ECC */
  20721. /* Add two Montgomery form projective points. The second point has a q value of
  20722. * one.
  20723. * Only the first point can be the same pointer as the result point.
  20724. *
  20725. * r Result of addition.
  20726. * p First point to add.
  20727. * q Second point to add.
  20728. * t Temporary ordinate data.
  20729. */
  20730. static void sp_256_proj_point_add_qz1_9(sp_point_256* r, const sp_point_256* p,
  20731. const sp_point_256* q, sp_digit* t)
  20732. {
  20733. sp_digit* t1 = t;
  20734. sp_digit* t2 = t + 2*9;
  20735. sp_digit* t3 = t + 4*9;
  20736. sp_digit* t4 = t + 6*9;
  20737. sp_digit* t5 = t + 8*9;
  20738. sp_digit* t6 = t + 10*9;
  20739. /* Check double */
  20740. (void)sp_256_sub_9(t1, p256_mod, q->y);
  20741. sp_256_norm_9(t1);
  20742. if ((~p->infinity & ~q->infinity &
  20743. sp_256_cmp_equal_9(p->x, q->x) & sp_256_cmp_equal_9(p->z, q->z) &
  20744. (sp_256_cmp_equal_9(p->y, q->y) | sp_256_cmp_equal_9(p->y, t1))) != 0) {
  20745. sp_256_proj_point_dbl_9(r, p, t);
  20746. }
  20747. else {
  20748. sp_digit maskp;
  20749. sp_digit maskq;
  20750. sp_digit maskt;
  20751. sp_digit* x = t2;
  20752. sp_digit* y = t5;
  20753. sp_digit* z = t6;
  20754. int i;
  20755. /* U2 = X2*Z1^2 */
  20756. sp_256_mont_sqr_9(t2, p->z, p256_mod, p256_mp_mod);
  20757. sp_256_mont_mul_9(t4, t2, p->z, p256_mod, p256_mp_mod);
  20758. sp_256_mont_mul_9(t2, t2, q->x, p256_mod, p256_mp_mod);
  20759. /* S2 = Y2*Z1^3 */
  20760. sp_256_mont_mul_9(t4, t4, q->y, p256_mod, p256_mp_mod);
  20761. /* H = U2 - X1 */
  20762. sp_256_mont_sub_9(t2, t2, p->x, p256_mod);
  20763. /* R = S2 - Y1 */
  20764. sp_256_mont_sub_9(t4, t4, p->y, p256_mod);
  20765. /* Z3 = H*Z1 */
  20766. sp_256_mont_mul_9(z, p->z, t2, p256_mod, p256_mp_mod);
  20767. /* X3 = R^2 - H^3 - 2*X1*H^2 */
  20768. sp_256_mont_sqr_9(t1, t4, p256_mod, p256_mp_mod);
  20769. sp_256_mont_sqr_9(t5, t2, p256_mod, p256_mp_mod);
  20770. sp_256_mont_mul_9(t3, p->x, t5, p256_mod, p256_mp_mod);
  20771. sp_256_mont_mul_9(t5, t5, t2, p256_mod, p256_mp_mod);
  20772. sp_256_mont_sub_9(x, t1, t5, p256_mod);
  20773. sp_256_mont_dbl_9(t1, t3, p256_mod);
  20774. sp_256_mont_sub_9(x, x, t1, p256_mod);
  20775. /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */
  20776. sp_256_mont_sub_lower_9(t3, t3, x, p256_mod);
  20777. sp_256_mont_mul_9(t3, t3, t4, p256_mod, p256_mp_mod);
  20778. sp_256_mont_mul_9(t5, t5, p->y, p256_mod, p256_mp_mod);
  20779. sp_256_mont_sub_9(y, t3, t5, p256_mod);
  20780. maskp = 0 - (q->infinity & (!p->infinity));
  20781. maskq = 0 - (p->infinity & (!q->infinity));
  20782. maskt = ~(maskp | maskq);
  20783. for (i = 0; i < 9; i++) {
  20784. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | (x[i] & maskt);
  20785. }
  20786. for (i = 0; i < 9; i++) {
  20787. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | (y[i] & maskt);
  20788. }
  20789. for (i = 0; i < 9; i++) {
  20790. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | (z[i] & maskt);
  20791. }
  20792. r->z[0] |= p->infinity & q->infinity;
  20793. r->infinity = p->infinity & q->infinity;
  20794. }
  20795. }
  20796. #ifdef FP_ECC
  20797. /* Convert the projective point to affine.
  20798. * Ordinates are in Montgomery form.
  20799. *
  20800. * a Point to convert.
  20801. * t Temporary data.
  20802. */
  20803. static void sp_256_proj_to_affine_9(sp_point_256* a, sp_digit* t)
  20804. {
  20805. sp_digit* t1 = t;
  20806. sp_digit* t2 = t + 2 * 9;
  20807. sp_digit* tmp = t + 4 * 9;
  20808. sp_256_mont_inv_9(t1, a->z, tmp);
  20809. sp_256_mont_sqr_9(t2, t1, p256_mod, p256_mp_mod);
  20810. sp_256_mont_mul_9(t1, t2, t1, p256_mod, p256_mp_mod);
  20811. sp_256_mont_mul_9(a->x, a->x, t2, p256_mod, p256_mp_mod);
  20812. sp_256_mont_mul_9(a->y, a->y, t1, p256_mod, p256_mp_mod);
  20813. XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod));
  20814. }
  20815. /* Generate the pre-computed table of points for the base point.
  20816. *
  20817. * width = 8
  20818. * 256 entries
  20819. * 32 bits between
  20820. *
  20821. * a The base point.
  20822. * table Place to store generated point data.
  20823. * tmp Temporary data.
  20824. * heap Heap to use for allocation.
  20825. */
  20826. static int sp_256_gen_stripe_table_9(const sp_point_256* a,
  20827. sp_table_entry_256* table, sp_digit* tmp, void* heap)
  20828. {
  20829. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  20830. sp_point_256* t = NULL;
  20831. #else
  20832. sp_point_256 t[3];
  20833. #endif
  20834. sp_point_256* s1 = NULL;
  20835. sp_point_256* s2 = NULL;
  20836. int i;
  20837. int j;
  20838. int err = MP_OKAY;
  20839. (void)heap;
  20840. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  20841. t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap,
  20842. DYNAMIC_TYPE_ECC);
  20843. if (t == NULL)
  20844. err = MEMORY_E;
  20845. #endif
  20846. if (err == MP_OKAY) {
  20847. s1 = t + 1;
  20848. s2 = t + 2;
  20849. err = sp_256_mod_mul_norm_9(t->x, a->x, p256_mod);
  20850. }
  20851. if (err == MP_OKAY) {
  20852. err = sp_256_mod_mul_norm_9(t->y, a->y, p256_mod);
  20853. }
  20854. if (err == MP_OKAY) {
  20855. err = sp_256_mod_mul_norm_9(t->z, a->z, p256_mod);
  20856. }
  20857. if (err == MP_OKAY) {
  20858. t->infinity = 0;
  20859. sp_256_proj_to_affine_9(t, tmp);
  20860. XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod));
  20861. s1->infinity = 0;
  20862. XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod));
  20863. s2->infinity = 0;
  20864. /* table[0] = {0, 0, infinity} */
  20865. XMEMSET(&table[0], 0, sizeof(sp_table_entry_256));
  20866. /* table[1] = Affine version of 'a' in Montgomery form */
  20867. XMEMCPY(table[1].x, t->x, sizeof(table->x));
  20868. XMEMCPY(table[1].y, t->y, sizeof(table->y));
  20869. for (i=1; i<8; i++) {
  20870. sp_256_proj_point_dbl_n_9(t, 32, tmp);
  20871. sp_256_proj_to_affine_9(t, tmp);
  20872. XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
  20873. XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
  20874. }
  20875. for (i=1; i<8; i++) {
  20876. XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
  20877. XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
  20878. for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
  20879. XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
  20880. XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
  20881. sp_256_proj_point_add_qz1_9(t, s1, s2, tmp);
  20882. sp_256_proj_to_affine_9(t, tmp);
  20883. XMEMCPY(table[j].x, t->x, sizeof(table->x));
  20884. XMEMCPY(table[j].y, t->y, sizeof(table->y));
  20885. }
  20886. }
  20887. }
  20888. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  20889. if (t != NULL)
  20890. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  20891. #endif
  20892. return err;
  20893. }
  20894. #endif /* FP_ECC */
  20895. #ifndef WC_NO_CACHE_RESISTANT
  20896. /* Touch each possible entry that could be being copied.
  20897. *
  20898. * r Point to copy into.
  20899. * table Table - start of the entires to access
  20900. * idx Index of entry to retrieve.
  20901. */
  20902. static void sp_256_get_entry_256_9(sp_point_256* r,
  20903. const sp_table_entry_256* table, int idx)
  20904. {
  20905. int i;
  20906. sp_digit mask;
  20907. r->x[0] = 0;
  20908. r->x[1] = 0;
  20909. r->x[2] = 0;
  20910. r->x[3] = 0;
  20911. r->x[4] = 0;
  20912. r->x[5] = 0;
  20913. r->x[6] = 0;
  20914. r->x[7] = 0;
  20915. r->x[8] = 0;
  20916. r->y[0] = 0;
  20917. r->y[1] = 0;
  20918. r->y[2] = 0;
  20919. r->y[3] = 0;
  20920. r->y[4] = 0;
  20921. r->y[5] = 0;
  20922. r->y[6] = 0;
  20923. r->y[7] = 0;
  20924. r->y[8] = 0;
  20925. for (i = 1; i < 256; i++) {
  20926. mask = 0 - (i == idx);
  20927. r->x[0] |= mask & table[i].x[0];
  20928. r->x[1] |= mask & table[i].x[1];
  20929. r->x[2] |= mask & table[i].x[2];
  20930. r->x[3] |= mask & table[i].x[3];
  20931. r->x[4] |= mask & table[i].x[4];
  20932. r->x[5] |= mask & table[i].x[5];
  20933. r->x[6] |= mask & table[i].x[6];
  20934. r->x[7] |= mask & table[i].x[7];
  20935. r->x[8] |= mask & table[i].x[8];
  20936. r->y[0] |= mask & table[i].y[0];
  20937. r->y[1] |= mask & table[i].y[1];
  20938. r->y[2] |= mask & table[i].y[2];
  20939. r->y[3] |= mask & table[i].y[3];
  20940. r->y[4] |= mask & table[i].y[4];
  20941. r->y[5] |= mask & table[i].y[5];
  20942. r->y[6] |= mask & table[i].y[6];
  20943. r->y[7] |= mask & table[i].y[7];
  20944. r->y[8] |= mask & table[i].y[8];
  20945. }
  20946. }
  20947. #endif /* !WC_NO_CACHE_RESISTANT */
  20948. /* Multiply the point by the scalar and return the result.
  20949. * If map is true then convert result to affine coordinates.
  20950. *
  20951. * Stripe implementation.
  20952. * Pre-generated: 2^0, 2^32, ...
  20953. * Pre-generated: products of all combinations of above.
  20954. * 8 doubles and adds (with qz=1)
  20955. *
  20956. * r Resulting point.
  20957. * k Scalar to multiply by.
  20958. * table Pre-computed table.
  20959. * map Indicates whether to convert result to affine.
  20960. * ct Constant time required.
  20961. * heap Heap to use for allocation.
  20962. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  20963. */
  20964. static int sp_256_ecc_mulmod_stripe_9(sp_point_256* r, const sp_point_256* g,
  20965. const sp_table_entry_256* table, const sp_digit* k, int map,
  20966. int ct, void* heap)
  20967. {
  20968. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  20969. sp_point_256* rt = NULL;
  20970. sp_digit* t = NULL;
  20971. #else
  20972. sp_point_256 rt[2];
  20973. sp_digit t[2 * 9 * 6];
  20974. #endif
  20975. sp_point_256* p = NULL;
  20976. int i;
  20977. int j;
  20978. int y;
  20979. int x;
  20980. int err = MP_OKAY;
  20981. (void)g;
  20982. /* Constant time used for cache attack resistance implementation. */
  20983. (void)ct;
  20984. (void)heap;
  20985. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  20986. rt = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap,
  20987. DYNAMIC_TYPE_ECC);
  20988. if (rt == NULL)
  20989. err = MEMORY_E;
  20990. if (err == MP_OKAY) {
  20991. t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 9 * 6, heap,
  20992. DYNAMIC_TYPE_ECC);
  20993. if (t == NULL)
  20994. err = MEMORY_E;
  20995. }
  20996. #endif
  20997. if (err == MP_OKAY) {
  20998. p = rt + 1;
  20999. XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod));
  21000. XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod));
  21001. y = 0;
  21002. x = 31;
  21003. for (j=0; j<8; j++) {
  21004. y |= (int)(((k[x / 29] >> (x % 29)) & 1) << j);
  21005. x += 32;
  21006. }
  21007. #ifndef WC_NO_CACHE_RESISTANT
  21008. if (ct) {
  21009. sp_256_get_entry_256_9(rt, table, y);
  21010. } else
  21011. #endif
  21012. {
  21013. XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
  21014. XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
  21015. }
  21016. rt->infinity = !y;
  21017. for (i=30; i>=0; i--) {
  21018. y = 0;
  21019. x = i;
  21020. for (j=0; j<8; j++) {
  21021. y |= (int)(((k[x / 29] >> (x % 29)) & 1) << j);
  21022. x += 32;
  21023. }
  21024. sp_256_proj_point_dbl_9(rt, rt, t);
  21025. #ifndef WC_NO_CACHE_RESISTANT
  21026. if (ct) {
  21027. sp_256_get_entry_256_9(p, table, y);
  21028. }
  21029. else
  21030. #endif
  21031. {
  21032. XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
  21033. XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
  21034. }
  21035. p->infinity = !y;
  21036. sp_256_proj_point_add_qz1_9(rt, rt, p, t);
  21037. }
  21038. if (map != 0) {
  21039. sp_256_map_9(r, rt, t);
  21040. }
  21041. else {
  21042. XMEMCPY(r, rt, sizeof(sp_point_256));
  21043. }
  21044. }
  21045. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  21046. if (t != NULL)
  21047. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  21048. if (rt != NULL)
  21049. XFREE(rt, heap, DYNAMIC_TYPE_ECC);
  21050. #endif
  21051. return err;
  21052. }
  21053. #ifdef FP_ECC
  21054. #ifndef FP_ENTRIES
  21055. #define FP_ENTRIES 16
  21056. #endif
  21057. /* Cache entry - holds precomputation tables for a point. */
  21058. typedef struct sp_cache_256_t {
  21059. /* X ordinate of point that table was generated from. */
  21060. sp_digit x[9];
  21061. /* Y ordinate of point that table was generated from. */
  21062. sp_digit y[9];
  21063. /* Precomputation table for point. */
  21064. sp_table_entry_256 table[256];
  21065. /* Count of entries in table. */
  21066. uint32_t cnt;
  21067. /* Point and table set in entry. */
  21068. int set;
  21069. } sp_cache_256_t;
  21070. /* Cache of tables. */
  21071. static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES];
  21072. /* Index of last entry in cache. */
  21073. static THREAD_LS_T int sp_cache_256_last = -1;
  21074. /* Cache has been initialized. */
  21075. static THREAD_LS_T int sp_cache_256_inited = 0;
  21076. #ifndef HAVE_THREAD_LS
  21077. static volatile int initCacheMutex_256 = 0;
  21078. static wolfSSL_Mutex sp_cache_256_lock;
  21079. #endif
  21080. /* Get the cache entry for the point.
  21081. *
  21082. * g [in] Point scalar multipling.
  21083. * cache [out] Cache table to use.
  21084. */
  21085. static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache)
  21086. {
  21087. int i;
  21088. int j;
  21089. uint32_t least;
  21090. if (sp_cache_256_inited == 0) {
  21091. for (i=0; i<FP_ENTRIES; i++) {
  21092. sp_cache_256[i].set = 0;
  21093. }
  21094. sp_cache_256_inited = 1;
  21095. }
  21096. /* Compare point with those in cache. */
  21097. for (i=0; i<FP_ENTRIES; i++) {
  21098. if (!sp_cache_256[i].set)
  21099. continue;
  21100. if (sp_256_cmp_equal_9(g->x, sp_cache_256[i].x) &
  21101. sp_256_cmp_equal_9(g->y, sp_cache_256[i].y)) {
  21102. sp_cache_256[i].cnt++;
  21103. break;
  21104. }
  21105. }
  21106. /* No match. */
  21107. if (i == FP_ENTRIES) {
  21108. /* Find empty entry. */
  21109. i = (sp_cache_256_last + 1) % FP_ENTRIES;
  21110. for (; i != sp_cache_256_last; i=(i+1)%FP_ENTRIES) {
  21111. if (!sp_cache_256[i].set) {
  21112. break;
  21113. }
  21114. }
  21115. /* Evict least used. */
  21116. if (i == sp_cache_256_last) {
  21117. least = sp_cache_256[0].cnt;
  21118. for (j=1; j<FP_ENTRIES; j++) {
  21119. if (sp_cache_256[j].cnt < least) {
  21120. i = j;
  21121. least = sp_cache_256[i].cnt;
  21122. }
  21123. }
  21124. }
  21125. XMEMCPY(sp_cache_256[i].x, g->x, sizeof(sp_cache_256[i].x));
  21126. XMEMCPY(sp_cache_256[i].y, g->y, sizeof(sp_cache_256[i].y));
  21127. sp_cache_256[i].set = 1;
  21128. sp_cache_256[i].cnt = 1;
  21129. }
  21130. *cache = &sp_cache_256[i];
  21131. sp_cache_256_last = i;
  21132. }
  21133. #endif /* FP_ECC */
  21134. /* Multiply the base point of P256 by the scalar and return the result.
  21135. * If map is true then convert result to affine coordinates.
  21136. *
  21137. * r Resulting point.
  21138. * g Point to multiply.
  21139. * k Scalar to multiply by.
  21140. * map Indicates whether to convert result to affine.
  21141. * ct Constant time required.
  21142. * heap Heap to use for allocation.
  21143. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  21144. */
  21145. static int sp_256_ecc_mulmod_9(sp_point_256* r, const sp_point_256* g, const sp_digit* k,
  21146. int map, int ct, void* heap)
  21147. {
  21148. #ifndef FP_ECC
  21149. return sp_256_ecc_mulmod_win_add_sub_9(r, g, k, map, ct, heap);
  21150. #else
  21151. sp_digit tmp[2 * 9 * 6];
  21152. sp_cache_256_t* cache;
  21153. int err = MP_OKAY;
  21154. #ifndef HAVE_THREAD_LS
  21155. if (initCacheMutex_256 == 0) {
  21156. wc_InitMutex(&sp_cache_256_lock);
  21157. initCacheMutex_256 = 1;
  21158. }
  21159. if (wc_LockMutex(&sp_cache_256_lock) != 0)
  21160. err = BAD_MUTEX_E;
  21161. #endif /* HAVE_THREAD_LS */
  21162. if (err == MP_OKAY) {
  21163. sp_ecc_get_cache_256(g, &cache);
  21164. if (cache->cnt == 2)
  21165. sp_256_gen_stripe_table_9(g, cache->table, tmp, heap);
  21166. #ifndef HAVE_THREAD_LS
  21167. wc_UnLockMutex(&sp_cache_256_lock);
  21168. #endif /* HAVE_THREAD_LS */
  21169. if (cache->cnt < 2) {
  21170. err = sp_256_ecc_mulmod_win_add_sub_9(r, g, k, map, ct, heap);
  21171. }
  21172. else {
  21173. err = sp_256_ecc_mulmod_stripe_9(r, g, cache->table, k,
  21174. map, ct, heap);
  21175. }
  21176. }
  21177. return err;
  21178. #endif
  21179. }
  21180. #endif
  21181. /* Multiply the point by the scalar and return the result.
  21182. * If map is true then convert result to affine coordinates.
  21183. *
  21184. * km Scalar to multiply by.
  21185. * p Point to multiply.
  21186. * r Resulting point.
  21187. * map Indicates whether to convert result to affine.
  21188. * heap Heap to use for allocation.
  21189. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  21190. */
  21191. int sp_ecc_mulmod_256(const mp_int* km, const ecc_point* gm, ecc_point* r,
  21192. int map, void* heap)
  21193. {
  21194. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  21195. sp_point_256* point = NULL;
  21196. sp_digit* k = NULL;
  21197. #else
  21198. sp_point_256 point[1];
  21199. sp_digit k[9];
  21200. #endif
  21201. int err = MP_OKAY;
  21202. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  21203. point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap,
  21204. DYNAMIC_TYPE_ECC);
  21205. if (point == NULL)
  21206. err = MEMORY_E;
  21207. if (err == MP_OKAY) {
  21208. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9, heap,
  21209. DYNAMIC_TYPE_ECC);
  21210. if (k == NULL)
  21211. err = MEMORY_E;
  21212. }
  21213. #endif
  21214. if (err == MP_OKAY) {
  21215. sp_256_from_mp(k, 9, km);
  21216. sp_256_point_from_ecc_point_9(point, gm);
  21217. err = sp_256_ecc_mulmod_9(point, point, k, map, 1, heap);
  21218. }
  21219. if (err == MP_OKAY) {
  21220. err = sp_256_point_to_ecc_point_9(point, r);
  21221. }
  21222. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  21223. if (k != NULL)
  21224. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  21225. if (point != NULL)
  21226. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  21227. #endif
  21228. return err;
  21229. }
  21230. /* Multiply the point by the scalar, add point a and return the result.
  21231. * If map is true then convert result to affine coordinates.
  21232. *
  21233. * km Scalar to multiply by.
  21234. * p Point to multiply.
  21235. * am Point to add to scalar mulitply result.
  21236. * inMont Point to add is in montgomery form.
  21237. * r Resulting point.
  21238. * map Indicates whether to convert result to affine.
  21239. * heap Heap to use for allocation.
  21240. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  21241. */
  21242. int sp_ecc_mulmod_add_256(const mp_int* km, const ecc_point* gm,
  21243. const ecc_point* am, int inMont, ecc_point* r, int map, void* heap)
  21244. {
  21245. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  21246. sp_point_256* point = NULL;
  21247. sp_digit* k = NULL;
  21248. #else
  21249. sp_point_256 point[2];
  21250. sp_digit k[9 + 9 * 2 * 6];
  21251. #endif
  21252. sp_point_256* addP = NULL;
  21253. sp_digit* tmp = NULL;
  21254. int err = MP_OKAY;
  21255. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  21256. point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap,
  21257. DYNAMIC_TYPE_ECC);
  21258. if (point == NULL)
  21259. err = MEMORY_E;
  21260. if (err == MP_OKAY) {
  21261. k = (sp_digit*)XMALLOC(
  21262. sizeof(sp_digit) * (9 + 9 * 2 * 6), heap,
  21263. DYNAMIC_TYPE_ECC);
  21264. if (k == NULL)
  21265. err = MEMORY_E;
  21266. }
  21267. #endif
  21268. if (err == MP_OKAY) {
  21269. addP = point + 1;
  21270. tmp = k + 9;
  21271. sp_256_from_mp(k, 9, km);
  21272. sp_256_point_from_ecc_point_9(point, gm);
  21273. sp_256_point_from_ecc_point_9(addP, am);
  21274. }
  21275. if ((err == MP_OKAY) && (!inMont)) {
  21276. err = sp_256_mod_mul_norm_9(addP->x, addP->x, p256_mod);
  21277. }
  21278. if ((err == MP_OKAY) && (!inMont)) {
  21279. err = sp_256_mod_mul_norm_9(addP->y, addP->y, p256_mod);
  21280. }
  21281. if ((err == MP_OKAY) && (!inMont)) {
  21282. err = sp_256_mod_mul_norm_9(addP->z, addP->z, p256_mod);
  21283. }
  21284. if (err == MP_OKAY) {
  21285. err = sp_256_ecc_mulmod_9(point, point, k, 0, 0, heap);
  21286. }
  21287. if (err == MP_OKAY) {
  21288. sp_256_proj_point_add_9(point, point, addP, tmp);
  21289. if (map) {
  21290. sp_256_map_9(point, point, tmp);
  21291. }
  21292. err = sp_256_point_to_ecc_point_9(point, r);
  21293. }
  21294. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  21295. if (k != NULL)
  21296. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  21297. if (point != NULL)
  21298. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  21299. #endif
  21300. return err;
  21301. }
  21302. #ifdef WOLFSSL_SP_SMALL
  21303. /* Multiply the base point of P256 by the scalar and return the result.
  21304. * If map is true then convert result to affine coordinates.
  21305. *
  21306. * r Resulting point.
  21307. * k Scalar to multiply by.
  21308. * map Indicates whether to convert result to affine.
  21309. * heap Heap to use for allocation.
  21310. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  21311. */
  21312. static int sp_256_ecc_mulmod_base_9(sp_point_256* r, const sp_digit* k,
  21313. int map, int ct, void* heap)
  21314. {
  21315. /* No pre-computed values. */
  21316. return sp_256_ecc_mulmod_9(r, &p256_base, k, map, ct, heap);
  21317. }
  21318. #else
  21319. /* Striping precomputation table.
  21320. * 8 points combined into a table of 256 points.
  21321. * Distance of 32 between points.
  21322. */
  21323. static const sp_table_entry_256 p256_table[256] = {
  21324. /* 0 */
  21325. { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
  21326. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
  21327. /* 1 */
  21328. { { 0x18a9143c,0x0f3986a0,0x1b6d805e,0x152bf8bf,0x0251075b,0x1995bbb1,
  21329. 0x1719e7ed,0x0ed4a6ea,0x0018905f },
  21330. { 0x0e95560a,0x0f929abe,0x06791737,0x1571c974,0x1f3258b4,0x03446e90,
  21331. 0x16174ba2,0x0304b10b,0x008571ff } },
  21332. /* 2 */
  21333. { { 0x0147519a,0x01443012,0x0cdcbc08,0x103d584d,0x1ebc8d09,0x13e553c2,
  21334. 0x03a6a752,0x01bb7beb,0x00d953c5 },
  21335. { 0x1d590f8f,0x0b1b0e67,0x19b245e7,0x12c4d689,0x164cf72e,0x10881175,
  21336. 0x03cdff65,0x0fd3d651,0x00863ebb } },
  21337. /* 3 */
  21338. { { 0x1cdb6485,0x02b5b11a,0x028be5de,0x1e1d445e,0x0300b808,0x0caa27bf,
  21339. 0x0280f9a3,0x0ab6bff0,0x00000760 },
  21340. { 0x038d2010,0x11a75cdc,0x10dc229d,0x029f7664,0x06606540,0x1e9cc215,
  21341. 0x1b838391,0x0c2686e7,0x00830877 } },
  21342. /* 4 */
  21343. { { 0x16a0d2bb,0x1c917e28,0x188d2653,0x1982d834,0x02c8b0d5,0x079d2be3,
  21344. 0x19fe4907,0x0c3fa36c,0x002f5e69 },
  21345. { 0x15a01797,0x00ae385f,0x05586497,0x01689ac1,0x1db523d2,0x0d9b838f,
  21346. 0x1dec1244,0x02d1ade1,0x00f648f9 } },
  21347. /* 5 */
  21348. { { 0x0137bbbc,0x12b3423f,0x1a82fb27,0x088d3d14,0x13463e43,0x13b0bceb,
  21349. 0x0056c710,0x10a267a0,0x005abe02 },
  21350. { 0x004c7dab,0x15541be6,0x098301e4,0x1b3e9886,0x0cc37573,0x0ab13c73,
  21351. 0x0e0c324c,0x0b6d6dee,0x0094bb72 } },
  21352. /* 6 */
  21353. { { 0x120f141c,0x1fcda47b,0x1d6f1d2e,0x13679a5b,0x045c4619,0x1094a088,
  21354. 0x13bf70fd,0x1965efb8,0x00cdd6bb },
  21355. { 0x0af436fd,0x0533805f,0x04c9afb3,0x08fedb73,0x125226f6,0x13c900a7,
  21356. 0x17d8303e,0x17a97b5c,0x00a361be } },
  21357. /* 7 */
  21358. { { 0x197c13c7,0x05512ac2,0x0df0f84a,0x1ac6bea1,0x09d1dc38,0x0d7679e0,
  21359. 0x04b01c0e,0x013896a5,0x00ba12ca },
  21360. { 0x19f91dfd,0x12047d22,0x1a81fee7,0x0876cd9d,0x00b293af,0x1844cebc,
  21361. 0x1d2c7b3a,0x13ae03fd,0x0053ebb9 } },
  21362. /* 8 */
  21363. { { 0x10e63d34,0x1f3f718d,0x1953ead3,0x000ae553,0x1b5a4f46,0x199a6af3,
  21364. 0x00c70124,0x1240daa9,0x008589fb },
  21365. { 0x0583553a,0x1387ae63,0x1592796a,0x121295c4,0x04652087,0x02838802,
  21366. 0x113f3241,0x0da04a83,0x00ebb069 } },
  21367. /* 9 */
  21368. { { 0x0c1647c5,0x10b650ad,0x13d5e651,0x04fa8f89,0x1fbacb81,0x1551bb26,
  21369. 0x168f7199,0x197a364f,0x00eb2820 },
  21370. { 0x0a87e008,0x0037c6c3,0x08de3ce5,0x1bf53b24,0x0ecb2d87,0x17214066,
  21371. 0x08755bb4,0x136ab4fb,0x001f2828 } },
  21372. /* 10 */
  21373. { { 0x1b89da99,0x1dd50601,0x0a1008aa,0x05af3d70,0x005e8a6f,0x1c315c0e,
  21374. 0x158c9e11,0x0b20bca9,0x00337a4b },
  21375. { 0x01f7794a,0x033a8069,0x1b5fd84f,0x000b6efa,0x1d6e8207,0x1bc08267,
  21376. 0x0f582968,0x1abe985f,0x000d65e0 } },
  21377. /* 11 */
  21378. { { 0x15275d38,0x0e84ddf5,0x1828d636,0x114e8a17,0x0b265426,0x17fa4b9f,
  21379. 0x08cbc1d8,0x084a5e94,0x00c23da2 },
  21380. { 0x0b94520c,0x0d0dc278,0x16f5e397,0x0ccec760,0x09ea1096,0x05c34a69,
  21381. 0x1fc4e937,0x1198f219,0x0019de3b } },
  21382. /* 12 */
  21383. { { 0x06c5fe04,0x01d38b61,0x0e86f6c6,0x11bc1677,0x1712c3b2,0x02c35265,
  21384. 0x0ff5d0cb,0x1a923f99,0x00e34dcb },
  21385. { 0x0aa58403,0x0046a35d,0x1a5e94ed,0x12e90d05,0x0a8af9a6,0x00939b55,
  21386. 0x1dfe78e4,0x088f69c1,0x00e7641f } },
  21387. /* 13 */
  21388. { { 0x1f64ba59,0x0ba9ca0e,0x0090bf1f,0x1e21d816,0x01859d33,0x0fe350ac,
  21389. 0x1efd3c1b,0x0ae0a54a,0x004a12df },
  21390. { 0x1439dbd0,0x1d319c7c,0x194f87ef,0x0497a97b,0x1b314d3c,0x07fd10f8,
  21391. 0x091bf579,0x12776b7d,0x006af5aa } },
  21392. /* 14 */
  21393. { { 0x10c91999,0x1085b4c8,0x16012476,0x09688054,0x020900a2,0x0a5a5c66,
  21394. 0x004cf802,0x0b4cd488,0x005fe347 },
  21395. { 0x193e7b4b,0x07c655ef,0x08fe46ac,0x16a034f8,0x06263292,0x04d7668f,
  21396. 0x04590ba2,0x011d9fd5,0x00b544e3 } },
  21397. /* 15 */
  21398. { { 0x16ddfdce,0x03c63748,0x045e7999,0x0522cdf1,0x067e12c3,0x173b26a7,
  21399. 0x082d3a35,0x17b4d618,0x00e0b6b2 },
  21400. { 0x1b7efb57,0x09896f95,0x031001c3,0x181bbcf2,0x1c9441aa,0x1b56b3cd,
  21401. 0x1dd3e40c,0x1bc4b4c6,0x0071c023 } },
  21402. /* 16 */
  21403. { { 0x1fe20925,0x15461225,0x173a19d8,0x0335871f,0x0706391c,0x12eaee9c,
  21404. 0x13d96a5a,0x1a843a64,0x0061d587 },
  21405. { 0x037173ea,0x03b39d15,0x1de2d97a,0x090010a6,0x0b43e238,0x020f02dd,
  21406. 0x1ef843e1,0x0248c43d,0x00fa11fe } },
  21407. /* 17 */
  21408. { { 0x0cb19ffd,0x0448f959,0x048f08c7,0x151ab763,0x1ca8e01b,0x1eb3c562,
  21409. 0x1b72db40,0x0983e277,0x00586eb0 },
  21410. { 0x07e8ed09,0x01ae3729,0x067b7883,0x03467830,0x052fa1e8,0x0b602b63,
  21411. 0x1c449e3f,0x010e10c9,0x0019d5ac } },
  21412. /* 18 */
  21413. { { 0x109a4e1f,0x14cfac09,0x09c01d07,0x1bce37d2,0x08d20ab7,0x1785f7e9,
  21414. 0x18fc9a97,0x07eff38a,0x00e7c007 },
  21415. { 0x0ef59f76,0x1b6b31d0,0x1f2c1407,0x1676a841,0x002d4669,0x0fbd3d33,
  21416. 0x102b0230,0x1fd8cb67,0x00e08504 } },
  21417. /* 19 */
  21418. { { 0x0031b3ca,0x04c7b46d,0x169b59bc,0x19573dcd,0x046e86d1,0x00fd4a79,
  21419. 0x1ad16ff6,0x104b6132,0x0078f018 },
  21420. { 0x1a25787f,0x1f77ef21,0x132b26ed,0x0df01a3b,0x1fc36801,0x043bd9ad,
  21421. 0x11e833a9,0x170fd28e,0x0043a773 } },
  21422. /* 20 */
  21423. { { 0x12b533d5,0x12bbb9a6,0x0f777018,0x1715ed43,0x0c293673,0x1e4d53cf,
  21424. 0x1ac55df9,0x0a38764c,0x00bb6de6 },
  21425. { 0x165259b3,0x1f4981d5,0x0e9d2039,0x015fa7a0,0x0fc27d6a,0x01e8cd9e,
  21426. 0x066f16b2,0x134ba317,0x0060b461 } },
  21427. /* 21 */
  21428. { { 0x1ae5aa1c,0x0b51c708,0x19cd962f,0x0eca5693,0x187edb8b,0x000a772f,
  21429. 0x1f342c4c,0x1655dd7f,0x009d0f27 },
  21430. { 0x1a730a55,0x1492318b,0x0ef20eb2,0x0ab65fbb,0x19a719c9,0x0ff05600,
  21431. 0x12341f07,0x0da6add8,0x00244a56 } },
  21432. /* 22 */
  21433. { { 0x0acf1f96,0x0d81ca57,0x1309c71b,0x02455204,0x1d3b99f2,0x160dc165,
  21434. 0x1da4989a,0x10e6b03d,0x0045e58c },
  21435. { 0x038f9dbc,0x1ffa3ced,0x02281034,0x15e28dd1,0x0bed7a8a,0x0fd92370,
  21436. 0x1e92516b,0x03983c96,0x00c040e2 } },
  21437. /* 23 */
  21438. { { 0x0f8117b6,0x03d78003,0x08d50ce1,0x12d3fee7,0x075eb651,0x1abb0eca,
  21439. 0x1b1d20ac,0x12ed058d,0x001cdf5c },
  21440. { 0x11f04839,0x0dbbada0,0x1785a61f,0x1d59e891,0x132197db,0x0ee8db85,
  21441. 0x1cf6ca48,0x1f1525bf,0x00046755 } },
  21442. /* 24 */
  21443. { { 0x1ce8ffcd,0x04562e95,0x1986a0b3,0x0789165f,0x0d6c70d5,0x10b93901,
  21444. 0x17cfdbc5,0x02277074,0x00046e5e },
  21445. { 0x18007f01,0x1dc7fb26,0x1d0c60f9,0x03de24b5,0x1a03c7fb,0x0f531af0,
  21446. 0x016c1171,0x186607a0,0x006e0106 } },
  21447. /* 25 */
  21448. { { 0x08dd73b1,0x0639ac24,0x17b43652,0x00e11f32,0x02ab7767,0x0f5462b5,
  21449. 0x1c7ce0e1,0x1dbd2039,0x00442594 },
  21450. { 0x12d4b65b,0x07d51648,0x12430dfe,0x0468772d,0x18d1f94c,0x1250af4b,
  21451. 0x1a3b4c9b,0x0a2985dc,0x00a796fa } },
  21452. /* 26 */
  21453. { { 0x023addd7,0x0cfdb024,0x19a4eccd,0x14c307ca,0x13c809e2,0x1bc71e5f,
  21454. 0x1ba7e216,0x1538d2ec,0x00e4ad2d },
  21455. { 0x0e048a61,0x0bfbfa14,0x04b6680d,0x1a331981,0x0d8ef082,0x0d7a601f,
  21456. 0x050ff0e8,0x08d86f6a,0x00c5e940 } },
  21457. /* 27 */
  21458. { { 0x0be75f9e,0x1b529c61,0x048e9e11,0x0353d196,0x1c04b6fd,0x06f85884,
  21459. 0x1d1f6179,0x15fb68c8,0x0063283d },
  21460. { 0x1af2df15,0x139467bd,0x1669fd33,0x0588aa15,0x0bcc3e59,0x1356f41a,
  21461. 0x04e3eac8,0x15633035,0x0068bd19 } },
  21462. /* 28 */
  21463. { { 0x1887d659,0x04756a88,0x164c16b0,0x09abe966,0x14fe3337,0x14c0e7f3,
  21464. 0x1f5a5a61,0x1ea78dfb,0x00495292 },
  21465. { 0x1acec896,0x143c64f0,0x16d12112,0x096421d8,0x160a7d96,0x1bf13326,
  21466. 0x00dd9a5b,0x01a4c06d,0x000ec753 } },
  21467. /* 29 */
  21468. { { 0x0d2687bb,0x0d09d02d,0x0b887e8b,0x1076d5e6,0x0607ba1f,0x0f7a8eea,
  21469. 0x1c2ce43d,0x14cc90c7,0x000f6207 },
  21470. { 0x0f138233,0x0b3f1dd8,0x0aa9c62f,0x0d72d84e,0x088aedd6,0x02039376,
  21471. 0x173e3b40,0x0e411dad,0x00ff0db0 } },
  21472. /* 30 */
  21473. { { 0x0c95d553,0x04fd080a,0x1a02a29d,0x00a5faba,0x1566fa44,0x018bff9d,
  21474. 0x1a8c60ed,0x07910e81,0x00313b51 },
  21475. { 0x08d11549,0x00171560,0x17b8872d,0x1dc21769,0x0320e071,0x03eea3f9,
  21476. 0x1e049ae6,0x1f30de33,0x002d3abc } },
  21477. /* 31 */
  21478. { { 0x015581a2,0x0144280c,0x08846bd3,0x14daacc6,0x12e999a0,0x1d078655,
  21479. 0x137c66e9,0x021bdb31,0x00c036fa },
  21480. { 0x01fbd009,0x0d7045d6,0x1456058a,0x1163200d,0x00d8f0b6,0x193bcdcf,
  21481. 0x06530bac,0x1896da80,0x00a6b2a2 } },
  21482. /* 32 */
  21483. { { 0x0d3549cf,0x019f287b,0x135997b5,0x06d2dff5,0x1fcb46f3,0x1ed66708,
  21484. 0x0181a56f,0x0a55ef93,0x00810ee2 },
  21485. { 0x1159bb2c,0x0a287f0b,0x02cd5ed9,0x1f7d7ceb,0x1ea72f7d,0x1f3a6b4f,
  21486. 0x1d14ac15,0x0f524e62,0x00d48571 } },
  21487. /* 33 */
  21488. { { 0x10cb5a98,0x0ba0d457,0x0c442fc4,0x151f263e,0x02adfd3d,0x1165d59c,
  21489. 0x01386653,0x14e5f34c,0x006a6045 },
  21490. { 0x02b2411d,0x186069fd,0x03a5b805,0x1d707ca2,0x1b3ccbe0,0x0fb9c432,
  21491. 0x1e40ef32,0x1f5f3c2a,0x00d3e45c } },
  21492. /* 34 */
  21493. { { 0x083f7669,0x10fb4ddf,0x01df5af3,0x115d04e5,0x0278d09f,0x172a1922,
  21494. 0x06725522,0x1bdc7858,0x00207755 },
  21495. { 0x0fef1945,0x1deb0ecb,0x0b4a30e1,0x0279df62,0x164aa188,0x08eb396f,
  21496. 0x00367ef3,0x1cae2a96,0x0048dc5e } },
  21497. /* 35 */
  21498. { { 0x17e5a199,0x11bc85ff,0x0732edc4,0x1f719f31,0x19c79e0e,0x15ff0528,
  21499. 0x111709e8,0x1dbbfede,0x00f2fb0a },
  21500. { 0x10b5025f,0x0e04abaf,0x1ea7c890,0x0a87ae81,0x1fbd0550,0x04569c05,
  21501. 0x14963e8f,0x02bb651a,0x00a13e90 } },
  21502. /* 36 */
  21503. { { 0x02b65cbc,0x0fbd1a85,0x119089be,0x0972e454,0x107a10b0,0x1120f11f,
  21504. 0x09bc9973,0x160292ea,0x002bf0d6 },
  21505. { 0x0b216fb7,0x1ea6e9fa,0x17689ab4,0x0f70cff7,0x0505cf7d,0x1c1fb384,
  21506. 0x027ebade,0x0b42c5fd,0x0042a94a } },
  21507. /* 37 */
  21508. { { 0x0aadf191,0x0235685f,0x089a35d6,0x1491204b,0x1c1f60f8,0x182824a6,
  21509. 0x18f7a180,0x0d38cbdb,0x002c2dd9 },
  21510. { 0x13849c17,0x0810b8ec,0x0894375b,0x0911743b,0x05485460,0x03831e1d,
  21511. 0x16f12043,0x03e858ad,0x00f437fa } },
  21512. /* 38 */
  21513. { { 0x0a0f7dab,0x1506b8a2,0x1dba6b1a,0x092f262e,0x197860f0,0x10287af9,
  21514. 0x0aa14b02,0x066a8e0f,0x00aaf45b },
  21515. { 0x018d364a,0x0f1be19e,0x125c5961,0x17360c7c,0x05444d40,0x0b408af6,
  21516. 0x0af3d05c,0x01be9e4e,0x00cdf631 } },
  21517. /* 39 */
  21518. { { 0x0ea8b7ef,0x039e311c,0x0f08a1dd,0x126a310b,0x08e3408e,0x13b915ed,
  21519. 0x1fc90655,0x175b53c5,0x00f0d008 },
  21520. { 0x0414d3b1,0x089338e9,0x067a9d8a,0x0a930b60,0x1cbdbb37,0x1cb6a29d,
  21521. 0x0e2d7186,0x1eb9510f,0x005bd5c2 } },
  21522. /* 40 */
  21523. { { 0x149a3154,0x187a34f7,0x0acba6bb,0x0b4b2adc,0x04a9c3e8,0x160f5549,
  21524. 0x1c6516ab,0x191413c8,0x00aa12df },
  21525. { 0x0df69f1d,0x1793913a,0x1fd79cc9,0x09905945,0x1dd44e0e,0x0739dbd4,
  21526. 0x0406e763,0x0e7c9195,0x006c036e } },
  21527. /* 41 */
  21528. { { 0x0f6e3138,0x07d70950,0x0b4d1697,0x0dde004b,0x12bc5696,0x0325a2b3,
  21529. 0x1892264f,0x0b12d5f7,0x00292ff6 },
  21530. { 0x1e213402,0x09286a22,0x04b27fb5,0x101c4e87,0x072e8f65,0x1cbfed0e,
  21531. 0x09d825ec,0x1206236e,0x00644e0c } },
  21532. /* 42 */
  21533. { { 0x047153f0,0x0f210f0d,0x01063278,0x1876f324,0x17672b86,0x0743b82e,
  21534. 0x09de4ef7,0x127956f3,0x00f25ae7 },
  21535. { 0x0d869d0c,0x198ca51b,0x01b09907,0x0b910493,0x0945e9d5,0x0f5184b7,
  21536. 0x08f927ed,0x0a627b61,0x0039b8e6 } },
  21537. /* 43 */
  21538. { { 0x16fd2e59,0x1baa1005,0x157263cd,0x0580cd24,0x0573935e,0x190d0715,
  21539. 0x0c1b676a,0x05e1e33b,0x0039122f },
  21540. { 0x03cad53c,0x1de70f00,0x1705f8f3,0x16581fcc,0x13877225,0x18e94d50,
  21541. 0x1e35caeb,0x1f19d01f,0x008de80a } },
  21542. /* 44 */
  21543. { { 0x007bbb76,0x1df546c9,0x1e09d62b,0x18fcf842,0x036b1921,0x1ba58e02,
  21544. 0x10137e8a,0x00c5c6d1,0x00871949 },
  21545. { 0x03993df5,0x0fc945dd,0x0cf49aad,0x1aeb6be7,0x15050639,0x13c542da,
  21546. 0x1784046a,0x0d4b6e9f,0x00fc315e } },
  21547. /* 45 */
  21548. { { 0x08d6ecfa,0x10fea0d7,0x1b1fe195,0x1889ec35,0x0741d5f8,0x153da492,
  21549. 0x02226114,0x15bdc712,0x00e6d4a7 },
  21550. { 0x0593c75d,0x02a9768a,0x09c45898,0x0e1b49ba,0x0c7db70a,0x0f49bdd1,
  21551. 0x195f4abb,0x13537c55,0x0035dfaf } },
  21552. /* 46 */
  21553. { { 0x0a736636,0x1cab7e6d,0x0b2adf9a,0x0a3b2f5c,0x0996609f,0x1fa0879a,
  21554. 0x14afec42,0x1ae39061,0x001da5c7 },
  21555. { 0x1cce6825,0x020f2419,0x15cf0ed7,0x1a231ff2,0x036b815a,0x0963f918,
  21556. 0x075a8a15,0x1fbb7e97,0x007077c0 } },
  21557. /* 47 */
  21558. { { 0x06b9661c,0x1b1ffc6a,0x0b3f5c6f,0x1fa6d61a,0x1f8f7a1d,0x10a05423,
  21559. 0x19100dcf,0x05dca1df,0x0053a863 },
  21560. { 0x096d8051,0x0bb7fb43,0x13d1a282,0x18192b8e,0x026bddae,0x06e1af27,
  21561. 0x13058a65,0x0da69c3f,0x00028ca7 } },
  21562. /* 48 */
  21563. { { 0x1c9877ee,0x08ea3ee7,0x074000b4,0x06c42100,0x060b6c8b,0x008baa61,
  21564. 0x011b400b,0x1b0d2c5e,0x0004c17c },
  21565. { 0x10daddf5,0x0cde84a5,0x1395701b,0x046aea49,0x003b5bea,0x0b73396d,
  21566. 0x11d198cd,0x1d3fdb2e,0x00f7ba4d } },
  21567. /* 49 */
  21568. { { 0x0be1263f,0x06dfd1a7,0x0b9f39b4,0x0c6e6ae3,0x0f523557,0x02a9c153,
  21569. 0x11074910,0x000a4263,0x00e31f96 },
  21570. { 0x0a6b6ec6,0x0ddc90b7,0x10bf1134,0x03a25ce7,0x0a29437a,0x1f5644e8,
  21571. 0x11ef0439,0x0b39c69a,0x00aa3a62 } },
  21572. /* 50 */
  21573. { { 0x16f3dcd3,0x1e7cefa9,0x0fdcd83e,0x1bdaa1a5,0x04f5b6ce,0x087d6fa8,
  21574. 0x0bb9245c,0x0c4fcf3b,0x002398dd },
  21575. { 0x0d09569e,0x1a382d1b,0x127dda73,0x0c3376a2,0x0034cea0,0x01bb9afb,
  21576. 0x0843fe70,0x1643808c,0x005717f5 } },
  21577. /* 51 */
  21578. { { 0x01dd895e,0x1f114e49,0x10a11467,0x030a0081,0x17ecd8e5,0x091c8eb1,
  21579. 0x037be84f,0x0ac1c785,0x00660a2c },
  21580. { 0x167fcbd0,0x06544576,0x0a7c25a7,0x0e48f01d,0x12b4dc84,0x1a40b974,
  21581. 0x114ccacb,0x0989ea44,0x00624ee5 } },
  21582. /* 52 */
  21583. { { 0x1897eccc,0x0aa4e726,0x06202a82,0x13a3b27f,0x07c204d4,0x1211821d,
  21584. 0x0f01c8f0,0x1f7257bf,0x004f392a },
  21585. { 0x1de44fd9,0x0b4fc7d3,0x0cc8559a,0x19f7c8af,0x0bc3cb66,0x14019b47,
  21586. 0x06736cbe,0x0ef99b67,0x008a3e79 } },
  21587. /* 53 */
  21588. { { 0x06c4b125,0x0f0c40f8,0x18f2a337,0x09c601ed,0x013e9ae3,0x0cef2e3d,
  21589. 0x1013bda6,0x046e1848,0x003888d0 },
  21590. { 0x04f91081,0x11401ab2,0x0055411d,0x1f9ec2be,0x0d36e3d9,0x16e43196,
  21591. 0x0cd8609f,0x08e30204,0x00a5e62e } },
  21592. /* 54 */
  21593. { { 0x0facd6c8,0x1412f719,0x0f2f1986,0x18c6a8a9,0x19931699,0x16fbcc6f,
  21594. 0x0b70338f,0x1cc8cd4b,0x002c4768 },
  21595. { 0x10a64bc9,0x1a37fc64,0x1de7d72c,0x14c041c8,0x1e884630,0x08325e02,
  21596. 0x0a836527,0x083f3cca,0x007b5e64 } },
  21597. /* 55 */
  21598. { { 0x1d28444a,0x0b4a1160,0x04da8e48,0x0d8bb17c,0x07fcee99,0x17f2fd86,
  21599. 0x11288e1e,0x196191ae,0x00b8af73 },
  21600. { 0x138b86fd,0x1ef41d51,0x02973fd7,0x07e2b14b,0x09433fee,0x07b79056,
  21601. 0x025727ba,0x0befe7e1,0x00a03639 } },
  21602. /* 56 */
  21603. { { 0x010f7770,0x039e35dd,0x0a838923,0x02db0342,0x02b9fa6f,0x1b4128de,
  21604. 0x14cc4037,0x0030ebf6,0x004be36b },
  21605. { 0x1fb56dbb,0x11304374,0x19e93e24,0x1fdf160f,0x12f20306,0x0602b36a,
  21606. 0x0303bab3,0x10e37b80,0x008cbc9a } },
  21607. /* 57 */
  21608. { { 0x00dac4ab,0x098c4ae6,0x0bfc44b8,0x094880e2,0x0ee57a87,0x173e350e,
  21609. 0x17e18cca,0x07c18106,0x0044e755 },
  21610. { 0x1734002d,0x0a81fffb,0x0d10971b,0x0b971616,0x138b59d3,0x013b0743,
  21611. 0x106257dc,0x074bd71f,0x00470a68 } },
  21612. /* 58 */
  21613. { { 0x10513482,0x0dbb0ee4,0x1a49daa0,0x0e405403,0x13083028,0x00f70673,
  21614. 0x1bbf3691,0x1218c7b8,0x00164106 },
  21615. { 0x0d06a2ed,0x081a5033,0x06c402fd,0x1aee8a31,0x018c9dd4,0x173955c1,
  21616. 0x0d3f6452,0x1faf5797,0x00d73479 } },
  21617. /* 59 */
  21618. { { 0x1ad4c6e5,0x16f7d8b2,0x01b4135f,0x19e11eb6,0x1cb14262,0x0dd8c2ba,
  21619. 0x19ac4bb5,0x1c60ee2c,0x00816469 },
  21620. { 0x161e291e,0x1d5cebca,0x17859875,0x1b5e4583,0x00513eb9,0x13f589af,
  21621. 0x1e73d260,0x047e1ba7,0x000a36dd } },
  21622. /* 60 */
  21623. { { 0x01d5533c,0x0c69963a,0x0118a3c2,0x1eb53d0d,0x1bd117c5,0x1456f1a4,
  21624. 0x0460e688,0x1adfb756,0x00e331df },
  21625. { 0x0bcc6ed8,0x08055b43,0x1e898394,0x01877bde,0x050d7716,0x0cd3de74,
  21626. 0x0e26418f,0x054925c6,0x00d3b478 } },
  21627. /* 61 */
  21628. { { 0x13821f90,0x0a4db747,0x1adeab68,0x1bb3dacd,0x1311692e,0x14a98d00,
  21629. 0x16f42ed9,0x0b4990d4,0x00728127 },
  21630. { 0x13ff47e5,0x01c2c7be,0x00591054,0x0c2d78c2,0x19bb15e1,0x188d3efe,
  21631. 0x01658ac3,0x0fd9c28a,0x002c062e } },
  21632. /* 62 */
  21633. { { 0x0159ac2e,0x1b7ccb78,0x16c9c4e9,0x1cee6d97,0x06047281,0x09440472,
  21634. 0x1bc4ab5b,0x1f2589cf,0x00282a35 },
  21635. { 0x00ce5cd2,0x01aa58f6,0x1e708a67,0x13df9226,0x0c11ecf9,0x179c1f41,
  21636. 0x0af664b2,0x026aa9a5,0x00c71cd5 } },
  21637. /* 63 */
  21638. { { 0x09b578f4,0x042ef4e0,0x0bfe9e92,0x09c4b1c7,0x02f1f188,0x18dbac8c,
  21639. 0x0e8e3dda,0x0819e8fe,0x00c50f67 },
  21640. { 0x174b68ea,0x0e256f99,0x0597f8aa,0x0de646d3,0x13050a40,0x111142d2,
  21641. 0x0370be1a,0x14e4252b,0x00b9ecb3 } },
  21642. /* 64 */
  21643. { { 0x14f8b16a,0x17c20877,0x1ec99a95,0x0835fd88,0x087c1972,0x15c736ce,
  21644. 0x0c6c2901,0x0059a855,0x00803f3e },
  21645. { 0x04dbec69,0x18184d40,0x0eb417df,0x170bee77,0x0197fa83,0x1939d6c7,
  21646. 0x17071825,0x01ca0cf5,0x00c09744 } },
  21647. /* 65 */
  21648. { { 0x0379ab34,0x0352b796,0x077e3461,0x1c0d1708,0x068efa8e,0x022c8bb6,
  21649. 0x1cc080c5,0x1ab22be3,0x00f1af32 },
  21650. { 0x1d75bd50,0x0e1ba98a,0x0bd9ef26,0x19ff75ee,0x1723f837,0x120c246b,
  21651. 0x122c184e,0x061c5a83,0x0023d0f1 } },
  21652. /* 66 */
  21653. { { 0x141500d9,0x0bd5b76f,0x0fab6a21,0x1215cbf9,0x059510d8,0x032444b9,
  21654. 0x0b754bfa,0x1ad8147f,0x00b0288d },
  21655. { 0x050bcb08,0x09907983,0x175b85a1,0x1ec626d2,0x1aa7671a,0x1053dcc4,
  21656. 0x0348c7d4,0x09fe8119,0x00ffd372 } },
  21657. /* 67 */
  21658. { { 0x1458e6cb,0x1cb47325,0x1e974a14,0x1b5a4062,0x15f56992,0x1705bd53,
  21659. 0x1b7ce052,0x095af184,0x00f5590f },
  21660. { 0x0f0ba55a,0x1e125e9e,0x1de2eb83,0x08e49418,0x1674a0fc,0x0327b41d,
  21661. 0x088073a6,0x0a9edee9,0x0018d6da } },
  21662. /* 68 */
  21663. { { 0x15be5a2b,0x0c9f112e,0x0d3cf1bb,0x0f3306b2,0x06ffc6fe,0x04931131,
  21664. 0x05a90c50,0x1b2f3204,0x0050bbb4 },
  21665. { 0x057ec63e,0x1c0c8e37,0x07736c8d,0x04588030,0x0e0f6654,0x04cd811b,
  21666. 0x070d06a0,0x03003fc9,0x002b1001 } },
  21667. /* 69 */
  21668. { { 0x1b391593,0x0345ae2c,0x009c3f3f,0x0beb44b3,0x0dcbbc38,0x19d568cd,
  21669. 0x1831c513,0x13307f75,0x00dd5589 },
  21670. { 0x14b82ff4,0x1dc45c73,0x19cd3264,0x007880e3,0x0322ad2e,0x0f57a1e0,
  21671. 0x010669ea,0x0a2293ac,0x00e6e4c5 } },
  21672. /* 70 */
  21673. { { 0x1e9af288,0x0fb2add8,0x0b6a4c55,0x1c34c9ef,0x020e5647,0x1f25e594,
  21674. 0x1bfd0da5,0x1620fdaa,0x0051e00d },
  21675. { 0x171c327e,0x1e8b4dc3,0x05b0ab50,0x1b641695,0x1477929c,0x08fa9ef5,
  21676. 0x05df01f5,0x08293052,0x00e22f42 } },
  21677. /* 71 */
  21678. { { 0x035f1abb,0x0a2f47a3,0x14e21d33,0x18196ad0,0x0034d7ed,0x160fdad4,
  21679. 0x0327251c,0x07aa5b89,0x00f70937 },
  21680. { 0x08af30d6,0x00cb35dd,0x0deda710,0x1ebe95e2,0x1c47e95b,0x0b1549b0,
  21681. 0x0c44e598,0x111ce4eb,0x00bd52d2 } },
  21682. /* 72 */
  21683. { { 0x1c5fa877,0x18aae3d4,0x0e8f522a,0x15ace4fa,0x189d817d,0x1fcf39e8,
  21684. 0x1e990fd0,0x1c99154e,0x00a0d0f8 },
  21685. { 0x0c94f92d,0x1df57ec6,0x1376ce82,0x11917c18,0x0ba14d81,0x12fc5c17,
  21686. 0x08008b31,0x18f28dad,0x00a56c78 } },
  21687. /* 73 */
  21688. { { 0x0dd09529,0x0b11c8d8,0x0b77f3ca,0x1c1d4c7b,0x1f481803,0x1a8fadad,
  21689. 0x19e8b1dc,0x1f0e6346,0x00d8befd },
  21690. { 0x1c0157f4,0x1c8cea17,0x1239942a,0x195daffd,0x08b0af51,0x05a0016a,
  21691. 0x11e337e7,0x14b9d3ec,0x00854a68 } },
  21692. /* 74 */
  21693. { { 0x03506ea5,0x01afb3db,0x1f8359b7,0x0d891349,0x1cd4d928,0x0e9dff4a,
  21694. 0x0a54fc40,0x0173108d,0x005cacea },
  21695. { 0x1ceac44d,0x086fb064,0x13470eaa,0x0535e86a,0x1babe3db,0x1ef456ae,
  21696. 0x1ea42374,0x0246bc9d,0x00e4982d } },
  21697. /* 75 */
  21698. { { 0x034cd55e,0x18825116,0x00344c88,0x12b7664d,0x1d943586,0x0d7d0fd0,
  21699. 0x1267ecd1,0x1ec2d640,0x008046b7 },
  21700. { 0x18e7d098,0x099ac0f1,0x1bc2dc2d,0x0c3d1be8,0x178c4d7f,0x14f52265,
  21701. 0x1d54c37a,0x0f721055,0x00eb17ca } },
  21702. /* 76 */
  21703. { { 0x16a145b9,0x1a8dacc3,0x0f1c7b05,0x1ed61f83,0x115bba5c,0x1ab29c93,
  21704. 0x04c74f80,0x175f56bc,0x00097b00 },
  21705. { 0x165f69e1,0x1336474a,0x0f94666a,0x11eeb56b,0x1d98477e,0x1d08ed27,
  21706. 0x127980ce,0x0f75fb79,0x00f95c74 } },
  21707. /* 77 */
  21708. { { 0x1ebae45e,0x0c780e9d,0x0f1a5555,0x17d3e189,0x04fc6a8e,0x02d8ede3,
  21709. 0x00debadc,0x03cacddb,0x00351260 },
  21710. { 0x1a1161cd,0x19b78f0f,0x197be1e4,0x1571aa98,0x121e5328,0x17713927,
  21711. 0x0dad1d5f,0x046c0d15,0x000ef971 } },
  21712. /* 78 */
  21713. { { 0x14ca4226,0x12cc67ba,0x190b2380,0x1bc271f0,0x017905ee,0x1fba2347,
  21714. 0x12552258,0x066769f7,0x00fc16d9 },
  21715. { 0x07c800ca,0x14b7d98f,0x1e2b6aaf,0x00c6624c,0x1e8b5138,0x024bb7f9,
  21716. 0x085cf589,0x1e372baf,0x0014ca4a } },
  21717. /* 79 */
  21718. { { 0x1d2f81d5,0x123b8dd5,0x1df4659e,0x1f3ad203,0x1c9071a5,0x1f7be56c,
  21719. 0x0c776262,0x0c7eb384,0x004057b0 },
  21720. { 0x09c05c0a,0x1fec17f4,0x1037e16f,0x0238de3b,0x016dbe49,0x065751ad,
  21721. 0x0c4cefbf,0x0c9e2661,0x001c3b5d } },
  21722. /* 80 */
  21723. { { 0x00ec21fe,0x1f0a5ff4,0x156fa097,0x1c22d584,0x05d67f6c,0x0d0397a5,
  21724. 0x0ebe62f1,0x091b6fcc,0x00fad271 },
  21725. { 0x09ab05b3,0x0605b561,0x0946b9a4,0x1350789c,0x0de7d37a,0x043ae155,
  21726. 0x0a1029f7,0x1c73e1c3,0x0077387d } },
  21727. /* 81 */
  21728. { { 0x056c0dd7,0x14f6624d,0x021b1d07,0x1ff9b08c,0x1aecea5c,0x0a047a82,
  21729. 0x11fa3de8,0x1817de18,0x00b37b85 },
  21730. { 0x0c0e6a8f,0x0cb5b726,0x0e23c8cd,0x1a977ed6,0x0ef4efd6,0x09fd61ce,
  21731. 0x0356ae91,0x191f3ec5,0x009c135a } },
  21732. /* 82 */
  21733. { { 0x04e35743,0x15519014,0x08f37bcc,0x1ad5630b,0x19819320,0x18bb0ef8,
  21734. 0x147ee086,0x03f88670,0x00572136 },
  21735. { 0x11fc9168,0x186d9b53,0x17100f07,0x1174e6bc,0x0d8f55f9,0x143f1bde,
  21736. 0x06f7d932,0x193cd762,0x00dcbac3 } },
  21737. /* 83 */
  21738. { { 0x0518cbe2,0x00eccb42,0x07ac13bc,0x05f83139,0x1eebfd24,0x11e3f23f,
  21739. 0x0189c9d9,0x13c5ac4d,0x00b8c1c8 },
  21740. { 0x08e1d569,0x0d2c5eee,0x16233414,0x1013916f,0x131eb563,0x1fecf88f,
  21741. 0x0b509b09,0x1b45f284,0x005d23bb } },
  21742. /* 84 */
  21743. { { 0x15c8f8be,0x10e394a4,0x1cd8afc2,0x03890077,0x1d4ac296,0x0201efb1,
  21744. 0x04027906,0x19723d9d,0x00c109f9 },
  21745. { 0x18945705,0x1684ae82,0x1ae17030,0x107b2dbb,0x0449bb90,0x15c6bd20,
  21746. 0x1b8611a4,0x09e5ddc3,0x009bc334 } },
  21747. /* 85 */
  21748. { { 0x02913074,0x0ad71ab2,0x0950ac43,0x12364e91,0x0732a554,0x1332d988,
  21749. 0x13051a72,0x0a4be349,0x0029591d },
  21750. { 0x184f983f,0x1b7adb5d,0x17e13879,0x1dde833e,0x0a189be7,0x0a4b405d,
  21751. 0x0cb04803,0x03e31de6,0x00637655 } },
  21752. /* 86 */
  21753. { { 0x162976cc,0x0d2f8a72,0x1c4b0e2f,0x1947cc1d,0x0985222b,0x18323665,
  21754. 0x01eaefe8,0x19011c53,0x00bdb79d },
  21755. { 0x0b06a772,0x0965ae4e,0x14db73bf,0x08eb55fc,0x15db838f,0x10113e15,
  21756. 0x052b0a8f,0x0035ba78,0x008ee860 } },
  21757. /* 87 */
  21758. { { 0x04ade873,0x1f4b4c0d,0x1ee92332,0x13549b89,0x14ba57ee,0x144cad02,
  21759. 0x092cb3b8,0x0f4deef5,0x0092e51d },
  21760. { 0x1190a34d,0x045d7d43,0x0f47b465,0x11eeb7ed,0x11144d69,0x13718657,
  21761. 0x0aab403b,0x0de14ad5,0x005182f8 } },
  21762. /* 88 */
  21763. { { 0x1a4cc99c,0x1d310963,0x1b67287e,0x0136d07c,0x18c5aff6,0x13e5ad64,
  21764. 0x1bc976ec,0x0ba80e74,0x0091dcab },
  21765. { 0x1f575a70,0x0db661ea,0x0361fe80,0x06c272df,0x017360cb,0x074644cc,
  21766. 0x1cac5975,0x1b72f2e9,0x0017a0ce } },
  21767. /* 89 */
  21768. { { 0x076c8d3a,0x0430f150,0x03e492ce,0x155a7242,0x035d9701,0x157209d4,
  21769. 0x1d065343,0x0d8fe99b,0x002e8ce3 },
  21770. { 0x037a862b,0x0939ed58,0x19323ea4,0x15376ec1,0x0f2dd01b,0x09c419dd,
  21771. 0x03cfe591,0x19669ecd,0x00f4ccc6 } },
  21772. /* 90 */
  21773. { { 0x11f79687,0x077a92e7,0x1bea0551,0x12a92b25,0x18d297c5,0x0ba0d2e3,
  21774. 0x0f27848c,0x111341be,0x00ac0db4 },
  21775. { 0x1f01747f,0x15fe388e,0x05f7c4e1,0x1726b1de,0x16bb5592,0x0727ae65,
  21776. 0x128b9620,0x0c32992e,0x0095a64a } },
  21777. /* 91 */
  21778. { { 0x015a4c93,0x160f7ed6,0x1614505c,0x0d36e704,0x10bad402,0x1d8e0b65,
  21779. 0x19ddaa37,0x17452420,0x00231e54 },
  21780. { 0x0ae6d2dc,0x186fc8bc,0x044a4629,0x154c7e72,0x172234d6,0x1935af2d,
  21781. 0x0787d89d,0x065b14e6,0x00ab0be0 } },
  21782. /* 92 */
  21783. { { 0x0d131f2d,0x0bd6874c,0x013c4042,0x1e13c676,0x1a748637,0x10cb6af4,
  21784. 0x19e46b21,0x10059ed4,0x00f1bcc8 },
  21785. { 0x08daacb4,0x0e348a07,0x1d940249,0x1c80aac1,0x137a63c4,0x047e23bc,
  21786. 0x09c56473,0x0d2b5d76,0x00851694 } },
  21787. /* 93 */
  21788. { { 0x11dcf593,0x11ae0a1f,0x062f8ef7,0x00565360,0x19d3d782,0x16e14dee,
  21789. 0x1763a736,0x1a5b55aa,0x008f67d9 },
  21790. { 0x1481ea5f,0x0088b2b3,0x13164321,0x05bbd3c6,0x13fa8e7d,0x01fa0282,
  21791. 0x0d77ff75,0x17380e51,0x00f84572 } },
  21792. /* 94 */
  21793. { { 0x17af71c9,0x10d3d38c,0x1cd95957,0x092888f4,0x15063a14,0x1703870e,
  21794. 0x106686d2,0x020c2d65,0x00edee27 },
  21795. { 0x11734121,0x1781a7a8,0x097a7c2c,0x18dcaa94,0x02ecf1ca,0x0479d206,
  21796. 0x1fd23705,0x13689d7a,0x009fd27e } },
  21797. /* 95 */
  21798. { { 0x16e2cb16,0x063b2c57,0x16466d8f,0x16fa59fc,0x15583e3e,0x0c0b0b46,
  21799. 0x0e1d6a31,0x16d2b1fe,0x00a40c2f },
  21800. { 0x1edcc158,0x04f62b07,0x1c8c15a3,0x10098cab,0x07e127ad,0x13824d18,
  21801. 0x1b3f64e5,0x170fb8db,0x0099bc9b } },
  21802. /* 96 */
  21803. { { 0x127dafc6,0x054a90ec,0x02734661,0x03f6d2b8,0x06dde52c,0x00d07c9b,
  21804. 0x19927656,0x01742daf,0x009abe21 },
  21805. { 0x08915220,0x0057c252,0x1605b192,0x062ed49b,0x1ca5afa7,0x1cc38b40,
  21806. 0x12c31f54,0x0af0fe68,0x007881c2 } },
  21807. /* 97 */
  21808. { { 0x00bcf3ff,0x19ccda8f,0x1fdd3da4,0x05978a24,0x1d9680d0,0x12d16e80,
  21809. 0x05023ed1,0x033461d1,0x0015e6e3 },
  21810. { 0x1e0e05f4,0x036b7069,0x16210119,0x0f7bb886,0x050d3fad,0x03e8e27c,
  21811. 0x0b3af987,0x19e3222e,0x000e55fa } },
  21812. /* 98 */
  21813. { { 0x18787564,0x14ecc037,0x1a17399f,0x062e4263,0x1e8d61a3,0x0c655c0c,
  21814. 0x15ddac05,0x0ecdfd2c,0x00d73d09 },
  21815. { 0x1eb7206e,0x1241a128,0x062ed090,0x12521f8c,0x0a520a51,0x1c2caf18,
  21816. 0x142d772e,0x0e91e2b4,0x009250a3 } },
  21817. /* 99 */
  21818. { { 0x1e577410,0x17f847c5,0x1dea31b2,0x011406a0,0x063a4fd4,0x1944f605,
  21819. 0x102fc7d8,0x10583991,0x00774140 },
  21820. { 0x0b0991cd,0x0d207d37,0x1f70a581,0x1410cc93,0x0fd40c1c,0x11e3d992,
  21821. 0x02e4e9a2,0x09a25d64,0x008cb04f } },
  21822. /* 100 */
  21823. { { 0x0906171c,0x0e1682ab,0x09030fec,0x07d39b60,0x06841907,0x15a7ec48,
  21824. 0x0d476e39,0x1de8e247,0x00e4e429 },
  21825. { 0x18ec36f4,0x1c6ea9e1,0x12da89c2,0x05b803fe,0x09a48f9d,0x1703c3cd,
  21826. 0x15497419,0x1fe78dcc,0x0037bca2 } },
  21827. /* 101 */
  21828. { { 0x1f562470,0x06971e3e,0x0592b253,0x04e54581,0x193be44f,0x0efcc063,
  21829. 0x08a9f1b5,0x1b860056,0x0059913e },
  21830. { 0x1750592a,0x109cd41a,0x00f7809e,0x003b01cf,0x1d64f99e,0x01baf502,
  21831. 0x089b3e30,0x0956027c,0x0043786e } },
  21832. /* 102 */
  21833. { { 0x1e56b5a6,0x1995876c,0x1f1a3e7f,0x01b34db3,0x046a7075,0x1422acbc,
  21834. 0x19ebb057,0x1316fcf3,0x008638ca },
  21835. { 0x0afc24b2,0x1ad704b0,0x0b3a3c8b,0x131d5e9b,0x1a78f053,0x0ee85765,
  21836. 0x1bc0edd9,0x0d4f6754,0x001ecdd3 } },
  21837. /* 103 */
  21838. { { 0x0c5ff2f3,0x09d66b13,0x1cea5e17,0x0a2d8050,0x10d54a2d,0x04fd6908,
  21839. 0x0cb6b653,0x10ba8b3e,0x00d85d0f },
  21840. { 0x10b11da3,0x1b805c68,0x00c63127,0x0458614f,0x0decdd2c,0x047a4904,
  21841. 0x118955a6,0x18769da7,0x00a04f19 } },
  21842. /* 104 */
  21843. { { 0x0d7f93bd,0x03c92647,0x0bd47d82,0x0958ba72,0x171afcb6,0x1985410d,
  21844. 0x02c1f2b8,0x1d4b812a,0x0092b2ee },
  21845. { 0x05b6e235,0x0d6264a4,0x0db03c21,0x19495252,0x08891ab2,0x1359f028,
  21846. 0x1db203ea,0x042b0684,0x001ee782 } },
  21847. /* 105 */
  21848. { { 0x063e79f7,0x10517007,0x067641a9,0x01cf65e7,0x1c09df59,0x02a53303,
  21849. 0x05424084,0x1b0af4dc,0x00f3f2ce },
  21850. { 0x110d9b55,0x0028879f,0x19099208,0x1f9f59b0,0x10e7c9d2,0x0d53f45e,
  21851. 0x0843958c,0x0a87b47c,0x000f56a4 } },
  21852. /* 106 */
  21853. { { 0x1043e0df,0x190dffd0,0x001f9b56,0x096d9938,0x0517a6c7,0x17606a54,
  21854. 0x098c6995,0x08232d3c,0x00bd8f17 },
  21855. { 0x1eb7494a,0x14dddc35,0x1cee0e22,0x0fa8de8b,0x1a79a156,0x0953d272,
  21856. 0x08277de8,0x06a6199f,0x002d1a1c } },
  21857. /* 107 */
  21858. { { 0x106508da,0x0971c09a,0x15e569c6,0x03018943,0x144b3336,0x0ca4bd4c,
  21859. 0x091b376d,0x0bd723f7,0x00a107a6 },
  21860. { 0x0f94d639,0x168e8e28,0x162df5f9,0x15e6eb14,0x1ca1c8b4,0x0ac25e9b,
  21861. 0x0bc869f1,0x015f0f53,0x00183d76 } },
  21862. /* 108 */
  21863. { { 0x0dde59a4,0x0eb4b888,0x02fbe1ca,0x1b1a0e1d,0x0be78f1a,0x04b1a797,
  21864. 0x1d508a6d,0x13b84d3a,0x001d4417 },
  21865. { 0x0390d30e,0x196e067c,0x1a04432c,0x164ea61b,0x0339a0a3,0x0ee295e0,
  21866. 0x0988c6bc,0x1852c0da,0x00771f9c } },
  21867. /* 109 */
  21868. { { 0x05040739,0x0cc9f3bc,0x09aa4e66,0x073b7300,0x0fc26445,0x1b797afc,
  21869. 0x063b3d03,0x06206c4e,0x0064427a },
  21870. { 0x05428aa8,0x1a796c3c,0x1ed26a13,0x15b87fd7,0x101ac7b7,0x1636f91e,
  21871. 0x15b4806c,0x092d5d21,0x0049d9b7 } },
  21872. /* 110 */
  21873. { { 0x035d1099,0x03c6c5e2,0x03468233,0x179a9d1d,0x08a412ad,0x1150165b,
  21874. 0x11140b0b,0x0367ec0a,0x009037d8 },
  21875. { 0x074c7b61,0x06dd6138,0x0ff5cb9f,0x006356af,0x15352fe2,0x164b2cb6,
  21876. 0x0e718733,0x0d4f980c,0x0008c3de } },
  21877. /* 111 */
  21878. { { 0x16d552ab,0x07ee8107,0x13607c48,0x15ff300b,0x1129156b,0x1e1f489a,
  21879. 0x0cbc1bed,0x0848af2d,0x00c69094 },
  21880. { 0x01231bd1,0x1d9d74e2,0x11608145,0x18dd0eb9,0x0a1221ea,0x1bd5fceb,
  21881. 0x0b008220,0x00595fc7,0x003fa3db } },
  21882. /* 112 */
  21883. { { 0x05058880,0x1ad1f328,0x0e50fcb5,0x06cbdec8,0x049257da,0x030e7d59,
  21884. 0x03fd051e,0x161fb701,0x00c5c4bd },
  21885. { 0x1272b56b,0x1a89f1a5,0x0e410e9c,0x04fd2a23,0x04969c83,0x11befc42,
  21886. 0x1ad7f633,0x1288d856,0x002d56db } },
  21887. /* 113 */
  21888. { { 0x1f46ac6b,0x030bc17f,0x08b90949,0x1ef24c0f,0x08de1d19,0x11e204d2,
  21889. 0x090bebfa,0x13bca077,0x000f56bd },
  21890. { 0x145cda49,0x1bea7689,0x1bca6744,0x02b1f902,0x03402821,0x12a5575a,
  21891. 0x17c79f1a,0x13a22e76,0x004003bb } },
  21892. /* 114 */
  21893. { { 0x00803387,0x1c740c4d,0x12f5010e,0x022bea73,0x17f21ece,0x1046e943,
  21894. 0x1e790a5c,0x04540fe5,0x00537655 },
  21895. { 0x08a4182d,0x04c0510d,0x0677de69,0x17a0f464,0x1a2d4a2b,0x05170d0c,
  21896. 0x15259d34,0x0b0d8ba8,0x007a056f } },
  21897. /* 115 */
  21898. { { 0x1d8a2a47,0x03592ac4,0x17c9dcd9,0x10529187,0x0d5395b5,0x000755f8,
  21899. 0x19d547b0,0x1e2f4344,0x0077d482 },
  21900. { 0x07853948,0x050decac,0x1efffbae,0x102f7ad9,0x01e47a6f,0x002bc034,
  21901. 0x0392adbb,0x05656716,0x00411501 } },
  21902. /* 116 */
  21903. { { 0x0de28ced,0x039f87a3,0x04fb11cf,0x1b4ec136,0x063921d5,0x074f372e,
  21904. 0x051986e3,0x0e5f7d41,0x00cdf045 },
  21905. { 0x0c53c3b0,0x059e2c5b,0x1ee10f07,0x1c782088,0x1780e97f,0x0570965c,
  21906. 0x0427ecae,0x1b52e706,0x00ee703d } },
  21907. /* 117 */
  21908. { { 0x1f57e43a,0x028a8a07,0x0e046e0d,0x0cc1a763,0x0b986d44,0x0effc7a1,
  21909. 0x1884aced,0x13b42c59,0x002a0ad8 },
  21910. { 0x0bc277ba,0x072534a3,0x10709d99,0x1192a982,0x16274c78,0x1326655f,
  21911. 0x1964506a,0x0cf58568,0x00d62d0b } },
  21912. /* 118 */
  21913. { { 0x0c054ac4,0x0e2ec3d9,0x1f7de20e,0x00b0b3e4,0x128d6570,0x05f9d8c0,
  21914. 0x109bb7df,0x1e532384,0x00b39a23 },
  21915. { 0x10b16ae5,0x094250af,0x0dbd46e5,0x140b6342,0x007830c6,0x009bf938,
  21916. 0x1314758f,0x12580ce9,0x0004ed00 } },
  21917. /* 119 */
  21918. { { 0x1ae90393,0x1a0c2e8c,0x0f593987,0x0f685294,0x0fc14304,0x00d34c2a,
  21919. 0x0e1eb800,0x18202ef8,0x00a0a91f },
  21920. { 0x0e2c831e,0x1851f80d,0x1c9f85bf,0x0d5d0456,0x075b4bb7,0x0450ad18,
  21921. 0x11063c4b,0x1113da41,0x00084cf9 } },
  21922. /* 120 */
  21923. { { 0x1ca6becf,0x0c284ef7,0x1fecca36,0x1d5d00fb,0x0e8b92fc,0x0ae223bc,
  21924. 0x1df97628,0x164e757e,0x00d57955 },
  21925. { 0x11b5d4f1,0x086d3cf1,0x1e9e8708,0x05e09679,0x1c20baa5,0x1044ee13,
  21926. 0x07c75344,0x08405a28,0x008e14ea } },
  21927. /* 121 */
  21928. { { 0x12897042,0x16a81a2f,0x100b12bb,0x0a663e86,0x1fb218d0,0x00ca645e,
  21929. 0x05632367,0x06e5549a,0x00597e1a },
  21930. { 0x0f0bd68c,0x193f60d6,0x00925140,0x17c1b956,0x03e846d4,0x06bd64ff,
  21931. 0x17a96e72,0x06c33369,0x00ca3f02 } },
  21932. /* 122 */
  21933. { { 0x0170bd20,0x095085ab,0x0fd779d6,0x112fe2da,0x0ade20ea,0x1ff8a259,
  21934. 0x1f928cd8,0x0fc61380,0x00bde7fd },
  21935. { 0x18f5432c,0x0b5db695,0x10d112d4,0x1b8397c0,0x15b5a210,0x0f37fc7c,
  21936. 0x0660f6c0,0x01c14fba,0x00b623ad } },
  21937. /* 123 */
  21938. { { 0x00c7b65b,0x1adeb3ab,0x0928a269,0x18ab2047,0x06795ab8,0x07e86bd9,
  21939. 0x0defe088,0x08cb1d82,0x00d6aa2e },
  21940. { 0x1138bb85,0x055e005a,0x0cea5704,0x03a243b0,0x0a32e8c3,0x18058b81,
  21941. 0x04eac93f,0x1c05b98a,0x00111662 } },
  21942. /* 124 */
  21943. { { 0x0fb42b87,0x008a00af,0x1b137fde,0x1ebae036,0x1c129bd9,0x066bd3eb,
  21944. 0x03e19bb3,0x197296ea,0x00db3ee1 },
  21945. { 0x134837cf,0x1379ed87,0x15e353ec,0x1da31772,0x0657de7e,0x0fc9be2b,
  21946. 0x096574b3,0x084a440d,0x00886a64 } },
  21947. /* 125 */
  21948. { { 0x05b569ea,0x011a67db,0x0846704f,0x022283ee,0x0619e200,0x042ed0ad,
  21949. 0x1ef22eb7,0x1d603142,0x00a70cf4 },
  21950. { 0x0c4a6a65,0x127cbd74,0x0d0de3c8,0x0b9e4e02,0x0096036e,0x104f27bf,
  21951. 0x0ddef8e9,0x157a2e8f,0x00aa4772 } },
  21952. /* 126 */
  21953. { { 0x1aa60cc0,0x1b3b098b,0x1a0457d9,0x02c6c206,0x1bb5ac79,0x05da5de0,
  21954. 0x05d37b66,0x1b861f5f,0x00611a6d },
  21955. { 0x015ee47a,0x073c65e6,0x0365a94c,0x12c5049c,0x1ed882e8,0x0d6f9eec,
  21956. 0x1220dbcd,0x1f02c853,0x005cfffa } },
  21957. /* 127 */
  21958. { { 0x1b7a99cd,0x06aa67fc,0x0f116870,0x07733b08,0x139e17bf,0x0847b163,
  21959. 0x05300e2a,0x046fb833,0x006e5a6b },
  21960. { 0x0ba5db77,0x1c5a2a70,0x1d8358fb,0x1100ff59,0x08378b7b,0x00633b30,
  21961. 0x0f339647,0x11a485b5,0x00481a23 } },
  21962. /* 128 */
  21963. { { 0x15d0b34a,0x1a0bde01,0x09f029f8,0x1670d706,0x162d1440,0x1316d601,
  21964. 0x050e3edc,0x099c19bf,0x002c4111 },
  21965. { 0x0d95a0b1,0x1d2e778d,0x1550d88a,0x166f50cf,0x086c9c09,0x06e900f2,
  21966. 0x0a5c9b5b,0x17e85ff2,0x0020477a } },
  21967. /* 129 */
  21968. { { 0x18d65dbf,0x1ba8b9e0,0x07b6b60b,0x1f281c67,0x1001c77b,0x0935ee78,
  21969. 0x1ad9c08b,0x1358ee72,0x00ac6640 },
  21970. { 0x06261cc3,0x185d9b7e,0x039fa422,0x1ef79232,0x06c10213,0x075d522f,
  21971. 0x1e159507,0x0eb98245,0x00ce8e69 } },
  21972. /* 130 */
  21973. { { 0x1c0a67d2,0x1890da0d,0x13492283,0x08ec1488,0x1473762d,0x078eb2cd,
  21974. 0x12a03811,0x0ca4a176,0x0008fde3 },
  21975. { 0x048bf287,0x07761ed4,0x0da75bab,0x0c4305a6,0x09482c2a,0x0fee4922,
  21976. 0x135cd60b,0x1a4acbad,0x002f7e2f } },
  21977. /* 131 */
  21978. { { 0x03770fa7,0x125c96de,0x0410fe6b,0x1d1ab86f,0x01171095,0x074e8bbb,
  21979. 0x0ab953cd,0x05d20ee0,0x00c65be9 },
  21980. { 0x16fd0a40,0x1ac5181f,0x139e12c9,0x1045c779,0x167bfe7d,0x1ac2a7cb,
  21981. 0x0ce9eb93,0x08fa2327,0x004bff8e } },
  21982. /* 132 */
  21983. { { 0x00ff1480,0x0a0e90f8,0x1536c5b3,0x11f6fa0e,0x0f3ea2ab,0x0977ddf0,
  21984. 0x19f6b207,0x1ccaee52,0x003e4e4a },
  21985. { 0x1c5303e6,0x10c79b69,0x0988e5df,0x13329724,0x0c3c03bd,0x07130992,
  21986. 0x00a27b5c,0x1fab1d8c,0x005388ae } },
  21987. /* 133 */
  21988. { { 0x1e5d7713,0x0898bf5a,0x179276ab,0x130bdceb,0x1b26109b,0x1e27e3a7,
  21989. 0x1838cbd6,0x1a29eeb7,0x005cf908 },
  21990. { 0x0e657b12,0x1021a884,0x1bb6799d,0x08434b72,0x0ccc2bfd,0x1a8fc4b8,
  21991. 0x138838a7,0x080c1e01,0x00a698ba } },
  21992. /* 134 */
  21993. { { 0x0f748fec,0x1ed8b437,0x074b3e5c,0x0eab44fd,0x05effe6e,0x12a26713,
  21994. 0x16358c2d,0x114f5d75,0x00b142ef },
  21995. { 0x17d5770a,0x098d7cf8,0x0cd04beb,0x1e76ce59,0x159de66a,0x068def99,
  21996. 0x01d5af58,0x12cb0a2a,0x00d1896a } },
  21997. /* 135 */
  21998. { { 0x13c41c08,0x02cabd59,0x1a38b87b,0x1d2958a8,0x12f6c87d,0x15b9d623,
  21999. 0x08e46205,0x016f303b,0x00267b0e },
  22000. { 0x0e62b988,0x12aa72ec,0x1b4879db,0x1b8eaa22,0x06f99d8d,0x1d781e95,
  22001. 0x0e4d1843,0x0f542232,0x00b54e28 } },
  22002. /* 136 */
  22003. { { 0x178a876b,0x100915a8,0x14412d02,0x1f2dfe10,0x09f7651f,0x18d58a79,
  22004. 0x1398142c,0x116bf0fa,0x0084abb2 },
  22005. { 0x0270790a,0x0f6a1cfc,0x18fd1af5,0x196b3b0b,0x022122d6,0x0e0db60f,
  22006. 0x1901d7d5,0x0ce2ecaa,0x00e5436f } },
  22007. /* 137 */
  22008. { { 0x0286e8d5,0x1fc812f1,0x1114ef94,0x192b690c,0x0e3a0353,0x1adef204,
  22009. 0x067b60cb,0x116b739d,0x000404f6 },
  22010. { 0x0781e8e5,0x1699def5,0x0f0bd6f2,0x1ea0302c,0x1caa33cd,0x14b0008c,
  22011. 0x1c055d5d,0x1be15838,0x003a4263 } },
  22012. /* 138 */
  22013. { { 0x1aeb596d,0x14b2f664,0x0f24ad30,0x1407ce04,0x1396101e,0x1a5b1700,
  22014. 0x0d9d1c12,0x07f20bd4,0x000ca8fd },
  22015. { 0x151b2b61,0x1291d212,0x03f341a4,0x0f513872,0x0a63e1eb,0x095f01c9,
  22016. 0x10cf9fc7,0x0c89bb61,0x0096dca2 } },
  22017. /* 139 */
  22018. { { 0x187510af,0x01dda1d1,0x08da8048,0x1fd55153,0x10378846,0x0bb817ca,
  22019. 0x077348e9,0x024755ab,0x004363e2 },
  22020. { 0x00246a47,0x121d0e3a,0x17749372,0x0571a5ca,0x1af96b36,0x03022ec7,
  22021. 0x0313e6c2,0x0b9b1773,0x00840e11 } },
  22022. /* 140 */
  22023. { { 0x1023e8a7,0x09102f10,0x171e82fc,0x11519bb1,0x05ddfc80,0x11390b1d,
  22024. 0x1b538a4a,0x17a61bda,0x005e0d6a },
  22025. { 0x1cfc0f64,0x1d390e13,0x157b6201,0x1d803a1c,0x19db242e,0x1f7c8e8f,
  22026. 0x09689a9e,0x1e8528b4,0x007dea48 } },
  22027. /* 141 */
  22028. { { 0x05060a81,0x1efb78e7,0x1e55856a,0x1f38e5f1,0x0268be79,0x162a0356,
  22029. 0x1b473f4d,0x17dd7fa2,0x00abc2a2 },
  22030. { 0x13e2eac7,0x16337c8e,0x174119a2,0x0174c7a5,0x0d31b6f1,0x11bb8141,
  22031. 0x1f059e43,0x128d8fdd,0x004ea353 } },
  22032. /* 142 */
  22033. { { 0x1266309d,0x0c517c6a,0x05168fbb,0x038d8103,0x05dc10a5,0x1a2d2bc6,
  22034. 0x1f0f3b2b,0x1123929f,0x003a76e6 },
  22035. { 0x1d7b0d0f,0x15674523,0x161297e6,0x159d2d1e,0x17fbe963,0x06392734,
  22036. 0x1191468c,0x0148cbcc,0x008212a1 } },
  22037. /* 143 */
  22038. { { 0x0fab8caa,0x1be30e1e,0x0508e43b,0x171d081c,0x133ca18e,0x1fb3bf4b,
  22039. 0x05933477,0x0e2b3396,0x00aa7cab },
  22040. { 0x1c837bd1,0x17e4939d,0x1abd75c0,0x080fa186,0x1da49c06,0x09497a11,
  22041. 0x1f0c5d88,0x0e7fc0c2,0x0040e380 } },
  22042. /* 144 */
  22043. { { 0x07bf9b7c,0x07c04125,0x0f8c343d,0x1a46407f,0x19ce3365,0x09904be7,
  22044. 0x149afef9,0x001660aa,0x00e36047 },
  22045. { 0x0cc6c2c7,0x0e5cc88b,0x132fb993,0x106e1174,0x0d9ec726,0x0a1a31bd,
  22046. 0x057f737b,0x0ef47bdc,0x006542d6 } },
  22047. /* 145 */
  22048. { { 0x1b6c377a,0x1995b683,0x0d122f8f,0x00708f20,0x08af76cb,0x09d4106d,
  22049. 0x1c875bf7,0x1dc1376d,0x00a6534a },
  22050. { 0x1035facf,0x050bc068,0x12d1f98c,0x0ab4673b,0x1f39335e,0x07f0e223,
  22051. 0x1c89ba94,0x05fb935d,0x00f3cb67 } },
  22052. /* 146 */
  22053. { { 0x1b55fd83,0x19b8cff1,0x1777443a,0x0f48d90e,0x0a784e0d,0x0fd482e7,
  22054. 0x039cceb2,0x05d55d0e,0x007cafaa },
  22055. { 0x1d53b338,0x1c0a6820,0x01f9b1a6,0x198141df,0x12b0fe0a,0x088408b3,
  22056. 0x08bbee4f,0x183737aa,0x000aab13 } },
  22057. /* 147 */
  22058. { { 0x12681297,0x0e6713c6,0x02551ab7,0x0a1d636a,0x1aaf2cb3,0x18b9bb30,
  22059. 0x0ba4b710,0x00508e02,0x004b91a6 },
  22060. { 0x12f8ddcf,0x07f884ab,0x0446bd37,0x17ec3d35,0x0430e08e,0x1b0561b9,
  22061. 0x12ad23d0,0x0a6e4643,0x0049534c } },
  22062. /* 148 */
  22063. { { 0x107b7e9d,0x1efbeb8f,0x13545be0,0x11df4627,0x07ee3a47,0x1325b602,
  22064. 0x17b9e3bc,0x09facb58,0x00caf46c },
  22065. { 0x12aa8266,0x026863bc,0x0da12ee8,0x08a8cd22,0x116b0edf,0x08b45725,
  22066. 0x1c3d5b99,0x0ae098ce,0x0014ce9e } },
  22067. /* 149 */
  22068. { { 0x165e8f91,0x0a22f1f4,0x03c924a6,0x19437596,0x0a0a0d3a,0x0387c864,
  22069. 0x09c74c73,0x14a7c993,0x001bb708 },
  22070. { 0x158bdd7a,0x0e54f34a,0x0289ac75,0x140a1003,0x0f1ec734,0x1538a64e,
  22071. 0x040ac24e,0x1e5b4600,0x00f9d126 } },
  22072. /* 150 */
  22073. { { 0x0ff9563e,0x04de53d5,0x0645281d,0x0ef5fd69,0x11671dd0,0x0188dfaf,
  22074. 0x11a789e8,0x172e53d9,0x00807afc },
  22075. { 0x09b08b77,0x1c5499be,0x0f1f8e1f,0x074f0a88,0x1d8ba86c,0x1d2ca3b7,
  22076. 0x163217eb,0x1a2cad19,0x00751adc } },
  22077. /* 151 */
  22078. { { 0x10715c0d,0x1751c5a0,0x1da5fde2,0x07d4e31e,0x1f06dd11,0x158a49fd,
  22079. 0x10fd997a,0x0d04a6ee,0x0029ec44 },
  22080. { 0x150bebbc,0x0ca38ce5,0x1415088f,0x1dcb7fc8,0x1edb1399,0x0d9d4696,
  22081. 0x1df64335,0x1c725480,0x00ff9370 } },
  22082. /* 152 */
  22083. { { 0x06b75b65,0x0d16b4de,0x19947156,0x11f1aa4c,0x1d7d2418,0x199f1ef4,
  22084. 0x0068a2a7,0x1174553a,0x00977647 },
  22085. { 0x129af2c7,0x0293116c,0x1a4248e2,0x1ebada9c,0x051e9334,0x03f2d44d,
  22086. 0x0beb39b3,0x07f585f0,0x0074a631 } },
  22087. /* 153 */
  22088. { { 0x175f079c,0x17a6feed,0x18dbeeec,0x00f92a31,0x136dd85b,0x1e7873e6,
  22089. 0x18f46db3,0x02a1fe90,0x00ab75be },
  22090. { 0x173fc9b7,0x0d9b3e00,0x1653f420,0x14e841a4,0x11236b90,0x1f81e204,
  22091. 0x07d857f6,0x05c1688b,0x004ebeac } },
  22092. /* 154 */
  22093. { { 0x1c9f2c53,0x1b62ff3a,0x0ba5047a,0x0440231d,0x0c5d8d25,0x1b19fcad,
  22094. 0x1ff32221,0x0f658375,0x00df9988 },
  22095. { 0x050aaecb,0x1bc77694,0x15a89cae,0x12303603,0x1bcac9d4,0x0a88d8e6,
  22096. 0x01625e37,0x14eef3e8,0x0027b040 } },
  22097. /* 155 */
  22098. { { 0x173b2eb2,0x0202edbf,0x06c84624,0x1f0a111c,0x0327ee0d,0x18a92cb1,
  22099. 0x0fd5406d,0x06fc99f4,0x00b393dd },
  22100. { 0x1fd75165,0x091873d9,0x14cd5528,0x06898579,0x15022d66,0x18df07bd,
  22101. 0x1065b0db,0x025a08c6,0x0009588c } },
  22102. /* 156 */
  22103. { { 0x02601c3b,0x043049f8,0x170cd7f8,0x04a5f19e,0x0ff28fb0,0x194044a5,
  22104. 0x122e5573,0x153b73ec,0x0081c879 },
  22105. { 0x06f56c51,0x007343e6,0x05d86301,0x08e2d27e,0x1353bfed,0x0520c82c,
  22106. 0x0f1113e2,0x1eabf823,0x00fa0d48 } },
  22107. /* 157 */
  22108. { { 0x01608e4d,0x0370e4ef,0x00a08b2f,0x1bb4226b,0x0c2d7010,0x0ee08abf,
  22109. 0x1f5bdadf,0x0ad6d46c,0x008ea0e1 },
  22110. { 0x0383b3b4,0x1aa70179,0x007d4f28,0x0cd7287e,0x03ca5699,0x119596f0,
  22111. 0x16b13fd9,0x049f4016,0x003f5ab9 } },
  22112. /* 158 */
  22113. { { 0x19739efb,0x1bdd86ca,0x1afb034c,0x0361e9cf,0x067d1c75,0x16eb208d,
  22114. 0x15b8b694,0x10e56e84,0x008bc768 },
  22115. { 0x02d3d253,0x0df1db94,0x035de7e9,0x0cf343eb,0x167bba9f,0x00b470b3,
  22116. 0x0d3e872b,0x120c1f9e,0x00b386f1 } },
  22117. /* 159 */
  22118. { { 0x0fedcfc2,0x0f9e09a9,0x1e2bc34c,0x0d7ec4c5,0x088c2539,0x1a7572b9,
  22119. 0x1136680a,0x1ee360d3,0x004cb460 },
  22120. { 0x1b8095ea,0x133da69a,0x101d80eb,0x17f0b2df,0x0a16592b,0x0fb35b0a,
  22121. 0x088f851d,0x0112bdea,0x0052c0d5 } },
  22122. /* 160 */
  22123. { { 0x15339848,0x18e10870,0x1de32348,0x1451d0e0,0x0e170e87,0x1330b4ab,
  22124. 0x102e7477,0x07057613,0x004ac3c9 },
  22125. { 0x0998987d,0x0df02a8b,0x027d3586,0x06ed895c,0x1933d8b2,0x1bb28d1f,
  22126. 0x17d07782,0x18fc72e0,0x00380d94 } },
  22127. /* 161 */
  22128. { { 0x01542e75,0x0d1aad54,0x006e6dc0,0x0e4943dc,0x1708796c,0x14bbb126,
  22129. 0x1ebdace8,0x0e3bc4c6,0x002ce3e1 },
  22130. { 0x15d5bc1a,0x1f7f5a4f,0x1df8ad73,0x0ac0fc4e,0x1756ca65,0x1617ca89,
  22131. 0x19353faa,0x0a416c49,0x002e6cd8 } },
  22132. /* 162 */
  22133. { { 0x0c31c31d,0x142caa5c,0x1c86830d,0x067a00b7,0x19ec9685,0x11373ae3,
  22134. 0x15502f5d,0x08e858d3,0x00ca1775 },
  22135. { 0x16d2dbb2,0x0376d7ff,0x12a74633,0x1b197a2e,0x178e8fd0,0x03c9d522,
  22136. 0x139a1d7a,0x02739565,0x00a976a7 } },
  22137. /* 163 */
  22138. { { 0x13fb353d,0x1328f8dc,0x1f3e9c82,0x195716af,0x15281d75,0x07d398d8,
  22139. 0x0666aa23,0x02e143e9,0x008720a7 },
  22140. { 0x093e1b90,0x01f469bb,0x1db7f0e3,0x0bb8162d,0x08742d34,0x08055a95,
  22141. 0x04f23aa3,0x0538ed31,0x009719ef } },
  22142. /* 164 */
  22143. { { 0x18e35909,0x10776c6a,0x177045a0,0x0db1b867,0x05026936,0x0ce83710,
  22144. 0x13075fe6,0x0edc2ae0,0x00a50729 },
  22145. { 0x04e70b2e,0x0151bf56,0x042aa280,0x19ecaed1,0x12a5c84d,0x1f8c322d,
  22146. 0x1c9735c6,0x13bef6ee,0x0099389c } },
  22147. /* 165 */
  22148. { { 0x1ada7a4b,0x1c604793,0x0e24d988,0x1d3a07fa,0x1512c3ab,0x1744bb37,
  22149. 0x0b91ad9c,0x15440590,0x00a88806 },
  22150. { 0x1380184e,0x10102256,0x1aa2e159,0x16f18824,0x04f17a8c,0x186056c2,
  22151. 0x13f9e759,0x1f68e71b,0x000043bf } },
  22152. /* 166 */
  22153. { { 0x16d5192e,0x0acdaee1,0x042cabe3,0x110ba68b,0x01781acf,0x168508b0,
  22154. 0x019a0d59,0x00374d89,0x0052f3ef },
  22155. { 0x0edcb64d,0x0c339950,0x1a0de7ce,0x10584700,0x0f3090a4,0x12fd3820,
  22156. 0x19d45b2f,0x1133de4f,0x003296bd } },
  22157. /* 167 */
  22158. { { 0x054d81d7,0x1b55d44a,0x1ae6cf11,0x1bcfdea3,0x179869ea,0x10e6c0e2,
  22159. 0x07a58668,0x17f5dcae,0x003b90fe },
  22160. { 0x1496f7cb,0x1c9811f2,0x0d46f124,0x1c83b0ff,0x0b5ce55b,0x0ea44cdf,
  22161. 0x0c600fc7,0x13b3f021,0x006e8806 } },
  22162. /* 168 */
  22163. { { 0x143ea1db,0x11bd588d,0x1674a4b3,0x1fe352a4,0x0f1860a7,0x0110c7c2,
  22164. 0x144e146c,0x1d5bdf55,0x00a7222b },
  22165. { 0x0b0a9144,0x1563c761,0x1e967168,0x0480a3e5,0x1ce385a0,0x1652b0a3,
  22166. 0x1a424747,0x04778558,0x00be94d5 } },
  22167. /* 169 */
  22168. { { 0x0b226ce7,0x17a4a2f0,0x1fa2dc1c,0x1fae8f2c,0x0c63eb8a,0x0378c2d3,
  22169. 0x1d9bb7a9,0x1fd37d18,0x007782de },
  22170. { 0x1db38626,0x10695521,0x1d9eb45d,0x15cf0eed,0x19cdb460,0x037e2a24,
  22171. 0x192cd06e,0x0cf45125,0x00038385 } },
  22172. /* 170 */
  22173. { { 0x19ec1a0f,0x0c6d77eb,0x0ce725cb,0x19adfb9d,0x01a953bb,0x0ffe2c7b,
  22174. 0x1083d55d,0x1895bef6,0x00dbd986 },
  22175. { 0x15f39eb7,0x0d5440a0,0x0365db20,0x05f9eb73,0x1717d6ee,0x03aee797,
  22176. 0x0f415195,0x188d0c17,0x008e24d3 } },
  22177. /* 171 */
  22178. { { 0x1a587390,0x04ec72a4,0x0fb1621d,0x16329e19,0x183c612b,0x1ed2592c,
  22179. 0x1f211b81,0x18880f75,0x00541a99 },
  22180. { 0x024c8842,0x1920b493,0x1b017ff6,0x098255b0,0x1cf62604,0x0a5a27bf,
  22181. 0x17471674,0x093eafa6,0x00c0092c } },
  22182. /* 172 */
  22183. { { 0x1f2e61ef,0x1e63ae1e,0x06cd72b4,0x1083905c,0x129f47e8,0x1868c84f,
  22184. 0x113718b4,0x068e50d2,0x0075e406 },
  22185. { 0x1bc237d0,0x1ea0fe2d,0x13c07279,0x06f7e1d8,0x1d534c95,0x0d0b1415,
  22186. 0x161a4714,0x0b18f090,0x005b7cb6 } },
  22187. /* 173 */
  22188. { { 0x0a28ead1,0x12538424,0x0ed1fda5,0x1b8a11fa,0x05b39802,0x1fe8bb3f,
  22189. 0x1e866b92,0x1751be12,0x007ae13e },
  22190. { 0x0add384e,0x090b77c7,0x0cbfc1bf,0x0345b36d,0x1b5f3036,0x0c3c25e6,
  22191. 0x0ff4812e,0x0e9c551c,0x00787d80 } },
  22192. /* 174 */
  22193. { { 0x157fbb1c,0x0f12eb5b,0x08077af1,0x17bb6594,0x033ffe47,0x14d1b691,
  22194. 0x12112957,0x0333de50,0x005c2228 },
  22195. { 0x08315250,0x19ea542c,0x1c25f05d,0x04345704,0x1d33f21b,0x0750ef7a,
  22196. 0x0ac2adf1,0x15775e1e,0x00e45d37 } },
  22197. /* 175 */
  22198. { { 0x08511c8a,0x16f8f1a1,0x129b34f4,0x0453917b,0x039a7ebb,0x18d3b13e,
  22199. 0x074d5e29,0x04509bf7,0x00ed7bc1 },
  22200. { 0x13dea561,0x191536fc,0x03c3b473,0x07e31ba9,0x123e8544,0x10a02dd6,
  22201. 0x149f62e1,0x1928b94d,0x00aac97c } },
  22202. /* 176 */
  22203. { { 0x016bd00a,0x1aa753a5,0x102f307a,0x13d35beb,0x1fc06d83,0x1bf88fcd,
  22204. 0x113824ae,0x16622c7b,0x00318f97 },
  22205. { 0x030d7138,0x06062df6,0x10c0883b,0x11be4757,0x0360644e,0x0b97d811,
  22206. 0x1d34aede,0x1433509f,0x00fa41fa } },
  22207. /* 177 */
  22208. { { 0x06642269,0x0016cba5,0x0de0ef51,0x10299d37,0x1e60bc81,0x1c723ca0,
  22209. 0x0788e634,0x0583a4dd,0x0038bb6b },
  22210. { 0x0a577f87,0x1272512b,0x047f8731,0x05a4a7b8,0x007288b5,0x155fb114,
  22211. 0x0697fccd,0x00b9cec0,0x0094dd09 } },
  22212. /* 178 */
  22213. { { 0x1e93f92a,0x0b67bee6,0x0d7cc545,0x06679713,0x1e750a01,0x06fce4ca,
  22214. 0x0ba40901,0x0cfa4b85,0x00920778 },
  22215. { 0x0bf39d44,0x1238f008,0x0ed4f5f8,0x1920412d,0x03d8f5f2,0x1bd9ae4e,
  22216. 0x0d453112,0x117a537d,0x0081e842 } },
  22217. /* 179 */
  22218. { { 0x0477199f,0x0ece15d6,0x17b3765b,0x11dddcd6,0x0fd0e8cb,0x0d9ff720,
  22219. 0x12c62bdf,0x0c5b77f4,0x001b94ab },
  22220. { 0x0e47f143,0x0786c59e,0x1d1858d1,0x0c47f8c7,0x1938351e,0x1387e62c,
  22221. 0x03bbc63c,0x0500aab2,0x0006a38e } },
  22222. /* 180 */
  22223. { { 0x13355b49,0x12d809cd,0x1afe66cb,0x04cac169,0x1f3dc20e,0x1d35e934,
  22224. 0x13e3023f,0x04107b3a,0x00a7b36c },
  22225. { 0x1b3e8830,0x068ae1d0,0x07e702d9,0x19d5c351,0x16930d5f,0x12517168,
  22226. 0x08833fbb,0x16945045,0x00be54c6 } },
  22227. /* 181 */
  22228. { { 0x0d91167c,0x166d9efc,0x099897b5,0x187ef3cf,0x0c7f4517,0x12479a35,
  22229. 0x0aedc415,0x157d5c04,0x00bf30a5 },
  22230. { 0x13828a68,0x13bc2df4,0x0fbc0da3,0x038664fe,0x146b2516,0x0ff5ac90,
  22231. 0x04eb846d,0x1bc4e65a,0x00d1c820 } },
  22232. /* 182 */
  22233. { { 0x1038b363,0x01f09a3c,0x01794641,0x023ea8d6,0x0cad158c,0x1d5f3013,
  22234. 0x168d3f95,0x1dad1431,0x00b7d17b },
  22235. { 0x029c2559,0x0652c48f,0x1fff6111,0x1406ecb7,0x069484f7,0x1257ba72,
  22236. 0x11912637,0x0bcc8259,0x003997fd } },
  22237. /* 183 */
  22238. { { 0x0bd61507,0x103a3414,0x09934abc,0x0265aa69,0x015e329e,0x0fd84545,
  22239. 0x0fa3ffb7,0x05278d82,0x000eeb89 },
  22240. { 0x07e259f8,0x0db4d1f5,0x0f9f99fa,0x1b6fcda2,0x1a685ce1,0x0c7b568f,
  22241. 0x1bbc9dcc,0x1f192456,0x00228916 } },
  22242. /* 184 */
  22243. { { 0x0a12ab5b,0x0cd712d8,0x1ef04da5,0x022e3f2a,0x02b0ccc1,0x014f68b7,
  22244. 0x05fa0161,0x03add261,0x00ec05ad },
  22245. { 0x0c3f3708,0x0bdd2df5,0x0d675dc5,0x15f26a61,0x034e531b,0x091b88c1,
  22246. 0x0cdd1ed5,0x0acffe23,0x007d3141 } },
  22247. /* 185 */
  22248. { { 0x16dfefab,0x1ece02e7,0x0cddc1de,0x1e44d1b9,0x0bb95be2,0x16cb9d1c,
  22249. 0x1e8f94fa,0x1f93783a,0x00e9ce66 },
  22250. { 0x0f6a02a1,0x0d50abb3,0x19803b5d,0x010fbec1,0x1c1b938c,0x1f9a3466,
  22251. 0x1947e251,0x002e4500,0x00d9650b } },
  22252. /* 186 */
  22253. { { 0x1a057e60,0x025a6252,0x1bc97914,0x19877d1b,0x1ccbdcbc,0x19040be0,
  22254. 0x1e8a98d4,0x135009d6,0x0014d669 },
  22255. { 0x1b1f411a,0x045420ae,0x035da70b,0x175e17f0,0x177ad09f,0x17c80e17,
  22256. 0x062ad37b,0x0821a86b,0x006f4c68 } },
  22257. /* 187 */
  22258. { { 0x16c24a96,0x1936fa74,0x0f6668e1,0x1b790bf9,0x0e30a534,0x17794595,
  22259. 0x0aecf119,0x1fac2313,0x004c4350 },
  22260. { 0x1855b8da,0x0b3fb8b7,0x0f0e284a,0x0847288c,0x1334341a,0x0a09f574,
  22261. 0x02d70df8,0x084b4623,0x00a726d2 } },
  22262. /* 188 */
  22263. { { 0x148c1086,0x17359f74,0x14e8b876,0x1ca07b97,0x022f3f1d,0x169f81e8,
  22264. 0x0e48fcd7,0x10598d9e,0x0013639e },
  22265. { 0x0dafaa86,0x1649c7de,0x15289626,0x178bf64c,0x11329f45,0x19372282,
  22266. 0x168c658e,0x1c383466,0x00ca9365 } },
  22267. /* 189 */
  22268. { { 0x0c3b2d20,0x10ad63aa,0x138906cd,0x14a82f20,0x1071d742,0x10e2664e,
  22269. 0x0a96c214,0x0692e16e,0x009ce29c },
  22270. { 0x0d3e0ad6,0x0640fb9b,0x1e10d323,0x01b53de5,0x062d9806,0x0e8d3674,
  22271. 0x1e60d7b4,0x1af56855,0x0048c4ab } },
  22272. /* 190 */
  22273. { { 0x00c7485a,0x110d8662,0x09d36ff4,0x08ab77ca,0x1d2e8ead,0x1b4c4931,
  22274. 0x0f2d24f1,0x065ecf66,0x0078017c },
  22275. { 0x130cb5ee,0x0e9abb4c,0x1023b4ae,0x029d2818,0x11a4dc0d,0x1faa9397,
  22276. 0x1013e2de,0x0a9bcb83,0x0053cd04 } },
  22277. /* 191 */
  22278. { { 0x1d28ccac,0x06ac2fd2,0x16dd1baf,0x047cac00,0x123aa5f8,0x1850e680,
  22279. 0x0a3df1e7,0x183a7aff,0x00eea465 },
  22280. { 0x0551803b,0x00832cf8,0x19abdc1e,0x16b33ef9,0x08e706c0,0x13b81494,
  22281. 0x064d0656,0x148f5cd2,0x001b6e42 } },
  22282. /* 192 */
  22283. { { 0x167d04c3,0x14049be7,0x1bae044b,0x0257c513,0x14d601e3,0x0c43c92c,
  22284. 0x14f55ad7,0x02830ff7,0x000224da },
  22285. { 0x0c5fe36f,0x1d5dc318,0x1d47d7e1,0x1e78c09d,0x029ec580,0x18dfd9da,
  22286. 0x1cce593e,0x1e0857ff,0x0060838e } },
  22287. /* 193 */
  22288. { { 0x1e0bbe99,0x19659793,0x0a8e7b90,0x1489e609,0x139037bd,0x1e3d4fd4,
  22289. 0x190d7d25,0x0045a662,0x00636eb2 },
  22290. { 0x13ae00aa,0x07e8730c,0x0b9b4bff,0x1401fc63,0x1901c875,0x0c514fc9,
  22291. 0x0eb3d0d9,0x16c72431,0x008844ee } },
  22292. /* 194 */
  22293. { { 0x0b3bae58,0x0a0b8e93,0x18e7cf84,0x07bee22f,0x0eada7db,0x1e3fc0d4,
  22294. 0x027b34de,0x1b8a3f6f,0x0027ba83 },
  22295. { 0x1bf54de5,0x1efa1cff,0x1f869c69,0x0e06176b,0x17a48727,0x071aed94,
  22296. 0x12ad0bba,0x0690fe74,0x00adb62d } },
  22297. /* 195 */
  22298. { { 0x0175df2a,0x188b4515,0x030cba66,0x15409ec3,0x10916082,0x19738a35,
  22299. 0x02cb2793,0x0ecebcf9,0x00b990fd },
  22300. { 0x0df37313,0x014ecb5a,0x0d01e242,0x00aaf3a1,0x077111c2,0x17253c04,
  22301. 0x06359b26,0x1f29a21a,0x0081707e } },
  22302. /* 196 */
  22303. { { 0x03d6ff96,0x1ebe5590,0x010cd825,0x0a37f81b,0x0db4b5b8,0x11e26821,
  22304. 0x09709a20,0x1d5ab515,0x003792da },
  22305. { 0x141afa0b,0x140c432c,0x160d9c54,0x13ce8285,0x0e0a7f3e,0x1293adf2,
  22306. 0x06e85f20,0x0bd29600,0x005abd63 } },
  22307. /* 197 */
  22308. { { 0x0ac4927c,0x13fd4270,0x1233c8dc,0x10c06b4f,0x0a0dfe38,0x0af5256e,
  22309. 0x184292f3,0x04308d56,0x005995bf },
  22310. { 0x029dfa33,0x087c305c,0x03f062fa,0x1fc55d2b,0x10366caa,0x17a23c31,
  22311. 0x047a6cee,0x145a9068,0x0044c32c } },
  22312. /* 198 */
  22313. { { 0x040ed80c,0x1a54bf8f,0x14b2a0a9,0x07196263,0x16ad95f9,0x0925be16,
  22314. 0x15314fc8,0x1f701054,0x001f2162 },
  22315. { 0x120b173e,0x1233e62b,0x17c4be5f,0x114ccc10,0x165dc40e,0x0107264e,
  22316. 0x1f2633af,0x05787d20,0x008f1d40 } },
  22317. /* 199 */
  22318. { { 0x1bc4058a,0x1ac97ce7,0x0bd59c13,0x1c296c52,0x18c57b15,0x1f1bde0e,
  22319. 0x0fe71573,0x08724ddb,0x00b1980f },
  22320. { 0x12c76b09,0x0619f049,0x0c1fde26,0x0a4f3a67,0x1b4611df,0x156a431d,
  22321. 0x1915bc23,0x1366e891,0x002828ad } },
  22322. /* 200 */
  22323. { { 0x04cf4ac5,0x0b391626,0x1992beda,0x18347fbb,0x10832f5a,0x1d517044,
  22324. 0x0e401546,0x04eb4296,0x004973f1 },
  22325. { 0x122eac5d,0x0cec19a9,0x166d5a39,0x0fddea17,0x083935e0,0x1907d12c,
  22326. 0x0b1eacd9,0x1a1b62d1,0x006dac8e } },
  22327. /* 201 */
  22328. { { 0x0da835ef,0x1daa2d77,0x043b547d,0x0227a43a,0x01b094aa,0x12f009ba,
  22329. 0x19300d69,0x0b24173b,0x004b23ef },
  22330. { 0x1c4c7341,0x015db401,0x162f0dfa,0x0ee0da7e,0x03ee8d45,0x1c31d28f,
  22331. 0x0939cd49,0x069bbe93,0x004dd715 } },
  22332. /* 202 */
  22333. { { 0x15476cd9,0x1ca23394,0x069c96ef,0x1a0e5fc6,0x167e0648,0x045c7e25,
  22334. 0x16ec5107,0x0005e949,0x00fd3170 },
  22335. { 0x0995d0e1,0x05a1ffa4,0x1dca6a87,0x0d2ba21d,0x1898276e,0x1cbb20bc,
  22336. 0x0d978357,0x1192ad3e,0x0014fac5 } },
  22337. /* 203 */
  22338. { { 0x1312ae18,0x0cd0032f,0x124ff26b,0x0b1b81f9,0x12846519,0x0120453e,
  22339. 0x09436685,0x0a26d57b,0x00ed7c76 },
  22340. { 0x05d4abbc,0x113878d1,0x0844fa91,0x1bb1e7e3,0x1952f9b5,0x183aada8,
  22341. 0x1d4f1826,0x1ee9a5d3,0x00fefcb7 } },
  22342. /* 204 */
  22343. { { 0x1a119185,0x084a4bd5,0x1116e92f,0x1d186155,0x01179d54,0x1cef5529,
  22344. 0x002d2491,0x0fd0fc1b,0x001801a5 },
  22345. { 0x1cafffb0,0x19e9fc6f,0x09549001,0x0678175c,0x1dfbc6cf,0x1b1dadaf,
  22346. 0x0191e075,0x03c3d5a2,0x009f8fc1 } },
  22347. /* 205 */
  22348. { { 0x1e69544c,0x0c1d0b8a,0x12de04c5,0x1f0acfe0,0x04c320ea,0x147e93c5,
  22349. 0x06a4788a,0x13a7a74d,0x00a9d380 },
  22350. { 0x19a2da3b,0x1b616162,0x057211e4,0x1979ec31,0x1086938c,0x122731ea,
  22351. 0x1bdd7994,0x15dc22f1,0x003006b9 } },
  22352. /* 206 */
  22353. { { 0x09eead28,0x1d8f9586,0x1d37ef02,0x1ec6bb13,0x089397ee,0x0bfed967,
  22354. 0x1d841d1d,0x1ae8bf1e,0x000ab85f },
  22355. { 0x1e5b4549,0x06d3e499,0x048bc87b,0x0576b92f,0x180404be,0x093a5a1d,
  22356. 0x0b089868,0x0ea23d28,0x00b122d6 } },
  22357. /* 207 */
  22358. { { 0x06a5ae7a,0x1f303df3,0x0b72f8ce,0x0e07f4ed,0x0e5c501e,0x0180a75b,
  22359. 0x0bb2be41,0x18212fb7,0x009f599d },
  22360. { 0x0ff250ed,0x0badb8c0,0x0688371b,0x122ae869,0x027a38eb,0x02d20859,
  22361. 0x0de10958,0x1c114529,0x007d5528 } },
  22362. /* 208 */
  22363. { { 0x00c26def,0x07ac7b31,0x0acb47bc,0x0b0bd4b0,0x03881025,0x0bcd80e7,
  22364. 0x1cc3ef9f,0x002607e2,0x0028ccea },
  22365. { 0x19644ba5,0x0ed5e68b,0x1ffc2e34,0x0c87d00d,0x1e17b1fc,0x1b7e3359,
  22366. 0x0efe9829,0x09143a02,0x00c18baf } },
  22367. /* 209 */
  22368. { { 0x1dc4216d,0x0731c642,0x1850ab0d,0x0020ce40,0x1064a00c,0x10b8cafa,
  22369. 0x05af514e,0x13b6f52b,0x009def80 },
  22370. { 0x07ab8d2c,0x0f432173,0x0de8ad90,0x080866c4,0x0218bb42,0x1536b262,
  22371. 0x1395f541,0x160d1011,0x000357f8 } },
  22372. /* 210 */
  22373. { { 0x0cd2cc88,0x14edf322,0x0e3ce763,0x03851be1,0x0a0c8cc6,0x0c3a6698,
  22374. 0x021d28c2,0x1ba36913,0x00e4a01a },
  22375. { 0x157cd8f9,0x168f7567,0x1653120b,0x0cfa7d7a,0x0f7871b7,0x0e38bde9,
  22376. 0x10c29ca5,0x0f39c219,0x00466d7d } },
  22377. /* 211 */
  22378. { { 0x1dada2c7,0x1e98c494,0x06a89f51,0x014d871f,0x059e14fa,0x1e944105,
  22379. 0x146a4393,0x0448a3d5,0x00c672a5 },
  22380. { 0x1d86b655,0x0303e642,0x0b52bc4c,0x06ba77f3,0x172a6f02,0x03402b88,
  22381. 0x144e6682,0x1f5e54ce,0x005e3d64 } },
  22382. /* 212 */
  22383. { { 0x1b3b4416,0x1320863c,0x0c9b666a,0x1f9f0bd5,0x16a74cd8,0x1ba56db2,
  22384. 0x0bf17aff,0x12bd71c8,0x006c8a7a },
  22385. { 0x102a63bd,0x06305d3d,0x03c011c4,0x1e460717,0x190b06b2,0x1b9c1896,
  22386. 0x0a4631b0,0x0455b059,0x00348ae4 } },
  22387. /* 213 */
  22388. { { 0x1ccda2fb,0x1a3a331a,0x01c9b49f,0x1995431c,0x11f2022a,0x1bc12495,
  22389. 0x14ba16b7,0x1c1b3de5,0x00c1074d },
  22390. { 0x0e9a65b3,0x079e7225,0x15c546ff,0x03c9580b,0x09788fd7,0x0fa86735,
  22391. 0x1ff351c4,0x1b793ca9,0x00fbadfb } },
  22392. /* 214 */
  22393. { { 0x00a99363,0x189f8e69,0x1c89dd45,0x0acb1ed9,0x159b2b91,0x1ae69269,
  22394. 0x1f365a05,0x16906e2d,0x00b7f976 },
  22395. { 0x1d6dbf74,0x1ac7126a,0x10ebcd95,0x0775fae3,0x1dfe38d2,0x1bb00121,
  22396. 0x001523d1,0x05d95f99,0x00f4d41b } },
  22397. /* 215 */
  22398. { { 0x1dabd48d,0x0f8e7947,0x101e2914,0x037c6c65,0x146e9ce8,0x14ba08b8,
  22399. 0x1c41ab38,0x1d5c02c1,0x00180824 },
  22400. { 0x06e58358,0x1c3b4c5b,0x1b28d600,0x0d0ea59c,0x1e6c5635,0x071a2f20,
  22401. 0x149608e0,0x073079ed,0x0067e5f6 } },
  22402. /* 216 */
  22403. { { 0x0f4899ef,0x04e65c6e,0x0ed1303e,0x002be13d,0x18ec9949,0x093b592c,
  22404. 0x1f1951be,0x13409823,0x009fef78 },
  22405. { 0x13d2a071,0x09b3f67a,0x1466c25b,0x1c34ff48,0x02eefb10,0x1fd8308f,
  22406. 0x188329ac,0x10353389,0x00bc80c1 } },
  22407. /* 217 */
  22408. { { 0x05eb82e6,0x1929b7c7,0x1b2e4825,0x109f8fea,0x1da5e1a4,0x10b8a85a,
  22409. 0x1c431e38,0x0c53f19b,0x0049270e },
  22410. { 0x0a6b50ad,0x11cdbddf,0x0e23ff06,0x05098344,0x1197b9a0,0x158bc083,
  22411. 0x1dfd500f,0x1f2c26e5,0x00d2ee52 } },
  22412. /* 218 */
  22413. { { 0x08e0362a,0x1be6942c,0x09765374,0x1f514f1f,0x0a526442,0x1b72d21a,
  22414. 0x1ccebfe0,0x17dcb576,0x00dfb478 },
  22415. { 0x073eede6,0x08f8e73b,0x16cbc12a,0x1215a856,0x0da2fa53,0x1bdfaa98,
  22416. 0x1ce9799b,0x16811be8,0x00d9a140 } },
  22417. /* 219 */
  22418. { { 0x0e8ea498,0x10110dab,0x18fb8243,0x08f0526a,0x12ade623,0x01c899ae,
  22419. 0x0c6b81ae,0x11ac47e9,0x00760c05 },
  22420. { 0x0198aa79,0x1c4dac66,0x1eae9fc2,0x1121a5e0,0x0556af74,0x00887ef1,
  22421. 0x10253881,0x05b1e320,0x00714198 } },
  22422. /* 220 */
  22423. { { 0x0d4b0f45,0x1850719a,0x0aa5385b,0x10167072,0x01d5ed92,0x126359e3,
  22424. 0x191cebcc,0x19d13aa9,0x003af9d1 },
  22425. { 0x00930371,0x0c7bcc09,0x105c25ff,0x04cc9843,0x0309beda,0x02ee6e21,
  22426. 0x17583a55,0x186e72af,0x00b1f815 } },
  22427. /* 221 */
  22428. { { 0x09fec44a,0x07d53c74,0x0a932be1,0x055c8e79,0x0a624c8c,0x003ee0db,
  22429. 0x0149a472,0x0282a87e,0x00a41aed },
  22430. { 0x1d5ffe04,0x121a9ccb,0x16db8810,0x1965bec4,0x177758ba,0x105f43c0,
  22431. 0x03be1759,0x1bb0df6c,0x00d6e9c1 } },
  22432. /* 222 */
  22433. { { 0x06853264,0x15174bf6,0x0c1282ce,0x0a676fc4,0x0e9be771,0x15dbdc75,
  22434. 0x03086e44,0x0215d37f,0x009c9c6e },
  22435. { 0x0030b74c,0x1184d2cf,0x18c7a428,0x0e929ad4,0x179f24ed,0x0591d24d,
  22436. 0x06da27d1,0x12c81f4c,0x00566bd5 } },
  22437. /* 223 */
  22438. { { 0x018061f3,0x136008c6,0x00ff1c01,0x164ba6f9,0x13245190,0x04701393,
  22439. 0x117bc17f,0x121ea4a6,0x00cf2c73 },
  22440. { 0x10eb30cf,0x04de75a0,0x1ddc0ea8,0x05d7741a,0x1f255cfd,0x021d0a87,
  22441. 0x05e7a10b,0x0ab15441,0x0002f517 } },
  22442. /* 224 */
  22443. { { 0x0ddb7d07,0x0b77bca5,0x1155400e,0x1f8e8448,0x0a3ce0b4,0x075663c5,
  22444. 0x05f7ebfe,0x14bd1a9b,0x0014e9ad },
  22445. { 0x0f7079e2,0x15240509,0x0c2003b6,0x15479bc9,0x0157d45b,0x0f16bc1c,
  22446. 0x0ba005d9,0x1571d3b3,0x00a0ad4f } },
  22447. /* 225 */
  22448. { { 0x0a653618,0x1fdbb10a,0x1aaa97c2,0x05027863,0x09d5e187,0x139ba24a,
  22449. 0x1478554f,0x170dcadd,0x00bcd530 },
  22450. { 0x12e9c47b,0x14df4299,0x00166ac5,0x0eedfd6a,0x1fbb4dc2,0x0bb08c95,
  22451. 0x107736ea,0x19ed2f26,0x00909283 } },
  22452. /* 226 */
  22453. { { 0x16e81a13,0x1d801923,0x05c48e59,0x1c3532c4,0x019d69be,0x1b0de997,
  22454. 0x126823b4,0x19359c2a,0x0035eeb7 },
  22455. { 0x1e4e5bdc,0x140572d3,0x13bb1b84,0x1a59a76d,0x06bc12dc,0x11263713,
  22456. 0x01914b90,0x1e88915d,0x009a8b2c } },
  22457. /* 227 */
  22458. { { 0x09d03b59,0x1238df90,0x16bcaafd,0x1cc5476c,0x1eec9c90,0x18b475ea,
  22459. 0x0de7fdff,0x1e9a8922,0x006bdb60 },
  22460. { 0x0a55bc30,0x16d7f5e4,0x025ff836,0x1d5a2c20,0x03bddc79,0x0ba0a60f,
  22461. 0x02a50b86,0x1fb29741,0x0001ec3c } },
  22462. /* 228 */
  22463. { { 0x1c9485c2,0x1313bf5e,0x1ec431ee,0x1934f245,0x08d8a48c,0x0b07b851,
  22464. 0x13d93d87,0x1808ea8c,0x00d1acb1 },
  22465. { 0x06f36612,0x13481589,0x186362f4,0x07489dc0,0x157ee59c,0x14099841,
  22466. 0x1b0937e2,0x13a80ac4,0x007dcd07 } },
  22467. /* 229 */
  22468. { { 0x105a4b48,0x073ea69f,0x08c1dc97,0x1a52a46e,0x0915aadc,0x1cb8c095,
  22469. 0x06e3463d,0x1126efa3,0x000bf535 },
  22470. { 0x0c68ea73,0x0f66cad3,0x0e96134d,0x07779504,0x1a723c7f,0x1a637a39,
  22471. 0x1bf27ed9,0x1b3c2cd0,0x00d28be4 } },
  22472. /* 230 */
  22473. { { 0x18fa8e4b,0x095cc831,0x0ff63f17,0x1e30dd12,0x1b6fc559,0x115521b7,
  22474. 0x0338e9b7,0x154a21f1,0x00d76007 },
  22475. { 0x123a4988,0x088555b2,0x17409ccb,0x0b9e88e9,0x07278b45,0x184151a0,
  22476. 0x0c05fd19,0x0d166077,0x00f2b52f } },
  22477. /* 231 */
  22478. { { 0x1835b4ca,0x0abf57d4,0x19a72f03,0x0465f976,0x031982d2,0x1b406332,
  22479. 0x14ea3bba,0x11d98b5d,0x00d8dbe9 },
  22480. { 0x05a02709,0x1d4df1fe,0x0e87ea32,0x1cd1cbeb,0x0a85230b,0x01e6f887,
  22481. 0x1c17faf5,0x147dcab2,0x00e01593 } },
  22482. /* 232 */
  22483. { { 0x0a75a0a6,0x1f2d7a87,0x01600cf4,0x044d58af,0x16406512,0x0a87e80b,
  22484. 0x1c19bf9b,0x1635d71d,0x00afec07 },
  22485. { 0x00bb0a31,0x1dccab3c,0x0c26ab9f,0x15e7986e,0x1f3896f1,0x10ad00d5,
  22486. 0x1f76454e,0x0a8dc5b7,0x00a71b93 } },
  22487. /* 233 */
  22488. { { 0x18f593d2,0x1c709700,0x1e048aef,0x12085140,0x0f2add1a,0x02ed85d2,
  22489. 0x0f645414,0x0b8c50a4,0x0053a200 },
  22490. { 0x07f2b935,0x1e45b1cf,0x00a58681,0x1f2eb583,0x0ca2c2bf,0x1753ba8c,
  22491. 0x18f61af3,0x1367ab11,0x00bf47d1 } },
  22492. /* 234 */
  22493. { { 0x1d7665d5,0x194b3d3e,0x0bd37959,0x0060ae5e,0x0903f4e3,0x02d7406a,
  22494. 0x06d85100,0x0fe73934,0x00001c2c },
  22495. { 0x09efc6d6,0x01d400a3,0x11e9c905,0x017b54f7,0x150a4c81,0x1385d3c0,
  22496. 0x066d7d95,0x1cf0dff7,0x00fdadf8 } },
  22497. /* 235 */
  22498. { { 0x1fc00785,0x09c65c47,0x123ad9ff,0x14eb2276,0x08fbc77f,0x082adf9b,
  22499. 0x12501153,0x09ab5487,0x003a838e },
  22500. { 0x1e97bb9a,0x10b31949,0x07653655,0x1266c688,0x12a839eb,0x08d3056d,
  22501. 0x168d4556,0x0af0e7c3,0x003cdb82 } },
  22502. /* 236 */
  22503. { { 0x1de77eab,0x1b8a054b,0x19204244,0x038a1a82,0x1d0dff7e,0x05696758,
  22504. 0x1ee9d8b7,0x113e3eaf,0x005a60cc },
  22505. { 0x00d45673,0x059b1c12,0x04f19560,0x057c32b2,0x0b7411b8,0x025c6eb2,
  22506. 0x1f0015ca,0x0dfb7fb1,0x00922ff5 } },
  22507. /* 237 */
  22508. { { 0x09a129a1,0x1932ef76,0x0a138106,0x039caf98,0x1be3ca5b,0x0623675f,
  22509. 0x158810e0,0x0fbed8b9,0x0072919a },
  22510. { 0x0fb90f9a,0x0c7a29d4,0x1900c6ca,0x13801711,0x11856d71,0x073bbcb7,
  22511. 0x026b8cb0,0x1006c481,0x005e7917 } },
  22512. /* 238 */
  22513. { { 0x1f63cdfb,0x00b762ab,0x12b93f57,0x146ae3e3,0x197ca8e6,0x15f52b02,
  22514. 0x1eaff389,0x0e3c4985,0x004e0a53 },
  22515. { 0x05765357,0x1b52069d,0x1ce8ad09,0x135e881a,0x11a323c8,0x185720e8,
  22516. 0x13bae3cd,0x031aacc0,0x00f5ff78 } },
  22517. /* 239 */
  22518. { { 0x1a09df21,0x1f9f1ff0,0x1ba391fe,0x0ba51dcc,0x0901526d,0x1e8514e4,
  22519. 0x1990825a,0x1d2a67eb,0x00e41df0 },
  22520. { 0x13ba9e3f,0x02fed205,0x0136254c,0x0819d64c,0x167c7f23,0x10c93f81,
  22521. 0x157c219b,0x0dd589e2,0x008edd7d } },
  22522. /* 240 */
  22523. { { 0x0bfc8ff3,0x0d0ee070,0x0dbd0bf2,0x1fb057d2,0x181ef14e,0x17be6651,
  22524. 0x1a599c05,0x195db15d,0x001432c1 },
  22525. { 0x10b23c26,0x0342414b,0x0d6c9cfb,0x1fd0e60e,0x10f5aa64,0x1b72f577,
  22526. 0x0b1b8e27,0x016b591a,0x00caef48 } },
  22527. /* 241 */
  22528. { { 0x15315922,0x122e4bc3,0x18f32954,0x12a2e260,0x0f2cbd82,0x10685b27,
  22529. 0x08dbcf39,0x0fd1df5c,0x00d0ba17 },
  22530. { 0x11b3af60,0x1d4d747d,0x0b688394,0x12d5ca7a,0x0ef281a7,0x1b02efcf,
  22531. 0x18580758,0x0f838a95,0x00f31c95 } },
  22532. /* 242 */
  22533. { { 0x09cc4597,0x07ac6a92,0x18280a30,0x002b6175,0x0814adc5,0x1e2ab9a5,
  22534. 0x10ebbf17,0x1972dc2f,0x00013404 },
  22535. { 0x09a824bf,0x14f12c2e,0x07abb5ec,0x0630bc00,0x168acd59,0x134130f7,
  22536. 0x19b235bb,0x09723267,0x006f377c } },
  22537. /* 243 */
  22538. { { 0x08333fd2,0x1c9dd68d,0x0aa56e27,0x060404b4,0x15acea89,0x081bf57b,
  22539. 0x14188479,0x09da5a12,0x006dba3e },
  22540. { 0x104399cd,0x0477cc66,0x0dceb7a9,0x038cddcd,0x0caf3181,0x03a960bf,
  22541. 0x129dcbd8,0x08477d9e,0x00f13cf3 } },
  22542. /* 244 */
  22543. { { 0x0919e2eb,0x175cf605,0x0b03da33,0x13432bec,0x0229983a,0x1ddb3d5d,
  22544. 0x0b4f3ee8,0x1524e977,0x00c83fa9 },
  22545. { 0x02fa1ce0,0x0be8d85b,0x063befc3,0x16c1ea68,0x06f04e58,0x17cf2938,
  22546. 0x1a0efea3,0x1e8bae04,0x00b49d70 } },
  22547. /* 245 */
  22548. { { 0x1ad5513b,0x0a63a887,0x1d478b64,0x065dd962,0x19d5905f,0x020c6cfd,
  22549. 0x073db614,0x1761861e,0x0059cfad },
  22550. { 0x15cb7fd6,0x0b3d611a,0x0109a8f8,0x06cf7104,0x18864249,0x02c64853,
  22551. 0x0d9fabbb,0x0c46a949,0x005babf3 } },
  22552. /* 246 */
  22553. { { 0x0e424865,0x1e4c0e8f,0x1955dfcd,0x0050f1e5,0x0c0588b0,0x1878dcf0,
  22554. 0x03c1c0a5,0x14f204d9,0x006188c6 },
  22555. { 0x10f244da,0x17cd0cde,0x02021cc1,0x19dab9f6,0x136371ec,0x07cdcf90,
  22556. 0x0764d51c,0x0ebbea17,0x00993fe4 } },
  22557. /* 247 */
  22558. { { 0x1b2c3609,0x0718e6fc,0x11b53a9a,0x16338058,0x1510184e,0x160d4d3b,
  22559. 0x05adeb27,0x0cc9900c,0x0081f764 },
  22560. { 0x15fbe978,0x0be152d3,0x00ecd587,0x07fda7e3,0x1d2bf674,0x0f82280e,
  22561. 0x18360e34,0x054bfd20,0x00564a81 } },
  22562. /* 248 */
  22563. { { 0x1a817d1d,0x12d327a7,0x0a0b83de,0x12d0897d,0x1f9aa55f,0x0d07e6ab,
  22564. 0x15b2d7fd,0x19e01ca3,0x00226bf3 },
  22565. { 0x0f2833cf,0x168d4fc9,0x13e26a35,0x0146b49e,0x17f7720a,0x1624c79f,
  22566. 0x00d8454d,0x08ffe4af,0x0068779f } },
  22567. /* 249 */
  22568. { { 0x13043d08,0x0d860e0b,0x10083e9e,0x08cee83f,0x126d0a54,0x1f144d36,
  22569. 0x182f4dd9,0x1a3d6125,0x0097bcb0 },
  22570. { 0x132ed3c3,0x15b75547,0x006f120a,0x09e2a365,0x178f3c8a,0x1a79dfd0,
  22571. 0x1955346f,0x1d014f08,0x00a872ff } },
  22572. /* 250 */
  22573. { { 0x032b2086,0x0d5bc9ad,0x183d21ac,0x16e21d02,0x0e6bee1e,0x06c89db5,
  22574. 0x0daa6f43,0x1f96e654,0x0002812b },
  22575. { 0x0f605318,0x11febe56,0x1f5b4769,0x1cbaa1fb,0x0d619646,0x01cc1081,
  22576. 0x1abe875a,0x193fca72,0x0007391c } },
  22577. /* 251 */
  22578. { { 0x0b80d02b,0x080abf84,0x01dfdff1,0x0667a2c5,0x142ae6b8,0x0d7c3c6a,
  22579. 0x0821eb28,0x1b8fcda5,0x00355d2a },
  22580. { 0x087386e1,0x00f99ad1,0x190c9d6d,0x0e5529f1,0x189eafd2,0x1166f3cc,
  22581. 0x09e4a1b2,0x1c6f8547,0x003dc2b1 } },
  22582. /* 252 */
  22583. { { 0x04581352,0x144e90e0,0x19e0afb5,0x01904a6e,0x1701f0a0,0x0ac84ff6,
  22584. 0x11ac80ef,0x020799b0,0x00c47869 },
  22585. { 0x04c768ed,0x0dd3b841,0x107d95d7,0x1dd404d0,0x0ce0e72f,0x1f6ab566,
  22586. 0x14c9ccc4,0x0d1ab769,0x00ccc429 } },
  22587. /* 253 */
  22588. { { 0x1d7620b9,0x07286f09,0x04a95aa5,0x14b914b3,0x087c9d89,0x1b2033aa,
  22589. 0x073f7001,0x0855490e,0x00e147eb },
  22590. { 0x0cf3ae46,0x1a55a775,0x0d43ef89,0x126df6a0,0x040eafd4,0x1f23a464,
  22591. 0x1b8f7cab,0x08e101d2,0x00239ac0 } },
  22592. /* 254 */
  22593. { { 0x0bfee8d4,0x00e8f9a9,0x1ec3fb12,0x016b9ff4,0x1af3cce8,0x064f1674,
  22594. 0x16744171,0x147ebefc,0x00c55fa1 },
  22595. { 0x0257c227,0x0c378a74,0x0af802cc,0x02ca7e68,0x04fb2c5b,0x04cc5548,
  22596. 0x1a6426bf,0x139a9e96,0x00094cd9 } },
  22597. /* 255 */
  22598. { { 0x1703beba,0x14c0e426,0x13aca462,0x03a2a065,0x149ec863,0x1964f1de,
  22599. 0x14ce9117,0x16c85575,0x00b90a30 },
  22600. { 0x14a5abf9,0x032a027d,0x16dd80ed,0x0ea186eb,0x1d89f004,0x0166651a,
  22601. 0x13ddbe69,0x13436f24,0x00019f8b } },
  22602. };
  22603. /* Multiply the base point of P256 by the scalar and return the result.
  22604. * If map is true then convert result to affine coordinates.
  22605. *
  22606. * Stripe implementation.
  22607. * Pre-generated: 2^0, 2^32, ...
  22608. * Pre-generated: products of all combinations of above.
  22609. * 8 doubles and adds (with qz=1)
  22610. *
  22611. * r Resulting point.
  22612. * k Scalar to multiply by.
  22613. * map Indicates whether to convert result to affine.
  22614. * ct Constant time required.
  22615. * heap Heap to use for allocation.
  22616. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  22617. */
  22618. static int sp_256_ecc_mulmod_base_9(sp_point_256* r, const sp_digit* k,
  22619. int map, int ct, void* heap)
  22620. {
  22621. return sp_256_ecc_mulmod_stripe_9(r, &p256_base, p256_table,
  22622. k, map, ct, heap);
  22623. }
  22624. #endif
  22625. /* Multiply the base point of P256 by the scalar and return the result.
  22626. * If map is true then convert result to affine coordinates.
  22627. *
  22628. * km Scalar to multiply by.
  22629. * r Resulting point.
  22630. * map Indicates whether to convert result to affine.
  22631. * heap Heap to use for allocation.
  22632. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  22633. */
  22634. int sp_ecc_mulmod_base_256(const mp_int* km, ecc_point* r, int map, void* heap)
  22635. {
  22636. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  22637. sp_point_256* point = NULL;
  22638. sp_digit* k = NULL;
  22639. #else
  22640. sp_point_256 point[1];
  22641. sp_digit k[9];
  22642. #endif
  22643. int err = MP_OKAY;
  22644. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  22645. point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap,
  22646. DYNAMIC_TYPE_ECC);
  22647. if (point == NULL)
  22648. err = MEMORY_E;
  22649. if (err == MP_OKAY) {
  22650. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9, heap,
  22651. DYNAMIC_TYPE_ECC);
  22652. if (k == NULL)
  22653. err = MEMORY_E;
  22654. }
  22655. #endif
  22656. if (err == MP_OKAY) {
  22657. sp_256_from_mp(k, 9, km);
  22658. err = sp_256_ecc_mulmod_base_9(point, k, map, 1, heap);
  22659. }
  22660. if (err == MP_OKAY) {
  22661. err = sp_256_point_to_ecc_point_9(point, r);
  22662. }
  22663. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  22664. if (k != NULL)
  22665. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  22666. if (point != NULL)
  22667. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  22668. #endif
  22669. return err;
  22670. }
  22671. /* Multiply the base point of P256 by the scalar, add point a and return
  22672. * the result. If map is true then convert result to affine coordinates.
  22673. *
  22674. * km Scalar to multiply by.
  22675. * am Point to add to scalar mulitply result.
  22676. * inMont Point to add is in montgomery form.
  22677. * r Resulting point.
  22678. * map Indicates whether to convert result to affine.
  22679. * heap Heap to use for allocation.
  22680. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  22681. */
  22682. int sp_ecc_mulmod_base_add_256(const mp_int* km, const ecc_point* am,
  22683. int inMont, ecc_point* r, int map, void* heap)
  22684. {
  22685. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  22686. sp_point_256* point = NULL;
  22687. sp_digit* k = NULL;
  22688. #else
  22689. sp_point_256 point[2];
  22690. sp_digit k[9 + 9 * 2 * 6];
  22691. #endif
  22692. sp_point_256* addP = NULL;
  22693. sp_digit* tmp = NULL;
  22694. int err = MP_OKAY;
  22695. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  22696. point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap,
  22697. DYNAMIC_TYPE_ECC);
  22698. if (point == NULL)
  22699. err = MEMORY_E;
  22700. if (err == MP_OKAY) {
  22701. k = (sp_digit*)XMALLOC(
  22702. sizeof(sp_digit) * (9 + 9 * 2 * 6),
  22703. heap, DYNAMIC_TYPE_ECC);
  22704. if (k == NULL)
  22705. err = MEMORY_E;
  22706. }
  22707. #endif
  22708. if (err == MP_OKAY) {
  22709. addP = point + 1;
  22710. tmp = k + 9;
  22711. sp_256_from_mp(k, 9, km);
  22712. sp_256_point_from_ecc_point_9(addP, am);
  22713. }
  22714. if ((err == MP_OKAY) && (!inMont)) {
  22715. err = sp_256_mod_mul_norm_9(addP->x, addP->x, p256_mod);
  22716. }
  22717. if ((err == MP_OKAY) && (!inMont)) {
  22718. err = sp_256_mod_mul_norm_9(addP->y, addP->y, p256_mod);
  22719. }
  22720. if ((err == MP_OKAY) && (!inMont)) {
  22721. err = sp_256_mod_mul_norm_9(addP->z, addP->z, p256_mod);
  22722. }
  22723. if (err == MP_OKAY) {
  22724. err = sp_256_ecc_mulmod_base_9(point, k, 0, 0, heap);
  22725. }
  22726. if (err == MP_OKAY) {
  22727. sp_256_proj_point_add_9(point, point, addP, tmp);
  22728. if (map) {
  22729. sp_256_map_9(point, point, tmp);
  22730. }
  22731. err = sp_256_point_to_ecc_point_9(point, r);
  22732. }
  22733. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  22734. if (k != NULL)
  22735. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  22736. if (point)
  22737. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  22738. #endif
  22739. return err;
  22740. }
  22741. #if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
  22742. defined(HAVE_ECC_VERIFY)
  22743. #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
  22744. /* Add 1 to a. (a = a + 1)
  22745. *
  22746. * r A single precision integer.
  22747. * a A single precision integer.
  22748. */
  22749. SP_NOINLINE static void sp_256_add_one_9(sp_digit* a)
  22750. {
  22751. a[0]++;
  22752. sp_256_norm_9(a);
  22753. }
  22754. /* Read big endian unsigned byte array into r.
  22755. *
  22756. * r A single precision integer.
  22757. * size Maximum number of bytes to convert
  22758. * a Byte array.
  22759. * n Number of bytes in array to read.
  22760. */
  22761. static void sp_256_from_bin(sp_digit* r, int size, const byte* a, int n)
  22762. {
  22763. int i;
  22764. int j = 0;
  22765. word32 s = 0;
  22766. r[0] = 0;
  22767. for (i = n-1; i >= 0; i--) {
  22768. r[j] |= (((sp_digit)a[i]) << s);
  22769. if (s >= 21U) {
  22770. r[j] &= 0x1fffffff;
  22771. s = 29U - s;
  22772. if (j + 1 >= size) {
  22773. break;
  22774. }
  22775. r[++j] = (sp_digit)a[i] >> s;
  22776. s = 8U - s;
  22777. }
  22778. else {
  22779. s += 8U;
  22780. }
  22781. }
  22782. for (j++; j < size; j++) {
  22783. r[j] = 0;
  22784. }
  22785. }
  22786. /* Generates a scalar that is in the range 1..order-1.
  22787. *
  22788. * rng Random number generator.
  22789. * k Scalar value.
  22790. * returns RNG failures, MEMORY_E when memory allocation fails and
  22791. * MP_OKAY on success.
  22792. */
  22793. static int sp_256_ecc_gen_k_9(WC_RNG* rng, sp_digit* k)
  22794. {
  22795. int err;
  22796. byte buf[32];
  22797. do {
  22798. err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf));
  22799. if (err == 0) {
  22800. sp_256_from_bin(k, 9, buf, (int)sizeof(buf));
  22801. if (sp_256_cmp_9(k, p256_order2) <= 0) {
  22802. sp_256_add_one_9(k);
  22803. break;
  22804. }
  22805. }
  22806. }
  22807. while (err == 0);
  22808. return err;
  22809. }
  22810. /* Makes a random EC key pair.
  22811. *
  22812. * rng Random number generator.
  22813. * priv Generated private value.
  22814. * pub Generated public point.
  22815. * heap Heap to use for allocation.
  22816. * returns ECC_INF_E when the point does not have the correct order, RNG
  22817. * failures, MEMORY_E when memory allocation fails and MP_OKAY on success.
  22818. */
  22819. int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap)
  22820. {
  22821. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  22822. sp_point_256* point = NULL;
  22823. sp_digit* k = NULL;
  22824. #else
  22825. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  22826. sp_point_256 point[2];
  22827. #else
  22828. sp_point_256 point[1];
  22829. #endif
  22830. sp_digit k[9];
  22831. #endif
  22832. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  22833. sp_point_256* infinity = NULL;
  22834. #endif
  22835. int err = MP_OKAY;
  22836. (void)heap;
  22837. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  22838. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  22839. point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, DYNAMIC_TYPE_ECC);
  22840. #else
  22841. point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC);
  22842. #endif
  22843. if (point == NULL)
  22844. err = MEMORY_E;
  22845. if (err == MP_OKAY) {
  22846. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9, heap,
  22847. DYNAMIC_TYPE_ECC);
  22848. if (k == NULL)
  22849. err = MEMORY_E;
  22850. }
  22851. #endif
  22852. if (err == MP_OKAY) {
  22853. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  22854. infinity = point + 1;
  22855. #endif
  22856. err = sp_256_ecc_gen_k_9(rng, k);
  22857. }
  22858. if (err == MP_OKAY) {
  22859. err = sp_256_ecc_mulmod_base_9(point, k, 1, 1, NULL);
  22860. }
  22861. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  22862. if (err == MP_OKAY) {
  22863. err = sp_256_ecc_mulmod_9(infinity, point, p256_order, 1, 1, NULL);
  22864. }
  22865. if (err == MP_OKAY) {
  22866. if (sp_256_iszero_9(point->x) || sp_256_iszero_9(point->y)) {
  22867. err = ECC_INF_E;
  22868. }
  22869. }
  22870. #endif
  22871. if (err == MP_OKAY) {
  22872. err = sp_256_to_mp(k, priv);
  22873. }
  22874. if (err == MP_OKAY) {
  22875. err = sp_256_point_to_ecc_point_9(point, pub);
  22876. }
  22877. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  22878. if (k != NULL)
  22879. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  22880. if (point != NULL) {
  22881. /* point is not sensitive, so no need to zeroize */
  22882. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  22883. }
  22884. #endif
  22885. return err;
  22886. }
  22887. #ifdef HAVE_ECC_DHE
  22888. /* Write r as big endian to byte array.
  22889. * Fixed length number of bytes written: 32
  22890. *
  22891. * r A single precision integer.
  22892. * a Byte array.
  22893. */
  22894. static void sp_256_to_bin_9(sp_digit* r, byte* a)
  22895. {
  22896. int i;
  22897. int j;
  22898. int s = 0;
  22899. int b;
  22900. for (i=0; i<8; i++) {
  22901. r[i+1] += r[i] >> 29;
  22902. r[i] &= 0x1fffffff;
  22903. }
  22904. j = 263 / 8 - 1;
  22905. a[j] = 0;
  22906. for (i=0; i<9 && j>=0; i++) {
  22907. b = 0;
  22908. /* lint allow cast of mismatch sp_digit and int */
  22909. a[j--] |= (byte)(r[i] << s); /*lint !e9033*/
  22910. b += 8 - s;
  22911. if (j < 0) {
  22912. break;
  22913. }
  22914. while (b < 29) {
  22915. a[j--] = (byte)(r[i] >> b);
  22916. b += 8;
  22917. if (j < 0) {
  22918. break;
  22919. }
  22920. }
  22921. s = 8 - (b - 29);
  22922. if (j >= 0) {
  22923. a[j] = 0;
  22924. }
  22925. if (s != 0) {
  22926. j++;
  22927. }
  22928. }
  22929. }
  22930. /* Multiply the point by the scalar and serialize the X ordinate.
  22931. * The number is 0 padded to maximum size on output.
  22932. *
  22933. * priv Scalar to multiply the point by.
  22934. * pub Point to multiply.
  22935. * out Buffer to hold X ordinate.
  22936. * outLen On entry, size of the buffer in bytes.
  22937. * On exit, length of data in buffer in bytes.
  22938. * heap Heap to use for allocation.
  22939. * returns BUFFER_E if the buffer is to small for output size,
  22940. * MEMORY_E when memory allocation fails and MP_OKAY on success.
  22941. */
  22942. int sp_ecc_secret_gen_256(const mp_int* priv, const ecc_point* pub, byte* out,
  22943. word32* outLen, void* heap)
  22944. {
  22945. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  22946. sp_point_256* point = NULL;
  22947. sp_digit* k = NULL;
  22948. #else
  22949. sp_point_256 point[1];
  22950. sp_digit k[9];
  22951. #endif
  22952. int err = MP_OKAY;
  22953. if (*outLen < 32U) {
  22954. err = BUFFER_E;
  22955. }
  22956. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  22957. if (err == MP_OKAY) {
  22958. point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap,
  22959. DYNAMIC_TYPE_ECC);
  22960. if (point == NULL)
  22961. err = MEMORY_E;
  22962. }
  22963. if (err == MP_OKAY) {
  22964. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9, heap,
  22965. DYNAMIC_TYPE_ECC);
  22966. if (k == NULL)
  22967. err = MEMORY_E;
  22968. }
  22969. #endif
  22970. if (err == MP_OKAY) {
  22971. sp_256_from_mp(k, 9, priv);
  22972. sp_256_point_from_ecc_point_9(point, pub);
  22973. err = sp_256_ecc_mulmod_9(point, point, k, 1, 1, heap);
  22974. }
  22975. if (err == MP_OKAY) {
  22976. sp_256_to_bin_9(point->x, out);
  22977. *outLen = 32;
  22978. }
  22979. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  22980. if (k != NULL)
  22981. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  22982. if (point != NULL)
  22983. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  22984. #endif
  22985. return err;
  22986. }
  22987. #endif /* HAVE_ECC_DHE */
  22988. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  22989. #endif
  22990. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  22991. SP_NOINLINE static void sp_256_rshift_9(sp_digit* r, const sp_digit* a,
  22992. byte n)
  22993. {
  22994. int i;
  22995. #ifdef WOLFSSL_SP_SMALL
  22996. for (i=0; i<8; i++) {
  22997. r[i] = ((a[i] >> n) | (a[i + 1] << (29 - n))) & 0x1fffffff;
  22998. }
  22999. #else
  23000. for (i=0; i<8; i += 8) {
  23001. r[i+0] = (a[i+0] >> n) | ((a[i+1] << (29 - n)) & 0x1fffffff);
  23002. r[i+1] = (a[i+1] >> n) | ((a[i+2] << (29 - n)) & 0x1fffffff);
  23003. r[i+2] = (a[i+2] >> n) | ((a[i+3] << (29 - n)) & 0x1fffffff);
  23004. r[i+3] = (a[i+3] >> n) | ((a[i+4] << (29 - n)) & 0x1fffffff);
  23005. r[i+4] = (a[i+4] >> n) | ((a[i+5] << (29 - n)) & 0x1fffffff);
  23006. r[i+5] = (a[i+5] >> n) | ((a[i+6] << (29 - n)) & 0x1fffffff);
  23007. r[i+6] = (a[i+6] >> n) | ((a[i+7] << (29 - n)) & 0x1fffffff);
  23008. r[i+7] = (a[i+7] >> n) | ((a[i+8] << (29 - n)) & 0x1fffffff);
  23009. }
  23010. #endif /* WOLFSSL_SP_SMALL */
  23011. r[8] = a[8] >> n;
  23012. }
  23013. /* Multiply a by scalar b into r. (r = a * b)
  23014. *
  23015. * r A single precision integer.
  23016. * a A single precision integer.
  23017. * b A scalar.
  23018. */
  23019. SP_NOINLINE static void sp_256_mul_d_9(sp_digit* r, const sp_digit* a,
  23020. sp_digit b)
  23021. {
  23022. #ifdef WOLFSSL_SP_SMALL
  23023. sp_int64 tb = b;
  23024. sp_int64 t = 0;
  23025. int i;
  23026. for (i = 0; i < 9; i++) {
  23027. t += tb * a[i];
  23028. r[i] = (sp_digit)(t & 0x1fffffff);
  23029. t >>= 29;
  23030. }
  23031. r[9] = (sp_digit)t;
  23032. #else
  23033. sp_int64 tb = b;
  23034. sp_int64 t[9];
  23035. t[ 0] = tb * a[ 0];
  23036. t[ 1] = tb * a[ 1];
  23037. t[ 2] = tb * a[ 2];
  23038. t[ 3] = tb * a[ 3];
  23039. t[ 4] = tb * a[ 4];
  23040. t[ 5] = tb * a[ 5];
  23041. t[ 6] = tb * a[ 6];
  23042. t[ 7] = tb * a[ 7];
  23043. t[ 8] = tb * a[ 8];
  23044. r[ 0] = (sp_digit) (t[ 0] & 0x1fffffff);
  23045. r[ 1] = (sp_digit)((t[ 0] >> 29) + (t[ 1] & 0x1fffffff));
  23046. r[ 2] = (sp_digit)((t[ 1] >> 29) + (t[ 2] & 0x1fffffff));
  23047. r[ 3] = (sp_digit)((t[ 2] >> 29) + (t[ 3] & 0x1fffffff));
  23048. r[ 4] = (sp_digit)((t[ 3] >> 29) + (t[ 4] & 0x1fffffff));
  23049. r[ 5] = (sp_digit)((t[ 4] >> 29) + (t[ 5] & 0x1fffffff));
  23050. r[ 6] = (sp_digit)((t[ 5] >> 29) + (t[ 6] & 0x1fffffff));
  23051. r[ 7] = (sp_digit)((t[ 6] >> 29) + (t[ 7] & 0x1fffffff));
  23052. r[ 8] = (sp_digit)((t[ 7] >> 29) + (t[ 8] & 0x1fffffff));
  23053. r[ 9] = (sp_digit) (t[ 8] >> 29);
  23054. #endif /* WOLFSSL_SP_SMALL */
  23055. }
  23056. SP_NOINLINE static void sp_256_lshift_18(sp_digit* r, const sp_digit* a,
  23057. byte n)
  23058. {
  23059. #ifdef WOLFSSL_SP_SMALL
  23060. int i;
  23061. r[18] = a[17] >> (29 - n);
  23062. for (i=17; i>0; i--) {
  23063. r[i] = ((a[i] << n) | (a[i-1] >> (29 - n))) & 0x1fffffff;
  23064. }
  23065. #else
  23066. sp_int_digit s;
  23067. sp_int_digit t;
  23068. s = (sp_int_digit)a[17];
  23069. r[18] = s >> (29U - n);
  23070. s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]);
  23071. r[17] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  23072. s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]);
  23073. r[16] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  23074. s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]);
  23075. r[15] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  23076. s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]);
  23077. r[14] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  23078. s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]);
  23079. r[13] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  23080. s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]);
  23081. r[12] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  23082. s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]);
  23083. r[11] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  23084. s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]);
  23085. r[10] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  23086. s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]);
  23087. r[9] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  23088. s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]);
  23089. r[8] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  23090. s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]);
  23091. r[7] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  23092. s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]);
  23093. r[6] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  23094. s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]);
  23095. r[5] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  23096. s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]);
  23097. r[4] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  23098. s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]);
  23099. r[3] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  23100. s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]);
  23101. r[2] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  23102. s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]);
  23103. r[1] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
  23104. #endif /* WOLFSSL_SP_SMALL */
  23105. r[0] = (a[0] << n) & 0x1fffffff;
  23106. }
  23107. /* Divide d in a and put remainder into r (m*d + r = a)
  23108. * m is not calculated as it is not needed at this time.
  23109. *
  23110. * Simplified based on top word of divisor being (1 << 29) - 1
  23111. *
  23112. * a Number to be divided.
  23113. * d Number to divide with.
  23114. * m Multiplier result.
  23115. * r Remainder from the division.
  23116. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  23117. */
  23118. static int sp_256_div_9(const sp_digit* a, const sp_digit* d,
  23119. const sp_digit* m, sp_digit* r)
  23120. {
  23121. int i;
  23122. sp_digit r1;
  23123. sp_digit mask;
  23124. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  23125. sp_digit* t1 = NULL;
  23126. #else
  23127. sp_digit t1[4 * 9 + 3];
  23128. #endif
  23129. sp_digit* t2 = NULL;
  23130. sp_digit* sd = NULL;
  23131. int err = MP_OKAY;
  23132. (void)m;
  23133. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  23134. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 9 + 3), NULL,
  23135. DYNAMIC_TYPE_TMP_BUFFER);
  23136. if (t1 == NULL)
  23137. err = MEMORY_E;
  23138. #endif
  23139. (void)m;
  23140. if (err == MP_OKAY) {
  23141. t2 = t1 + 18 + 1;
  23142. sd = t2 + 9 + 1;
  23143. sp_256_mul_d_9(sd, d, (sp_digit)1 << 5);
  23144. sp_256_lshift_18(t1, a, 5);
  23145. t1[9 + 9] += t1[9 + 9 - 1] >> 29;
  23146. t1[9 + 9 - 1] &= 0x1fffffff;
  23147. for (i=8; i>=0; i--) {
  23148. r1 = t1[9 + i];
  23149. sp_256_mul_d_9(t2, sd, r1);
  23150. (void)sp_256_sub_9(&t1[i], &t1[i], t2);
  23151. t1[9 + i] -= t2[9];
  23152. sp_256_norm_9(&t1[i + 1]);
  23153. mask = ~((t1[9 + i] - 1) >> 31);
  23154. sp_256_cond_sub_9(t1 + i, t1 + i, sd, mask);
  23155. sp_256_norm_9(&t1[i + 1]);
  23156. }
  23157. sp_256_norm_9(t1);
  23158. sp_256_rshift_9(r, t1, 5);
  23159. }
  23160. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  23161. if (t1 != NULL)
  23162. XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  23163. #endif
  23164. return err;
  23165. }
  23166. /* Reduce a modulo m into r. (r = a mod m)
  23167. *
  23168. * r A single precision number that is the reduced result.
  23169. * a A single precision number that is to be reduced.
  23170. * m A single precision number that is the modulus to reduce with.
  23171. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  23172. */
  23173. static int sp_256_mod_9(sp_digit* r, const sp_digit* a, const sp_digit* m)
  23174. {
  23175. return sp_256_div_9(a, m, NULL, r);
  23176. }
  23177. #endif
  23178. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  23179. /* Multiply two number mod the order of P256 curve. (r = a * b mod order)
  23180. *
  23181. * r Result of the multiplication.
  23182. * a First operand of the multiplication.
  23183. * b Second operand of the multiplication.
  23184. */
  23185. static void sp_256_mont_mul_order_9(sp_digit* r, const sp_digit* a, const sp_digit* b)
  23186. {
  23187. sp_256_mul_9(r, a, b);
  23188. sp_256_mont_reduce_order_9(r, p256_order, p256_mp_order);
  23189. }
  23190. #if defined(HAVE_ECC_SIGN) || (defined(HAVE_ECC_VERIFY) && defined(WOLFSSL_SP_SMALL))
  23191. #ifdef WOLFSSL_SP_SMALL
  23192. /* Order-2 for the P256 curve. */
  23193. static const uint32_t p256_order_minus_2[8] = {
  23194. 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU,0xffffffffU,0xffffffffU,
  23195. 0x00000000U,0xffffffffU
  23196. };
  23197. #else
  23198. /* The low half of the order-2 of the P256 curve. */
  23199. static const sp_int_digit p256_order_low[4] = {
  23200. 0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU
  23201. };
  23202. #endif /* WOLFSSL_SP_SMALL */
  23203. /* Square number mod the order of P256 curve. (r = a * a mod order)
  23204. *
  23205. * r Result of the squaring.
  23206. * a Number to square.
  23207. */
  23208. static void sp_256_mont_sqr_order_9(sp_digit* r, const sp_digit* a)
  23209. {
  23210. sp_256_sqr_9(r, a);
  23211. sp_256_mont_reduce_order_9(r, p256_order, p256_mp_order);
  23212. }
  23213. #ifndef WOLFSSL_SP_SMALL
  23214. /* Square number mod the order of P256 curve a number of times.
  23215. * (r = a ^ n mod order)
  23216. *
  23217. * r Result of the squaring.
  23218. * a Number to square.
  23219. */
  23220. static void sp_256_mont_sqr_n_order_9(sp_digit* r, const sp_digit* a, int n)
  23221. {
  23222. int i;
  23223. sp_256_mont_sqr_order_9(r, a);
  23224. for (i=1; i<n; i++) {
  23225. sp_256_mont_sqr_order_9(r, r);
  23226. }
  23227. }
  23228. #endif /* !WOLFSSL_SP_SMALL */
  23229. /* Invert the number, in Montgomery form, modulo the order of the P256 curve.
  23230. * (r = 1 / a mod order)
  23231. *
  23232. * r Inverse result.
  23233. * a Number to invert.
  23234. * td Temporary data.
  23235. */
  23236. #ifdef WOLFSSL_SP_NONBLOCK
  23237. typedef struct sp_256_mont_inv_order_9_ctx {
  23238. int state;
  23239. int i;
  23240. } sp_256_mont_inv_order_9_ctx;
  23241. static int sp_256_mont_inv_order_9_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a,
  23242. sp_digit* t)
  23243. {
  23244. int err = FP_WOULDBLOCK;
  23245. sp_256_mont_inv_order_9_ctx* ctx = (sp_256_mont_inv_order_9_ctx*)sp_ctx;
  23246. typedef char ctx_size_test[sizeof(sp_256_mont_inv_order_9_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  23247. (void)sizeof(ctx_size_test);
  23248. switch (ctx->state) {
  23249. case 0:
  23250. XMEMCPY(t, a, sizeof(sp_digit) * 9);
  23251. ctx->i = 254;
  23252. ctx->state = 1;
  23253. break;
  23254. case 1:
  23255. sp_256_mont_sqr_order_9(t, t);
  23256. ctx->state = 2;
  23257. break;
  23258. case 2:
  23259. if ((p256_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) {
  23260. sp_256_mont_mul_order_9(t, t, a);
  23261. }
  23262. ctx->i--;
  23263. ctx->state = (ctx->i == 0) ? 3 : 1;
  23264. break;
  23265. case 3:
  23266. XMEMCPY(r, t, sizeof(sp_digit) * 9U);
  23267. err = MP_OKAY;
  23268. break;
  23269. }
  23270. return err;
  23271. }
  23272. #endif /* WOLFSSL_SP_NONBLOCK */
  23273. static void sp_256_mont_inv_order_9(sp_digit* r, const sp_digit* a,
  23274. sp_digit* td)
  23275. {
  23276. #ifdef WOLFSSL_SP_SMALL
  23277. sp_digit* t = td;
  23278. int i;
  23279. XMEMCPY(t, a, sizeof(sp_digit) * 9);
  23280. for (i=254; i>=0; i--) {
  23281. sp_256_mont_sqr_order_9(t, t);
  23282. if ((p256_order_minus_2[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
  23283. sp_256_mont_mul_order_9(t, t, a);
  23284. }
  23285. }
  23286. XMEMCPY(r, t, sizeof(sp_digit) * 9U);
  23287. #else
  23288. sp_digit* t = td;
  23289. sp_digit* t2 = td + 2 * 9;
  23290. sp_digit* t3 = td + 4 * 9;
  23291. int i;
  23292. /* t = a^2 */
  23293. sp_256_mont_sqr_order_9(t, a);
  23294. /* t = a^3 = t * a */
  23295. sp_256_mont_mul_order_9(t, t, a);
  23296. /* t2= a^c = t ^ 2 ^ 2 */
  23297. sp_256_mont_sqr_n_order_9(t2, t, 2);
  23298. /* t3= a^f = t2 * t */
  23299. sp_256_mont_mul_order_9(t3, t2, t);
  23300. /* t2= a^f0 = t3 ^ 2 ^ 4 */
  23301. sp_256_mont_sqr_n_order_9(t2, t3, 4);
  23302. /* t = a^ff = t2 * t3 */
  23303. sp_256_mont_mul_order_9(t, t2, t3);
  23304. /* t3= a^ff00 = t ^ 2 ^ 8 */
  23305. sp_256_mont_sqr_n_order_9(t2, t, 8);
  23306. /* t = a^ffff = t2 * t */
  23307. sp_256_mont_mul_order_9(t, t2, t);
  23308. /* t2= a^ffff0000 = t ^ 2 ^ 16 */
  23309. sp_256_mont_sqr_n_order_9(t2, t, 16);
  23310. /* t = a^ffffffff = t2 * t */
  23311. sp_256_mont_mul_order_9(t, t2, t);
  23312. /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */
  23313. sp_256_mont_sqr_n_order_9(t2, t, 64);
  23314. /* t2= a^ffffffff00000000ffffffff = t2 * t */
  23315. sp_256_mont_mul_order_9(t2, t2, t);
  23316. /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */
  23317. sp_256_mont_sqr_n_order_9(t2, t2, 32);
  23318. /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */
  23319. sp_256_mont_mul_order_9(t2, t2, t);
  23320. /* t2= a^ffffffff00000000ffffffffffffffffbce6 */
  23321. for (i=127; i>=112; i--) {
  23322. sp_256_mont_sqr_order_9(t2, t2);
  23323. if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
  23324. sp_256_mont_mul_order_9(t2, t2, a);
  23325. }
  23326. }
  23327. /* t2= a^ffffffff00000000ffffffffffffffffbce6f */
  23328. sp_256_mont_sqr_n_order_9(t2, t2, 4);
  23329. sp_256_mont_mul_order_9(t2, t2, t3);
  23330. /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */
  23331. for (i=107; i>=64; i--) {
  23332. sp_256_mont_sqr_order_9(t2, t2);
  23333. if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
  23334. sp_256_mont_mul_order_9(t2, t2, a);
  23335. }
  23336. }
  23337. /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */
  23338. sp_256_mont_sqr_n_order_9(t2, t2, 4);
  23339. sp_256_mont_mul_order_9(t2, t2, t3);
  23340. /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */
  23341. for (i=59; i>=32; i--) {
  23342. sp_256_mont_sqr_order_9(t2, t2);
  23343. if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
  23344. sp_256_mont_mul_order_9(t2, t2, a);
  23345. }
  23346. }
  23347. /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */
  23348. sp_256_mont_sqr_n_order_9(t2, t2, 4);
  23349. sp_256_mont_mul_order_9(t2, t2, t3);
  23350. /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */
  23351. for (i=27; i>=0; i--) {
  23352. sp_256_mont_sqr_order_9(t2, t2);
  23353. if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
  23354. sp_256_mont_mul_order_9(t2, t2, a);
  23355. }
  23356. }
  23357. /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */
  23358. sp_256_mont_sqr_n_order_9(t2, t2, 4);
  23359. /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */
  23360. sp_256_mont_mul_order_9(r, t2, t3);
  23361. #endif /* WOLFSSL_SP_SMALL */
  23362. }
  23363. #endif /* HAVE_ECC_SIGN || (HAVE_ECC_VERIFY && WOLFSSL_SP_SMALL) */
  23364. #endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
  23365. #ifdef HAVE_ECC_SIGN
  23366. #ifndef SP_ECC_MAX_SIG_GEN
  23367. #define SP_ECC_MAX_SIG_GEN 64
  23368. #endif
  23369. /* Calculate second signature value S from R, k and private value.
  23370. *
  23371. * s = (r * x + e) / k
  23372. *
  23373. * s Signature value.
  23374. * r First signature value.
  23375. * k Ephemeral private key.
  23376. * x Private key as a number.
  23377. * e Hash of message as a number.
  23378. * tmp Temporary storage for intermediate numbers.
  23379. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  23380. */
  23381. static int sp_256_calc_s_9(sp_digit* s, const sp_digit* r, sp_digit* k,
  23382. sp_digit* x, const sp_digit* e, sp_digit* tmp)
  23383. {
  23384. int err;
  23385. sp_digit carry;
  23386. sp_int32 c;
  23387. sp_digit* kInv = k;
  23388. /* Conv k to Montgomery form (mod order) */
  23389. sp_256_mul_9(k, k, p256_norm_order);
  23390. err = sp_256_mod_9(k, k, p256_order);
  23391. if (err == MP_OKAY) {
  23392. sp_256_norm_9(k);
  23393. /* kInv = 1/k mod order */
  23394. sp_256_mont_inv_order_9(kInv, k, tmp);
  23395. sp_256_norm_9(kInv);
  23396. /* s = r * x + e */
  23397. sp_256_mul_9(x, x, r);
  23398. err = sp_256_mod_9(x, x, p256_order);
  23399. }
  23400. if (err == MP_OKAY) {
  23401. sp_256_norm_9(x);
  23402. carry = sp_256_add_9(s, e, x);
  23403. sp_256_cond_sub_9(s, s, p256_order, 0 - carry);
  23404. sp_256_norm_9(s);
  23405. c = sp_256_cmp_9(s, p256_order);
  23406. sp_256_cond_sub_9(s, s, p256_order,
  23407. (sp_digit)0 - (sp_digit)(c >= 0));
  23408. sp_256_norm_9(s);
  23409. /* s = s * k^-1 mod order */
  23410. sp_256_mont_mul_order_9(s, s, kInv);
  23411. sp_256_norm_9(s);
  23412. }
  23413. return err;
  23414. }
  23415. /* Sign the hash using the private key.
  23416. * e = [hash, 256 bits] from binary
  23417. * r = (k.G)->x mod order
  23418. * s = (r * x + e) / k mod order
  23419. * The hash is truncated to the first 256 bits.
  23420. *
  23421. * hash Hash to sign.
  23422. * hashLen Length of the hash data.
  23423. * rng Random number generator.
  23424. * priv Private part of key - scalar.
  23425. * rm First part of result as an mp_int.
  23426. * sm Sirst part of result as an mp_int.
  23427. * heap Heap to use for allocation.
  23428. * returns RNG failures, MEMORY_E when memory allocation fails and
  23429. * MP_OKAY on success.
  23430. */
  23431. #ifdef WOLFSSL_SP_NONBLOCK
  23432. typedef struct sp_ecc_sign_256_ctx {
  23433. int state;
  23434. union {
  23435. sp_256_ecc_mulmod_9_ctx mulmod_ctx;
  23436. sp_256_mont_inv_order_9_ctx mont_inv_order_ctx;
  23437. };
  23438. sp_digit e[2*9];
  23439. sp_digit x[2*9];
  23440. sp_digit k[2*9];
  23441. sp_digit r[2*9];
  23442. sp_digit tmp[3 * 2*9];
  23443. sp_point_256 point;
  23444. sp_digit* s;
  23445. sp_digit* kInv;
  23446. int i;
  23447. } sp_ecc_sign_256_ctx;
  23448. int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng,
  23449. mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
  23450. {
  23451. int err = FP_WOULDBLOCK;
  23452. sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data;
  23453. typedef char ctx_size_test[sizeof(sp_ecc_sign_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  23454. (void)sizeof(ctx_size_test);
  23455. (void)heap;
  23456. switch (ctx->state) {
  23457. case 0: /* INIT */
  23458. ctx->s = ctx->e;
  23459. ctx->kInv = ctx->k;
  23460. ctx->i = SP_ECC_MAX_SIG_GEN;
  23461. ctx->state = 1;
  23462. break;
  23463. case 1: /* GEN */
  23464. /* New random point. */
  23465. if (km == NULL || mp_iszero(km)) {
  23466. err = sp_256_ecc_gen_k_9(rng, ctx->k);
  23467. }
  23468. else {
  23469. sp_256_from_mp(ctx->k, 9, km);
  23470. mp_zero(km);
  23471. }
  23472. XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
  23473. ctx->state = 2;
  23474. break;
  23475. case 2: /* MULMOD */
  23476. err = sp_256_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
  23477. &ctx->point, &p256_base, ctx->k, 1, 1, heap);
  23478. if (err == MP_OKAY) {
  23479. ctx->state = 3;
  23480. }
  23481. break;
  23482. case 3: /* MODORDER */
  23483. {
  23484. sp_int32 c;
  23485. /* r = point->x mod order */
  23486. XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 9U);
  23487. sp_256_norm_9(ctx->r);
  23488. c = sp_256_cmp_9(ctx->r, p256_order);
  23489. sp_256_cond_sub_9(ctx->r, ctx->r, p256_order,
  23490. (sp_digit)0 - (sp_digit)(c >= 0));
  23491. sp_256_norm_9(ctx->r);
  23492. if (hashLen > 32U) {
  23493. hashLen = 32U;
  23494. }
  23495. sp_256_from_mp(ctx->x, 9, priv);
  23496. sp_256_from_bin(ctx->e, 9, hash, (int)hashLen);
  23497. ctx->state = 4;
  23498. break;
  23499. }
  23500. case 4: /* KMODORDER */
  23501. /* Conv k to Montgomery form (mod order) */
  23502. sp_256_mul_9(ctx->k, ctx->k, p256_norm_order);
  23503. err = sp_256_mod_9(ctx->k, ctx->k, p256_order);
  23504. if (err == MP_OKAY) {
  23505. sp_256_norm_9(ctx->k);
  23506. XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
  23507. ctx->state = 5;
  23508. }
  23509. break;
  23510. case 5: /* KINV */
  23511. /* kInv = 1/k mod order */
  23512. err = sp_256_mont_inv_order_9_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp);
  23513. if (err == MP_OKAY) {
  23514. XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
  23515. ctx->state = 6;
  23516. }
  23517. break;
  23518. case 6: /* KINVNORM */
  23519. sp_256_norm_9(ctx->kInv);
  23520. ctx->state = 7;
  23521. break;
  23522. case 7: /* R */
  23523. /* s = r * x + e */
  23524. sp_256_mul_9(ctx->x, ctx->x, ctx->r);
  23525. ctx->state = 8;
  23526. break;
  23527. case 8: /* S1 */
  23528. err = sp_256_mod_9(ctx->x, ctx->x, p256_order);
  23529. if (err == MP_OKAY)
  23530. ctx->state = 9;
  23531. break;
  23532. case 9: /* S2 */
  23533. {
  23534. sp_digit carry;
  23535. sp_int32 c;
  23536. sp_256_norm_9(ctx->x);
  23537. carry = sp_256_add_9(ctx->s, ctx->e, ctx->x);
  23538. sp_256_cond_sub_9(ctx->s, ctx->s,
  23539. p256_order, 0 - carry);
  23540. sp_256_norm_9(ctx->s);
  23541. c = sp_256_cmp_9(ctx->s, p256_order);
  23542. sp_256_cond_sub_9(ctx->s, ctx->s, p256_order,
  23543. (sp_digit)0 - (sp_digit)(c >= 0));
  23544. sp_256_norm_9(ctx->s);
  23545. /* s = s * k^-1 mod order */
  23546. sp_256_mont_mul_order_9(ctx->s, ctx->s, ctx->kInv);
  23547. sp_256_norm_9(ctx->s);
  23548. /* Check that signature is usable. */
  23549. if (sp_256_iszero_9(ctx->s) == 0) {
  23550. ctx->state = 10;
  23551. break;
  23552. }
  23553. #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
  23554. ctx->i = 1;
  23555. #endif
  23556. /* not usable gen, try again */
  23557. ctx->i--;
  23558. if (ctx->i == 0) {
  23559. err = RNG_FAILURE_E;
  23560. }
  23561. ctx->state = 1;
  23562. break;
  23563. }
  23564. case 10: /* RES */
  23565. err = sp_256_to_mp(ctx->r, rm);
  23566. if (err == MP_OKAY) {
  23567. err = sp_256_to_mp(ctx->s, sm);
  23568. }
  23569. break;
  23570. }
  23571. if (err == MP_OKAY && ctx->state != 10) {
  23572. err = FP_WOULDBLOCK;
  23573. }
  23574. if (err != FP_WOULDBLOCK) {
  23575. XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 9U);
  23576. XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 9U);
  23577. XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 9U);
  23578. XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 9U);
  23579. XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 9U);
  23580. }
  23581. return err;
  23582. }
  23583. #endif /* WOLFSSL_SP_NONBLOCK */
  23584. int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng,
  23585. const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
  23586. {
  23587. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  23588. sp_digit* e = NULL;
  23589. sp_point_256* point = NULL;
  23590. #else
  23591. sp_digit e[7 * 2 * 9];
  23592. sp_point_256 point[1];
  23593. #endif
  23594. sp_digit* x = NULL;
  23595. sp_digit* k = NULL;
  23596. sp_digit* r = NULL;
  23597. sp_digit* tmp = NULL;
  23598. sp_digit* s = NULL;
  23599. sp_int32 c;
  23600. int err = MP_OKAY;
  23601. int i;
  23602. (void)heap;
  23603. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  23604. if (err == MP_OKAY) {
  23605. point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap,
  23606. DYNAMIC_TYPE_ECC);
  23607. if (point == NULL)
  23608. err = MEMORY_E;
  23609. }
  23610. if (err == MP_OKAY) {
  23611. e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 9, heap,
  23612. DYNAMIC_TYPE_ECC);
  23613. if (e == NULL)
  23614. err = MEMORY_E;
  23615. }
  23616. #endif
  23617. if (err == MP_OKAY) {
  23618. x = e + 2 * 9;
  23619. k = e + 4 * 9;
  23620. r = e + 6 * 9;
  23621. tmp = e + 8 * 9;
  23622. s = e;
  23623. if (hashLen > 32U) {
  23624. hashLen = 32U;
  23625. }
  23626. }
  23627. for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) {
  23628. /* New random point. */
  23629. if (km == NULL || mp_iszero(km)) {
  23630. err = sp_256_ecc_gen_k_9(rng, k);
  23631. }
  23632. else {
  23633. sp_256_from_mp(k, 9, km);
  23634. mp_zero(km);
  23635. }
  23636. if (err == MP_OKAY) {
  23637. err = sp_256_ecc_mulmod_base_9(point, k, 1, 1, heap);
  23638. }
  23639. if (err == MP_OKAY) {
  23640. /* r = point->x mod order */
  23641. XMEMCPY(r, point->x, sizeof(sp_digit) * 9U);
  23642. sp_256_norm_9(r);
  23643. c = sp_256_cmp_9(r, p256_order);
  23644. sp_256_cond_sub_9(r, r, p256_order,
  23645. (sp_digit)0 - (sp_digit)(c >= 0));
  23646. sp_256_norm_9(r);
  23647. sp_256_from_mp(x, 9, priv);
  23648. sp_256_from_bin(e, 9, hash, (int)hashLen);
  23649. err = sp_256_calc_s_9(s, r, k, x, e, tmp);
  23650. }
  23651. /* Check that signature is usable. */
  23652. if ((err == MP_OKAY) && (sp_256_iszero_9(s) == 0)) {
  23653. break;
  23654. }
  23655. #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
  23656. i = 1;
  23657. #endif
  23658. }
  23659. if (i == 0) {
  23660. err = RNG_FAILURE_E;
  23661. }
  23662. if (err == MP_OKAY) {
  23663. err = sp_256_to_mp(r, rm);
  23664. }
  23665. if (err == MP_OKAY) {
  23666. err = sp_256_to_mp(s, sm);
  23667. }
  23668. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  23669. if (e != NULL)
  23670. #endif
  23671. {
  23672. ForceZero(e, sizeof(sp_digit) * 7 * 2 * 9);
  23673. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  23674. XFREE(e, heap, DYNAMIC_TYPE_ECC);
  23675. #endif
  23676. }
  23677. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  23678. if (point != NULL)
  23679. #endif
  23680. {
  23681. ForceZero(point, sizeof(sp_point_256));
  23682. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  23683. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  23684. #endif
  23685. }
  23686. return err;
  23687. }
  23688. #endif /* HAVE_ECC_SIGN */
  23689. #ifndef WOLFSSL_SP_SMALL
  23690. static const char sp_256_tab32_9[32] = {
  23691. 1, 10, 2, 11, 14, 22, 3, 30,
  23692. 12, 15, 17, 19, 23, 26, 4, 31,
  23693. 9, 13, 21, 29, 16, 18, 25, 8,
  23694. 20, 28, 24, 7, 27, 6, 5, 32};
  23695. static int sp_256_num_bits_29_9(sp_digit v)
  23696. {
  23697. v |= v >> 1;
  23698. v |= v >> 2;
  23699. v |= v >> 4;
  23700. v |= v >> 8;
  23701. v |= v >> 16;
  23702. return sp_256_tab32_9[(uint32_t)(v*0x07C4ACDD) >> 27];
  23703. }
  23704. static int sp_256_num_bits_9(const sp_digit* a)
  23705. {
  23706. int i;
  23707. int r = 0;
  23708. for (i = 8; i >= 0; i--) {
  23709. if (a[i] != 0) {
  23710. r = sp_256_num_bits_29_9(a[i]);
  23711. r += i * 29;
  23712. break;
  23713. }
  23714. }
  23715. return r;
  23716. }
  23717. /* Non-constant time modular inversion.
  23718. *
  23719. * @param [out] r Resulting number.
  23720. * @param [in] a Number to invert.
  23721. * @param [in] m Modulus.
  23722. * @return MP_OKAY on success.
  23723. * @return MEMEORY_E when dynamic memory allocation fails.
  23724. */
  23725. static int sp_256_mod_inv_9(sp_digit* r, const sp_digit* a, const sp_digit* m)
  23726. {
  23727. int err = MP_OKAY;
  23728. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  23729. sp_digit* u = NULL;
  23730. #else
  23731. sp_digit u[9 * 4];
  23732. #endif
  23733. sp_digit* v = NULL;
  23734. sp_digit* b = NULL;
  23735. sp_digit* d = NULL;
  23736. int ut;
  23737. int vt;
  23738. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  23739. u = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9 * 4, NULL,
  23740. DYNAMIC_TYPE_ECC);
  23741. if (u == NULL)
  23742. err = MEMORY_E;
  23743. #endif
  23744. if (err == MP_OKAY) {
  23745. v = u + 9;
  23746. b = u + 2 * 9;
  23747. d = u + 3 * 9;
  23748. XMEMCPY(u, m, sizeof(sp_digit) * 9);
  23749. XMEMCPY(v, a, sizeof(sp_digit) * 9);
  23750. ut = sp_256_num_bits_9(u);
  23751. vt = sp_256_num_bits_9(v);
  23752. XMEMSET(b, 0, sizeof(sp_digit) * 9);
  23753. if ((v[0] & 1) == 0) {
  23754. sp_256_rshift1_9(v, v);
  23755. XMEMCPY(d, m, sizeof(sp_digit) * 9);
  23756. d[0]++;
  23757. sp_256_rshift1_9(d, d);
  23758. vt--;
  23759. while ((v[0] & 1) == 0) {
  23760. sp_256_rshift1_9(v, v);
  23761. if (d[0] & 1)
  23762. sp_256_add_9(d, d, m);
  23763. sp_256_rshift1_9(d, d);
  23764. vt--;
  23765. }
  23766. }
  23767. else {
  23768. XMEMSET(d+1, 0, sizeof(sp_digit) * (9 - 1));
  23769. d[0] = 1;
  23770. }
  23771. while (ut > 1 && vt > 1) {
  23772. if (ut > vt || (ut == vt &&
  23773. sp_256_cmp_9(u, v) >= 0)) {
  23774. sp_256_sub_9(u, u, v);
  23775. sp_256_norm_9(u);
  23776. sp_256_sub_9(b, b, d);
  23777. sp_256_norm_9(b);
  23778. if (b[8] < 0)
  23779. sp_256_add_9(b, b, m);
  23780. sp_256_norm_9(b);
  23781. ut = sp_256_num_bits_9(u);
  23782. do {
  23783. sp_256_rshift1_9(u, u);
  23784. if (b[0] & 1)
  23785. sp_256_add_9(b, b, m);
  23786. sp_256_rshift1_9(b, b);
  23787. ut--;
  23788. }
  23789. while (ut > 0 && (u[0] & 1) == 0);
  23790. }
  23791. else {
  23792. sp_256_sub_9(v, v, u);
  23793. sp_256_norm_9(v);
  23794. sp_256_sub_9(d, d, b);
  23795. sp_256_norm_9(d);
  23796. if (d[8] < 0)
  23797. sp_256_add_9(d, d, m);
  23798. sp_256_norm_9(d);
  23799. vt = sp_256_num_bits_9(v);
  23800. do {
  23801. sp_256_rshift1_9(v, v);
  23802. if (d[0] & 1)
  23803. sp_256_add_9(d, d, m);
  23804. sp_256_rshift1_9(d, d);
  23805. vt--;
  23806. }
  23807. while (vt > 0 && (v[0] & 1) == 0);
  23808. }
  23809. }
  23810. if (ut == 1)
  23811. XMEMCPY(r, b, sizeof(sp_digit) * 9);
  23812. else
  23813. XMEMCPY(r, d, sizeof(sp_digit) * 9);
  23814. }
  23815. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  23816. if (u != NULL)
  23817. XFREE(u, NULL, DYNAMIC_TYPE_ECC);
  23818. #endif
  23819. return err;
  23820. }
  23821. #endif /* WOLFSSL_SP_SMALL */
  23822. /* Add point p1 into point p2. Handles p1 == p2 and result at infinity.
  23823. *
  23824. * p1 First point to add and holds result.
  23825. * p2 Second point to add.
  23826. * tmp Temporary storage for intermediate numbers.
  23827. */
  23828. static void sp_256_add_points_9(sp_point_256* p1, const sp_point_256* p2,
  23829. sp_digit* tmp)
  23830. {
  23831. sp_256_proj_point_add_9(p1, p1, p2, tmp);
  23832. if (sp_256_iszero_9(p1->z)) {
  23833. if (sp_256_iszero_9(p1->x) && sp_256_iszero_9(p1->y)) {
  23834. sp_256_proj_point_dbl_9(p1, p2, tmp);
  23835. }
  23836. else {
  23837. /* Y ordinate is not used from here - don't set. */
  23838. p1->x[0] = 0;
  23839. p1->x[1] = 0;
  23840. p1->x[2] = 0;
  23841. p1->x[3] = 0;
  23842. p1->x[4] = 0;
  23843. p1->x[5] = 0;
  23844. p1->x[6] = 0;
  23845. p1->x[7] = 0;
  23846. p1->x[8] = 0;
  23847. XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod));
  23848. }
  23849. }
  23850. }
  23851. /* Calculate the verification point: [e/s]G + [r/s]Q
  23852. *
  23853. * p1 Calculated point.
  23854. * p2 Public point and temporary.
  23855. * s Second part of signature as a number.
  23856. * u1 Temporary number.
  23857. * u2 Temproray number.
  23858. * heap Heap to use for allocation.
  23859. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  23860. */
  23861. static int sp_256_calc_vfy_point_9(sp_point_256* p1, sp_point_256* p2,
  23862. sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap)
  23863. {
  23864. int err;
  23865. #ifndef WOLFSSL_SP_SMALL
  23866. err = sp_256_mod_inv_9(s, s, p256_order);
  23867. if (err == MP_OKAY)
  23868. #endif /* !WOLFSSL_SP_SMALL */
  23869. {
  23870. sp_256_mul_9(s, s, p256_norm_order);
  23871. err = sp_256_mod_9(s, s, p256_order);
  23872. }
  23873. if (err == MP_OKAY) {
  23874. sp_256_norm_9(s);
  23875. #ifdef WOLFSSL_SP_SMALL
  23876. {
  23877. sp_256_mont_inv_order_9(s, s, tmp);
  23878. sp_256_mont_mul_order_9(u1, u1, s);
  23879. sp_256_mont_mul_order_9(u2, u2, s);
  23880. }
  23881. #else
  23882. {
  23883. sp_256_mont_mul_order_9(u1, u1, s);
  23884. sp_256_mont_mul_order_9(u2, u2, s);
  23885. }
  23886. #endif /* WOLFSSL_SP_SMALL */
  23887. {
  23888. err = sp_256_ecc_mulmod_base_9(p1, u1, 0, 0, heap);
  23889. }
  23890. }
  23891. if ((err == MP_OKAY) && sp_256_iszero_9(p1->z)) {
  23892. p1->infinity = 1;
  23893. }
  23894. if (err == MP_OKAY) {
  23895. err = sp_256_ecc_mulmod_9(p2, p2, u2, 0, 0, heap);
  23896. }
  23897. if ((err == MP_OKAY) && sp_256_iszero_9(p2->z)) {
  23898. p2->infinity = 1;
  23899. }
  23900. if (err == MP_OKAY) {
  23901. sp_256_add_points_9(p1, p2, tmp);
  23902. }
  23903. return err;
  23904. }
  23905. #ifdef HAVE_ECC_VERIFY
  23906. /* Verify the signature values with the hash and public key.
  23907. * e = Truncate(hash, 256)
  23908. * u1 = e/s mod order
  23909. * u2 = r/s mod order
  23910. * r == (u1.G + u2.Q)->x mod order
  23911. * Optimization: Leave point in projective form.
  23912. * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z')
  23913. * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x'
  23914. * The hash is truncated to the first 256 bits.
  23915. *
  23916. * hash Hash to sign.
  23917. * hashLen Length of the hash data.
  23918. * rng Random number generator.
  23919. * priv Private part of key - scalar.
  23920. * rm First part of result as an mp_int.
  23921. * sm Sirst part of result as an mp_int.
  23922. * heap Heap to use for allocation.
  23923. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  23924. */
  23925. #ifdef WOLFSSL_SP_NONBLOCK
  23926. typedef struct sp_ecc_verify_256_ctx {
  23927. int state;
  23928. union {
  23929. sp_256_ecc_mulmod_9_ctx mulmod_ctx;
  23930. sp_256_mont_inv_order_9_ctx mont_inv_order_ctx;
  23931. sp_256_proj_point_dbl_9_ctx dbl_ctx;
  23932. sp_256_proj_point_add_9_ctx add_ctx;
  23933. };
  23934. sp_digit u1[2*9];
  23935. sp_digit u2[2*9];
  23936. sp_digit s[2*9];
  23937. sp_digit tmp[2*9 * 6];
  23938. sp_point_256 p1;
  23939. sp_point_256 p2;
  23940. } sp_ecc_verify_256_ctx;
  23941. int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash,
  23942. word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ,
  23943. const mp_int* rm, const mp_int* sm, int* res, void* heap)
  23944. {
  23945. int err = FP_WOULDBLOCK;
  23946. sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data;
  23947. typedef char ctx_size_test[sizeof(sp_ecc_verify_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  23948. (void)sizeof(ctx_size_test);
  23949. switch (ctx->state) {
  23950. case 0: /* INIT */
  23951. if (hashLen > 32U) {
  23952. hashLen = 32U;
  23953. }
  23954. sp_256_from_bin(ctx->u1, 9, hash, (int)hashLen);
  23955. sp_256_from_mp(ctx->u2, 9, rm);
  23956. sp_256_from_mp(ctx->s, 9, sm);
  23957. sp_256_from_mp(ctx->p2.x, 9, pX);
  23958. sp_256_from_mp(ctx->p2.y, 9, pY);
  23959. sp_256_from_mp(ctx->p2.z, 9, pZ);
  23960. ctx->state = 1;
  23961. break;
  23962. case 1: /* NORMS0 */
  23963. sp_256_mul_9(ctx->s, ctx->s, p256_norm_order);
  23964. err = sp_256_mod_9(ctx->s, ctx->s, p256_order);
  23965. if (err == MP_OKAY)
  23966. ctx->state = 2;
  23967. break;
  23968. case 2: /* NORMS1 */
  23969. sp_256_norm_9(ctx->s);
  23970. XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
  23971. ctx->state = 3;
  23972. break;
  23973. case 3: /* NORMS2 */
  23974. err = sp_256_mont_inv_order_9_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp);
  23975. if (err == MP_OKAY) {
  23976. ctx->state = 4;
  23977. }
  23978. break;
  23979. case 4: /* NORMS3 */
  23980. sp_256_mont_mul_order_9(ctx->u1, ctx->u1, ctx->s);
  23981. ctx->state = 5;
  23982. break;
  23983. case 5: /* NORMS4 */
  23984. sp_256_mont_mul_order_9(ctx->u2, ctx->u2, ctx->s);
  23985. XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
  23986. ctx->state = 6;
  23987. break;
  23988. case 6: /* MULBASE */
  23989. err = sp_256_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p256_base, ctx->u1, 0, 0, heap);
  23990. if (err == MP_OKAY) {
  23991. if (sp_256_iszero_9(ctx->p1.z)) {
  23992. ctx->p1.infinity = 1;
  23993. }
  23994. XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
  23995. ctx->state = 7;
  23996. }
  23997. break;
  23998. case 7: /* MULMOD */
  23999. err = sp_256_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, 0, heap);
  24000. if (err == MP_OKAY) {
  24001. if (sp_256_iszero_9(ctx->p2.z)) {
  24002. ctx->p2.infinity = 1;
  24003. }
  24004. XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx));
  24005. ctx->state = 8;
  24006. }
  24007. break;
  24008. case 8: /* ADD */
  24009. err = sp_256_proj_point_add_9_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp);
  24010. if (err == MP_OKAY)
  24011. ctx->state = 9;
  24012. break;
  24013. case 9: /* MONT */
  24014. /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
  24015. /* Reload r and convert to Montgomery form. */
  24016. sp_256_from_mp(ctx->u2, 9, rm);
  24017. err = sp_256_mod_mul_norm_9(ctx->u2, ctx->u2, p256_mod);
  24018. if (err == MP_OKAY)
  24019. ctx->state = 10;
  24020. break;
  24021. case 10: /* SQR */
  24022. /* u1 = r.z'.z' mod prime */
  24023. sp_256_mont_sqr_9(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod);
  24024. ctx->state = 11;
  24025. break;
  24026. case 11: /* MUL */
  24027. sp_256_mont_mul_9(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod);
  24028. ctx->state = 12;
  24029. break;
  24030. case 12: /* RES */
  24031. {
  24032. sp_int32 c = 0;
  24033. err = MP_OKAY; /* math okay, now check result */
  24034. *res = (int)(sp_256_cmp_9(ctx->p1.x, ctx->u1) == 0);
  24035. if (*res == 0) {
  24036. sp_digit carry;
  24037. /* Reload r and add order. */
  24038. sp_256_from_mp(ctx->u2, 9, rm);
  24039. carry = sp_256_add_9(ctx->u2, ctx->u2, p256_order);
  24040. /* Carry means result is greater than mod and is not valid. */
  24041. if (carry == 0) {
  24042. sp_256_norm_9(ctx->u2);
  24043. /* Compare with mod and if greater or equal then not valid. */
  24044. c = sp_256_cmp_9(ctx->u2, p256_mod);
  24045. }
  24046. }
  24047. if ((*res == 0) && (c < 0)) {
  24048. /* Convert to Montogomery form */
  24049. err = sp_256_mod_mul_norm_9(ctx->u2, ctx->u2, p256_mod);
  24050. if (err == MP_OKAY) {
  24051. /* u1 = (r + 1*order).z'.z' mod prime */
  24052. sp_256_mont_mul_9(ctx->u1, ctx->u2, ctx->p1.z, p256_mod,
  24053. p256_mp_mod);
  24054. *res = (int)(sp_256_cmp_9(ctx->p1.x, ctx->u1) == 0);
  24055. }
  24056. }
  24057. break;
  24058. }
  24059. } /* switch */
  24060. if (err == MP_OKAY && ctx->state != 12) {
  24061. err = FP_WOULDBLOCK;
  24062. }
  24063. return err;
  24064. }
  24065. #endif /* WOLFSSL_SP_NONBLOCK */
  24066. int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX,
  24067. const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm,
  24068. int* res, void* heap)
  24069. {
  24070. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24071. sp_digit* u1 = NULL;
  24072. sp_point_256* p1 = NULL;
  24073. #else
  24074. sp_digit u1[18 * 9];
  24075. sp_point_256 p1[2];
  24076. #endif
  24077. sp_digit* u2 = NULL;
  24078. sp_digit* s = NULL;
  24079. sp_digit* tmp = NULL;
  24080. sp_point_256* p2 = NULL;
  24081. sp_digit carry;
  24082. sp_int32 c = 0;
  24083. int err = MP_OKAY;
  24084. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24085. if (err == MP_OKAY) {
  24086. p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap,
  24087. DYNAMIC_TYPE_ECC);
  24088. if (p1 == NULL)
  24089. err = MEMORY_E;
  24090. }
  24091. if (err == MP_OKAY) {
  24092. u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 9, heap,
  24093. DYNAMIC_TYPE_ECC);
  24094. if (u1 == NULL)
  24095. err = MEMORY_E;
  24096. }
  24097. #endif
  24098. if (err == MP_OKAY) {
  24099. u2 = u1 + 2 * 9;
  24100. s = u1 + 4 * 9;
  24101. tmp = u1 + 6 * 9;
  24102. p2 = p1 + 1;
  24103. if (hashLen > 32U) {
  24104. hashLen = 32U;
  24105. }
  24106. sp_256_from_bin(u1, 9, hash, (int)hashLen);
  24107. sp_256_from_mp(u2, 9, rm);
  24108. sp_256_from_mp(s, 9, sm);
  24109. sp_256_from_mp(p2->x, 9, pX);
  24110. sp_256_from_mp(p2->y, 9, pY);
  24111. sp_256_from_mp(p2->z, 9, pZ);
  24112. err = sp_256_calc_vfy_point_9(p1, p2, s, u1, u2, tmp, heap);
  24113. }
  24114. if (err == MP_OKAY) {
  24115. /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
  24116. /* Reload r and convert to Montgomery form. */
  24117. sp_256_from_mp(u2, 9, rm);
  24118. err = sp_256_mod_mul_norm_9(u2, u2, p256_mod);
  24119. }
  24120. if (err == MP_OKAY) {
  24121. /* u1 = r.z'.z' mod prime */
  24122. sp_256_mont_sqr_9(p1->z, p1->z, p256_mod, p256_mp_mod);
  24123. sp_256_mont_mul_9(u1, u2, p1->z, p256_mod, p256_mp_mod);
  24124. *res = (int)(sp_256_cmp_9(p1->x, u1) == 0);
  24125. if (*res == 0) {
  24126. /* Reload r and add order. */
  24127. sp_256_from_mp(u2, 9, rm);
  24128. carry = sp_256_add_9(u2, u2, p256_order);
  24129. /* Carry means result is greater than mod and is not valid. */
  24130. if (carry == 0) {
  24131. sp_256_norm_9(u2);
  24132. /* Compare with mod and if greater or equal then not valid. */
  24133. c = sp_256_cmp_9(u2, p256_mod);
  24134. }
  24135. }
  24136. if ((*res == 0) && (c < 0)) {
  24137. /* Convert to Montogomery form */
  24138. err = sp_256_mod_mul_norm_9(u2, u2, p256_mod);
  24139. if (err == MP_OKAY) {
  24140. /* u1 = (r + 1*order).z'.z' mod prime */
  24141. {
  24142. sp_256_mont_mul_9(u1, u2, p1->z, p256_mod, p256_mp_mod);
  24143. }
  24144. *res = (sp_256_cmp_9(p1->x, u1) == 0);
  24145. }
  24146. }
  24147. }
  24148. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24149. if (u1 != NULL)
  24150. XFREE(u1, heap, DYNAMIC_TYPE_ECC);
  24151. if (p1 != NULL)
  24152. XFREE(p1, heap, DYNAMIC_TYPE_ECC);
  24153. #endif
  24154. return err;
  24155. }
  24156. #endif /* HAVE_ECC_VERIFY */
  24157. #ifdef HAVE_ECC_CHECK_KEY
  24158. /* Check that the x and y oridinates are a valid point on the curve.
  24159. *
  24160. * point EC point.
  24161. * heap Heap to use if dynamically allocating.
  24162. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  24163. * not on the curve and MP_OKAY otherwise.
  24164. */
  24165. static int sp_256_ecc_is_point_9(const sp_point_256* point,
  24166. void* heap)
  24167. {
  24168. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24169. sp_digit* t1 = NULL;
  24170. #else
  24171. sp_digit t1[9 * 4];
  24172. #endif
  24173. sp_digit* t2 = NULL;
  24174. int err = MP_OKAY;
  24175. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24176. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9 * 4, heap, DYNAMIC_TYPE_ECC);
  24177. if (t1 == NULL)
  24178. err = MEMORY_E;
  24179. #endif
  24180. (void)heap;
  24181. if (err == MP_OKAY) {
  24182. t2 = t1 + 2 * 9;
  24183. sp_256_sqr_9(t1, point->y);
  24184. (void)sp_256_mod_9(t1, t1, p256_mod);
  24185. sp_256_sqr_9(t2, point->x);
  24186. (void)sp_256_mod_9(t2, t2, p256_mod);
  24187. sp_256_mul_9(t2, t2, point->x);
  24188. (void)sp_256_mod_9(t2, t2, p256_mod);
  24189. (void)sp_256_sub_9(t2, p256_mod, t2);
  24190. sp_256_mont_add_9(t1, t1, t2, p256_mod);
  24191. sp_256_mont_add_9(t1, t1, point->x, p256_mod);
  24192. sp_256_mont_add_9(t1, t1, point->x, p256_mod);
  24193. sp_256_mont_add_9(t1, t1, point->x, p256_mod);
  24194. if (sp_256_cmp_9(t1, p256_b) != 0) {
  24195. err = MP_VAL;
  24196. }
  24197. }
  24198. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24199. if (t1 != NULL)
  24200. XFREE(t1, heap, DYNAMIC_TYPE_ECC);
  24201. #endif
  24202. return err;
  24203. }
  24204. /* Check that the x and y oridinates are a valid point on the curve.
  24205. *
  24206. * pX X ordinate of EC point.
  24207. * pY Y ordinate of EC point.
  24208. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  24209. * not on the curve and MP_OKAY otherwise.
  24210. */
  24211. int sp_ecc_is_point_256(const mp_int* pX, const mp_int* pY)
  24212. {
  24213. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24214. sp_point_256* pub = NULL;
  24215. #else
  24216. sp_point_256 pub[1];
  24217. #endif
  24218. const byte one[1] = { 1 };
  24219. int err = MP_OKAY;
  24220. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24221. pub = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL,
  24222. DYNAMIC_TYPE_ECC);
  24223. if (pub == NULL)
  24224. err = MEMORY_E;
  24225. #endif
  24226. if (err == MP_OKAY) {
  24227. sp_256_from_mp(pub->x, 9, pX);
  24228. sp_256_from_mp(pub->y, 9, pY);
  24229. sp_256_from_bin(pub->z, 9, one, (int)sizeof(one));
  24230. err = sp_256_ecc_is_point_9(pub, NULL);
  24231. }
  24232. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24233. if (pub != NULL)
  24234. XFREE(pub, NULL, DYNAMIC_TYPE_ECC);
  24235. #endif
  24236. return err;
  24237. }
  24238. /* Check that the private scalar generates the EC point (px, py), the point is
  24239. * on the curve and the point has the correct order.
  24240. *
  24241. * pX X ordinate of EC point.
  24242. * pY Y ordinate of EC point.
  24243. * privm Private scalar that generates EC point.
  24244. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  24245. * not on the curve, ECC_INF_E if the point does not have the correct order,
  24246. * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
  24247. * MP_OKAY otherwise.
  24248. */
  24249. int sp_ecc_check_key_256(const mp_int* pX, const mp_int* pY,
  24250. const mp_int* privm, void* heap)
  24251. {
  24252. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24253. sp_digit* priv = NULL;
  24254. sp_point_256* pub = NULL;
  24255. #else
  24256. sp_digit priv[9];
  24257. sp_point_256 pub[2];
  24258. #endif
  24259. sp_point_256* p = NULL;
  24260. const byte one[1] = { 1 };
  24261. int err = MP_OKAY;
  24262. /* Quick check the lengs of public key ordinates and private key are in
  24263. * range. Proper check later.
  24264. */
  24265. if (((mp_count_bits(pX) > 256) ||
  24266. (mp_count_bits(pY) > 256) ||
  24267. ((privm != NULL) && (mp_count_bits(privm) > 256)))) {
  24268. err = ECC_OUT_OF_RANGE_E;
  24269. }
  24270. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24271. if (err == MP_OKAY) {
  24272. pub = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap,
  24273. DYNAMIC_TYPE_ECC);
  24274. if (pub == NULL)
  24275. err = MEMORY_E;
  24276. }
  24277. if (err == MP_OKAY && privm) {
  24278. priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9, heap,
  24279. DYNAMIC_TYPE_ECC);
  24280. if (priv == NULL)
  24281. err = MEMORY_E;
  24282. }
  24283. #endif
  24284. if (err == MP_OKAY) {
  24285. p = pub + 1;
  24286. sp_256_from_mp(pub->x, 9, pX);
  24287. sp_256_from_mp(pub->y, 9, pY);
  24288. sp_256_from_bin(pub->z, 9, one, (int)sizeof(one));
  24289. if (privm)
  24290. sp_256_from_mp(priv, 9, privm);
  24291. /* Check point at infinitiy. */
  24292. if ((sp_256_iszero_9(pub->x) != 0) &&
  24293. (sp_256_iszero_9(pub->y) != 0)) {
  24294. err = ECC_INF_E;
  24295. }
  24296. }
  24297. /* Check range of X and Y */
  24298. if ((err == MP_OKAY) &&
  24299. ((sp_256_cmp_9(pub->x, p256_mod) >= 0) ||
  24300. (sp_256_cmp_9(pub->y, p256_mod) >= 0))) {
  24301. err = ECC_OUT_OF_RANGE_E;
  24302. }
  24303. if (err == MP_OKAY) {
  24304. /* Check point is on curve */
  24305. err = sp_256_ecc_is_point_9(pub, heap);
  24306. }
  24307. if (err == MP_OKAY) {
  24308. /* Point * order = infinity */
  24309. err = sp_256_ecc_mulmod_9(p, pub, p256_order, 1, 1, heap);
  24310. }
  24311. /* Check result is infinity */
  24312. if ((err == MP_OKAY) && ((sp_256_iszero_9(p->x) == 0) ||
  24313. (sp_256_iszero_9(p->y) == 0))) {
  24314. err = ECC_INF_E;
  24315. }
  24316. if (privm) {
  24317. if (err == MP_OKAY) {
  24318. /* Base * private = point */
  24319. err = sp_256_ecc_mulmod_base_9(p, priv, 1, 1, heap);
  24320. }
  24321. /* Check result is public key */
  24322. if ((err == MP_OKAY) &&
  24323. ((sp_256_cmp_9(p->x, pub->x) != 0) ||
  24324. (sp_256_cmp_9(p->y, pub->y) != 0))) {
  24325. err = ECC_PRIV_KEY_E;
  24326. }
  24327. }
  24328. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24329. if (pub != NULL)
  24330. XFREE(pub, heap, DYNAMIC_TYPE_ECC);
  24331. if (priv != NULL)
  24332. XFREE(priv, heap, DYNAMIC_TYPE_ECC);
  24333. #endif
  24334. return err;
  24335. }
  24336. #endif
  24337. #ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL
  24338. /* Add two projective EC points together.
  24339. * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ)
  24340. *
  24341. * pX First EC point's X ordinate.
  24342. * pY First EC point's Y ordinate.
  24343. * pZ First EC point's Z ordinate.
  24344. * qX Second EC point's X ordinate.
  24345. * qY Second EC point's Y ordinate.
  24346. * qZ Second EC point's Z ordinate.
  24347. * rX Resultant EC point's X ordinate.
  24348. * rY Resultant EC point's Y ordinate.
  24349. * rZ Resultant EC point's Z ordinate.
  24350. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  24351. */
  24352. int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ,
  24353. mp_int* qX, mp_int* qY, mp_int* qZ,
  24354. mp_int* rX, mp_int* rY, mp_int* rZ)
  24355. {
  24356. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24357. sp_digit* tmp = NULL;
  24358. sp_point_256* p = NULL;
  24359. #else
  24360. sp_digit tmp[2 * 9 * 6];
  24361. sp_point_256 p[2];
  24362. #endif
  24363. sp_point_256* q = NULL;
  24364. int err = MP_OKAY;
  24365. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24366. if (err == MP_OKAY) {
  24367. p = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, NULL,
  24368. DYNAMIC_TYPE_ECC);
  24369. if (p == NULL)
  24370. err = MEMORY_E;
  24371. }
  24372. if (err == MP_OKAY) {
  24373. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 9 * 6, NULL,
  24374. DYNAMIC_TYPE_ECC);
  24375. if (tmp == NULL) {
  24376. err = MEMORY_E;
  24377. }
  24378. }
  24379. #endif
  24380. if (err == MP_OKAY) {
  24381. q = p + 1;
  24382. sp_256_from_mp(p->x, 9, pX);
  24383. sp_256_from_mp(p->y, 9, pY);
  24384. sp_256_from_mp(p->z, 9, pZ);
  24385. sp_256_from_mp(q->x, 9, qX);
  24386. sp_256_from_mp(q->y, 9, qY);
  24387. sp_256_from_mp(q->z, 9, qZ);
  24388. p->infinity = sp_256_iszero_9(p->x) &
  24389. sp_256_iszero_9(p->y);
  24390. q->infinity = sp_256_iszero_9(q->x) &
  24391. sp_256_iszero_9(q->y);
  24392. sp_256_proj_point_add_9(p, p, q, tmp);
  24393. }
  24394. if (err == MP_OKAY) {
  24395. err = sp_256_to_mp(p->x, rX);
  24396. }
  24397. if (err == MP_OKAY) {
  24398. err = sp_256_to_mp(p->y, rY);
  24399. }
  24400. if (err == MP_OKAY) {
  24401. err = sp_256_to_mp(p->z, rZ);
  24402. }
  24403. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24404. if (tmp != NULL)
  24405. XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
  24406. if (p != NULL)
  24407. XFREE(p, NULL, DYNAMIC_TYPE_ECC);
  24408. #endif
  24409. return err;
  24410. }
  24411. /* Double a projective EC point.
  24412. * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ)
  24413. *
  24414. * pX EC point's X ordinate.
  24415. * pY EC point's Y ordinate.
  24416. * pZ EC point's Z ordinate.
  24417. * rX Resultant EC point's X ordinate.
  24418. * rY Resultant EC point's Y ordinate.
  24419. * rZ Resultant EC point's Z ordinate.
  24420. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  24421. */
  24422. int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ,
  24423. mp_int* rX, mp_int* rY, mp_int* rZ)
  24424. {
  24425. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24426. sp_digit* tmp = NULL;
  24427. sp_point_256* p = NULL;
  24428. #else
  24429. sp_digit tmp[2 * 9 * 2];
  24430. sp_point_256 p[1];
  24431. #endif
  24432. int err = MP_OKAY;
  24433. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24434. if (err == MP_OKAY) {
  24435. p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL,
  24436. DYNAMIC_TYPE_ECC);
  24437. if (p == NULL)
  24438. err = MEMORY_E;
  24439. }
  24440. if (err == MP_OKAY) {
  24441. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 9 * 2, NULL,
  24442. DYNAMIC_TYPE_ECC);
  24443. if (tmp == NULL)
  24444. err = MEMORY_E;
  24445. }
  24446. #endif
  24447. if (err == MP_OKAY) {
  24448. sp_256_from_mp(p->x, 9, pX);
  24449. sp_256_from_mp(p->y, 9, pY);
  24450. sp_256_from_mp(p->z, 9, pZ);
  24451. p->infinity = sp_256_iszero_9(p->x) &
  24452. sp_256_iszero_9(p->y);
  24453. sp_256_proj_point_dbl_9(p, p, tmp);
  24454. }
  24455. if (err == MP_OKAY) {
  24456. err = sp_256_to_mp(p->x, rX);
  24457. }
  24458. if (err == MP_OKAY) {
  24459. err = sp_256_to_mp(p->y, rY);
  24460. }
  24461. if (err == MP_OKAY) {
  24462. err = sp_256_to_mp(p->z, rZ);
  24463. }
  24464. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24465. if (tmp != NULL)
  24466. XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
  24467. if (p != NULL)
  24468. XFREE(p, NULL, DYNAMIC_TYPE_ECC);
  24469. #endif
  24470. return err;
  24471. }
  24472. /* Map a projective EC point to affine in place.
  24473. * pZ will be one.
  24474. *
  24475. * pX EC point's X ordinate.
  24476. * pY EC point's Y ordinate.
  24477. * pZ EC point's Z ordinate.
  24478. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  24479. */
  24480. int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ)
  24481. {
  24482. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24483. sp_digit* tmp = NULL;
  24484. sp_point_256* p = NULL;
  24485. #else
  24486. sp_digit tmp[2 * 9 * 4];
  24487. sp_point_256 p[1];
  24488. #endif
  24489. int err = MP_OKAY;
  24490. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24491. if (err == MP_OKAY) {
  24492. p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL,
  24493. DYNAMIC_TYPE_ECC);
  24494. if (p == NULL)
  24495. err = MEMORY_E;
  24496. }
  24497. if (err == MP_OKAY) {
  24498. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 9 * 4, NULL,
  24499. DYNAMIC_TYPE_ECC);
  24500. if (tmp == NULL)
  24501. err = MEMORY_E;
  24502. }
  24503. #endif
  24504. if (err == MP_OKAY) {
  24505. sp_256_from_mp(p->x, 9, pX);
  24506. sp_256_from_mp(p->y, 9, pY);
  24507. sp_256_from_mp(p->z, 9, pZ);
  24508. p->infinity = sp_256_iszero_9(p->x) &
  24509. sp_256_iszero_9(p->y);
  24510. sp_256_map_9(p, p, tmp);
  24511. }
  24512. if (err == MP_OKAY) {
  24513. err = sp_256_to_mp(p->x, pX);
  24514. }
  24515. if (err == MP_OKAY) {
  24516. err = sp_256_to_mp(p->y, pY);
  24517. }
  24518. if (err == MP_OKAY) {
  24519. err = sp_256_to_mp(p->z, pZ);
  24520. }
  24521. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24522. if (tmp != NULL)
  24523. XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
  24524. if (p != NULL)
  24525. XFREE(p, NULL, DYNAMIC_TYPE_ECC);
  24526. #endif
  24527. return err;
  24528. }
  24529. #endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */
  24530. #ifdef HAVE_COMP_KEY
  24531. /* Find the square root of a number mod the prime of the curve.
  24532. *
  24533. * y The number to operate on and the result.
  24534. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  24535. */
  24536. static int sp_256_mont_sqrt_9(sp_digit* y)
  24537. {
  24538. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24539. sp_digit* t1 = NULL;
  24540. #else
  24541. sp_digit t1[4 * 9];
  24542. #endif
  24543. sp_digit* t2 = NULL;
  24544. int err = MP_OKAY;
  24545. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24546. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 9, NULL, DYNAMIC_TYPE_ECC);
  24547. if (t1 == NULL) {
  24548. err = MEMORY_E;
  24549. }
  24550. #endif
  24551. if (err == MP_OKAY) {
  24552. t2 = t1 + 2 * 9;
  24553. {
  24554. /* t2 = y ^ 0x2 */
  24555. sp_256_mont_sqr_9(t2, y, p256_mod, p256_mp_mod);
  24556. /* t1 = y ^ 0x3 */
  24557. sp_256_mont_mul_9(t1, t2, y, p256_mod, p256_mp_mod);
  24558. /* t2 = y ^ 0xc */
  24559. sp_256_mont_sqr_n_9(t2, t1, 2, p256_mod, p256_mp_mod);
  24560. /* t1 = y ^ 0xf */
  24561. sp_256_mont_mul_9(t1, t1, t2, p256_mod, p256_mp_mod);
  24562. /* t2 = y ^ 0xf0 */
  24563. sp_256_mont_sqr_n_9(t2, t1, 4, p256_mod, p256_mp_mod);
  24564. /* t1 = y ^ 0xff */
  24565. sp_256_mont_mul_9(t1, t1, t2, p256_mod, p256_mp_mod);
  24566. /* t2 = y ^ 0xff00 */
  24567. sp_256_mont_sqr_n_9(t2, t1, 8, p256_mod, p256_mp_mod);
  24568. /* t1 = y ^ 0xffff */
  24569. sp_256_mont_mul_9(t1, t1, t2, p256_mod, p256_mp_mod);
  24570. /* t2 = y ^ 0xffff0000 */
  24571. sp_256_mont_sqr_n_9(t2, t1, 16, p256_mod, p256_mp_mod);
  24572. /* t1 = y ^ 0xffffffff */
  24573. sp_256_mont_mul_9(t1, t1, t2, p256_mod, p256_mp_mod);
  24574. /* t1 = y ^ 0xffffffff00000000 */
  24575. sp_256_mont_sqr_n_9(t1, t1, 32, p256_mod, p256_mp_mod);
  24576. /* t1 = y ^ 0xffffffff00000001 */
  24577. sp_256_mont_mul_9(t1, t1, y, p256_mod, p256_mp_mod);
  24578. /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */
  24579. sp_256_mont_sqr_n_9(t1, t1, 96, p256_mod, p256_mp_mod);
  24580. /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */
  24581. sp_256_mont_mul_9(t1, t1, y, p256_mod, p256_mp_mod);
  24582. sp_256_mont_sqr_n_9(y, t1, 94, p256_mod, p256_mp_mod);
  24583. }
  24584. }
  24585. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24586. if (t1 != NULL)
  24587. XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
  24588. #endif
  24589. return err;
  24590. }
  24591. /* Uncompress the point given the X ordinate.
  24592. *
  24593. * xm X ordinate.
  24594. * odd Whether the Y ordinate is odd.
  24595. * ym Calculated Y ordinate.
  24596. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  24597. */
  24598. int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym)
  24599. {
  24600. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24601. sp_digit* x = NULL;
  24602. #else
  24603. sp_digit x[4 * 9];
  24604. #endif
  24605. sp_digit* y = NULL;
  24606. int err = MP_OKAY;
  24607. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24608. x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 9, NULL, DYNAMIC_TYPE_ECC);
  24609. if (x == NULL)
  24610. err = MEMORY_E;
  24611. #endif
  24612. if (err == MP_OKAY) {
  24613. y = x + 2 * 9;
  24614. sp_256_from_mp(x, 9, xm);
  24615. err = sp_256_mod_mul_norm_9(x, x, p256_mod);
  24616. }
  24617. if (err == MP_OKAY) {
  24618. /* y = x^3 */
  24619. {
  24620. sp_256_mont_sqr_9(y, x, p256_mod, p256_mp_mod);
  24621. sp_256_mont_mul_9(y, y, x, p256_mod, p256_mp_mod);
  24622. }
  24623. /* y = x^3 - 3x */
  24624. sp_256_mont_sub_9(y, y, x, p256_mod);
  24625. sp_256_mont_sub_9(y, y, x, p256_mod);
  24626. sp_256_mont_sub_9(y, y, x, p256_mod);
  24627. /* y = x^3 - 3x + b */
  24628. err = sp_256_mod_mul_norm_9(x, p256_b, p256_mod);
  24629. }
  24630. if (err == MP_OKAY) {
  24631. sp_256_mont_add_9(y, y, x, p256_mod);
  24632. /* y = sqrt(x^3 - 3x + b) */
  24633. err = sp_256_mont_sqrt_9(y);
  24634. }
  24635. if (err == MP_OKAY) {
  24636. XMEMSET(y + 9, 0, 9U * sizeof(sp_digit));
  24637. sp_256_mont_reduce_9(y, p256_mod, p256_mp_mod);
  24638. if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) {
  24639. sp_256_mont_sub_9(y, p256_mod, y, p256_mod);
  24640. }
  24641. err = sp_256_to_mp(y, ym);
  24642. }
  24643. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  24644. if (x != NULL)
  24645. XFREE(x, NULL, DYNAMIC_TYPE_ECC);
  24646. #endif
  24647. return err;
  24648. }
  24649. #endif
  24650. #endif /* !WOLFSSL_SP_NO_256 */
  24651. #ifdef WOLFSSL_SP_384
  24652. /* Point structure to use. */
  24653. typedef struct sp_point_384 {
  24654. /* X ordinate of point. */
  24655. sp_digit x[2 * 15];
  24656. /* Y ordinate of point. */
  24657. sp_digit y[2 * 15];
  24658. /* Z ordinate of point. */
  24659. sp_digit z[2 * 15];
  24660. /* Indicates point is at infinity. */
  24661. int infinity;
  24662. } sp_point_384;
  24663. /* The modulus (prime) of the curve P384. */
  24664. static const sp_digit p384_mod[15] = {
  24665. 0x3ffffff,0x000003f,0x0000000,0x3fc0000,0x2ffffff,0x3ffffff,0x3ffffff,
  24666. 0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,
  24667. 0x00fffff
  24668. };
  24669. /* The Montgomery normalizer for modulus of the curve P384. */
  24670. static const sp_digit p384_norm_mod[15] = {
  24671. 0x0000001,0x3ffffc0,0x3ffffff,0x003ffff,0x1000000,0x0000000,0x0000000,
  24672. 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
  24673. 0x0000000
  24674. };
  24675. /* The Montgomery multiplier for modulus of the curve P384. */
  24676. static sp_digit p384_mp_mod = 0x000001;
  24677. #if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
  24678. defined(HAVE_ECC_VERIFY)
  24679. /* The order of the curve P384. */
  24680. static const sp_digit p384_order[15] = {
  24681. 0x0c52973,0x3065ab3,0x277aece,0x2c922c2,0x3581a0d,0x10dcb77,0x234d81f,
  24682. 0x3ffff1d,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,
  24683. 0x00fffff
  24684. };
  24685. #endif
  24686. /* The order of the curve P384 minus 2. */
  24687. static const sp_digit p384_order2[15] = {
  24688. 0x0c52971,0x3065ab3,0x277aece,0x2c922c2,0x3581a0d,0x10dcb77,0x234d81f,
  24689. 0x3ffff1d,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,
  24690. 0x00fffff
  24691. };
  24692. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  24693. /* The Montgomery normalizer for order of the curve P384. */
  24694. static const sp_digit p384_norm_order[15] = {
  24695. 0x33ad68d,0x0f9a54c,0x1885131,0x136dd3d,0x0a7e5f2,0x2f23488,0x1cb27e0,
  24696. 0x00000e2,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
  24697. 0x0000000
  24698. };
  24699. #endif
  24700. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  24701. /* The Montgomery multiplier for order of the curve P384. */
  24702. static sp_digit p384_mp_order = 0x8fdc45;
  24703. #endif
  24704. /* The base point of curve P384. */
  24705. static const sp_point_384 p384_base = {
  24706. /* X ordinate */
  24707. {
  24708. 0x2760ab7,0x1178e1c,0x296c3a5,0x176fd54,0x05502f2,0x0950a8e,0x3741e08,
  24709. 0x26e6167,0x3628ba7,0x11b874e,0x3320ad7,0x2c71c7b,0x305378e,0x288afa2,
  24710. 0x00aa87c,
  24711. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  24712. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  24713. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0
  24714. },
  24715. /* Y ordinate */
  24716. {
  24717. 0x0ea0e5f,0x0c75f24,0x019d7a4,0x33875fa,0x00a60b1,0x17c2e30,0x1a3113b,
  24718. 0x051f3a7,0x1bd289a,0x27e3d07,0x1292dc2,0x27a62fe,0x22c6f5d,0x392a589,
  24719. 0x003617d,
  24720. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  24721. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  24722. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0
  24723. },
  24724. /* Z ordinate */
  24725. {
  24726. 0x0000001,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
  24727. 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
  24728. 0x0000000,
  24729. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  24730. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  24731. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0
  24732. },
  24733. /* infinity */
  24734. 0
  24735. };
  24736. #if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY)
  24737. static const sp_digit p384_b[15] = {
  24738. 0x3ec2aef,0x1723b74,0x119d2a8,0x23628bb,0x2c65639,0x004e1d6,0x14088f5,
  24739. 0x104480c,0x06efe81,0x2460767,0x23f82d1,0x23815af,0x2e7e498,0x3e9f88f,
  24740. 0x00b3312
  24741. };
  24742. #endif
  24743. #ifdef WOLFSSL_SP_SMALL
  24744. /* Multiply a and b into r. (r = a * b)
  24745. *
  24746. * r A single precision integer.
  24747. * a A single precision integer.
  24748. * b A single precision integer.
  24749. */
  24750. SP_NOINLINE static void sp_384_mul_15(sp_digit* r, const sp_digit* a,
  24751. const sp_digit* b)
  24752. {
  24753. int i;
  24754. int imax;
  24755. int k;
  24756. sp_uint64 c;
  24757. sp_uint64 lo;
  24758. c = ((sp_uint64)a[14]) * b[14];
  24759. r[29] = (sp_digit)(c >> 26);
  24760. c &= 0x3ffffff;
  24761. for (k = 27; k >= 0; k--) {
  24762. if (k >= 15) {
  24763. i = k - 14;
  24764. imax = 14;
  24765. }
  24766. else {
  24767. i = 0;
  24768. imax = k;
  24769. }
  24770. lo = 0;
  24771. for (; i <= imax; i++) {
  24772. lo += ((sp_uint64)a[i]) * b[k - i];
  24773. }
  24774. c += lo >> 26;
  24775. r[k + 2] += (sp_digit)(c >> 26);
  24776. r[k + 1] = (sp_digit)(c & 0x3ffffff);
  24777. c = lo & 0x3ffffff;
  24778. }
  24779. r[0] = (sp_digit)c;
  24780. }
  24781. #else
  24782. /* Multiply a and b into r. (r = a * b)
  24783. *
  24784. * r A single precision integer.
  24785. * a A single precision integer.
  24786. * b A single precision integer.
  24787. */
  24788. SP_NOINLINE static void sp_384_mul_15(sp_digit* r, const sp_digit* a,
  24789. const sp_digit* b)
  24790. {
  24791. sp_int64 t0 = ((sp_int64)a[ 0]) * b[ 0];
  24792. sp_int64 t1 = ((sp_int64)a[ 0]) * b[ 1]
  24793. + ((sp_int64)a[ 1]) * b[ 0];
  24794. sp_int64 t2 = ((sp_int64)a[ 0]) * b[ 2]
  24795. + ((sp_int64)a[ 1]) * b[ 1]
  24796. + ((sp_int64)a[ 2]) * b[ 0];
  24797. sp_int64 t3 = ((sp_int64)a[ 0]) * b[ 3]
  24798. + ((sp_int64)a[ 1]) * b[ 2]
  24799. + ((sp_int64)a[ 2]) * b[ 1]
  24800. + ((sp_int64)a[ 3]) * b[ 0];
  24801. sp_int64 t4 = ((sp_int64)a[ 0]) * b[ 4]
  24802. + ((sp_int64)a[ 1]) * b[ 3]
  24803. + ((sp_int64)a[ 2]) * b[ 2]
  24804. + ((sp_int64)a[ 3]) * b[ 1]
  24805. + ((sp_int64)a[ 4]) * b[ 0];
  24806. sp_int64 t5 = ((sp_int64)a[ 0]) * b[ 5]
  24807. + ((sp_int64)a[ 1]) * b[ 4]
  24808. + ((sp_int64)a[ 2]) * b[ 3]
  24809. + ((sp_int64)a[ 3]) * b[ 2]
  24810. + ((sp_int64)a[ 4]) * b[ 1]
  24811. + ((sp_int64)a[ 5]) * b[ 0];
  24812. sp_int64 t6 = ((sp_int64)a[ 0]) * b[ 6]
  24813. + ((sp_int64)a[ 1]) * b[ 5]
  24814. + ((sp_int64)a[ 2]) * b[ 4]
  24815. + ((sp_int64)a[ 3]) * b[ 3]
  24816. + ((sp_int64)a[ 4]) * b[ 2]
  24817. + ((sp_int64)a[ 5]) * b[ 1]
  24818. + ((sp_int64)a[ 6]) * b[ 0];
  24819. sp_int64 t7 = ((sp_int64)a[ 0]) * b[ 7]
  24820. + ((sp_int64)a[ 1]) * b[ 6]
  24821. + ((sp_int64)a[ 2]) * b[ 5]
  24822. + ((sp_int64)a[ 3]) * b[ 4]
  24823. + ((sp_int64)a[ 4]) * b[ 3]
  24824. + ((sp_int64)a[ 5]) * b[ 2]
  24825. + ((sp_int64)a[ 6]) * b[ 1]
  24826. + ((sp_int64)a[ 7]) * b[ 0];
  24827. sp_int64 t8 = ((sp_int64)a[ 0]) * b[ 8]
  24828. + ((sp_int64)a[ 1]) * b[ 7]
  24829. + ((sp_int64)a[ 2]) * b[ 6]
  24830. + ((sp_int64)a[ 3]) * b[ 5]
  24831. + ((sp_int64)a[ 4]) * b[ 4]
  24832. + ((sp_int64)a[ 5]) * b[ 3]
  24833. + ((sp_int64)a[ 6]) * b[ 2]
  24834. + ((sp_int64)a[ 7]) * b[ 1]
  24835. + ((sp_int64)a[ 8]) * b[ 0];
  24836. sp_int64 t9 = ((sp_int64)a[ 0]) * b[ 9]
  24837. + ((sp_int64)a[ 1]) * b[ 8]
  24838. + ((sp_int64)a[ 2]) * b[ 7]
  24839. + ((sp_int64)a[ 3]) * b[ 6]
  24840. + ((sp_int64)a[ 4]) * b[ 5]
  24841. + ((sp_int64)a[ 5]) * b[ 4]
  24842. + ((sp_int64)a[ 6]) * b[ 3]
  24843. + ((sp_int64)a[ 7]) * b[ 2]
  24844. + ((sp_int64)a[ 8]) * b[ 1]
  24845. + ((sp_int64)a[ 9]) * b[ 0];
  24846. sp_int64 t10 = ((sp_int64)a[ 0]) * b[10]
  24847. + ((sp_int64)a[ 1]) * b[ 9]
  24848. + ((sp_int64)a[ 2]) * b[ 8]
  24849. + ((sp_int64)a[ 3]) * b[ 7]
  24850. + ((sp_int64)a[ 4]) * b[ 6]
  24851. + ((sp_int64)a[ 5]) * b[ 5]
  24852. + ((sp_int64)a[ 6]) * b[ 4]
  24853. + ((sp_int64)a[ 7]) * b[ 3]
  24854. + ((sp_int64)a[ 8]) * b[ 2]
  24855. + ((sp_int64)a[ 9]) * b[ 1]
  24856. + ((sp_int64)a[10]) * b[ 0];
  24857. sp_int64 t11 = ((sp_int64)a[ 0]) * b[11]
  24858. + ((sp_int64)a[ 1]) * b[10]
  24859. + ((sp_int64)a[ 2]) * b[ 9]
  24860. + ((sp_int64)a[ 3]) * b[ 8]
  24861. + ((sp_int64)a[ 4]) * b[ 7]
  24862. + ((sp_int64)a[ 5]) * b[ 6]
  24863. + ((sp_int64)a[ 6]) * b[ 5]
  24864. + ((sp_int64)a[ 7]) * b[ 4]
  24865. + ((sp_int64)a[ 8]) * b[ 3]
  24866. + ((sp_int64)a[ 9]) * b[ 2]
  24867. + ((sp_int64)a[10]) * b[ 1]
  24868. + ((sp_int64)a[11]) * b[ 0];
  24869. sp_int64 t12 = ((sp_int64)a[ 0]) * b[12]
  24870. + ((sp_int64)a[ 1]) * b[11]
  24871. + ((sp_int64)a[ 2]) * b[10]
  24872. + ((sp_int64)a[ 3]) * b[ 9]
  24873. + ((sp_int64)a[ 4]) * b[ 8]
  24874. + ((sp_int64)a[ 5]) * b[ 7]
  24875. + ((sp_int64)a[ 6]) * b[ 6]
  24876. + ((sp_int64)a[ 7]) * b[ 5]
  24877. + ((sp_int64)a[ 8]) * b[ 4]
  24878. + ((sp_int64)a[ 9]) * b[ 3]
  24879. + ((sp_int64)a[10]) * b[ 2]
  24880. + ((sp_int64)a[11]) * b[ 1]
  24881. + ((sp_int64)a[12]) * b[ 0];
  24882. sp_int64 t13 = ((sp_int64)a[ 0]) * b[13]
  24883. + ((sp_int64)a[ 1]) * b[12]
  24884. + ((sp_int64)a[ 2]) * b[11]
  24885. + ((sp_int64)a[ 3]) * b[10]
  24886. + ((sp_int64)a[ 4]) * b[ 9]
  24887. + ((sp_int64)a[ 5]) * b[ 8]
  24888. + ((sp_int64)a[ 6]) * b[ 7]
  24889. + ((sp_int64)a[ 7]) * b[ 6]
  24890. + ((sp_int64)a[ 8]) * b[ 5]
  24891. + ((sp_int64)a[ 9]) * b[ 4]
  24892. + ((sp_int64)a[10]) * b[ 3]
  24893. + ((sp_int64)a[11]) * b[ 2]
  24894. + ((sp_int64)a[12]) * b[ 1]
  24895. + ((sp_int64)a[13]) * b[ 0];
  24896. sp_int64 t14 = ((sp_int64)a[ 0]) * b[14]
  24897. + ((sp_int64)a[ 1]) * b[13]
  24898. + ((sp_int64)a[ 2]) * b[12]
  24899. + ((sp_int64)a[ 3]) * b[11]
  24900. + ((sp_int64)a[ 4]) * b[10]
  24901. + ((sp_int64)a[ 5]) * b[ 9]
  24902. + ((sp_int64)a[ 6]) * b[ 8]
  24903. + ((sp_int64)a[ 7]) * b[ 7]
  24904. + ((sp_int64)a[ 8]) * b[ 6]
  24905. + ((sp_int64)a[ 9]) * b[ 5]
  24906. + ((sp_int64)a[10]) * b[ 4]
  24907. + ((sp_int64)a[11]) * b[ 3]
  24908. + ((sp_int64)a[12]) * b[ 2]
  24909. + ((sp_int64)a[13]) * b[ 1]
  24910. + ((sp_int64)a[14]) * b[ 0];
  24911. sp_int64 t15 = ((sp_int64)a[ 1]) * b[14]
  24912. + ((sp_int64)a[ 2]) * b[13]
  24913. + ((sp_int64)a[ 3]) * b[12]
  24914. + ((sp_int64)a[ 4]) * b[11]
  24915. + ((sp_int64)a[ 5]) * b[10]
  24916. + ((sp_int64)a[ 6]) * b[ 9]
  24917. + ((sp_int64)a[ 7]) * b[ 8]
  24918. + ((sp_int64)a[ 8]) * b[ 7]
  24919. + ((sp_int64)a[ 9]) * b[ 6]
  24920. + ((sp_int64)a[10]) * b[ 5]
  24921. + ((sp_int64)a[11]) * b[ 4]
  24922. + ((sp_int64)a[12]) * b[ 3]
  24923. + ((sp_int64)a[13]) * b[ 2]
  24924. + ((sp_int64)a[14]) * b[ 1];
  24925. sp_int64 t16 = ((sp_int64)a[ 2]) * b[14]
  24926. + ((sp_int64)a[ 3]) * b[13]
  24927. + ((sp_int64)a[ 4]) * b[12]
  24928. + ((sp_int64)a[ 5]) * b[11]
  24929. + ((sp_int64)a[ 6]) * b[10]
  24930. + ((sp_int64)a[ 7]) * b[ 9]
  24931. + ((sp_int64)a[ 8]) * b[ 8]
  24932. + ((sp_int64)a[ 9]) * b[ 7]
  24933. + ((sp_int64)a[10]) * b[ 6]
  24934. + ((sp_int64)a[11]) * b[ 5]
  24935. + ((sp_int64)a[12]) * b[ 4]
  24936. + ((sp_int64)a[13]) * b[ 3]
  24937. + ((sp_int64)a[14]) * b[ 2];
  24938. sp_int64 t17 = ((sp_int64)a[ 3]) * b[14]
  24939. + ((sp_int64)a[ 4]) * b[13]
  24940. + ((sp_int64)a[ 5]) * b[12]
  24941. + ((sp_int64)a[ 6]) * b[11]
  24942. + ((sp_int64)a[ 7]) * b[10]
  24943. + ((sp_int64)a[ 8]) * b[ 9]
  24944. + ((sp_int64)a[ 9]) * b[ 8]
  24945. + ((sp_int64)a[10]) * b[ 7]
  24946. + ((sp_int64)a[11]) * b[ 6]
  24947. + ((sp_int64)a[12]) * b[ 5]
  24948. + ((sp_int64)a[13]) * b[ 4]
  24949. + ((sp_int64)a[14]) * b[ 3];
  24950. sp_int64 t18 = ((sp_int64)a[ 4]) * b[14]
  24951. + ((sp_int64)a[ 5]) * b[13]
  24952. + ((sp_int64)a[ 6]) * b[12]
  24953. + ((sp_int64)a[ 7]) * b[11]
  24954. + ((sp_int64)a[ 8]) * b[10]
  24955. + ((sp_int64)a[ 9]) * b[ 9]
  24956. + ((sp_int64)a[10]) * b[ 8]
  24957. + ((sp_int64)a[11]) * b[ 7]
  24958. + ((sp_int64)a[12]) * b[ 6]
  24959. + ((sp_int64)a[13]) * b[ 5]
  24960. + ((sp_int64)a[14]) * b[ 4];
  24961. sp_int64 t19 = ((sp_int64)a[ 5]) * b[14]
  24962. + ((sp_int64)a[ 6]) * b[13]
  24963. + ((sp_int64)a[ 7]) * b[12]
  24964. + ((sp_int64)a[ 8]) * b[11]
  24965. + ((sp_int64)a[ 9]) * b[10]
  24966. + ((sp_int64)a[10]) * b[ 9]
  24967. + ((sp_int64)a[11]) * b[ 8]
  24968. + ((sp_int64)a[12]) * b[ 7]
  24969. + ((sp_int64)a[13]) * b[ 6]
  24970. + ((sp_int64)a[14]) * b[ 5];
  24971. sp_int64 t20 = ((sp_int64)a[ 6]) * b[14]
  24972. + ((sp_int64)a[ 7]) * b[13]
  24973. + ((sp_int64)a[ 8]) * b[12]
  24974. + ((sp_int64)a[ 9]) * b[11]
  24975. + ((sp_int64)a[10]) * b[10]
  24976. + ((sp_int64)a[11]) * b[ 9]
  24977. + ((sp_int64)a[12]) * b[ 8]
  24978. + ((sp_int64)a[13]) * b[ 7]
  24979. + ((sp_int64)a[14]) * b[ 6];
  24980. sp_int64 t21 = ((sp_int64)a[ 7]) * b[14]
  24981. + ((sp_int64)a[ 8]) * b[13]
  24982. + ((sp_int64)a[ 9]) * b[12]
  24983. + ((sp_int64)a[10]) * b[11]
  24984. + ((sp_int64)a[11]) * b[10]
  24985. + ((sp_int64)a[12]) * b[ 9]
  24986. + ((sp_int64)a[13]) * b[ 8]
  24987. + ((sp_int64)a[14]) * b[ 7];
  24988. sp_int64 t22 = ((sp_int64)a[ 8]) * b[14]
  24989. + ((sp_int64)a[ 9]) * b[13]
  24990. + ((sp_int64)a[10]) * b[12]
  24991. + ((sp_int64)a[11]) * b[11]
  24992. + ((sp_int64)a[12]) * b[10]
  24993. + ((sp_int64)a[13]) * b[ 9]
  24994. + ((sp_int64)a[14]) * b[ 8];
  24995. sp_int64 t23 = ((sp_int64)a[ 9]) * b[14]
  24996. + ((sp_int64)a[10]) * b[13]
  24997. + ((sp_int64)a[11]) * b[12]
  24998. + ((sp_int64)a[12]) * b[11]
  24999. + ((sp_int64)a[13]) * b[10]
  25000. + ((sp_int64)a[14]) * b[ 9];
  25001. sp_int64 t24 = ((sp_int64)a[10]) * b[14]
  25002. + ((sp_int64)a[11]) * b[13]
  25003. + ((sp_int64)a[12]) * b[12]
  25004. + ((sp_int64)a[13]) * b[11]
  25005. + ((sp_int64)a[14]) * b[10];
  25006. sp_int64 t25 = ((sp_int64)a[11]) * b[14]
  25007. + ((sp_int64)a[12]) * b[13]
  25008. + ((sp_int64)a[13]) * b[12]
  25009. + ((sp_int64)a[14]) * b[11];
  25010. sp_int64 t26 = ((sp_int64)a[12]) * b[14]
  25011. + ((sp_int64)a[13]) * b[13]
  25012. + ((sp_int64)a[14]) * b[12];
  25013. sp_int64 t27 = ((sp_int64)a[13]) * b[14]
  25014. + ((sp_int64)a[14]) * b[13];
  25015. sp_int64 t28 = ((sp_int64)a[14]) * b[14];
  25016. t1 += t0 >> 26; r[ 0] = t0 & 0x3ffffff;
  25017. t2 += t1 >> 26; r[ 1] = t1 & 0x3ffffff;
  25018. t3 += t2 >> 26; r[ 2] = t2 & 0x3ffffff;
  25019. t4 += t3 >> 26; r[ 3] = t3 & 0x3ffffff;
  25020. t5 += t4 >> 26; r[ 4] = t4 & 0x3ffffff;
  25021. t6 += t5 >> 26; r[ 5] = t5 & 0x3ffffff;
  25022. t7 += t6 >> 26; r[ 6] = t6 & 0x3ffffff;
  25023. t8 += t7 >> 26; r[ 7] = t7 & 0x3ffffff;
  25024. t9 += t8 >> 26; r[ 8] = t8 & 0x3ffffff;
  25025. t10 += t9 >> 26; r[ 9] = t9 & 0x3ffffff;
  25026. t11 += t10 >> 26; r[10] = t10 & 0x3ffffff;
  25027. t12 += t11 >> 26; r[11] = t11 & 0x3ffffff;
  25028. t13 += t12 >> 26; r[12] = t12 & 0x3ffffff;
  25029. t14 += t13 >> 26; r[13] = t13 & 0x3ffffff;
  25030. t15 += t14 >> 26; r[14] = t14 & 0x3ffffff;
  25031. t16 += t15 >> 26; r[15] = t15 & 0x3ffffff;
  25032. t17 += t16 >> 26; r[16] = t16 & 0x3ffffff;
  25033. t18 += t17 >> 26; r[17] = t17 & 0x3ffffff;
  25034. t19 += t18 >> 26; r[18] = t18 & 0x3ffffff;
  25035. t20 += t19 >> 26; r[19] = t19 & 0x3ffffff;
  25036. t21 += t20 >> 26; r[20] = t20 & 0x3ffffff;
  25037. t22 += t21 >> 26; r[21] = t21 & 0x3ffffff;
  25038. t23 += t22 >> 26; r[22] = t22 & 0x3ffffff;
  25039. t24 += t23 >> 26; r[23] = t23 & 0x3ffffff;
  25040. t25 += t24 >> 26; r[24] = t24 & 0x3ffffff;
  25041. t26 += t25 >> 26; r[25] = t25 & 0x3ffffff;
  25042. t27 += t26 >> 26; r[26] = t26 & 0x3ffffff;
  25043. t28 += t27 >> 26; r[27] = t27 & 0x3ffffff;
  25044. r[29] = (sp_digit)(t28 >> 26);
  25045. r[28] = t28 & 0x3ffffff;
  25046. }
  25047. #endif /* WOLFSSL_SP_SMALL */
  25048. #ifdef WOLFSSL_SP_SMALL
  25049. /* Square a and put result in r. (r = a * a)
  25050. *
  25051. * r A single precision integer.
  25052. * a A single precision integer.
  25053. */
  25054. SP_NOINLINE static void sp_384_sqr_15(sp_digit* r, const sp_digit* a)
  25055. {
  25056. int i;
  25057. int imax;
  25058. int k;
  25059. sp_uint64 c;
  25060. sp_uint64 t;
  25061. c = ((sp_uint64)a[14]) * a[14];
  25062. r[29] = (sp_digit)(c >> 26);
  25063. c = (c & 0x3ffffff) << 26;
  25064. for (k = 27; k >= 0; k--) {
  25065. i = (k + 1) / 2;
  25066. if ((k & 1) == 0) {
  25067. c += ((sp_uint64)a[i]) * a[i];
  25068. i++;
  25069. }
  25070. if (k < 14) {
  25071. imax = k;
  25072. }
  25073. else {
  25074. imax = 14;
  25075. }
  25076. t = 0;
  25077. for (; i <= imax; i++) {
  25078. t += ((sp_uint64)a[i]) * a[k - i];
  25079. }
  25080. c += t * 2;
  25081. r[k + 2] += (sp_digit) (c >> 52);
  25082. r[k + 1] = (sp_digit)((c >> 26) & 0x3ffffff);
  25083. c = (c & 0x3ffffff) << 26;
  25084. }
  25085. r[0] = (sp_digit)(c >> 26);
  25086. }
  25087. #else
  25088. /* Square a and put result in r. (r = a * a)
  25089. *
  25090. * r A single precision integer.
  25091. * a A single precision integer.
  25092. */
  25093. SP_NOINLINE static void sp_384_sqr_15(sp_digit* r, const sp_digit* a)
  25094. {
  25095. sp_int64 t0 = ((sp_int64)a[ 0]) * a[ 0];
  25096. sp_int64 t1 = (((sp_int64)a[ 0]) * a[ 1]) * 2;
  25097. sp_int64 t2 = (((sp_int64)a[ 0]) * a[ 2]) * 2
  25098. + ((sp_int64)a[ 1]) * a[ 1];
  25099. sp_int64 t3 = (((sp_int64)a[ 0]) * a[ 3]
  25100. + ((sp_int64)a[ 1]) * a[ 2]) * 2;
  25101. sp_int64 t4 = (((sp_int64)a[ 0]) * a[ 4]
  25102. + ((sp_int64)a[ 1]) * a[ 3]) * 2
  25103. + ((sp_int64)a[ 2]) * a[ 2];
  25104. sp_int64 t5 = (((sp_int64)a[ 0]) * a[ 5]
  25105. + ((sp_int64)a[ 1]) * a[ 4]
  25106. + ((sp_int64)a[ 2]) * a[ 3]) * 2;
  25107. sp_int64 t6 = (((sp_int64)a[ 0]) * a[ 6]
  25108. + ((sp_int64)a[ 1]) * a[ 5]
  25109. + ((sp_int64)a[ 2]) * a[ 4]) * 2
  25110. + ((sp_int64)a[ 3]) * a[ 3];
  25111. sp_int64 t7 = (((sp_int64)a[ 0]) * a[ 7]
  25112. + ((sp_int64)a[ 1]) * a[ 6]
  25113. + ((sp_int64)a[ 2]) * a[ 5]
  25114. + ((sp_int64)a[ 3]) * a[ 4]) * 2;
  25115. sp_int64 t8 = (((sp_int64)a[ 0]) * a[ 8]
  25116. + ((sp_int64)a[ 1]) * a[ 7]
  25117. + ((sp_int64)a[ 2]) * a[ 6]
  25118. + ((sp_int64)a[ 3]) * a[ 5]) * 2
  25119. + ((sp_int64)a[ 4]) * a[ 4];
  25120. sp_int64 t9 = (((sp_int64)a[ 0]) * a[ 9]
  25121. + ((sp_int64)a[ 1]) * a[ 8]
  25122. + ((sp_int64)a[ 2]) * a[ 7]
  25123. + ((sp_int64)a[ 3]) * a[ 6]
  25124. + ((sp_int64)a[ 4]) * a[ 5]) * 2;
  25125. sp_int64 t10 = (((sp_int64)a[ 0]) * a[10]
  25126. + ((sp_int64)a[ 1]) * a[ 9]
  25127. + ((sp_int64)a[ 2]) * a[ 8]
  25128. + ((sp_int64)a[ 3]) * a[ 7]
  25129. + ((sp_int64)a[ 4]) * a[ 6]) * 2
  25130. + ((sp_int64)a[ 5]) * a[ 5];
  25131. sp_int64 t11 = (((sp_int64)a[ 0]) * a[11]
  25132. + ((sp_int64)a[ 1]) * a[10]
  25133. + ((sp_int64)a[ 2]) * a[ 9]
  25134. + ((sp_int64)a[ 3]) * a[ 8]
  25135. + ((sp_int64)a[ 4]) * a[ 7]
  25136. + ((sp_int64)a[ 5]) * a[ 6]) * 2;
  25137. sp_int64 t12 = (((sp_int64)a[ 0]) * a[12]
  25138. + ((sp_int64)a[ 1]) * a[11]
  25139. + ((sp_int64)a[ 2]) * a[10]
  25140. + ((sp_int64)a[ 3]) * a[ 9]
  25141. + ((sp_int64)a[ 4]) * a[ 8]
  25142. + ((sp_int64)a[ 5]) * a[ 7]) * 2
  25143. + ((sp_int64)a[ 6]) * a[ 6];
  25144. sp_int64 t13 = (((sp_int64)a[ 0]) * a[13]
  25145. + ((sp_int64)a[ 1]) * a[12]
  25146. + ((sp_int64)a[ 2]) * a[11]
  25147. + ((sp_int64)a[ 3]) * a[10]
  25148. + ((sp_int64)a[ 4]) * a[ 9]
  25149. + ((sp_int64)a[ 5]) * a[ 8]
  25150. + ((sp_int64)a[ 6]) * a[ 7]) * 2;
  25151. sp_int64 t14 = (((sp_int64)a[ 0]) * a[14]
  25152. + ((sp_int64)a[ 1]) * a[13]
  25153. + ((sp_int64)a[ 2]) * a[12]
  25154. + ((sp_int64)a[ 3]) * a[11]
  25155. + ((sp_int64)a[ 4]) * a[10]
  25156. + ((sp_int64)a[ 5]) * a[ 9]
  25157. + ((sp_int64)a[ 6]) * a[ 8]) * 2
  25158. + ((sp_int64)a[ 7]) * a[ 7];
  25159. sp_int64 t15 = (((sp_int64)a[ 1]) * a[14]
  25160. + ((sp_int64)a[ 2]) * a[13]
  25161. + ((sp_int64)a[ 3]) * a[12]
  25162. + ((sp_int64)a[ 4]) * a[11]
  25163. + ((sp_int64)a[ 5]) * a[10]
  25164. + ((sp_int64)a[ 6]) * a[ 9]
  25165. + ((sp_int64)a[ 7]) * a[ 8]) * 2;
  25166. sp_int64 t16 = (((sp_int64)a[ 2]) * a[14]
  25167. + ((sp_int64)a[ 3]) * a[13]
  25168. + ((sp_int64)a[ 4]) * a[12]
  25169. + ((sp_int64)a[ 5]) * a[11]
  25170. + ((sp_int64)a[ 6]) * a[10]
  25171. + ((sp_int64)a[ 7]) * a[ 9]) * 2
  25172. + ((sp_int64)a[ 8]) * a[ 8];
  25173. sp_int64 t17 = (((sp_int64)a[ 3]) * a[14]
  25174. + ((sp_int64)a[ 4]) * a[13]
  25175. + ((sp_int64)a[ 5]) * a[12]
  25176. + ((sp_int64)a[ 6]) * a[11]
  25177. + ((sp_int64)a[ 7]) * a[10]
  25178. + ((sp_int64)a[ 8]) * a[ 9]) * 2;
  25179. sp_int64 t18 = (((sp_int64)a[ 4]) * a[14]
  25180. + ((sp_int64)a[ 5]) * a[13]
  25181. + ((sp_int64)a[ 6]) * a[12]
  25182. + ((sp_int64)a[ 7]) * a[11]
  25183. + ((sp_int64)a[ 8]) * a[10]) * 2
  25184. + ((sp_int64)a[ 9]) * a[ 9];
  25185. sp_int64 t19 = (((sp_int64)a[ 5]) * a[14]
  25186. + ((sp_int64)a[ 6]) * a[13]
  25187. + ((sp_int64)a[ 7]) * a[12]
  25188. + ((sp_int64)a[ 8]) * a[11]
  25189. + ((sp_int64)a[ 9]) * a[10]) * 2;
  25190. sp_int64 t20 = (((sp_int64)a[ 6]) * a[14]
  25191. + ((sp_int64)a[ 7]) * a[13]
  25192. + ((sp_int64)a[ 8]) * a[12]
  25193. + ((sp_int64)a[ 9]) * a[11]) * 2
  25194. + ((sp_int64)a[10]) * a[10];
  25195. sp_int64 t21 = (((sp_int64)a[ 7]) * a[14]
  25196. + ((sp_int64)a[ 8]) * a[13]
  25197. + ((sp_int64)a[ 9]) * a[12]
  25198. + ((sp_int64)a[10]) * a[11]) * 2;
  25199. sp_int64 t22 = (((sp_int64)a[ 8]) * a[14]
  25200. + ((sp_int64)a[ 9]) * a[13]
  25201. + ((sp_int64)a[10]) * a[12]) * 2
  25202. + ((sp_int64)a[11]) * a[11];
  25203. sp_int64 t23 = (((sp_int64)a[ 9]) * a[14]
  25204. + ((sp_int64)a[10]) * a[13]
  25205. + ((sp_int64)a[11]) * a[12]) * 2;
  25206. sp_int64 t24 = (((sp_int64)a[10]) * a[14]
  25207. + ((sp_int64)a[11]) * a[13]) * 2
  25208. + ((sp_int64)a[12]) * a[12];
  25209. sp_int64 t25 = (((sp_int64)a[11]) * a[14]
  25210. + ((sp_int64)a[12]) * a[13]) * 2;
  25211. sp_int64 t26 = (((sp_int64)a[12]) * a[14]) * 2
  25212. + ((sp_int64)a[13]) * a[13];
  25213. sp_int64 t27 = (((sp_int64)a[13]) * a[14]) * 2;
  25214. sp_int64 t28 = ((sp_int64)a[14]) * a[14];
  25215. t1 += t0 >> 26; r[ 0] = t0 & 0x3ffffff;
  25216. t2 += t1 >> 26; r[ 1] = t1 & 0x3ffffff;
  25217. t3 += t2 >> 26; r[ 2] = t2 & 0x3ffffff;
  25218. t4 += t3 >> 26; r[ 3] = t3 & 0x3ffffff;
  25219. t5 += t4 >> 26; r[ 4] = t4 & 0x3ffffff;
  25220. t6 += t5 >> 26; r[ 5] = t5 & 0x3ffffff;
  25221. t7 += t6 >> 26; r[ 6] = t6 & 0x3ffffff;
  25222. t8 += t7 >> 26; r[ 7] = t7 & 0x3ffffff;
  25223. t9 += t8 >> 26; r[ 8] = t8 & 0x3ffffff;
  25224. t10 += t9 >> 26; r[ 9] = t9 & 0x3ffffff;
  25225. t11 += t10 >> 26; r[10] = t10 & 0x3ffffff;
  25226. t12 += t11 >> 26; r[11] = t11 & 0x3ffffff;
  25227. t13 += t12 >> 26; r[12] = t12 & 0x3ffffff;
  25228. t14 += t13 >> 26; r[13] = t13 & 0x3ffffff;
  25229. t15 += t14 >> 26; r[14] = t14 & 0x3ffffff;
  25230. t16 += t15 >> 26; r[15] = t15 & 0x3ffffff;
  25231. t17 += t16 >> 26; r[16] = t16 & 0x3ffffff;
  25232. t18 += t17 >> 26; r[17] = t17 & 0x3ffffff;
  25233. t19 += t18 >> 26; r[18] = t18 & 0x3ffffff;
  25234. t20 += t19 >> 26; r[19] = t19 & 0x3ffffff;
  25235. t21 += t20 >> 26; r[20] = t20 & 0x3ffffff;
  25236. t22 += t21 >> 26; r[21] = t21 & 0x3ffffff;
  25237. t23 += t22 >> 26; r[22] = t22 & 0x3ffffff;
  25238. t24 += t23 >> 26; r[23] = t23 & 0x3ffffff;
  25239. t25 += t24 >> 26; r[24] = t24 & 0x3ffffff;
  25240. t26 += t25 >> 26; r[25] = t25 & 0x3ffffff;
  25241. t27 += t26 >> 26; r[26] = t26 & 0x3ffffff;
  25242. t28 += t27 >> 26; r[27] = t27 & 0x3ffffff;
  25243. r[29] = (sp_digit)(t28 >> 26);
  25244. r[28] = t28 & 0x3ffffff;
  25245. }
  25246. #endif /* WOLFSSL_SP_SMALL */
  25247. #ifdef WOLFSSL_SP_SMALL
  25248. /* Add b to a into r. (r = a + b)
  25249. *
  25250. * r A single precision integer.
  25251. * a A single precision integer.
  25252. * b A single precision integer.
  25253. */
  25254. SP_NOINLINE static int sp_384_add_15(sp_digit* r, const sp_digit* a,
  25255. const sp_digit* b)
  25256. {
  25257. int i;
  25258. for (i = 0; i < 15; i++) {
  25259. r[i] = a[i] + b[i];
  25260. }
  25261. return 0;
  25262. }
  25263. #else
  25264. /* Add b to a into r. (r = a + b)
  25265. *
  25266. * r A single precision integer.
  25267. * a A single precision integer.
  25268. * b A single precision integer.
  25269. */
  25270. SP_NOINLINE static int sp_384_add_15(sp_digit* r, const sp_digit* a,
  25271. const sp_digit* b)
  25272. {
  25273. r[ 0] = a[ 0] + b[ 0];
  25274. r[ 1] = a[ 1] + b[ 1];
  25275. r[ 2] = a[ 2] + b[ 2];
  25276. r[ 3] = a[ 3] + b[ 3];
  25277. r[ 4] = a[ 4] + b[ 4];
  25278. r[ 5] = a[ 5] + b[ 5];
  25279. r[ 6] = a[ 6] + b[ 6];
  25280. r[ 7] = a[ 7] + b[ 7];
  25281. r[ 8] = a[ 8] + b[ 8];
  25282. r[ 9] = a[ 9] + b[ 9];
  25283. r[10] = a[10] + b[10];
  25284. r[11] = a[11] + b[11];
  25285. r[12] = a[12] + b[12];
  25286. r[13] = a[13] + b[13];
  25287. r[14] = a[14] + b[14];
  25288. return 0;
  25289. }
  25290. #endif /* WOLFSSL_SP_SMALL */
  25291. #ifdef WOLFSSL_SP_SMALL
  25292. /* Sub b from a into r. (r = a - b)
  25293. *
  25294. * r A single precision integer.
  25295. * a A single precision integer.
  25296. * b A single precision integer.
  25297. */
  25298. SP_NOINLINE static int sp_384_sub_15(sp_digit* r, const sp_digit* a,
  25299. const sp_digit* b)
  25300. {
  25301. int i;
  25302. for (i = 0; i < 15; i++) {
  25303. r[i] = a[i] - b[i];
  25304. }
  25305. return 0;
  25306. }
  25307. #else
  25308. /* Sub b from a into r. (r = a - b)
  25309. *
  25310. * r A single precision integer.
  25311. * a A single precision integer.
  25312. * b A single precision integer.
  25313. */
  25314. SP_NOINLINE static int sp_384_sub_15(sp_digit* r, const sp_digit* a,
  25315. const sp_digit* b)
  25316. {
  25317. r[ 0] = a[ 0] - b[ 0];
  25318. r[ 1] = a[ 1] - b[ 1];
  25319. r[ 2] = a[ 2] - b[ 2];
  25320. r[ 3] = a[ 3] - b[ 3];
  25321. r[ 4] = a[ 4] - b[ 4];
  25322. r[ 5] = a[ 5] - b[ 5];
  25323. r[ 6] = a[ 6] - b[ 6];
  25324. r[ 7] = a[ 7] - b[ 7];
  25325. r[ 8] = a[ 8] - b[ 8];
  25326. r[ 9] = a[ 9] - b[ 9];
  25327. r[10] = a[10] - b[10];
  25328. r[11] = a[11] - b[11];
  25329. r[12] = a[12] - b[12];
  25330. r[13] = a[13] - b[13];
  25331. r[14] = a[14] - b[14];
  25332. return 0;
  25333. }
  25334. #endif /* WOLFSSL_SP_SMALL */
  25335. /* Convert an mp_int to an array of sp_digit.
  25336. *
  25337. * r A single precision integer.
  25338. * size Maximum number of bytes to convert
  25339. * a A multi-precision integer.
  25340. */
  25341. static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a)
  25342. {
  25343. #if DIGIT_BIT == 26
  25344. int j;
  25345. XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
  25346. for (j = a->used; j < size; j++) {
  25347. r[j] = 0;
  25348. }
  25349. #elif DIGIT_BIT > 26
  25350. int i;
  25351. int j = 0;
  25352. word32 s = 0;
  25353. r[0] = 0;
  25354. for (i = 0; i < a->used && j < size; i++) {
  25355. r[j] |= ((sp_digit)a->dp[i] << s);
  25356. r[j] &= 0x3ffffff;
  25357. s = 26U - s;
  25358. if (j + 1 >= size) {
  25359. break;
  25360. }
  25361. /* lint allow cast of mismatch word32 and mp_digit */
  25362. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  25363. while ((s + 26U) <= (word32)DIGIT_BIT) {
  25364. s += 26U;
  25365. r[j] &= 0x3ffffff;
  25366. if (j + 1 >= size) {
  25367. break;
  25368. }
  25369. if (s < (word32)DIGIT_BIT) {
  25370. /* lint allow cast of mismatch word32 and mp_digit */
  25371. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  25372. }
  25373. else {
  25374. r[++j] = (sp_digit)0;
  25375. }
  25376. }
  25377. s = (word32)DIGIT_BIT - s;
  25378. }
  25379. for (j++; j < size; j++) {
  25380. r[j] = 0;
  25381. }
  25382. #else
  25383. int i;
  25384. int j = 0;
  25385. int s = 0;
  25386. r[0] = 0;
  25387. for (i = 0; i < a->used && j < size; i++) {
  25388. r[j] |= ((sp_digit)a->dp[i]) << s;
  25389. if (s + DIGIT_BIT >= 26) {
  25390. r[j] &= 0x3ffffff;
  25391. if (j + 1 >= size) {
  25392. break;
  25393. }
  25394. s = 26 - s;
  25395. if (s == DIGIT_BIT) {
  25396. r[++j] = 0;
  25397. s = 0;
  25398. }
  25399. else {
  25400. r[++j] = a->dp[i] >> s;
  25401. s = DIGIT_BIT - s;
  25402. }
  25403. }
  25404. else {
  25405. s += DIGIT_BIT;
  25406. }
  25407. }
  25408. for (j++; j < size; j++) {
  25409. r[j] = 0;
  25410. }
  25411. #endif
  25412. }
  25413. /* Convert a point of type ecc_point to type sp_point_384.
  25414. *
  25415. * p Point of type sp_point_384 (result).
  25416. * pm Point of type ecc_point.
  25417. */
  25418. static void sp_384_point_from_ecc_point_15(sp_point_384* p,
  25419. const ecc_point* pm)
  25420. {
  25421. XMEMSET(p->x, 0, sizeof(p->x));
  25422. XMEMSET(p->y, 0, sizeof(p->y));
  25423. XMEMSET(p->z, 0, sizeof(p->z));
  25424. sp_384_from_mp(p->x, 15, pm->x);
  25425. sp_384_from_mp(p->y, 15, pm->y);
  25426. sp_384_from_mp(p->z, 15, pm->z);
  25427. p->infinity = 0;
  25428. }
  25429. /* Convert an array of sp_digit to an mp_int.
  25430. *
  25431. * a A single precision integer.
  25432. * r A multi-precision integer.
  25433. */
  25434. static int sp_384_to_mp(const sp_digit* a, mp_int* r)
  25435. {
  25436. int err;
  25437. err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT);
  25438. if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
  25439. #if DIGIT_BIT == 26
  25440. XMEMCPY(r->dp, a, sizeof(sp_digit) * 15);
  25441. r->used = 15;
  25442. mp_clamp(r);
  25443. #elif DIGIT_BIT < 26
  25444. int i;
  25445. int j = 0;
  25446. int s = 0;
  25447. r->dp[0] = 0;
  25448. for (i = 0; i < 15; i++) {
  25449. r->dp[j] |= (mp_digit)(a[i] << s);
  25450. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  25451. s = DIGIT_BIT - s;
  25452. r->dp[++j] = (mp_digit)(a[i] >> s);
  25453. while (s + DIGIT_BIT <= 26) {
  25454. s += DIGIT_BIT;
  25455. r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  25456. if (s == SP_WORD_SIZE) {
  25457. r->dp[j] = 0;
  25458. }
  25459. else {
  25460. r->dp[j] = (mp_digit)(a[i] >> s);
  25461. }
  25462. }
  25463. s = 26 - s;
  25464. }
  25465. r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT;
  25466. mp_clamp(r);
  25467. #else
  25468. int i;
  25469. int j = 0;
  25470. int s = 0;
  25471. r->dp[0] = 0;
  25472. for (i = 0; i < 15; i++) {
  25473. r->dp[j] |= ((mp_digit)a[i]) << s;
  25474. if (s + 26 >= DIGIT_BIT) {
  25475. #if DIGIT_BIT != 32 && DIGIT_BIT != 64
  25476. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  25477. #endif
  25478. s = DIGIT_BIT - s;
  25479. r->dp[++j] = a[i] >> s;
  25480. s = 26 - s;
  25481. }
  25482. else {
  25483. s += 26;
  25484. }
  25485. }
  25486. r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT;
  25487. mp_clamp(r);
  25488. #endif
  25489. }
  25490. return err;
  25491. }
  25492. /* Convert a point of type sp_point_384 to type ecc_point.
  25493. *
  25494. * p Point of type sp_point_384.
  25495. * pm Point of type ecc_point (result).
  25496. * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
  25497. * MP_OKAY.
  25498. */
  25499. static int sp_384_point_to_ecc_point_15(const sp_point_384* p, ecc_point* pm)
  25500. {
  25501. int err;
  25502. err = sp_384_to_mp(p->x, pm->x);
  25503. if (err == MP_OKAY) {
  25504. err = sp_384_to_mp(p->y, pm->y);
  25505. }
  25506. if (err == MP_OKAY) {
  25507. err = sp_384_to_mp(p->z, pm->z);
  25508. }
  25509. return err;
  25510. }
  25511. /* Compare a with b in constant time.
  25512. *
  25513. * a A single precision integer.
  25514. * b A single precision integer.
  25515. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  25516. * respectively.
  25517. */
  25518. static sp_digit sp_384_cmp_15(const sp_digit* a, const sp_digit* b)
  25519. {
  25520. sp_digit r = 0;
  25521. #ifdef WOLFSSL_SP_SMALL
  25522. int i;
  25523. for (i=14; i>=0; i--) {
  25524. r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 25);
  25525. }
  25526. #else
  25527. r |= (a[14] - b[14]) & (0 - (sp_digit)1);
  25528. r |= (a[13] - b[13]) & ~(((sp_digit)0 - r) >> 25);
  25529. r |= (a[12] - b[12]) & ~(((sp_digit)0 - r) >> 25);
  25530. r |= (a[11] - b[11]) & ~(((sp_digit)0 - r) >> 25);
  25531. r |= (a[10] - b[10]) & ~(((sp_digit)0 - r) >> 25);
  25532. r |= (a[ 9] - b[ 9]) & ~(((sp_digit)0 - r) >> 25);
  25533. r |= (a[ 8] - b[ 8]) & ~(((sp_digit)0 - r) >> 25);
  25534. r |= (a[ 7] - b[ 7]) & ~(((sp_digit)0 - r) >> 25);
  25535. r |= (a[ 6] - b[ 6]) & ~(((sp_digit)0 - r) >> 25);
  25536. r |= (a[ 5] - b[ 5]) & ~(((sp_digit)0 - r) >> 25);
  25537. r |= (a[ 4] - b[ 4]) & ~(((sp_digit)0 - r) >> 25);
  25538. r |= (a[ 3] - b[ 3]) & ~(((sp_digit)0 - r) >> 25);
  25539. r |= (a[ 2] - b[ 2]) & ~(((sp_digit)0 - r) >> 25);
  25540. r |= (a[ 1] - b[ 1]) & ~(((sp_digit)0 - r) >> 25);
  25541. r |= (a[ 0] - b[ 0]) & ~(((sp_digit)0 - r) >> 25);
  25542. #endif /* WOLFSSL_SP_SMALL */
  25543. return r;
  25544. }
  25545. /* Conditionally subtract b from a using the mask m.
  25546. * m is -1 to subtract and 0 when not.
  25547. *
  25548. * r A single precision number representing condition subtract result.
  25549. * a A single precision number to subtract from.
  25550. * b A single precision number to subtract.
  25551. * m Mask value to apply.
  25552. */
  25553. static void sp_384_cond_sub_15(sp_digit* r, const sp_digit* a,
  25554. const sp_digit* b, const sp_digit m)
  25555. {
  25556. #ifdef WOLFSSL_SP_SMALL
  25557. int i;
  25558. for (i = 0; i < 15; i++) {
  25559. r[i] = a[i] - (b[i] & m);
  25560. }
  25561. #else
  25562. r[ 0] = a[ 0] - (b[ 0] & m);
  25563. r[ 1] = a[ 1] - (b[ 1] & m);
  25564. r[ 2] = a[ 2] - (b[ 2] & m);
  25565. r[ 3] = a[ 3] - (b[ 3] & m);
  25566. r[ 4] = a[ 4] - (b[ 4] & m);
  25567. r[ 5] = a[ 5] - (b[ 5] & m);
  25568. r[ 6] = a[ 6] - (b[ 6] & m);
  25569. r[ 7] = a[ 7] - (b[ 7] & m);
  25570. r[ 8] = a[ 8] - (b[ 8] & m);
  25571. r[ 9] = a[ 9] - (b[ 9] & m);
  25572. r[10] = a[10] - (b[10] & m);
  25573. r[11] = a[11] - (b[11] & m);
  25574. r[12] = a[12] - (b[12] & m);
  25575. r[13] = a[13] - (b[13] & m);
  25576. r[14] = a[14] - (b[14] & m);
  25577. #endif /* WOLFSSL_SP_SMALL */
  25578. }
  25579. /* Mul a by scalar b and add into r. (r += a * b)
  25580. *
  25581. * r A single precision integer.
  25582. * a A single precision integer.
  25583. * b A scalar.
  25584. */
  25585. SP_NOINLINE static void sp_384_mul_add_15(sp_digit* r, const sp_digit* a,
  25586. const sp_digit b)
  25587. {
  25588. #ifdef WOLFSSL_SP_SMALL
  25589. sp_int64 tb = b;
  25590. sp_int64 t[4];
  25591. int i;
  25592. t[0] = 0;
  25593. for (i = 0; i < 12; i += 4) {
  25594. t[0] += (tb * a[i+0]) + r[i+0];
  25595. t[1] = (tb * a[i+1]) + r[i+1];
  25596. t[2] = (tb * a[i+2]) + r[i+2];
  25597. t[3] = (tb * a[i+3]) + r[i+3];
  25598. r[i+0] = t[0] & 0x3ffffff;
  25599. t[1] += t[0] >> 26;
  25600. r[i+1] = t[1] & 0x3ffffff;
  25601. t[2] += t[1] >> 26;
  25602. r[i+2] = t[2] & 0x3ffffff;
  25603. t[3] += t[2] >> 26;
  25604. r[i+3] = t[3] & 0x3ffffff;
  25605. t[0] = t[3] >> 26;
  25606. }
  25607. t[0] += (tb * a[12]) + r[12];
  25608. t[1] = (tb * a[13]) + r[13];
  25609. t[2] = (tb * a[14]) + r[14];
  25610. r[12] = t[0] & 0x3ffffff;
  25611. t[1] += t[0] >> 26;
  25612. r[13] = t[1] & 0x3ffffff;
  25613. t[2] += t[1] >> 26;
  25614. r[14] = t[2] & 0x3ffffff;
  25615. r[15] += (sp_digit)(t[2] >> 26);
  25616. #else
  25617. sp_int64 tb = b;
  25618. sp_int64 t[15];
  25619. t[ 0] = tb * a[ 0];
  25620. t[ 1] = tb * a[ 1];
  25621. t[ 2] = tb * a[ 2];
  25622. t[ 3] = tb * a[ 3];
  25623. t[ 4] = tb * a[ 4];
  25624. t[ 5] = tb * a[ 5];
  25625. t[ 6] = tb * a[ 6];
  25626. t[ 7] = tb * a[ 7];
  25627. t[ 8] = tb * a[ 8];
  25628. t[ 9] = tb * a[ 9];
  25629. t[10] = tb * a[10];
  25630. t[11] = tb * a[11];
  25631. t[12] = tb * a[12];
  25632. t[13] = tb * a[13];
  25633. t[14] = tb * a[14];
  25634. r[ 0] += (sp_digit) (t[ 0] & 0x3ffffff);
  25635. r[ 1] += (sp_digit)((t[ 0] >> 26) + (t[ 1] & 0x3ffffff));
  25636. r[ 2] += (sp_digit)((t[ 1] >> 26) + (t[ 2] & 0x3ffffff));
  25637. r[ 3] += (sp_digit)((t[ 2] >> 26) + (t[ 3] & 0x3ffffff));
  25638. r[ 4] += (sp_digit)((t[ 3] >> 26) + (t[ 4] & 0x3ffffff));
  25639. r[ 5] += (sp_digit)((t[ 4] >> 26) + (t[ 5] & 0x3ffffff));
  25640. r[ 6] += (sp_digit)((t[ 5] >> 26) + (t[ 6] & 0x3ffffff));
  25641. r[ 7] += (sp_digit)((t[ 6] >> 26) + (t[ 7] & 0x3ffffff));
  25642. r[ 8] += (sp_digit)((t[ 7] >> 26) + (t[ 8] & 0x3ffffff));
  25643. r[ 9] += (sp_digit)((t[ 8] >> 26) + (t[ 9] & 0x3ffffff));
  25644. r[10] += (sp_digit)((t[ 9] >> 26) + (t[10] & 0x3ffffff));
  25645. r[11] += (sp_digit)((t[10] >> 26) + (t[11] & 0x3ffffff));
  25646. r[12] += (sp_digit)((t[11] >> 26) + (t[12] & 0x3ffffff));
  25647. r[13] += (sp_digit)((t[12] >> 26) + (t[13] & 0x3ffffff));
  25648. r[14] += (sp_digit)((t[13] >> 26) + (t[14] & 0x3ffffff));
  25649. r[15] += (sp_digit) (t[14] >> 26);
  25650. #endif /* WOLFSSL_SP_SMALL */
  25651. }
  25652. /* Normalize the values in each word to 26 bits.
  25653. *
  25654. * a Array of sp_digit to normalize.
  25655. */
  25656. static void sp_384_norm_15(sp_digit* a)
  25657. {
  25658. #ifdef WOLFSSL_SP_SMALL
  25659. int i;
  25660. for (i = 0; i < 14; i++) {
  25661. a[i+1] += a[i] >> 26;
  25662. a[i] &= 0x3ffffff;
  25663. }
  25664. #else
  25665. a[1] += a[0] >> 26; a[0] &= 0x3ffffff;
  25666. a[2] += a[1] >> 26; a[1] &= 0x3ffffff;
  25667. a[3] += a[2] >> 26; a[2] &= 0x3ffffff;
  25668. a[4] += a[3] >> 26; a[3] &= 0x3ffffff;
  25669. a[5] += a[4] >> 26; a[4] &= 0x3ffffff;
  25670. a[6] += a[5] >> 26; a[5] &= 0x3ffffff;
  25671. a[7] += a[6] >> 26; a[6] &= 0x3ffffff;
  25672. a[8] += a[7] >> 26; a[7] &= 0x3ffffff;
  25673. a[9] += a[8] >> 26; a[8] &= 0x3ffffff;
  25674. a[10] += a[9] >> 26; a[9] &= 0x3ffffff;
  25675. a[11] += a[10] >> 26; a[10] &= 0x3ffffff;
  25676. a[12] += a[11] >> 26; a[11] &= 0x3ffffff;
  25677. a[13] += a[12] >> 26; a[12] &= 0x3ffffff;
  25678. a[14] += a[13] >> 26; a[13] &= 0x3ffffff;
  25679. #endif /* WOLFSSL_SP_SMALL */
  25680. }
  25681. /* Shift the result in the high 384 bits down to the bottom.
  25682. *
  25683. * r A single precision number.
  25684. * a A single precision number.
  25685. */
  25686. static void sp_384_mont_shift_15(sp_digit* r, const sp_digit* a)
  25687. {
  25688. #ifdef WOLFSSL_SP_SMALL
  25689. int i;
  25690. sp_int64 n = a[14] >> 20;
  25691. n += ((sp_int64)a[15]) << 6;
  25692. for (i = 0; i < 14; i++) {
  25693. r[i] = n & 0x3ffffff;
  25694. n >>= 26;
  25695. n += ((sp_int64)a[16 + i]) << 6;
  25696. }
  25697. r[14] = (sp_digit)n;
  25698. #else
  25699. sp_int64 n = a[14] >> 20;
  25700. n += ((sp_int64)a[15]) << 6;
  25701. r[ 0] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[16]) << 6;
  25702. r[ 1] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[17]) << 6;
  25703. r[ 2] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[18]) << 6;
  25704. r[ 3] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[19]) << 6;
  25705. r[ 4] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[20]) << 6;
  25706. r[ 5] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[21]) << 6;
  25707. r[ 6] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[22]) << 6;
  25708. r[ 7] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[23]) << 6;
  25709. r[ 8] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[24]) << 6;
  25710. r[ 9] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[25]) << 6;
  25711. r[10] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[26]) << 6;
  25712. r[11] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[27]) << 6;
  25713. r[12] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[28]) << 6;
  25714. r[13] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[29]) << 6;
  25715. r[14] = (sp_digit)n;
  25716. #endif /* WOLFSSL_SP_SMALL */
  25717. XMEMSET(&r[15], 0, sizeof(*r) * 15U);
  25718. }
  25719. /* Reduce the number back to 384 bits using Montgomery reduction.
  25720. *
  25721. * a A single precision number to reduce in place.
  25722. * m The single precision number representing the modulus.
  25723. * mp The digit representing the negative inverse of m mod 2^n.
  25724. */
  25725. static void sp_384_mont_reduce_order_15(sp_digit* a, const sp_digit* m, sp_digit mp)
  25726. {
  25727. int i;
  25728. sp_digit mu;
  25729. sp_digit over;
  25730. sp_384_norm_15(a + 15);
  25731. for (i=0; i<14; i++) {
  25732. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x3ffffff;
  25733. sp_384_mul_add_15(a+i, m, mu);
  25734. a[i+1] += a[i] >> 26;
  25735. }
  25736. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffL;
  25737. sp_384_mul_add_15(a+i, m, mu);
  25738. a[i+1] += a[i] >> 26;
  25739. a[i] &= 0x3ffffff;
  25740. sp_384_mont_shift_15(a, a);
  25741. over = a[14] >> 20;
  25742. sp_384_cond_sub_15(a, a, m, ~((over - 1) >> 31));
  25743. sp_384_norm_15(a);
  25744. }
  25745. /* Reduce the number back to 384 bits using Montgomery reduction.
  25746. *
  25747. * a A single precision number to reduce in place.
  25748. * m The single precision number representing the modulus.
  25749. * mp The digit representing the negative inverse of m mod 2^n.
  25750. */
  25751. static void sp_384_mont_reduce_15(sp_digit* a, const sp_digit* m, sp_digit mp)
  25752. {
  25753. int i;
  25754. sp_digit am;
  25755. (void)m;
  25756. (void)mp;
  25757. for (i = 0; i < 14; i++) {
  25758. am = (a[i] * 0x1) & 0x3ffffff;
  25759. a[i + 1] += (am << 6) & 0x3ffffff;
  25760. a[i + 2] += am >> 20;
  25761. a[i + 3] -= (am << 18) & 0x3ffffff;
  25762. a[i + 4] -= am >> 8;
  25763. a[i + 4] -= (am << 24) & 0x3ffffff;
  25764. a[i + 5] -= am >> 2;
  25765. a[i + 14] += (am << 20) & 0x3ffffff;
  25766. a[i + 15] += am >> 6;
  25767. a[i + 1] += a[i] >> 26;
  25768. }
  25769. am = (a[14] * 0x1) & 0xfffff;
  25770. a[14 + 1] += (am << 6) & 0x3ffffff;
  25771. a[14 + 2] += am >> 20;
  25772. a[14 + 3] -= (am << 18) & 0x3ffffff;
  25773. a[14 + 4] -= am >> 8;
  25774. a[14 + 4] -= (am << 24) & 0x3ffffff;
  25775. a[14 + 5] -= am >> 2;
  25776. a[14 + 14] += (am << 20) & 0x3ffffff;
  25777. a[14 + 15] += am >> 6;
  25778. a[0] = (a[14] >> 20) + ((a[15] << 6) & 0x3ffffff);
  25779. a[1] = (a[15] >> 20) + ((a[16] << 6) & 0x3ffffff);
  25780. a[2] = (a[16] >> 20) + ((a[17] << 6) & 0x3ffffff);
  25781. a[3] = (a[17] >> 20) + ((a[18] << 6) & 0x3ffffff);
  25782. a[4] = (a[18] >> 20) + ((a[19] << 6) & 0x3ffffff);
  25783. a[5] = (a[19] >> 20) + ((a[20] << 6) & 0x3ffffff);
  25784. a[6] = (a[20] >> 20) + ((a[21] << 6) & 0x3ffffff);
  25785. a[7] = (a[21] >> 20) + ((a[22] << 6) & 0x3ffffff);
  25786. a[8] = (a[22] >> 20) + ((a[23] << 6) & 0x3ffffff);
  25787. a[9] = (a[23] >> 20) + ((a[24] << 6) & 0x3ffffff);
  25788. a[10] = (a[24] >> 20) + ((a[25] << 6) & 0x3ffffff);
  25789. a[11] = (a[25] >> 20) + ((a[26] << 6) & 0x3ffffff);
  25790. a[12] = (a[26] >> 20) + ((a[27] << 6) & 0x3ffffff);
  25791. a[13] = (a[27] >> 20) + ((a[28] << 6) & 0x3ffffff);
  25792. a[14] = (a[14 + 14] >> 20) + (a[29] << 6);
  25793. a[1] += a[0] >> 26; a[0] &= 0x3ffffff;
  25794. a[2] += a[1] >> 26; a[1] &= 0x3ffffff;
  25795. a[3] += a[2] >> 26; a[2] &= 0x3ffffff;
  25796. a[4] += a[3] >> 26; a[3] &= 0x3ffffff;
  25797. a[5] += a[4] >> 26; a[4] &= 0x3ffffff;
  25798. a[6] += a[5] >> 26; a[5] &= 0x3ffffff;
  25799. a[7] += a[6] >> 26; a[6] &= 0x3ffffff;
  25800. a[8] += a[7] >> 26; a[7] &= 0x3ffffff;
  25801. a[9] += a[8] >> 26; a[8] &= 0x3ffffff;
  25802. a[10] += a[9] >> 26; a[9] &= 0x3ffffff;
  25803. a[11] += a[10] >> 26; a[10] &= 0x3ffffff;
  25804. a[12] += a[11] >> 26; a[11] &= 0x3ffffff;
  25805. a[13] += a[12] >> 26; a[12] &= 0x3ffffff;
  25806. a[14] += a[13] >> 26; a[13] &= 0x3ffffff;
  25807. /* Get the bit over, if any. */
  25808. am = a[14] >> 20;
  25809. /* Create mask. */
  25810. am = 0 - am;
  25811. a[0] -= 0x03ffffff & am;
  25812. a[1] -= 0x0000003f & am;
  25813. /* p384_mod[2] is zero */
  25814. a[3] -= 0x03fc0000 & am;
  25815. a[4] -= 0x02ffffff & am;
  25816. a[5] -= 0x03ffffff & am;
  25817. a[6] -= 0x03ffffff & am;
  25818. a[7] -= 0x03ffffff & am;
  25819. a[8] -= 0x03ffffff & am;
  25820. a[9] -= 0x03ffffff & am;
  25821. a[10] -= 0x03ffffff & am;
  25822. a[11] -= 0x03ffffff & am;
  25823. a[12] -= 0x03ffffff & am;
  25824. a[13] -= 0x03ffffff & am;
  25825. a[14] -= 0x000fffff & am;
  25826. a[1] += a[0] >> 26; a[0] &= 0x3ffffff;
  25827. a[2] += a[1] >> 26; a[1] &= 0x3ffffff;
  25828. a[3] += a[2] >> 26; a[2] &= 0x3ffffff;
  25829. a[4] += a[3] >> 26; a[3] &= 0x3ffffff;
  25830. a[5] += a[4] >> 26; a[4] &= 0x3ffffff;
  25831. a[6] += a[5] >> 26; a[5] &= 0x3ffffff;
  25832. a[7] += a[6] >> 26; a[6] &= 0x3ffffff;
  25833. a[8] += a[7] >> 26; a[7] &= 0x3ffffff;
  25834. a[9] += a[8] >> 26; a[8] &= 0x3ffffff;
  25835. a[10] += a[9] >> 26; a[9] &= 0x3ffffff;
  25836. a[11] += a[10] >> 26; a[10] &= 0x3ffffff;
  25837. a[12] += a[11] >> 26; a[11] &= 0x3ffffff;
  25838. a[13] += a[12] >> 26; a[12] &= 0x3ffffff;
  25839. a[14] += a[13] >> 26; a[13] &= 0x3ffffff;
  25840. }
  25841. /* Multiply two Montgomery form numbers mod the modulus (prime).
  25842. * (r = a * b mod m)
  25843. *
  25844. * r Result of multiplication.
  25845. * a First number to multiply in Montgomery form.
  25846. * b Second number to multiply in Montgomery form.
  25847. * m Modulus (prime).
  25848. * mp Montgomery mulitplier.
  25849. */
  25850. SP_NOINLINE static void sp_384_mont_mul_15(sp_digit* r, const sp_digit* a,
  25851. const sp_digit* b, const sp_digit* m, sp_digit mp)
  25852. {
  25853. sp_384_mul_15(r, a, b);
  25854. sp_384_mont_reduce_15(r, m, mp);
  25855. }
  25856. /* Square the Montgomery form number. (r = a * a mod m)
  25857. *
  25858. * r Result of squaring.
  25859. * a Number to square in Montgomery form.
  25860. * m Modulus (prime).
  25861. * mp Montgomery mulitplier.
  25862. */
  25863. SP_NOINLINE static void sp_384_mont_sqr_15(sp_digit* r, const sp_digit* a,
  25864. const sp_digit* m, sp_digit mp)
  25865. {
  25866. sp_384_sqr_15(r, a);
  25867. sp_384_mont_reduce_15(r, m, mp);
  25868. }
  25869. #if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY)
  25870. /* Square the Montgomery form number a number of times. (r = a ^ n mod m)
  25871. *
  25872. * r Result of squaring.
  25873. * a Number to square in Montgomery form.
  25874. * n Number of times to square.
  25875. * m Modulus (prime).
  25876. * mp Montgomery mulitplier.
  25877. */
  25878. static void sp_384_mont_sqr_n_15(sp_digit* r, const sp_digit* a, int n,
  25879. const sp_digit* m, sp_digit mp)
  25880. {
  25881. sp_384_mont_sqr_15(r, a, m, mp);
  25882. for (; n > 1; n--) {
  25883. sp_384_mont_sqr_15(r, r, m, mp);
  25884. }
  25885. }
  25886. #endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */
  25887. #ifdef WOLFSSL_SP_SMALL
  25888. /* Mod-2 for the P384 curve. */
  25889. static const uint32_t p384_mod_minus_2[12] = {
  25890. 0xfffffffdU,0x00000000U,0x00000000U,0xffffffffU,0xfffffffeU,0xffffffffU,
  25891. 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU
  25892. };
  25893. #endif /* !WOLFSSL_SP_SMALL */
  25894. /* Invert the number, in Montgomery form, modulo the modulus (prime) of the
  25895. * P384 curve. (r = 1 / a mod m)
  25896. *
  25897. * r Inverse result.
  25898. * a Number to invert.
  25899. * td Temporary data.
  25900. */
  25901. static void sp_384_mont_inv_15(sp_digit* r, const sp_digit* a, sp_digit* td)
  25902. {
  25903. #ifdef WOLFSSL_SP_SMALL
  25904. sp_digit* t = td;
  25905. int i;
  25906. XMEMCPY(t, a, sizeof(sp_digit) * 15);
  25907. for (i=382; i>=0; i--) {
  25908. sp_384_mont_sqr_15(t, t, p384_mod, p384_mp_mod);
  25909. if (p384_mod_minus_2[i / 32] & ((sp_digit)1 << (i % 32)))
  25910. sp_384_mont_mul_15(t, t, a, p384_mod, p384_mp_mod);
  25911. }
  25912. XMEMCPY(r, t, sizeof(sp_digit) * 15);
  25913. #else
  25914. sp_digit* t1 = td;
  25915. sp_digit* t2 = td + 2 * 15;
  25916. sp_digit* t3 = td + 4 * 15;
  25917. sp_digit* t4 = td + 6 * 15;
  25918. sp_digit* t5 = td + 8 * 15;
  25919. /* 0x2 */
  25920. sp_384_mont_sqr_15(t1, a, p384_mod, p384_mp_mod);
  25921. /* 0x3 */
  25922. sp_384_mont_mul_15(t5, t1, a, p384_mod, p384_mp_mod);
  25923. /* 0xc */
  25924. sp_384_mont_sqr_n_15(t1, t5, 2, p384_mod, p384_mp_mod);
  25925. /* 0xf */
  25926. sp_384_mont_mul_15(t2, t5, t1, p384_mod, p384_mp_mod);
  25927. /* 0x1e */
  25928. sp_384_mont_sqr_15(t1, t2, p384_mod, p384_mp_mod);
  25929. /* 0x1f */
  25930. sp_384_mont_mul_15(t4, t1, a, p384_mod, p384_mp_mod);
  25931. /* 0x3e0 */
  25932. sp_384_mont_sqr_n_15(t1, t4, 5, p384_mod, p384_mp_mod);
  25933. /* 0x3ff */
  25934. sp_384_mont_mul_15(t2, t4, t1, p384_mod, p384_mp_mod);
  25935. /* 0x7fe0 */
  25936. sp_384_mont_sqr_n_15(t1, t2, 5, p384_mod, p384_mp_mod);
  25937. /* 0x7fff */
  25938. sp_384_mont_mul_15(t4, t4, t1, p384_mod, p384_mp_mod);
  25939. /* 0x3fff8000 */
  25940. sp_384_mont_sqr_n_15(t1, t4, 15, p384_mod, p384_mp_mod);
  25941. /* 0x3fffffff */
  25942. sp_384_mont_mul_15(t2, t4, t1, p384_mod, p384_mp_mod);
  25943. /* 0xfffffffc */
  25944. sp_384_mont_sqr_n_15(t3, t2, 2, p384_mod, p384_mp_mod);
  25945. /* 0xfffffffd */
  25946. sp_384_mont_mul_15(r, t3, a, p384_mod, p384_mp_mod);
  25947. /* 0xffffffff */
  25948. sp_384_mont_mul_15(t3, t5, t3, p384_mod, p384_mp_mod);
  25949. /* 0xfffffffc0000000 */
  25950. sp_384_mont_sqr_n_15(t1, t2, 30, p384_mod, p384_mp_mod);
  25951. /* 0xfffffffffffffff */
  25952. sp_384_mont_mul_15(t2, t2, t1, p384_mod, p384_mp_mod);
  25953. /* 0xfffffffffffffff000000000000000 */
  25954. sp_384_mont_sqr_n_15(t1, t2, 60, p384_mod, p384_mp_mod);
  25955. /* 0xffffffffffffffffffffffffffffff */
  25956. sp_384_mont_mul_15(t2, t2, t1, p384_mod, p384_mp_mod);
  25957. /* 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */
  25958. sp_384_mont_sqr_n_15(t1, t2, 120, p384_mod, p384_mp_mod);
  25959. /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */
  25960. sp_384_mont_mul_15(t2, t2, t1, p384_mod, p384_mp_mod);
  25961. /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */
  25962. sp_384_mont_sqr_n_15(t1, t2, 15, p384_mod, p384_mp_mod);
  25963. /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */
  25964. sp_384_mont_mul_15(t2, t4, t1, p384_mod, p384_mp_mod);
  25965. /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000 */
  25966. sp_384_mont_sqr_n_15(t1, t2, 33, p384_mod, p384_mp_mod);
  25967. /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff */
  25968. sp_384_mont_mul_15(t2, t3, t1, p384_mod, p384_mp_mod);
  25969. /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff000000000000000000000000 */
  25970. sp_384_mont_sqr_n_15(t1, t2, 96, p384_mod, p384_mp_mod);
  25971. /* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffd */
  25972. sp_384_mont_mul_15(r, r, t1, p384_mod, p384_mp_mod);
  25973. #endif /* WOLFSSL_SP_SMALL */
  25974. }
  25975. /* Map the Montgomery form projective coordinate point to an affine point.
  25976. *
  25977. * r Resulting affine coordinate point.
  25978. * p Montgomery form projective coordinate point.
  25979. * t Temporary ordinate data.
  25980. */
  25981. static void sp_384_map_15(sp_point_384* r, const sp_point_384* p,
  25982. sp_digit* t)
  25983. {
  25984. sp_digit* t1 = t;
  25985. sp_digit* t2 = t + 2*15;
  25986. sp_int32 n;
  25987. sp_384_mont_inv_15(t1, p->z, t + 2*15);
  25988. sp_384_mont_sqr_15(t2, t1, p384_mod, p384_mp_mod);
  25989. sp_384_mont_mul_15(t1, t2, t1, p384_mod, p384_mp_mod);
  25990. /* x /= z^2 */
  25991. sp_384_mont_mul_15(r->x, p->x, t2, p384_mod, p384_mp_mod);
  25992. XMEMSET(r->x + 15, 0, sizeof(r->x) / 2U);
  25993. sp_384_mont_reduce_15(r->x, p384_mod, p384_mp_mod);
  25994. /* Reduce x to less than modulus */
  25995. n = sp_384_cmp_15(r->x, p384_mod);
  25996. sp_384_cond_sub_15(r->x, r->x, p384_mod, ~(n >> 25));
  25997. sp_384_norm_15(r->x);
  25998. /* y /= z^3 */
  25999. sp_384_mont_mul_15(r->y, p->y, t1, p384_mod, p384_mp_mod);
  26000. XMEMSET(r->y + 15, 0, sizeof(r->y) / 2U);
  26001. sp_384_mont_reduce_15(r->y, p384_mod, p384_mp_mod);
  26002. /* Reduce y to less than modulus */
  26003. n = sp_384_cmp_15(r->y, p384_mod);
  26004. sp_384_cond_sub_15(r->y, r->y, p384_mod, ~(n >> 25));
  26005. sp_384_norm_15(r->y);
  26006. XMEMSET(r->z, 0, sizeof(r->z) / 2);
  26007. r->z[0] = 1;
  26008. }
  26009. /* Add two Montgomery form numbers (r = a + b % m).
  26010. *
  26011. * r Result of addition.
  26012. * a First number to add in Montgomery form.
  26013. * b Second number to add in Montgomery form.
  26014. * m Modulus (prime).
  26015. */
  26016. static void sp_384_mont_add_15(sp_digit* r, const sp_digit* a, const sp_digit* b,
  26017. const sp_digit* m)
  26018. {
  26019. sp_digit over;
  26020. (void)sp_384_add_15(r, a, b);
  26021. sp_384_norm_15(r);
  26022. over = r[14] >> 20;
  26023. sp_384_cond_sub_15(r, r, m, ~((over - 1) >> 31));
  26024. sp_384_norm_15(r);
  26025. }
  26026. /* Double a Montgomery form number (r = a + a % m).
  26027. *
  26028. * r Result of doubling.
  26029. * a Number to double in Montgomery form.
  26030. * m Modulus (prime).
  26031. */
  26032. static void sp_384_mont_dbl_15(sp_digit* r, const sp_digit* a, const sp_digit* m)
  26033. {
  26034. sp_digit over;
  26035. (void)sp_384_add_15(r, a, a);
  26036. sp_384_norm_15(r);
  26037. over = r[14] >> 20;
  26038. sp_384_cond_sub_15(r, r, m, ~((over - 1) >> 31));
  26039. sp_384_norm_15(r);
  26040. }
  26041. /* Triple a Montgomery form number (r = a + a + a % m).
  26042. *
  26043. * r Result of Tripling.
  26044. * a Number to triple in Montgomery form.
  26045. * m Modulus (prime).
  26046. */
  26047. static void sp_384_mont_tpl_15(sp_digit* r, const sp_digit* a, const sp_digit* m)
  26048. {
  26049. sp_digit over;
  26050. (void)sp_384_add_15(r, a, a);
  26051. sp_384_norm_15(r);
  26052. over = r[14] >> 20;
  26053. sp_384_cond_sub_15(r, r, m, ~((over - 1) >> 31));
  26054. sp_384_norm_15(r);
  26055. (void)sp_384_add_15(r, r, a);
  26056. sp_384_norm_15(r);
  26057. over = r[14] >> 20;
  26058. sp_384_cond_sub_15(r, r, m, ~((over - 1) >> 31));
  26059. sp_384_norm_15(r);
  26060. }
  26061. #ifdef WOLFSSL_SP_SMALL
  26062. /* Conditionally add a and b using the mask m.
  26063. * m is -1 to add and 0 when not.
  26064. *
  26065. * r A single precision number representing conditional add result.
  26066. * a A single precision number to add with.
  26067. * b A single precision number to add.
  26068. * m Mask value to apply.
  26069. */
  26070. static void sp_384_cond_add_15(sp_digit* r, const sp_digit* a,
  26071. const sp_digit* b, const sp_digit m)
  26072. {
  26073. int i;
  26074. for (i = 0; i < 15; i++) {
  26075. r[i] = a[i] + (b[i] & m);
  26076. }
  26077. }
  26078. #endif /* WOLFSSL_SP_SMALL */
  26079. #ifndef WOLFSSL_SP_SMALL
  26080. /* Conditionally add a and b using the mask m.
  26081. * m is -1 to add and 0 when not.
  26082. *
  26083. * r A single precision number representing conditional add result.
  26084. * a A single precision number to add with.
  26085. * b A single precision number to add.
  26086. * m Mask value to apply.
  26087. */
  26088. static void sp_384_cond_add_15(sp_digit* r, const sp_digit* a,
  26089. const sp_digit* b, const sp_digit m)
  26090. {
  26091. r[ 0] = a[ 0] + (b[ 0] & m);
  26092. r[ 1] = a[ 1] + (b[ 1] & m);
  26093. r[ 2] = a[ 2] + (b[ 2] & m);
  26094. r[ 3] = a[ 3] + (b[ 3] & m);
  26095. r[ 4] = a[ 4] + (b[ 4] & m);
  26096. r[ 5] = a[ 5] + (b[ 5] & m);
  26097. r[ 6] = a[ 6] + (b[ 6] & m);
  26098. r[ 7] = a[ 7] + (b[ 7] & m);
  26099. r[ 8] = a[ 8] + (b[ 8] & m);
  26100. r[ 9] = a[ 9] + (b[ 9] & m);
  26101. r[10] = a[10] + (b[10] & m);
  26102. r[11] = a[11] + (b[11] & m);
  26103. r[12] = a[12] + (b[12] & m);
  26104. r[13] = a[13] + (b[13] & m);
  26105. r[14] = a[14] + (b[14] & m);
  26106. }
  26107. #endif /* !WOLFSSL_SP_SMALL */
  26108. /* Subtract two Montgomery form numbers (r = a - b % m).
  26109. *
  26110. * r Result of subtration.
  26111. * a Number to subtract from in Montgomery form.
  26112. * b Number to subtract with in Montgomery form.
  26113. * m Modulus (prime).
  26114. */
  26115. static void sp_384_mont_sub_15(sp_digit* r, const sp_digit* a, const sp_digit* b,
  26116. const sp_digit* m)
  26117. {
  26118. (void)sp_384_sub_15(r, a, b);
  26119. sp_384_norm_15(r);
  26120. sp_384_cond_add_15(r, r, m, r[14] >> 20);
  26121. sp_384_norm_15(r);
  26122. }
  26123. #define sp_384_mont_sub_lower_15 sp_384_mont_sub_15
  26124. /* Shift number left one bit.
  26125. * Bottom bit is lost.
  26126. *
  26127. * r Result of shift.
  26128. * a Number to shift.
  26129. */
  26130. SP_NOINLINE static void sp_384_rshift1_15(sp_digit* r, const sp_digit* a)
  26131. {
  26132. #ifdef WOLFSSL_SP_SMALL
  26133. int i;
  26134. for (i=0; i<14; i++) {
  26135. r[i] = (a[i] >> 1) + ((a[i + 1] << 25) & 0x3ffffff);
  26136. }
  26137. #else
  26138. r[0] = (a[0] >> 1) + ((a[1] << 25) & 0x3ffffff);
  26139. r[1] = (a[1] >> 1) + ((a[2] << 25) & 0x3ffffff);
  26140. r[2] = (a[2] >> 1) + ((a[3] << 25) & 0x3ffffff);
  26141. r[3] = (a[3] >> 1) + ((a[4] << 25) & 0x3ffffff);
  26142. r[4] = (a[4] >> 1) + ((a[5] << 25) & 0x3ffffff);
  26143. r[5] = (a[5] >> 1) + ((a[6] << 25) & 0x3ffffff);
  26144. r[6] = (a[6] >> 1) + ((a[7] << 25) & 0x3ffffff);
  26145. r[7] = (a[7] >> 1) + ((a[8] << 25) & 0x3ffffff);
  26146. r[8] = (a[8] >> 1) + ((a[9] << 25) & 0x3ffffff);
  26147. r[9] = (a[9] >> 1) + ((a[10] << 25) & 0x3ffffff);
  26148. r[10] = (a[10] >> 1) + ((a[11] << 25) & 0x3ffffff);
  26149. r[11] = (a[11] >> 1) + ((a[12] << 25) & 0x3ffffff);
  26150. r[12] = (a[12] >> 1) + ((a[13] << 25) & 0x3ffffff);
  26151. r[13] = (a[13] >> 1) + ((a[14] << 25) & 0x3ffffff);
  26152. #endif
  26153. r[14] = a[14] >> 1;
  26154. }
  26155. /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
  26156. *
  26157. * r Result of division by 2.
  26158. * a Number to divide.
  26159. * m Modulus (prime).
  26160. */
  26161. static void sp_384_div2_15(sp_digit* r, const sp_digit* a, const sp_digit* m)
  26162. {
  26163. sp_384_cond_add_15(r, a, m, 0 - (a[0] & 1));
  26164. sp_384_norm_15(r);
  26165. sp_384_rshift1_15(r, r);
  26166. }
  26167. /* Double the Montgomery form projective point p.
  26168. *
  26169. * r Result of doubling point.
  26170. * p Point to double.
  26171. * t Temporary ordinate data.
  26172. */
  26173. #ifdef WOLFSSL_SP_NONBLOCK
  26174. typedef struct sp_384_proj_point_dbl_15_ctx {
  26175. int state;
  26176. sp_digit* t1;
  26177. sp_digit* t2;
  26178. sp_digit* x;
  26179. sp_digit* y;
  26180. sp_digit* z;
  26181. } sp_384_proj_point_dbl_15_ctx;
  26182. static int sp_384_proj_point_dbl_15_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, const sp_point_384* p, sp_digit* t)
  26183. {
  26184. int err = FP_WOULDBLOCK;
  26185. sp_384_proj_point_dbl_15_ctx* ctx = (sp_384_proj_point_dbl_15_ctx*)sp_ctx->data;
  26186. typedef char ctx_size_test[sizeof(sp_384_proj_point_dbl_15_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  26187. (void)sizeof(ctx_size_test);
  26188. switch (ctx->state) {
  26189. case 0:
  26190. ctx->t1 = t;
  26191. ctx->t2 = t + 2*15;
  26192. ctx->x = r->x;
  26193. ctx->y = r->y;
  26194. ctx->z = r->z;
  26195. /* Put infinity into result. */
  26196. if (r != p) {
  26197. r->infinity = p->infinity;
  26198. }
  26199. ctx->state = 1;
  26200. break;
  26201. case 1:
  26202. /* T1 = Z * Z */
  26203. sp_384_mont_sqr_15(ctx->t1, p->z, p384_mod, p384_mp_mod);
  26204. ctx->state = 2;
  26205. break;
  26206. case 2:
  26207. /* Z = Y * Z */
  26208. sp_384_mont_mul_15(ctx->z, p->y, p->z, p384_mod, p384_mp_mod);
  26209. ctx->state = 3;
  26210. break;
  26211. case 3:
  26212. /* Z = 2Z */
  26213. sp_384_mont_dbl_15(ctx->z, ctx->z, p384_mod);
  26214. ctx->state = 4;
  26215. break;
  26216. case 4:
  26217. /* T2 = X - T1 */
  26218. sp_384_mont_sub_15(ctx->t2, p->x, ctx->t1, p384_mod);
  26219. ctx->state = 5;
  26220. break;
  26221. case 5:
  26222. /* T1 = X + T1 */
  26223. sp_384_mont_add_15(ctx->t1, p->x, ctx->t1, p384_mod);
  26224. ctx->state = 6;
  26225. break;
  26226. case 6:
  26227. /* T2 = T1 * T2 */
  26228. sp_384_mont_mul_15(ctx->t2, ctx->t1, ctx->t2, p384_mod, p384_mp_mod);
  26229. ctx->state = 7;
  26230. break;
  26231. case 7:
  26232. /* T1 = 3T2 */
  26233. sp_384_mont_tpl_15(ctx->t1, ctx->t2, p384_mod);
  26234. ctx->state = 8;
  26235. break;
  26236. case 8:
  26237. /* Y = 2Y */
  26238. sp_384_mont_dbl_15(ctx->y, p->y, p384_mod);
  26239. ctx->state = 9;
  26240. break;
  26241. case 9:
  26242. /* Y = Y * Y */
  26243. sp_384_mont_sqr_15(ctx->y, ctx->y, p384_mod, p384_mp_mod);
  26244. ctx->state = 10;
  26245. break;
  26246. case 10:
  26247. /* T2 = Y * Y */
  26248. sp_384_mont_sqr_15(ctx->t2, ctx->y, p384_mod, p384_mp_mod);
  26249. ctx->state = 11;
  26250. break;
  26251. case 11:
  26252. /* T2 = T2/2 */
  26253. sp_384_div2_15(ctx->t2, ctx->t2, p384_mod);
  26254. ctx->state = 12;
  26255. break;
  26256. case 12:
  26257. /* Y = Y * X */
  26258. sp_384_mont_mul_15(ctx->y, ctx->y, p->x, p384_mod, p384_mp_mod);
  26259. ctx->state = 13;
  26260. break;
  26261. case 13:
  26262. /* X = T1 * T1 */
  26263. sp_384_mont_sqr_15(ctx->x, ctx->t1, p384_mod, p384_mp_mod);
  26264. ctx->state = 14;
  26265. break;
  26266. case 14:
  26267. /* X = X - Y */
  26268. sp_384_mont_sub_15(ctx->x, ctx->x, ctx->y, p384_mod);
  26269. ctx->state = 15;
  26270. break;
  26271. case 15:
  26272. /* X = X - Y */
  26273. sp_384_mont_sub_15(ctx->x, ctx->x, ctx->y, p384_mod);
  26274. ctx->state = 16;
  26275. break;
  26276. case 16:
  26277. /* Y = Y - X */
  26278. sp_384_mont_sub_lower_15(ctx->y, ctx->y, ctx->x, p384_mod);
  26279. ctx->state = 17;
  26280. break;
  26281. case 17:
  26282. /* Y = Y * T1 */
  26283. sp_384_mont_mul_15(ctx->y, ctx->y, ctx->t1, p384_mod, p384_mp_mod);
  26284. ctx->state = 18;
  26285. break;
  26286. case 18:
  26287. /* Y = Y - T2 */
  26288. sp_384_mont_sub_15(ctx->y, ctx->y, ctx->t2, p384_mod);
  26289. ctx->state = 19;
  26290. /* fall-through */
  26291. case 19:
  26292. err = MP_OKAY;
  26293. break;
  26294. }
  26295. if (err == MP_OKAY && ctx->state != 19) {
  26296. err = FP_WOULDBLOCK;
  26297. }
  26298. return err;
  26299. }
  26300. #endif /* WOLFSSL_SP_NONBLOCK */
  26301. static void sp_384_proj_point_dbl_15(sp_point_384* r, const sp_point_384* p,
  26302. sp_digit* t)
  26303. {
  26304. sp_digit* t1 = t;
  26305. sp_digit* t2 = t + 2*15;
  26306. sp_digit* x;
  26307. sp_digit* y;
  26308. sp_digit* z;
  26309. x = r->x;
  26310. y = r->y;
  26311. z = r->z;
  26312. /* Put infinity into result. */
  26313. if (r != p) {
  26314. r->infinity = p->infinity;
  26315. }
  26316. /* T1 = Z * Z */
  26317. sp_384_mont_sqr_15(t1, p->z, p384_mod, p384_mp_mod);
  26318. /* Z = Y * Z */
  26319. sp_384_mont_mul_15(z, p->y, p->z, p384_mod, p384_mp_mod);
  26320. /* Z = 2Z */
  26321. sp_384_mont_dbl_15(z, z, p384_mod);
  26322. /* T2 = X - T1 */
  26323. sp_384_mont_sub_15(t2, p->x, t1, p384_mod);
  26324. /* T1 = X + T1 */
  26325. sp_384_mont_add_15(t1, p->x, t1, p384_mod);
  26326. /* T2 = T1 * T2 */
  26327. sp_384_mont_mul_15(t2, t1, t2, p384_mod, p384_mp_mod);
  26328. /* T1 = 3T2 */
  26329. sp_384_mont_tpl_15(t1, t2, p384_mod);
  26330. /* Y = 2Y */
  26331. sp_384_mont_dbl_15(y, p->y, p384_mod);
  26332. /* Y = Y * Y */
  26333. sp_384_mont_sqr_15(y, y, p384_mod, p384_mp_mod);
  26334. /* T2 = Y * Y */
  26335. sp_384_mont_sqr_15(t2, y, p384_mod, p384_mp_mod);
  26336. /* T2 = T2/2 */
  26337. sp_384_div2_15(t2, t2, p384_mod);
  26338. /* Y = Y * X */
  26339. sp_384_mont_mul_15(y, y, p->x, p384_mod, p384_mp_mod);
  26340. /* X = T1 * T1 */
  26341. sp_384_mont_sqr_15(x, t1, p384_mod, p384_mp_mod);
  26342. /* X = X - Y */
  26343. sp_384_mont_sub_15(x, x, y, p384_mod);
  26344. /* X = X - Y */
  26345. sp_384_mont_sub_15(x, x, y, p384_mod);
  26346. /* Y = Y - X */
  26347. sp_384_mont_sub_lower_15(y, y, x, p384_mod);
  26348. /* Y = Y * T1 */
  26349. sp_384_mont_mul_15(y, y, t1, p384_mod, p384_mp_mod);
  26350. /* Y = Y - T2 */
  26351. sp_384_mont_sub_15(y, y, t2, p384_mod);
  26352. }
  26353. /* Compare two numbers to determine if they are equal.
  26354. * Constant time implementation.
  26355. *
  26356. * a First number to compare.
  26357. * b Second number to compare.
  26358. * returns 1 when equal and 0 otherwise.
  26359. */
  26360. static int sp_384_cmp_equal_15(const sp_digit* a, const sp_digit* b)
  26361. {
  26362. return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) |
  26363. (a[3] ^ b[3]) | (a[4] ^ b[4]) | (a[5] ^ b[5]) |
  26364. (a[6] ^ b[6]) | (a[7] ^ b[7]) | (a[8] ^ b[8]) |
  26365. (a[9] ^ b[9]) | (a[10] ^ b[10]) | (a[11] ^ b[11]) |
  26366. (a[12] ^ b[12]) | (a[13] ^ b[13]) | (a[14] ^ b[14])) == 0;
  26367. }
  26368. /* Returns 1 if the number of zero.
  26369. * Implementation is constant time.
  26370. *
  26371. * a Number to check.
  26372. * returns 1 if the number is zero and 0 otherwise.
  26373. */
  26374. static int sp_384_iszero_15(const sp_digit* a)
  26375. {
  26376. return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] |
  26377. a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14]) == 0;
  26378. }
  26379. /* Add two Montgomery form projective points.
  26380. *
  26381. * r Result of addition.
  26382. * p First point to add.
  26383. * q Second point to add.
  26384. * t Temporary ordinate data.
  26385. */
  26386. #ifdef WOLFSSL_SP_NONBLOCK
  26387. typedef struct sp_384_proj_point_add_15_ctx {
  26388. int state;
  26389. sp_384_proj_point_dbl_15_ctx dbl_ctx;
  26390. const sp_point_384* ap[2];
  26391. sp_point_384* rp[2];
  26392. sp_digit* t1;
  26393. sp_digit* t2;
  26394. sp_digit* t3;
  26395. sp_digit* t4;
  26396. sp_digit* t5;
  26397. sp_digit* t6;
  26398. sp_digit* x;
  26399. sp_digit* y;
  26400. sp_digit* z;
  26401. } sp_384_proj_point_add_15_ctx;
  26402. static int sp_384_proj_point_add_15_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r,
  26403. const sp_point_384* p, const sp_point_384* q, sp_digit* t)
  26404. {
  26405. int err = FP_WOULDBLOCK;
  26406. sp_384_proj_point_add_15_ctx* ctx = (sp_384_proj_point_add_15_ctx*)sp_ctx->data;
  26407. /* Ensure only the first point is the same as the result. */
  26408. if (q == r) {
  26409. const sp_point_384* a = p;
  26410. p = q;
  26411. q = a;
  26412. }
  26413. typedef char ctx_size_test[sizeof(sp_384_proj_point_add_15_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  26414. (void)sizeof(ctx_size_test);
  26415. switch (ctx->state) {
  26416. case 0: /* INIT */
  26417. ctx->t1 = t;
  26418. ctx->t2 = t + 2*15;
  26419. ctx->t3 = t + 4*15;
  26420. ctx->t4 = t + 6*15;
  26421. ctx->t5 = t + 8*15;
  26422. ctx->t6 = t + 10*15;
  26423. ctx->x = ctx->t6;
  26424. ctx->y = ctx->t1;
  26425. ctx->z = ctx->t2;
  26426. ctx->state = 1;
  26427. break;
  26428. case 1:
  26429. /* Check double */
  26430. (void)sp_384_sub_15(ctx->t1, p384_mod, q->y);
  26431. sp_384_norm_15(ctx->t1);
  26432. if ((~p->infinity & ~q->infinity &
  26433. sp_384_cmp_equal_15(p->x, q->x) & sp_384_cmp_equal_15(p->z, q->z) &
  26434. (sp_384_cmp_equal_15(p->y, q->y) | sp_384_cmp_equal_15(p->y, ctx->t1))) != 0)
  26435. {
  26436. XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
  26437. ctx->state = 2;
  26438. }
  26439. else {
  26440. ctx->state = 3;
  26441. }
  26442. break;
  26443. case 2:
  26444. err = sp_384_proj_point_dbl_15_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t);
  26445. if (err == MP_OKAY)
  26446. ctx->state = 27; /* done */
  26447. break;
  26448. case 3:
  26449. {
  26450. ctx->state = 4;
  26451. break;
  26452. }
  26453. case 4:
  26454. /* U1 = X1*Z2^2 */
  26455. sp_384_mont_sqr_15(ctx->t1, q->z, p384_mod, p384_mp_mod);
  26456. ctx->state = 5;
  26457. break;
  26458. case 5:
  26459. sp_384_mont_mul_15(ctx->t3, ctx->t1, q->z, p384_mod, p384_mp_mod);
  26460. ctx->state = 6;
  26461. break;
  26462. case 6:
  26463. sp_384_mont_mul_15(ctx->t1, ctx->t1, p->x, p384_mod, p384_mp_mod);
  26464. ctx->state = 7;
  26465. break;
  26466. case 7:
  26467. /* U2 = X2*Z1^2 */
  26468. sp_384_mont_sqr_15(ctx->t2, p->z, p384_mod, p384_mp_mod);
  26469. ctx->state = 8;
  26470. break;
  26471. case 8:
  26472. sp_384_mont_mul_15(ctx->t4, ctx->t2, p->z, p384_mod, p384_mp_mod);
  26473. ctx->state = 9;
  26474. break;
  26475. case 9:
  26476. sp_384_mont_mul_15(ctx->t2, ctx->t2, q->x, p384_mod, p384_mp_mod);
  26477. ctx->state = 10;
  26478. break;
  26479. case 10:
  26480. /* S1 = Y1*Z2^3 */
  26481. sp_384_mont_mul_15(ctx->t3, ctx->t3, p->y, p384_mod, p384_mp_mod);
  26482. ctx->state = 11;
  26483. break;
  26484. case 11:
  26485. /* S2 = Y2*Z1^3 */
  26486. sp_384_mont_mul_15(ctx->t4, ctx->t4, q->y, p384_mod, p384_mp_mod);
  26487. ctx->state = 12;
  26488. break;
  26489. case 12:
  26490. /* H = U2 - U1 */
  26491. sp_384_mont_sub_15(ctx->t2, ctx->t2, ctx->t1, p384_mod);
  26492. ctx->state = 13;
  26493. break;
  26494. case 13:
  26495. /* R = S2 - S1 */
  26496. sp_384_mont_sub_15(ctx->t4, ctx->t4, ctx->t3, p384_mod);
  26497. ctx->state = 14;
  26498. break;
  26499. case 14:
  26500. /* X3 = R^2 - H^3 - 2*U1*H^2 */
  26501. sp_384_mont_sqr_15(ctx->t5, ctx->t2, p384_mod, p384_mp_mod);
  26502. ctx->state = 15;
  26503. break;
  26504. case 15:
  26505. sp_384_mont_mul_15(ctx->y, ctx->t1, ctx->t5, p384_mod, p384_mp_mod);
  26506. ctx->state = 16;
  26507. break;
  26508. case 16:
  26509. sp_384_mont_mul_15(ctx->t5, ctx->t5, ctx->t2, p384_mod, p384_mp_mod);
  26510. ctx->state = 17;
  26511. break;
  26512. case 17:
  26513. /* Z3 = H*Z1*Z2 */
  26514. sp_384_mont_mul_15(ctx->z, p->z, ctx->t2, p384_mod, p384_mp_mod);
  26515. ctx->state = 18;
  26516. break;
  26517. case 18:
  26518. sp_384_mont_mul_15(ctx->z, ctx->z, q->z, p384_mod, p384_mp_mod);
  26519. ctx->state = 19;
  26520. break;
  26521. case 19:
  26522. sp_384_mont_sqr_15(ctx->x, ctx->t4, p384_mod, p384_mp_mod);
  26523. ctx->state = 20;
  26524. break;
  26525. case 20:
  26526. sp_384_mont_sub_15(ctx->x, ctx->x, ctx->t5, p384_mod);
  26527. ctx->state = 21;
  26528. break;
  26529. case 21:
  26530. sp_384_mont_mul_15(ctx->t5, ctx->t5, ctx->t3, p384_mod, p384_mp_mod);
  26531. ctx->state = 22;
  26532. break;
  26533. case 22:
  26534. sp_384_mont_dbl_15(ctx->t3, ctx->y, p384_mod);
  26535. ctx->state = 23;
  26536. break;
  26537. case 23:
  26538. sp_384_mont_sub_15(ctx->x, ctx->x, ctx->t3, p384_mod);
  26539. ctx->state = 24;
  26540. break;
  26541. case 24:
  26542. /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
  26543. sp_384_mont_sub_lower_15(ctx->y, ctx->y, ctx->x, p384_mod);
  26544. ctx->state = 25;
  26545. break;
  26546. case 25:
  26547. sp_384_mont_mul_15(ctx->y, ctx->y, ctx->t4, p384_mod, p384_mp_mod);
  26548. ctx->state = 26;
  26549. break;
  26550. case 26:
  26551. sp_384_mont_sub_15(ctx->y, ctx->y, ctx->t5, p384_mod);
  26552. ctx->state = 27;
  26553. /* fall-through */
  26554. case 27:
  26555. {
  26556. int i;
  26557. sp_digit maskp = 0 - (q->infinity & (!p->infinity));
  26558. sp_digit maskq = 0 - (p->infinity & (!q->infinity));
  26559. sp_digit maskt = ~(maskp | maskq);
  26560. for (i = 0; i < 15; i++) {
  26561. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) |
  26562. (ctx->x[i] & maskt);
  26563. }
  26564. for (i = 0; i < 15; i++) {
  26565. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) |
  26566. (ctx->y[i] & maskt);
  26567. }
  26568. for (i = 0; i < 15; i++) {
  26569. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) |
  26570. (ctx->z[i] & maskt);
  26571. }
  26572. r->z[0] |= p->infinity & q->infinity;
  26573. r->infinity = p->infinity & q->infinity;
  26574. err = MP_OKAY;
  26575. break;
  26576. }
  26577. }
  26578. if (err == MP_OKAY && ctx->state != 27) {
  26579. err = FP_WOULDBLOCK;
  26580. }
  26581. return err;
  26582. }
  26583. #endif /* WOLFSSL_SP_NONBLOCK */
  26584. static void sp_384_proj_point_add_15(sp_point_384* r,
  26585. const sp_point_384* p, const sp_point_384* q, sp_digit* t)
  26586. {
  26587. sp_digit* t1 = t;
  26588. sp_digit* t2 = t + 2*15;
  26589. sp_digit* t3 = t + 4*15;
  26590. sp_digit* t4 = t + 6*15;
  26591. sp_digit* t5 = t + 8*15;
  26592. sp_digit* t6 = t + 10*15;
  26593. /* Check double */
  26594. (void)sp_384_sub_15(t1, p384_mod, q->y);
  26595. sp_384_norm_15(t1);
  26596. if ((~p->infinity & ~q->infinity &
  26597. sp_384_cmp_equal_15(p->x, q->x) & sp_384_cmp_equal_15(p->z, q->z) &
  26598. (sp_384_cmp_equal_15(p->y, q->y) | sp_384_cmp_equal_15(p->y, t1))) != 0) {
  26599. sp_384_proj_point_dbl_15(r, p, t);
  26600. }
  26601. else {
  26602. sp_digit maskp;
  26603. sp_digit maskq;
  26604. sp_digit maskt;
  26605. sp_digit* x = t6;
  26606. sp_digit* y = t1;
  26607. sp_digit* z = t2;
  26608. int i;
  26609. maskp = 0 - (q->infinity & (!p->infinity));
  26610. maskq = 0 - (p->infinity & (!q->infinity));
  26611. maskt = ~(maskp | maskq);
  26612. /* U1 = X1*Z2^2 */
  26613. sp_384_mont_sqr_15(t1, q->z, p384_mod, p384_mp_mod);
  26614. sp_384_mont_mul_15(t3, t1, q->z, p384_mod, p384_mp_mod);
  26615. sp_384_mont_mul_15(t1, t1, p->x, p384_mod, p384_mp_mod);
  26616. /* U2 = X2*Z1^2 */
  26617. sp_384_mont_sqr_15(t2, p->z, p384_mod, p384_mp_mod);
  26618. sp_384_mont_mul_15(t4, t2, p->z, p384_mod, p384_mp_mod);
  26619. sp_384_mont_mul_15(t2, t2, q->x, p384_mod, p384_mp_mod);
  26620. /* S1 = Y1*Z2^3 */
  26621. sp_384_mont_mul_15(t3, t3, p->y, p384_mod, p384_mp_mod);
  26622. /* S2 = Y2*Z1^3 */
  26623. sp_384_mont_mul_15(t4, t4, q->y, p384_mod, p384_mp_mod);
  26624. /* H = U2 - U1 */
  26625. sp_384_mont_sub_15(t2, t2, t1, p384_mod);
  26626. /* R = S2 - S1 */
  26627. sp_384_mont_sub_15(t4, t4, t3, p384_mod);
  26628. if (~p->infinity & ~q->infinity &
  26629. sp_384_iszero_15(t2) & sp_384_iszero_15(t4) & maskt) {
  26630. sp_384_proj_point_dbl_15(r, p, t);
  26631. }
  26632. else {
  26633. /* X3 = R^2 - H^3 - 2*U1*H^2 */
  26634. sp_384_mont_sqr_15(t5, t2, p384_mod, p384_mp_mod);
  26635. sp_384_mont_mul_15(y, t1, t5, p384_mod, p384_mp_mod);
  26636. sp_384_mont_mul_15(t5, t5, t2, p384_mod, p384_mp_mod);
  26637. /* Z3 = H*Z1*Z2 */
  26638. sp_384_mont_mul_15(z, p->z, t2, p384_mod, p384_mp_mod);
  26639. sp_384_mont_mul_15(z, z, q->z, p384_mod, p384_mp_mod);
  26640. sp_384_mont_sqr_15(x, t4, p384_mod, p384_mp_mod);
  26641. sp_384_mont_sub_15(x, x, t5, p384_mod);
  26642. sp_384_mont_mul_15(t5, t5, t3, p384_mod, p384_mp_mod);
  26643. sp_384_mont_dbl_15(t3, y, p384_mod);
  26644. sp_384_mont_sub_15(x, x, t3, p384_mod);
  26645. /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
  26646. sp_384_mont_sub_lower_15(y, y, x, p384_mod);
  26647. sp_384_mont_mul_15(y, y, t4, p384_mod, p384_mp_mod);
  26648. sp_384_mont_sub_15(y, y, t5, p384_mod);
  26649. for (i = 0; i < 15; i++) {
  26650. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) |
  26651. (x[i] & maskt);
  26652. }
  26653. for (i = 0; i < 15; i++) {
  26654. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) |
  26655. (y[i] & maskt);
  26656. }
  26657. for (i = 0; i < 15; i++) {
  26658. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) |
  26659. (z[i] & maskt);
  26660. }
  26661. r->z[0] |= p->infinity & q->infinity;
  26662. r->infinity = p->infinity & q->infinity;
  26663. }
  26664. }
  26665. }
  26666. /* Multiply a number by Montgomery normalizer mod modulus (prime).
  26667. *
  26668. * r The resulting Montgomery form number.
  26669. * a The number to convert.
  26670. * m The modulus (prime).
  26671. * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
  26672. */
  26673. static int sp_384_mod_mul_norm_15(sp_digit* r, const sp_digit* a, const sp_digit* m)
  26674. {
  26675. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  26676. int64_t* t = NULL;
  26677. #else
  26678. int64_t t[2 * 12];
  26679. #endif
  26680. int64_t* a32 = NULL;
  26681. int64_t o;
  26682. int err = MP_OKAY;
  26683. (void)m;
  26684. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  26685. t = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 12, NULL, DYNAMIC_TYPE_ECC);
  26686. if (t == NULL)
  26687. err = MEMORY_E;
  26688. #endif
  26689. if (err == MP_OKAY) {
  26690. a32 = t + 12;
  26691. a32[0] = a[0];
  26692. a32[0] |= a[1] << 26U;
  26693. a32[0] &= 0xffffffffL;
  26694. a32[1] = (a[1] >> 6);
  26695. a32[1] |= a[2] << 20U;
  26696. a32[1] &= 0xffffffffL;
  26697. a32[2] = (a[2] >> 12);
  26698. a32[2] |= a[3] << 14U;
  26699. a32[2] &= 0xffffffffL;
  26700. a32[3] = (a[3] >> 18);
  26701. a32[3] |= a[4] << 8U;
  26702. a32[3] &= 0xffffffffL;
  26703. a32[4] = (a[4] >> 24);
  26704. a32[4] |= a[5] << 2U;
  26705. a32[4] |= a[6] << 28U;
  26706. a32[4] &= 0xffffffffL;
  26707. a32[5] = (a[6] >> 4);
  26708. a32[5] |= a[7] << 22U;
  26709. a32[5] &= 0xffffffffL;
  26710. a32[6] = (a[7] >> 10);
  26711. a32[6] |= a[8] << 16U;
  26712. a32[6] &= 0xffffffffL;
  26713. a32[7] = (a[8] >> 16);
  26714. a32[7] |= a[9] << 10U;
  26715. a32[7] &= 0xffffffffL;
  26716. a32[8] = (a[9] >> 22);
  26717. a32[8] |= a[10] << 4U;
  26718. a32[8] |= a[11] << 30U;
  26719. a32[8] &= 0xffffffffL;
  26720. a32[9] = (a[11] >> 2);
  26721. a32[9] |= a[12] << 24U;
  26722. a32[9] &= 0xffffffffL;
  26723. a32[10] = (a[12] >> 8);
  26724. a32[10] |= a[13] << 18U;
  26725. a32[10] &= 0xffffffffL;
  26726. a32[11] = (a[13] >> 14);
  26727. a32[11] |= a[14] << 12U;
  26728. a32[11] &= 0xffffffffL;
  26729. /* 1 0 0 0 0 0 0 0 1 1 0 -1 */
  26730. t[0] = 0 + a32[0] + a32[8] + a32[9] - a32[11];
  26731. /* -1 1 0 0 0 0 0 0 -1 0 1 1 */
  26732. t[1] = 0 - a32[0] + a32[1] - a32[8] + a32[10] + a32[11];
  26733. /* 0 -1 1 0 0 0 0 0 0 -1 0 1 */
  26734. t[2] = 0 - a32[1] + a32[2] - a32[9] + a32[11];
  26735. /* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */
  26736. t[3] = 0 + a32[0] - a32[2] + a32[3] + a32[8] + a32[9] - a32[10] - a32[11];
  26737. /* 1 1 0 -1 1 0 0 0 1 2 1 -2 */
  26738. t[4] = 0 + a32[0] + a32[1] - a32[3] + a32[4] + a32[8] + 2 * a32[9] + a32[10] - 2 * a32[11];
  26739. /* 0 1 1 0 -1 1 0 0 0 1 2 1 */
  26740. t[5] = 0 + a32[1] + a32[2] - a32[4] + a32[5] + a32[9] + 2 * a32[10] + a32[11];
  26741. /* 0 0 1 1 0 -1 1 0 0 0 1 2 */
  26742. t[6] = 0 + a32[2] + a32[3] - a32[5] + a32[6] + a32[10] + 2 * a32[11];
  26743. /* 0 0 0 1 1 0 -1 1 0 0 0 1 */
  26744. t[7] = 0 + a32[3] + a32[4] - a32[6] + a32[7] + a32[11];
  26745. /* 0 0 0 0 1 1 0 -1 1 0 0 0 */
  26746. t[8] = 0 + a32[4] + a32[5] - a32[7] + a32[8];
  26747. /* 0 0 0 0 0 1 1 0 -1 1 0 0 */
  26748. t[9] = 0 + a32[5] + a32[6] - a32[8] + a32[9];
  26749. /* 0 0 0 0 0 0 1 1 0 -1 1 0 */
  26750. t[10] = 0 + a32[6] + a32[7] - a32[9] + a32[10];
  26751. /* 0 0 0 0 0 0 0 1 1 0 -1 1 */
  26752. t[11] = 0 + a32[7] + a32[8] - a32[10] + a32[11];
  26753. t[1] += t[0] >> 32; t[0] &= 0xffffffff;
  26754. t[2] += t[1] >> 32; t[1] &= 0xffffffff;
  26755. t[3] += t[2] >> 32; t[2] &= 0xffffffff;
  26756. t[4] += t[3] >> 32; t[3] &= 0xffffffff;
  26757. t[5] += t[4] >> 32; t[4] &= 0xffffffff;
  26758. t[6] += t[5] >> 32; t[5] &= 0xffffffff;
  26759. t[7] += t[6] >> 32; t[6] &= 0xffffffff;
  26760. t[8] += t[7] >> 32; t[7] &= 0xffffffff;
  26761. t[9] += t[8] >> 32; t[8] &= 0xffffffff;
  26762. t[10] += t[9] >> 32; t[9] &= 0xffffffff;
  26763. t[11] += t[10] >> 32; t[10] &= 0xffffffff;
  26764. o = t[11] >> 32; t[11] &= 0xffffffff;
  26765. t[0] += o;
  26766. t[1] -= o;
  26767. t[3] += o;
  26768. t[4] += o;
  26769. t[1] += t[0] >> 32; t[0] &= 0xffffffff;
  26770. t[2] += t[1] >> 32; t[1] &= 0xffffffff;
  26771. t[3] += t[2] >> 32; t[2] &= 0xffffffff;
  26772. t[4] += t[3] >> 32; t[3] &= 0xffffffff;
  26773. t[5] += t[4] >> 32; t[4] &= 0xffffffff;
  26774. t[6] += t[5] >> 32; t[5] &= 0xffffffff;
  26775. t[7] += t[6] >> 32; t[6] &= 0xffffffff;
  26776. t[8] += t[7] >> 32; t[7] &= 0xffffffff;
  26777. t[9] += t[8] >> 32; t[8] &= 0xffffffff;
  26778. t[10] += t[9] >> 32; t[9] &= 0xffffffff;
  26779. t[11] += t[10] >> 32; t[10] &= 0xffffffff;
  26780. r[0] = (sp_digit)(t[0]) & 0x3ffffffL;
  26781. r[1] = (sp_digit)(t[0] >> 26U);
  26782. r[1] |= (sp_digit)(t[1] << 6U);
  26783. r[1] &= 0x3ffffffL;
  26784. r[2] = (sp_digit)(t[1] >> 20U);
  26785. r[2] |= (sp_digit)(t[2] << 12U);
  26786. r[2] &= 0x3ffffffL;
  26787. r[3] = (sp_digit)(t[2] >> 14U);
  26788. r[3] |= (sp_digit)(t[3] << 18U);
  26789. r[3] &= 0x3ffffffL;
  26790. r[4] = (sp_digit)(t[3] >> 8U);
  26791. r[4] |= (sp_digit)(t[4] << 24U);
  26792. r[4] &= 0x3ffffffL;
  26793. r[5] = (sp_digit)(t[4] >> 2U) & 0x3ffffffL;
  26794. r[6] = (sp_digit)(t[4] >> 28U);
  26795. r[6] |= (sp_digit)(t[5] << 4U);
  26796. r[6] &= 0x3ffffffL;
  26797. r[7] = (sp_digit)(t[5] >> 22U);
  26798. r[7] |= (sp_digit)(t[6] << 10U);
  26799. r[7] &= 0x3ffffffL;
  26800. r[8] = (sp_digit)(t[6] >> 16U);
  26801. r[8] |= (sp_digit)(t[7] << 16U);
  26802. r[8] &= 0x3ffffffL;
  26803. r[9] = (sp_digit)(t[7] >> 10U);
  26804. r[9] |= (sp_digit)(t[8] << 22U);
  26805. r[9] &= 0x3ffffffL;
  26806. r[10] = (sp_digit)(t[8] >> 4U) & 0x3ffffffL;
  26807. r[11] = (sp_digit)(t[8] >> 30U);
  26808. r[11] |= (sp_digit)(t[9] << 2U);
  26809. r[11] &= 0x3ffffffL;
  26810. r[12] = (sp_digit)(t[9] >> 24U);
  26811. r[12] |= (sp_digit)(t[10] << 8U);
  26812. r[12] &= 0x3ffffffL;
  26813. r[13] = (sp_digit)(t[10] >> 18U);
  26814. r[13] |= (sp_digit)(t[11] << 14U);
  26815. r[13] &= 0x3ffffffL;
  26816. r[14] = (sp_digit)(t[11] >> 12U);
  26817. }
  26818. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  26819. if (t != NULL)
  26820. XFREE(t, NULL, DYNAMIC_TYPE_ECC);
  26821. #endif
  26822. return err;
  26823. }
  26824. #ifdef WOLFSSL_SP_SMALL
  26825. /* Multiply the point by the scalar and return the result.
  26826. * If map is true then convert result to affine coordinates.
  26827. *
  26828. * Small implementation using add and double that is cache attack resistant but
  26829. * allocates memory rather than use large stacks.
  26830. * 384 adds and doubles.
  26831. *
  26832. * r Resulting point.
  26833. * g Point to multiply.
  26834. * k Scalar to multiply by.
  26835. * map Indicates whether to convert result to affine.
  26836. * ct Constant time required.
  26837. * heap Heap to use for allocation.
  26838. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  26839. */
  26840. #ifdef WOLFSSL_SP_NONBLOCK
  26841. typedef struct sp_384_ecc_mulmod_15_ctx {
  26842. int state;
  26843. union {
  26844. sp_384_proj_point_dbl_15_ctx dbl_ctx;
  26845. sp_384_proj_point_add_15_ctx add_ctx;
  26846. };
  26847. sp_point_384 t[3];
  26848. sp_digit tmp[2 * 15 * 6];
  26849. sp_digit n;
  26850. int i;
  26851. int c;
  26852. int y;
  26853. } sp_384_ecc_mulmod_15_ctx;
  26854. static int sp_384_ecc_mulmod_15_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r,
  26855. const sp_point_384* g, const sp_digit* k, int map, int ct, void* heap)
  26856. {
  26857. int err = FP_WOULDBLOCK;
  26858. sp_384_ecc_mulmod_15_ctx* ctx = (sp_384_ecc_mulmod_15_ctx*)sp_ctx->data;
  26859. typedef char ctx_size_test[sizeof(sp_384_ecc_mulmod_15_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  26860. (void)sizeof(ctx_size_test);
  26861. /* Implementation is constant time. */
  26862. (void)ct;
  26863. switch (ctx->state) {
  26864. case 0: /* INIT */
  26865. XMEMSET(ctx->t, 0, sizeof(sp_point_384) * 3);
  26866. ctx->i = 14;
  26867. ctx->c = 20;
  26868. ctx->n = k[ctx->i--] << (26 - ctx->c);
  26869. /* t[0] = {0, 0, 1} * norm */
  26870. ctx->t[0].infinity = 1;
  26871. ctx->state = 1;
  26872. break;
  26873. case 1: /* T1X */
  26874. /* t[1] = {g->x, g->y, g->z} * norm */
  26875. err = sp_384_mod_mul_norm_15(ctx->t[1].x, g->x, p384_mod);
  26876. ctx->state = 2;
  26877. break;
  26878. case 2: /* T1Y */
  26879. err = sp_384_mod_mul_norm_15(ctx->t[1].y, g->y, p384_mod);
  26880. ctx->state = 3;
  26881. break;
  26882. case 3: /* T1Z */
  26883. err = sp_384_mod_mul_norm_15(ctx->t[1].z, g->z, p384_mod);
  26884. ctx->state = 4;
  26885. break;
  26886. case 4: /* ADDPREP */
  26887. if (ctx->c == 0) {
  26888. if (ctx->i == -1) {
  26889. ctx->state = 7;
  26890. break;
  26891. }
  26892. ctx->n = k[ctx->i--];
  26893. ctx->c = 26;
  26894. }
  26895. ctx->y = (ctx->n >> 25) & 1;
  26896. ctx->n <<= 1;
  26897. XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx));
  26898. ctx->state = 5;
  26899. break;
  26900. case 5: /* ADD */
  26901. err = sp_384_proj_point_add_15_nb((sp_ecc_ctx_t*)&ctx->add_ctx,
  26902. &ctx->t[ctx->y^1], &ctx->t[0], &ctx->t[1], ctx->tmp);
  26903. if (err == MP_OKAY) {
  26904. XMEMCPY(&ctx->t[2], (void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) +
  26905. ((size_t)&ctx->t[1] & addr_mask[ctx->y])),
  26906. sizeof(sp_point_384));
  26907. XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
  26908. ctx->state = 6;
  26909. }
  26910. break;
  26911. case 6: /* DBL */
  26912. err = sp_384_proj_point_dbl_15_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->t[2],
  26913. &ctx->t[2], ctx->tmp);
  26914. if (err == MP_OKAY) {
  26915. XMEMCPY((void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) +
  26916. ((size_t)&ctx->t[1] & addr_mask[ctx->y])), &ctx->t[2],
  26917. sizeof(sp_point_384));
  26918. ctx->state = 4;
  26919. ctx->c--;
  26920. }
  26921. break;
  26922. case 7: /* MAP */
  26923. if (map != 0) {
  26924. sp_384_map_15(r, &ctx->t[0], ctx->tmp);
  26925. }
  26926. else {
  26927. XMEMCPY(r, &ctx->t[0], sizeof(sp_point_384));
  26928. }
  26929. err = MP_OKAY;
  26930. break;
  26931. }
  26932. if (err == MP_OKAY && ctx->state != 7) {
  26933. err = FP_WOULDBLOCK;
  26934. }
  26935. if (err != FP_WOULDBLOCK) {
  26936. ForceZero(ctx->tmp, sizeof(ctx->tmp));
  26937. ForceZero(ctx->t, sizeof(ctx->t));
  26938. }
  26939. (void)heap;
  26940. return err;
  26941. }
  26942. #endif /* WOLFSSL_SP_NONBLOCK */
  26943. static int sp_384_ecc_mulmod_15(sp_point_384* r, const sp_point_384* g,
  26944. const sp_digit* k, int map, int ct, void* heap)
  26945. {
  26946. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  26947. sp_point_384* t = NULL;
  26948. sp_digit* tmp = NULL;
  26949. #else
  26950. sp_point_384 t[3];
  26951. sp_digit tmp[2 * 15 * 6];
  26952. #endif
  26953. sp_digit n;
  26954. int i;
  26955. int c;
  26956. int y;
  26957. int err = MP_OKAY;
  26958. /* Implementation is constant time. */
  26959. (void)ct;
  26960. (void)heap;
  26961. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  26962. t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap,
  26963. DYNAMIC_TYPE_ECC);
  26964. if (t == NULL)
  26965. err = MEMORY_E;
  26966. if (err == MP_OKAY) {
  26967. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 6, heap,
  26968. DYNAMIC_TYPE_ECC);
  26969. if (tmp == NULL)
  26970. err = MEMORY_E;
  26971. }
  26972. #endif
  26973. if (err == MP_OKAY) {
  26974. XMEMSET(t, 0, sizeof(sp_point_384) * 3);
  26975. /* t[0] = {0, 0, 1} * norm */
  26976. t[0].infinity = 1;
  26977. /* t[1] = {g->x, g->y, g->z} * norm */
  26978. err = sp_384_mod_mul_norm_15(t[1].x, g->x, p384_mod);
  26979. }
  26980. if (err == MP_OKAY)
  26981. err = sp_384_mod_mul_norm_15(t[1].y, g->y, p384_mod);
  26982. if (err == MP_OKAY)
  26983. err = sp_384_mod_mul_norm_15(t[1].z, g->z, p384_mod);
  26984. if (err == MP_OKAY) {
  26985. i = 14;
  26986. c = 20;
  26987. n = k[i--] << (26 - c);
  26988. for (; ; c--) {
  26989. if (c == 0) {
  26990. if (i == -1)
  26991. break;
  26992. n = k[i--];
  26993. c = 26;
  26994. }
  26995. y = (n >> 25) & 1;
  26996. n <<= 1;
  26997. sp_384_proj_point_add_15(&t[y^1], &t[0], &t[1], tmp);
  26998. XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) +
  26999. ((size_t)&t[1] & addr_mask[y])),
  27000. sizeof(sp_point_384));
  27001. sp_384_proj_point_dbl_15(&t[2], &t[2], tmp);
  27002. XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) +
  27003. ((size_t)&t[1] & addr_mask[y])), &t[2],
  27004. sizeof(sp_point_384));
  27005. }
  27006. if (map != 0) {
  27007. sp_384_map_15(r, &t[0], tmp);
  27008. }
  27009. else {
  27010. XMEMCPY(r, &t[0], sizeof(sp_point_384));
  27011. }
  27012. }
  27013. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  27014. if (tmp != NULL)
  27015. #endif
  27016. {
  27017. ForceZero(tmp, sizeof(sp_digit) * 2 * 15 * 6);
  27018. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  27019. XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
  27020. #endif
  27021. }
  27022. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  27023. if (t != NULL)
  27024. #endif
  27025. {
  27026. ForceZero(t, sizeof(sp_point_384) * 3);
  27027. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  27028. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  27029. #endif
  27030. }
  27031. return err;
  27032. }
  27033. #else
  27034. /* A table entry for pre-computed points. */
  27035. typedef struct sp_table_entry_384 {
  27036. sp_digit x[15];
  27037. sp_digit y[15];
  27038. } sp_table_entry_384;
  27039. /* Conditionally copy a into r using the mask m.
  27040. * m is -1 to copy and 0 when not.
  27041. *
  27042. * r A single precision number to copy over.
  27043. * a A single precision number to copy.
  27044. * m Mask value to apply.
  27045. */
  27046. static void sp_384_cond_copy_15(sp_digit* r, const sp_digit* a, const sp_digit m)
  27047. {
  27048. sp_digit t[15];
  27049. #ifdef WOLFSSL_SP_SMALL
  27050. int i;
  27051. for (i = 0; i < 15; i++) {
  27052. t[i] = r[i] ^ a[i];
  27053. }
  27054. for (i = 0; i < 15; i++) {
  27055. r[i] ^= t[i] & m;
  27056. }
  27057. #else
  27058. t[ 0] = r[ 0] ^ a[ 0];
  27059. t[ 1] = r[ 1] ^ a[ 1];
  27060. t[ 2] = r[ 2] ^ a[ 2];
  27061. t[ 3] = r[ 3] ^ a[ 3];
  27062. t[ 4] = r[ 4] ^ a[ 4];
  27063. t[ 5] = r[ 5] ^ a[ 5];
  27064. t[ 6] = r[ 6] ^ a[ 6];
  27065. t[ 7] = r[ 7] ^ a[ 7];
  27066. t[ 8] = r[ 8] ^ a[ 8];
  27067. t[ 9] = r[ 9] ^ a[ 9];
  27068. t[10] = r[10] ^ a[10];
  27069. t[11] = r[11] ^ a[11];
  27070. t[12] = r[12] ^ a[12];
  27071. t[13] = r[13] ^ a[13];
  27072. t[14] = r[14] ^ a[14];
  27073. r[ 0] ^= t[ 0] & m;
  27074. r[ 1] ^= t[ 1] & m;
  27075. r[ 2] ^= t[ 2] & m;
  27076. r[ 3] ^= t[ 3] & m;
  27077. r[ 4] ^= t[ 4] & m;
  27078. r[ 5] ^= t[ 5] & m;
  27079. r[ 6] ^= t[ 6] & m;
  27080. r[ 7] ^= t[ 7] & m;
  27081. r[ 8] ^= t[ 8] & m;
  27082. r[ 9] ^= t[ 9] & m;
  27083. r[10] ^= t[10] & m;
  27084. r[11] ^= t[11] & m;
  27085. r[12] ^= t[12] & m;
  27086. r[13] ^= t[13] & m;
  27087. r[14] ^= t[14] & m;
  27088. #endif /* WOLFSSL_SP_SMALL */
  27089. }
  27090. #define sp_384_mont_dbl_lower_15 sp_384_mont_dbl_15
  27091. #define sp_384_mont_tpl_lower_15 sp_384_mont_tpl_15
  27092. /* Double the Montgomery form projective point p a number of times.
  27093. *
  27094. * r Result of repeated doubling of point.
  27095. * p Point to double.
  27096. * n Number of times to double
  27097. * t Temporary ordinate data.
  27098. */
  27099. static void sp_384_proj_point_dbl_n_15(sp_point_384* p, int i,
  27100. sp_digit* t)
  27101. {
  27102. sp_digit* w = t;
  27103. sp_digit* a = t + 2*15;
  27104. sp_digit* b = t + 4*15;
  27105. sp_digit* t1 = t + 6*15;
  27106. sp_digit* t2 = t + 8*15;
  27107. sp_digit* x;
  27108. sp_digit* y;
  27109. sp_digit* z;
  27110. volatile int n = i;
  27111. x = p->x;
  27112. y = p->y;
  27113. z = p->z;
  27114. /* Y = 2*Y */
  27115. sp_384_mont_dbl_15(y, y, p384_mod);
  27116. /* W = Z^4 */
  27117. sp_384_mont_sqr_15(w, z, p384_mod, p384_mp_mod);
  27118. sp_384_mont_sqr_15(w, w, p384_mod, p384_mp_mod);
  27119. #ifndef WOLFSSL_SP_SMALL
  27120. while (--n > 0)
  27121. #else
  27122. while (--n >= 0)
  27123. #endif
  27124. {
  27125. /* A = 3*(X^2 - W) */
  27126. sp_384_mont_sqr_15(t1, x, p384_mod, p384_mp_mod);
  27127. sp_384_mont_sub_15(t1, t1, w, p384_mod);
  27128. sp_384_mont_tpl_lower_15(a, t1, p384_mod);
  27129. /* B = X*Y^2 */
  27130. sp_384_mont_sqr_15(t1, y, p384_mod, p384_mp_mod);
  27131. sp_384_mont_mul_15(b, t1, x, p384_mod, p384_mp_mod);
  27132. /* X = A^2 - 2B */
  27133. sp_384_mont_sqr_15(x, a, p384_mod, p384_mp_mod);
  27134. sp_384_mont_dbl_15(t2, b, p384_mod);
  27135. sp_384_mont_sub_15(x, x, t2, p384_mod);
  27136. /* b = 2.(B - X) */
  27137. sp_384_mont_sub_lower_15(t2, b, x, p384_mod);
  27138. sp_384_mont_dbl_lower_15(b, t2, p384_mod);
  27139. /* Z = Z*Y */
  27140. sp_384_mont_mul_15(z, z, y, p384_mod, p384_mp_mod);
  27141. /* t1 = Y^4 */
  27142. sp_384_mont_sqr_15(t1, t1, p384_mod, p384_mp_mod);
  27143. #ifdef WOLFSSL_SP_SMALL
  27144. if (n != 0)
  27145. #endif
  27146. {
  27147. /* W = W*Y^4 */
  27148. sp_384_mont_mul_15(w, w, t1, p384_mod, p384_mp_mod);
  27149. }
  27150. /* y = 2*A*(B - X) - Y^4 */
  27151. sp_384_mont_mul_15(y, b, a, p384_mod, p384_mp_mod);
  27152. sp_384_mont_sub_15(y, y, t1, p384_mod);
  27153. }
  27154. #ifndef WOLFSSL_SP_SMALL
  27155. /* A = 3*(X^2 - W) */
  27156. sp_384_mont_sqr_15(t1, x, p384_mod, p384_mp_mod);
  27157. sp_384_mont_sub_15(t1, t1, w, p384_mod);
  27158. sp_384_mont_tpl_lower_15(a, t1, p384_mod);
  27159. /* B = X*Y^2 */
  27160. sp_384_mont_sqr_15(t1, y, p384_mod, p384_mp_mod);
  27161. sp_384_mont_mul_15(b, t1, x, p384_mod, p384_mp_mod);
  27162. /* X = A^2 - 2B */
  27163. sp_384_mont_sqr_15(x, a, p384_mod, p384_mp_mod);
  27164. sp_384_mont_dbl_15(t2, b, p384_mod);
  27165. sp_384_mont_sub_15(x, x, t2, p384_mod);
  27166. /* b = 2.(B - X) */
  27167. sp_384_mont_sub_lower_15(t2, b, x, p384_mod);
  27168. sp_384_mont_dbl_lower_15(b, t2, p384_mod);
  27169. /* Z = Z*Y */
  27170. sp_384_mont_mul_15(z, z, y, p384_mod, p384_mp_mod);
  27171. /* t1 = Y^4 */
  27172. sp_384_mont_sqr_15(t1, t1, p384_mod, p384_mp_mod);
  27173. /* y = 2*A*(B - X) - Y^4 */
  27174. sp_384_mont_mul_15(y, b, a, p384_mod, p384_mp_mod);
  27175. sp_384_mont_sub_15(y, y, t1, p384_mod);
  27176. #endif
  27177. /* Y = Y/2 */
  27178. sp_384_div2_15(y, y, p384_mod);
  27179. }
  27180. /* Double the Montgomery form projective point p a number of times.
  27181. *
  27182. * r Result of repeated doubling of point.
  27183. * p Point to double.
  27184. * n Number of times to double
  27185. * t Temporary ordinate data.
  27186. */
  27187. static void sp_384_proj_point_dbl_n_store_15(sp_point_384* r,
  27188. const sp_point_384* p, int n, int m, sp_digit* t)
  27189. {
  27190. sp_digit* w = t;
  27191. sp_digit* a = t + 2*15;
  27192. sp_digit* b = t + 4*15;
  27193. sp_digit* t1 = t + 6*15;
  27194. sp_digit* t2 = t + 8*15;
  27195. sp_digit* x = r[2*m].x;
  27196. sp_digit* y = r[(1<<n)*m].y;
  27197. sp_digit* z = r[2*m].z;
  27198. int i;
  27199. int j;
  27200. for (i=0; i<15; i++) {
  27201. x[i] = p->x[i];
  27202. }
  27203. for (i=0; i<15; i++) {
  27204. y[i] = p->y[i];
  27205. }
  27206. for (i=0; i<15; i++) {
  27207. z[i] = p->z[i];
  27208. }
  27209. /* Y = 2*Y */
  27210. sp_384_mont_dbl_15(y, y, p384_mod);
  27211. /* W = Z^4 */
  27212. sp_384_mont_sqr_15(w, z, p384_mod, p384_mp_mod);
  27213. sp_384_mont_sqr_15(w, w, p384_mod, p384_mp_mod);
  27214. j = m;
  27215. for (i=1; i<=n; i++) {
  27216. j *= 2;
  27217. /* A = 3*(X^2 - W) */
  27218. sp_384_mont_sqr_15(t1, x, p384_mod, p384_mp_mod);
  27219. sp_384_mont_sub_15(t1, t1, w, p384_mod);
  27220. sp_384_mont_tpl_lower_15(a, t1, p384_mod);
  27221. /* B = X*Y^2 */
  27222. sp_384_mont_sqr_15(t1, y, p384_mod, p384_mp_mod);
  27223. sp_384_mont_mul_15(b, t1, x, p384_mod, p384_mp_mod);
  27224. x = r[j].x;
  27225. /* X = A^2 - 2B */
  27226. sp_384_mont_sqr_15(x, a, p384_mod, p384_mp_mod);
  27227. sp_384_mont_dbl_15(t2, b, p384_mod);
  27228. sp_384_mont_sub_15(x, x, t2, p384_mod);
  27229. /* b = 2.(B - X) */
  27230. sp_384_mont_sub_lower_15(t2, b, x, p384_mod);
  27231. sp_384_mont_dbl_lower_15(b, t2, p384_mod);
  27232. /* Z = Z*Y */
  27233. sp_384_mont_mul_15(r[j].z, z, y, p384_mod, p384_mp_mod);
  27234. z = r[j].z;
  27235. /* t1 = Y^4 */
  27236. sp_384_mont_sqr_15(t1, t1, p384_mod, p384_mp_mod);
  27237. if (i != n) {
  27238. /* W = W*Y^4 */
  27239. sp_384_mont_mul_15(w, w, t1, p384_mod, p384_mp_mod);
  27240. }
  27241. /* y = 2*A*(B - X) - Y^4 */
  27242. sp_384_mont_mul_15(y, b, a, p384_mod, p384_mp_mod);
  27243. sp_384_mont_sub_15(y, y, t1, p384_mod);
  27244. /* Y = Y/2 */
  27245. sp_384_div2_15(r[j].y, y, p384_mod);
  27246. r[j].infinity = 0;
  27247. }
  27248. }
  27249. /* Add two Montgomery form projective points.
  27250. *
  27251. * ra Result of addition.
  27252. * rs Result of subtraction.
  27253. * p First point to add.
  27254. * q Second point to add.
  27255. * t Temporary ordinate data.
  27256. */
  27257. static void sp_384_proj_point_add_sub_15(sp_point_384* ra,
  27258. sp_point_384* rs, const sp_point_384* p, const sp_point_384* q,
  27259. sp_digit* t)
  27260. {
  27261. sp_digit* t1 = t;
  27262. sp_digit* t2 = t + 2*15;
  27263. sp_digit* t3 = t + 4*15;
  27264. sp_digit* t4 = t + 6*15;
  27265. sp_digit* t5 = t + 8*15;
  27266. sp_digit* t6 = t + 10*15;
  27267. sp_digit* xa = ra->x;
  27268. sp_digit* ya = ra->y;
  27269. sp_digit* za = ra->z;
  27270. sp_digit* xs = rs->x;
  27271. sp_digit* ys = rs->y;
  27272. sp_digit* zs = rs->z;
  27273. XMEMCPY(xa, p->x, sizeof(p->x) / 2);
  27274. XMEMCPY(ya, p->y, sizeof(p->y) / 2);
  27275. XMEMCPY(za, p->z, sizeof(p->z) / 2);
  27276. ra->infinity = 0;
  27277. rs->infinity = 0;
  27278. /* U1 = X1*Z2^2 */
  27279. sp_384_mont_sqr_15(t1, q->z, p384_mod, p384_mp_mod);
  27280. sp_384_mont_mul_15(t3, t1, q->z, p384_mod, p384_mp_mod);
  27281. sp_384_mont_mul_15(t1, t1, xa, p384_mod, p384_mp_mod);
  27282. /* U2 = X2*Z1^2 */
  27283. sp_384_mont_sqr_15(t2, za, p384_mod, p384_mp_mod);
  27284. sp_384_mont_mul_15(t4, t2, za, p384_mod, p384_mp_mod);
  27285. sp_384_mont_mul_15(t2, t2, q->x, p384_mod, p384_mp_mod);
  27286. /* S1 = Y1*Z2^3 */
  27287. sp_384_mont_mul_15(t3, t3, ya, p384_mod, p384_mp_mod);
  27288. /* S2 = Y2*Z1^3 */
  27289. sp_384_mont_mul_15(t4, t4, q->y, p384_mod, p384_mp_mod);
  27290. /* H = U2 - U1 */
  27291. sp_384_mont_sub_15(t2, t2, t1, p384_mod);
  27292. /* RS = S2 + S1 */
  27293. sp_384_mont_add_15(t6, t4, t3, p384_mod);
  27294. /* R = S2 - S1 */
  27295. sp_384_mont_sub_15(t4, t4, t3, p384_mod);
  27296. /* Z3 = H*Z1*Z2 */
  27297. /* ZS = H*Z1*Z2 */
  27298. sp_384_mont_mul_15(za, za, q->z, p384_mod, p384_mp_mod);
  27299. sp_384_mont_mul_15(za, za, t2, p384_mod, p384_mp_mod);
  27300. XMEMCPY(zs, za, sizeof(p->z)/2);
  27301. /* X3 = R^2 - H^3 - 2*U1*H^2 */
  27302. /* XS = RS^2 - H^3 - 2*U1*H^2 */
  27303. sp_384_mont_sqr_15(xa, t4, p384_mod, p384_mp_mod);
  27304. sp_384_mont_sqr_15(xs, t6, p384_mod, p384_mp_mod);
  27305. sp_384_mont_sqr_15(t5, t2, p384_mod, p384_mp_mod);
  27306. sp_384_mont_mul_15(ya, t1, t5, p384_mod, p384_mp_mod);
  27307. sp_384_mont_mul_15(t5, t5, t2, p384_mod, p384_mp_mod);
  27308. sp_384_mont_sub_15(xa, xa, t5, p384_mod);
  27309. sp_384_mont_sub_15(xs, xs, t5, p384_mod);
  27310. sp_384_mont_dbl_15(t1, ya, p384_mod);
  27311. sp_384_mont_sub_15(xa, xa, t1, p384_mod);
  27312. sp_384_mont_sub_15(xs, xs, t1, p384_mod);
  27313. /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
  27314. /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */
  27315. sp_384_mont_sub_lower_15(ys, ya, xs, p384_mod);
  27316. sp_384_mont_sub_lower_15(ya, ya, xa, p384_mod);
  27317. sp_384_mont_mul_15(ya, ya, t4, p384_mod, p384_mp_mod);
  27318. sp_384_sub_15(t6, p384_mod, t6);
  27319. sp_384_mont_mul_15(ys, ys, t6, p384_mod, p384_mp_mod);
  27320. sp_384_mont_mul_15(t5, t5, t3, p384_mod, p384_mp_mod);
  27321. sp_384_mont_sub_15(ya, ya, t5, p384_mod);
  27322. sp_384_mont_sub_15(ys, ys, t5, p384_mod);
  27323. }
  27324. /* Structure used to describe recoding of scalar multiplication. */
  27325. typedef struct ecc_recode_384 {
  27326. /* Index into pre-computation table. */
  27327. uint8_t i;
  27328. /* Use the negative of the point. */
  27329. uint8_t neg;
  27330. } ecc_recode_384;
  27331. /* The index into pre-computation table to use. */
  27332. static const uint8_t recode_index_15_6[66] = {
  27333. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
  27334. 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
  27335. 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
  27336. 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
  27337. 0, 1,
  27338. };
  27339. /* Whether to negate y-ordinate. */
  27340. static const uint8_t recode_neg_15_6[66] = {
  27341. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  27342. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  27343. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  27344. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  27345. 0, 0,
  27346. };
  27347. /* Recode the scalar for multiplication using pre-computed values and
  27348. * subtraction.
  27349. *
  27350. * k Scalar to multiply by.
  27351. * v Vector of operations to perform.
  27352. */
  27353. static void sp_384_ecc_recode_6_15(const sp_digit* k, ecc_recode_384* v)
  27354. {
  27355. int i;
  27356. int j;
  27357. uint8_t y;
  27358. int carry = 0;
  27359. int o;
  27360. sp_digit n;
  27361. j = 0;
  27362. n = k[j];
  27363. o = 0;
  27364. for (i=0; i<65; i++) {
  27365. y = (int8_t)n;
  27366. if (o + 6 < 26) {
  27367. y &= 0x3f;
  27368. n >>= 6;
  27369. o += 6;
  27370. }
  27371. else if (o + 6 == 26) {
  27372. n >>= 6;
  27373. if (++j < 15)
  27374. n = k[j];
  27375. o = 0;
  27376. }
  27377. else if (++j < 15) {
  27378. n = k[j];
  27379. y |= (uint8_t)((n << (26 - o)) & 0x3f);
  27380. o -= 20;
  27381. n >>= o;
  27382. }
  27383. y += (uint8_t)carry;
  27384. v[i].i = recode_index_15_6[y];
  27385. v[i].neg = recode_neg_15_6[y];
  27386. carry = (y >> 6) + v[i].neg;
  27387. }
  27388. }
  27389. #ifndef WC_NO_CACHE_RESISTANT
  27390. /* Touch each possible point that could be being copied.
  27391. *
  27392. * r Point to copy into.
  27393. * table Table - start of the entires to access
  27394. * idx Index of entry to retrieve.
  27395. */
  27396. static void sp_384_get_point_33_15(sp_point_384* r, const sp_point_384* table,
  27397. int idx)
  27398. {
  27399. int i;
  27400. sp_digit mask;
  27401. r->x[0] = 0;
  27402. r->x[1] = 0;
  27403. r->x[2] = 0;
  27404. r->x[3] = 0;
  27405. r->x[4] = 0;
  27406. r->x[5] = 0;
  27407. r->x[6] = 0;
  27408. r->x[7] = 0;
  27409. r->x[8] = 0;
  27410. r->x[9] = 0;
  27411. r->x[10] = 0;
  27412. r->x[11] = 0;
  27413. r->x[12] = 0;
  27414. r->x[13] = 0;
  27415. r->x[14] = 0;
  27416. r->y[0] = 0;
  27417. r->y[1] = 0;
  27418. r->y[2] = 0;
  27419. r->y[3] = 0;
  27420. r->y[4] = 0;
  27421. r->y[5] = 0;
  27422. r->y[6] = 0;
  27423. r->y[7] = 0;
  27424. r->y[8] = 0;
  27425. r->y[9] = 0;
  27426. r->y[10] = 0;
  27427. r->y[11] = 0;
  27428. r->y[12] = 0;
  27429. r->y[13] = 0;
  27430. r->y[14] = 0;
  27431. r->z[0] = 0;
  27432. r->z[1] = 0;
  27433. r->z[2] = 0;
  27434. r->z[3] = 0;
  27435. r->z[4] = 0;
  27436. r->z[5] = 0;
  27437. r->z[6] = 0;
  27438. r->z[7] = 0;
  27439. r->z[8] = 0;
  27440. r->z[9] = 0;
  27441. r->z[10] = 0;
  27442. r->z[11] = 0;
  27443. r->z[12] = 0;
  27444. r->z[13] = 0;
  27445. r->z[14] = 0;
  27446. for (i = 1; i < 33; i++) {
  27447. mask = 0 - (i == idx);
  27448. r->x[0] |= mask & table[i].x[0];
  27449. r->x[1] |= mask & table[i].x[1];
  27450. r->x[2] |= mask & table[i].x[2];
  27451. r->x[3] |= mask & table[i].x[3];
  27452. r->x[4] |= mask & table[i].x[4];
  27453. r->x[5] |= mask & table[i].x[5];
  27454. r->x[6] |= mask & table[i].x[6];
  27455. r->x[7] |= mask & table[i].x[7];
  27456. r->x[8] |= mask & table[i].x[8];
  27457. r->x[9] |= mask & table[i].x[9];
  27458. r->x[10] |= mask & table[i].x[10];
  27459. r->x[11] |= mask & table[i].x[11];
  27460. r->x[12] |= mask & table[i].x[12];
  27461. r->x[13] |= mask & table[i].x[13];
  27462. r->x[14] |= mask & table[i].x[14];
  27463. r->y[0] |= mask & table[i].y[0];
  27464. r->y[1] |= mask & table[i].y[1];
  27465. r->y[2] |= mask & table[i].y[2];
  27466. r->y[3] |= mask & table[i].y[3];
  27467. r->y[4] |= mask & table[i].y[4];
  27468. r->y[5] |= mask & table[i].y[5];
  27469. r->y[6] |= mask & table[i].y[6];
  27470. r->y[7] |= mask & table[i].y[7];
  27471. r->y[8] |= mask & table[i].y[8];
  27472. r->y[9] |= mask & table[i].y[9];
  27473. r->y[10] |= mask & table[i].y[10];
  27474. r->y[11] |= mask & table[i].y[11];
  27475. r->y[12] |= mask & table[i].y[12];
  27476. r->y[13] |= mask & table[i].y[13];
  27477. r->y[14] |= mask & table[i].y[14];
  27478. r->z[0] |= mask & table[i].z[0];
  27479. r->z[1] |= mask & table[i].z[1];
  27480. r->z[2] |= mask & table[i].z[2];
  27481. r->z[3] |= mask & table[i].z[3];
  27482. r->z[4] |= mask & table[i].z[4];
  27483. r->z[5] |= mask & table[i].z[5];
  27484. r->z[6] |= mask & table[i].z[6];
  27485. r->z[7] |= mask & table[i].z[7];
  27486. r->z[8] |= mask & table[i].z[8];
  27487. r->z[9] |= mask & table[i].z[9];
  27488. r->z[10] |= mask & table[i].z[10];
  27489. r->z[11] |= mask & table[i].z[11];
  27490. r->z[12] |= mask & table[i].z[12];
  27491. r->z[13] |= mask & table[i].z[13];
  27492. r->z[14] |= mask & table[i].z[14];
  27493. }
  27494. }
  27495. #endif /* !WC_NO_CACHE_RESISTANT */
  27496. /* Multiply the point by the scalar and return the result.
  27497. * If map is true then convert result to affine coordinates.
  27498. *
  27499. * Window technique of 6 bits. (Add-Sub variation.)
  27500. * Calculate 0..32 times the point. Use function that adds and
  27501. * subtracts the same two points.
  27502. * Recode to add or subtract one of the computed points.
  27503. * Double to push up.
  27504. * NOT a sliding window.
  27505. *
  27506. * r Resulting point.
  27507. * g Point to multiply.
  27508. * k Scalar to multiply by.
  27509. * map Indicates whether to convert result to affine.
  27510. * ct Constant time required.
  27511. * heap Heap to use for allocation.
  27512. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  27513. */
  27514. static int sp_384_ecc_mulmod_win_add_sub_15(sp_point_384* r, const sp_point_384* g,
  27515. const sp_digit* k, int map, int ct, void* heap)
  27516. {
  27517. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  27518. sp_point_384* t = NULL;
  27519. sp_digit* tmp = NULL;
  27520. #else
  27521. sp_point_384 t[33+2];
  27522. sp_digit tmp[2 * 15 * 6];
  27523. #endif
  27524. sp_point_384* rt = NULL;
  27525. sp_point_384* p = NULL;
  27526. sp_digit* negy;
  27527. int i;
  27528. ecc_recode_384 v[65];
  27529. int err = MP_OKAY;
  27530. /* Constant time used for cache attack resistance implementation. */
  27531. (void)ct;
  27532. (void)heap;
  27533. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  27534. t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) *
  27535. (33+2), heap, DYNAMIC_TYPE_ECC);
  27536. if (t == NULL)
  27537. err = MEMORY_E;
  27538. if (err == MP_OKAY) {
  27539. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 6,
  27540. heap, DYNAMIC_TYPE_ECC);
  27541. if (tmp == NULL)
  27542. err = MEMORY_E;
  27543. }
  27544. #endif
  27545. if (err == MP_OKAY) {
  27546. rt = t + 33;
  27547. p = t + 33+1;
  27548. /* t[0] = {0, 0, 1} * norm */
  27549. XMEMSET(&t[0], 0, sizeof(t[0]));
  27550. t[0].infinity = 1;
  27551. /* t[1] = {g->x, g->y, g->z} * norm */
  27552. err = sp_384_mod_mul_norm_15(t[1].x, g->x, p384_mod);
  27553. }
  27554. if (err == MP_OKAY) {
  27555. err = sp_384_mod_mul_norm_15(t[1].y, g->y, p384_mod);
  27556. }
  27557. if (err == MP_OKAY) {
  27558. err = sp_384_mod_mul_norm_15(t[1].z, g->z, p384_mod);
  27559. }
  27560. if (err == MP_OKAY) {
  27561. t[1].infinity = 0;
  27562. /* t[2] ... t[32] */
  27563. sp_384_proj_point_dbl_n_store_15(t, &t[ 1], 5, 1, tmp);
  27564. sp_384_proj_point_add_15(&t[ 3], &t[ 2], &t[ 1], tmp);
  27565. sp_384_proj_point_dbl_15(&t[ 6], &t[ 3], tmp);
  27566. sp_384_proj_point_add_sub_15(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp);
  27567. sp_384_proj_point_dbl_15(&t[10], &t[ 5], tmp);
  27568. sp_384_proj_point_add_sub_15(&t[11], &t[ 9], &t[10], &t[ 1], tmp);
  27569. sp_384_proj_point_dbl_15(&t[12], &t[ 6], tmp);
  27570. sp_384_proj_point_dbl_15(&t[14], &t[ 7], tmp);
  27571. sp_384_proj_point_add_sub_15(&t[15], &t[13], &t[14], &t[ 1], tmp);
  27572. sp_384_proj_point_dbl_15(&t[18], &t[ 9], tmp);
  27573. sp_384_proj_point_add_sub_15(&t[19], &t[17], &t[18], &t[ 1], tmp);
  27574. sp_384_proj_point_dbl_15(&t[20], &t[10], tmp);
  27575. sp_384_proj_point_dbl_15(&t[22], &t[11], tmp);
  27576. sp_384_proj_point_add_sub_15(&t[23], &t[21], &t[22], &t[ 1], tmp);
  27577. sp_384_proj_point_dbl_15(&t[24], &t[12], tmp);
  27578. sp_384_proj_point_dbl_15(&t[26], &t[13], tmp);
  27579. sp_384_proj_point_add_sub_15(&t[27], &t[25], &t[26], &t[ 1], tmp);
  27580. sp_384_proj_point_dbl_15(&t[28], &t[14], tmp);
  27581. sp_384_proj_point_dbl_15(&t[30], &t[15], tmp);
  27582. sp_384_proj_point_add_sub_15(&t[31], &t[29], &t[30], &t[ 1], tmp);
  27583. negy = t[0].y;
  27584. sp_384_ecc_recode_6_15(k, v);
  27585. i = 64;
  27586. #ifndef WC_NO_CACHE_RESISTANT
  27587. if (ct) {
  27588. sp_384_get_point_33_15(rt, t, v[i].i);
  27589. rt->infinity = !v[i].i;
  27590. }
  27591. else
  27592. #endif
  27593. {
  27594. XMEMCPY(rt, &t[v[i].i], sizeof(sp_point_384));
  27595. }
  27596. for (--i; i>=0; i--) {
  27597. sp_384_proj_point_dbl_n_15(rt, 6, tmp);
  27598. #ifndef WC_NO_CACHE_RESISTANT
  27599. if (ct) {
  27600. sp_384_get_point_33_15(p, t, v[i].i);
  27601. p->infinity = !v[i].i;
  27602. }
  27603. else
  27604. #endif
  27605. {
  27606. XMEMCPY(p, &t[v[i].i], sizeof(sp_point_384));
  27607. }
  27608. sp_384_sub_15(negy, p384_mod, p->y);
  27609. sp_384_norm_15(negy);
  27610. sp_384_cond_copy_15(p->y, negy, (sp_digit)0 - v[i].neg);
  27611. sp_384_proj_point_add_15(rt, rt, p, tmp);
  27612. }
  27613. if (map != 0) {
  27614. sp_384_map_15(r, rt, tmp);
  27615. }
  27616. else {
  27617. XMEMCPY(r, rt, sizeof(sp_point_384));
  27618. }
  27619. }
  27620. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  27621. if (t != NULL)
  27622. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  27623. if (tmp != NULL)
  27624. XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
  27625. #endif
  27626. return err;
  27627. }
  27628. #ifdef FP_ECC
  27629. #endif /* FP_ECC */
  27630. /* Add two Montgomery form projective points. The second point has a q value of
  27631. * one.
  27632. * Only the first point can be the same pointer as the result point.
  27633. *
  27634. * r Result of addition.
  27635. * p First point to add.
  27636. * q Second point to add.
  27637. * t Temporary ordinate data.
  27638. */
  27639. static void sp_384_proj_point_add_qz1_15(sp_point_384* r, const sp_point_384* p,
  27640. const sp_point_384* q, sp_digit* t)
  27641. {
  27642. sp_digit* t1 = t;
  27643. sp_digit* t2 = t + 2*15;
  27644. sp_digit* t3 = t + 4*15;
  27645. sp_digit* t4 = t + 6*15;
  27646. sp_digit* t5 = t + 8*15;
  27647. sp_digit* t6 = t + 10*15;
  27648. /* Check double */
  27649. (void)sp_384_sub_15(t1, p384_mod, q->y);
  27650. sp_384_norm_15(t1);
  27651. if ((~p->infinity & ~q->infinity &
  27652. sp_384_cmp_equal_15(p->x, q->x) & sp_384_cmp_equal_15(p->z, q->z) &
  27653. (sp_384_cmp_equal_15(p->y, q->y) | sp_384_cmp_equal_15(p->y, t1))) != 0) {
  27654. sp_384_proj_point_dbl_15(r, p, t);
  27655. }
  27656. else {
  27657. sp_digit maskp;
  27658. sp_digit maskq;
  27659. sp_digit maskt;
  27660. sp_digit* x = t2;
  27661. sp_digit* y = t5;
  27662. sp_digit* z = t6;
  27663. int i;
  27664. /* U2 = X2*Z1^2 */
  27665. sp_384_mont_sqr_15(t2, p->z, p384_mod, p384_mp_mod);
  27666. sp_384_mont_mul_15(t4, t2, p->z, p384_mod, p384_mp_mod);
  27667. sp_384_mont_mul_15(t2, t2, q->x, p384_mod, p384_mp_mod);
  27668. /* S2 = Y2*Z1^3 */
  27669. sp_384_mont_mul_15(t4, t4, q->y, p384_mod, p384_mp_mod);
  27670. /* H = U2 - X1 */
  27671. sp_384_mont_sub_15(t2, t2, p->x, p384_mod);
  27672. /* R = S2 - Y1 */
  27673. sp_384_mont_sub_15(t4, t4, p->y, p384_mod);
  27674. /* Z3 = H*Z1 */
  27675. sp_384_mont_mul_15(z, p->z, t2, p384_mod, p384_mp_mod);
  27676. /* X3 = R^2 - H^3 - 2*X1*H^2 */
  27677. sp_384_mont_sqr_15(t1, t4, p384_mod, p384_mp_mod);
  27678. sp_384_mont_sqr_15(t5, t2, p384_mod, p384_mp_mod);
  27679. sp_384_mont_mul_15(t3, p->x, t5, p384_mod, p384_mp_mod);
  27680. sp_384_mont_mul_15(t5, t5, t2, p384_mod, p384_mp_mod);
  27681. sp_384_mont_sub_15(x, t1, t5, p384_mod);
  27682. sp_384_mont_dbl_15(t1, t3, p384_mod);
  27683. sp_384_mont_sub_15(x, x, t1, p384_mod);
  27684. /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */
  27685. sp_384_mont_sub_lower_15(t3, t3, x, p384_mod);
  27686. sp_384_mont_mul_15(t3, t3, t4, p384_mod, p384_mp_mod);
  27687. sp_384_mont_mul_15(t5, t5, p->y, p384_mod, p384_mp_mod);
  27688. sp_384_mont_sub_15(y, t3, t5, p384_mod);
  27689. maskp = 0 - (q->infinity & (!p->infinity));
  27690. maskq = 0 - (p->infinity & (!q->infinity));
  27691. maskt = ~(maskp | maskq);
  27692. for (i = 0; i < 15; i++) {
  27693. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | (x[i] & maskt);
  27694. }
  27695. for (i = 0; i < 15; i++) {
  27696. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | (y[i] & maskt);
  27697. }
  27698. for (i = 0; i < 15; i++) {
  27699. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | (z[i] & maskt);
  27700. }
  27701. r->z[0] |= p->infinity & q->infinity;
  27702. r->infinity = p->infinity & q->infinity;
  27703. }
  27704. }
  27705. #ifdef FP_ECC
  27706. /* Convert the projective point to affine.
  27707. * Ordinates are in Montgomery form.
  27708. *
  27709. * a Point to convert.
  27710. * t Temporary data.
  27711. */
  27712. static void sp_384_proj_to_affine_15(sp_point_384* a, sp_digit* t)
  27713. {
  27714. sp_digit* t1 = t;
  27715. sp_digit* t2 = t + 2 * 15;
  27716. sp_digit* tmp = t + 4 * 15;
  27717. sp_384_mont_inv_15(t1, a->z, tmp);
  27718. sp_384_mont_sqr_15(t2, t1, p384_mod, p384_mp_mod);
  27719. sp_384_mont_mul_15(t1, t2, t1, p384_mod, p384_mp_mod);
  27720. sp_384_mont_mul_15(a->x, a->x, t2, p384_mod, p384_mp_mod);
  27721. sp_384_mont_mul_15(a->y, a->y, t1, p384_mod, p384_mp_mod);
  27722. XMEMCPY(a->z, p384_norm_mod, sizeof(p384_norm_mod));
  27723. }
  27724. /* Generate the pre-computed table of points for the base point.
  27725. *
  27726. * width = 8
  27727. * 256 entries
  27728. * 48 bits between
  27729. *
  27730. * a The base point.
  27731. * table Place to store generated point data.
  27732. * tmp Temporary data.
  27733. * heap Heap to use for allocation.
  27734. */
  27735. static int sp_384_gen_stripe_table_15(const sp_point_384* a,
  27736. sp_table_entry_384* table, sp_digit* tmp, void* heap)
  27737. {
  27738. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  27739. sp_point_384* t = NULL;
  27740. #else
  27741. sp_point_384 t[3];
  27742. #endif
  27743. sp_point_384* s1 = NULL;
  27744. sp_point_384* s2 = NULL;
  27745. int i;
  27746. int j;
  27747. int err = MP_OKAY;
  27748. (void)heap;
  27749. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  27750. t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap,
  27751. DYNAMIC_TYPE_ECC);
  27752. if (t == NULL)
  27753. err = MEMORY_E;
  27754. #endif
  27755. if (err == MP_OKAY) {
  27756. s1 = t + 1;
  27757. s2 = t + 2;
  27758. err = sp_384_mod_mul_norm_15(t->x, a->x, p384_mod);
  27759. }
  27760. if (err == MP_OKAY) {
  27761. err = sp_384_mod_mul_norm_15(t->y, a->y, p384_mod);
  27762. }
  27763. if (err == MP_OKAY) {
  27764. err = sp_384_mod_mul_norm_15(t->z, a->z, p384_mod);
  27765. }
  27766. if (err == MP_OKAY) {
  27767. t->infinity = 0;
  27768. sp_384_proj_to_affine_15(t, tmp);
  27769. XMEMCPY(s1->z, p384_norm_mod, sizeof(p384_norm_mod));
  27770. s1->infinity = 0;
  27771. XMEMCPY(s2->z, p384_norm_mod, sizeof(p384_norm_mod));
  27772. s2->infinity = 0;
  27773. /* table[0] = {0, 0, infinity} */
  27774. XMEMSET(&table[0], 0, sizeof(sp_table_entry_384));
  27775. /* table[1] = Affine version of 'a' in Montgomery form */
  27776. XMEMCPY(table[1].x, t->x, sizeof(table->x));
  27777. XMEMCPY(table[1].y, t->y, sizeof(table->y));
  27778. for (i=1; i<8; i++) {
  27779. sp_384_proj_point_dbl_n_15(t, 48, tmp);
  27780. sp_384_proj_to_affine_15(t, tmp);
  27781. XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
  27782. XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
  27783. }
  27784. for (i=1; i<8; i++) {
  27785. XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
  27786. XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
  27787. for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
  27788. XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
  27789. XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
  27790. sp_384_proj_point_add_qz1_15(t, s1, s2, tmp);
  27791. sp_384_proj_to_affine_15(t, tmp);
  27792. XMEMCPY(table[j].x, t->x, sizeof(table->x));
  27793. XMEMCPY(table[j].y, t->y, sizeof(table->y));
  27794. }
  27795. }
  27796. }
  27797. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  27798. if (t != NULL)
  27799. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  27800. #endif
  27801. return err;
  27802. }
  27803. #endif /* FP_ECC */
  27804. #ifndef WC_NO_CACHE_RESISTANT
  27805. /* Touch each possible entry that could be being copied.
  27806. *
  27807. * r Point to copy into.
  27808. * table Table - start of the entires to access
  27809. * idx Index of entry to retrieve.
  27810. */
  27811. static void sp_384_get_entry_256_15(sp_point_384* r,
  27812. const sp_table_entry_384* table, int idx)
  27813. {
  27814. int i;
  27815. sp_digit mask;
  27816. r->x[0] = 0;
  27817. r->x[1] = 0;
  27818. r->x[2] = 0;
  27819. r->x[3] = 0;
  27820. r->x[4] = 0;
  27821. r->x[5] = 0;
  27822. r->x[6] = 0;
  27823. r->x[7] = 0;
  27824. r->x[8] = 0;
  27825. r->x[9] = 0;
  27826. r->x[10] = 0;
  27827. r->x[11] = 0;
  27828. r->x[12] = 0;
  27829. r->x[13] = 0;
  27830. r->x[14] = 0;
  27831. r->y[0] = 0;
  27832. r->y[1] = 0;
  27833. r->y[2] = 0;
  27834. r->y[3] = 0;
  27835. r->y[4] = 0;
  27836. r->y[5] = 0;
  27837. r->y[6] = 0;
  27838. r->y[7] = 0;
  27839. r->y[8] = 0;
  27840. r->y[9] = 0;
  27841. r->y[10] = 0;
  27842. r->y[11] = 0;
  27843. r->y[12] = 0;
  27844. r->y[13] = 0;
  27845. r->y[14] = 0;
  27846. for (i = 1; i < 256; i++) {
  27847. mask = 0 - (i == idx);
  27848. r->x[0] |= mask & table[i].x[0];
  27849. r->x[1] |= mask & table[i].x[1];
  27850. r->x[2] |= mask & table[i].x[2];
  27851. r->x[3] |= mask & table[i].x[3];
  27852. r->x[4] |= mask & table[i].x[4];
  27853. r->x[5] |= mask & table[i].x[5];
  27854. r->x[6] |= mask & table[i].x[6];
  27855. r->x[7] |= mask & table[i].x[7];
  27856. r->x[8] |= mask & table[i].x[8];
  27857. r->x[9] |= mask & table[i].x[9];
  27858. r->x[10] |= mask & table[i].x[10];
  27859. r->x[11] |= mask & table[i].x[11];
  27860. r->x[12] |= mask & table[i].x[12];
  27861. r->x[13] |= mask & table[i].x[13];
  27862. r->x[14] |= mask & table[i].x[14];
  27863. r->y[0] |= mask & table[i].y[0];
  27864. r->y[1] |= mask & table[i].y[1];
  27865. r->y[2] |= mask & table[i].y[2];
  27866. r->y[3] |= mask & table[i].y[3];
  27867. r->y[4] |= mask & table[i].y[4];
  27868. r->y[5] |= mask & table[i].y[5];
  27869. r->y[6] |= mask & table[i].y[6];
  27870. r->y[7] |= mask & table[i].y[7];
  27871. r->y[8] |= mask & table[i].y[8];
  27872. r->y[9] |= mask & table[i].y[9];
  27873. r->y[10] |= mask & table[i].y[10];
  27874. r->y[11] |= mask & table[i].y[11];
  27875. r->y[12] |= mask & table[i].y[12];
  27876. r->y[13] |= mask & table[i].y[13];
  27877. r->y[14] |= mask & table[i].y[14];
  27878. }
  27879. }
  27880. #endif /* !WC_NO_CACHE_RESISTANT */
  27881. /* Multiply the point by the scalar and return the result.
  27882. * If map is true then convert result to affine coordinates.
  27883. *
  27884. * Stripe implementation.
  27885. * Pre-generated: 2^0, 2^48, ...
  27886. * Pre-generated: products of all combinations of above.
  27887. * 8 doubles and adds (with qz=1)
  27888. *
  27889. * r Resulting point.
  27890. * k Scalar to multiply by.
  27891. * table Pre-computed table.
  27892. * map Indicates whether to convert result to affine.
  27893. * ct Constant time required.
  27894. * heap Heap to use for allocation.
  27895. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  27896. */
  27897. static int sp_384_ecc_mulmod_stripe_15(sp_point_384* r, const sp_point_384* g,
  27898. const sp_table_entry_384* table, const sp_digit* k, int map,
  27899. int ct, void* heap)
  27900. {
  27901. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  27902. sp_point_384* rt = NULL;
  27903. sp_digit* t = NULL;
  27904. #else
  27905. sp_point_384 rt[2];
  27906. sp_digit t[2 * 15 * 6];
  27907. #endif
  27908. sp_point_384* p = NULL;
  27909. int i;
  27910. int j;
  27911. int y;
  27912. int x;
  27913. int err = MP_OKAY;
  27914. (void)g;
  27915. /* Constant time used for cache attack resistance implementation. */
  27916. (void)ct;
  27917. (void)heap;
  27918. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  27919. rt = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap,
  27920. DYNAMIC_TYPE_ECC);
  27921. if (rt == NULL)
  27922. err = MEMORY_E;
  27923. if (err == MP_OKAY) {
  27924. t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 6, heap,
  27925. DYNAMIC_TYPE_ECC);
  27926. if (t == NULL)
  27927. err = MEMORY_E;
  27928. }
  27929. #endif
  27930. if (err == MP_OKAY) {
  27931. p = rt + 1;
  27932. XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod));
  27933. XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod));
  27934. y = 0;
  27935. x = 47;
  27936. for (j=0; j<8; j++) {
  27937. y |= (int)(((k[x / 26] >> (x % 26)) & 1) << j);
  27938. x += 48;
  27939. }
  27940. #ifndef WC_NO_CACHE_RESISTANT
  27941. if (ct) {
  27942. sp_384_get_entry_256_15(rt, table, y);
  27943. } else
  27944. #endif
  27945. {
  27946. XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
  27947. XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
  27948. }
  27949. rt->infinity = !y;
  27950. for (i=46; i>=0; i--) {
  27951. y = 0;
  27952. x = i;
  27953. for (j=0; j<8; j++) {
  27954. y |= (int)(((k[x / 26] >> (x % 26)) & 1) << j);
  27955. x += 48;
  27956. }
  27957. sp_384_proj_point_dbl_15(rt, rt, t);
  27958. #ifndef WC_NO_CACHE_RESISTANT
  27959. if (ct) {
  27960. sp_384_get_entry_256_15(p, table, y);
  27961. }
  27962. else
  27963. #endif
  27964. {
  27965. XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
  27966. XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
  27967. }
  27968. p->infinity = !y;
  27969. sp_384_proj_point_add_qz1_15(rt, rt, p, t);
  27970. }
  27971. if (map != 0) {
  27972. sp_384_map_15(r, rt, t);
  27973. }
  27974. else {
  27975. XMEMCPY(r, rt, sizeof(sp_point_384));
  27976. }
  27977. }
  27978. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  27979. if (t != NULL)
  27980. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  27981. if (rt != NULL)
  27982. XFREE(rt, heap, DYNAMIC_TYPE_ECC);
  27983. #endif
  27984. return err;
  27985. }
  27986. #ifdef FP_ECC
  27987. #ifndef FP_ENTRIES
  27988. #define FP_ENTRIES 16
  27989. #endif
  27990. /* Cache entry - holds precomputation tables for a point. */
  27991. typedef struct sp_cache_384_t {
  27992. /* X ordinate of point that table was generated from. */
  27993. sp_digit x[15];
  27994. /* Y ordinate of point that table was generated from. */
  27995. sp_digit y[15];
  27996. /* Precomputation table for point. */
  27997. sp_table_entry_384 table[256];
  27998. /* Count of entries in table. */
  27999. uint32_t cnt;
  28000. /* Point and table set in entry. */
  28001. int set;
  28002. } sp_cache_384_t;
  28003. /* Cache of tables. */
  28004. static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES];
  28005. /* Index of last entry in cache. */
  28006. static THREAD_LS_T int sp_cache_384_last = -1;
  28007. /* Cache has been initialized. */
  28008. static THREAD_LS_T int sp_cache_384_inited = 0;
  28009. #ifndef HAVE_THREAD_LS
  28010. static volatile int initCacheMutex_384 = 0;
  28011. static wolfSSL_Mutex sp_cache_384_lock;
  28012. #endif
  28013. /* Get the cache entry for the point.
  28014. *
  28015. * g [in] Point scalar multipling.
  28016. * cache [out] Cache table to use.
  28017. */
  28018. static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache)
  28019. {
  28020. int i;
  28021. int j;
  28022. uint32_t least;
  28023. if (sp_cache_384_inited == 0) {
  28024. for (i=0; i<FP_ENTRIES; i++) {
  28025. sp_cache_384[i].set = 0;
  28026. }
  28027. sp_cache_384_inited = 1;
  28028. }
  28029. /* Compare point with those in cache. */
  28030. for (i=0; i<FP_ENTRIES; i++) {
  28031. if (!sp_cache_384[i].set)
  28032. continue;
  28033. if (sp_384_cmp_equal_15(g->x, sp_cache_384[i].x) &
  28034. sp_384_cmp_equal_15(g->y, sp_cache_384[i].y)) {
  28035. sp_cache_384[i].cnt++;
  28036. break;
  28037. }
  28038. }
  28039. /* No match. */
  28040. if (i == FP_ENTRIES) {
  28041. /* Find empty entry. */
  28042. i = (sp_cache_384_last + 1) % FP_ENTRIES;
  28043. for (; i != sp_cache_384_last; i=(i+1)%FP_ENTRIES) {
  28044. if (!sp_cache_384[i].set) {
  28045. break;
  28046. }
  28047. }
  28048. /* Evict least used. */
  28049. if (i == sp_cache_384_last) {
  28050. least = sp_cache_384[0].cnt;
  28051. for (j=1; j<FP_ENTRIES; j++) {
  28052. if (sp_cache_384[j].cnt < least) {
  28053. i = j;
  28054. least = sp_cache_384[i].cnt;
  28055. }
  28056. }
  28057. }
  28058. XMEMCPY(sp_cache_384[i].x, g->x, sizeof(sp_cache_384[i].x));
  28059. XMEMCPY(sp_cache_384[i].y, g->y, sizeof(sp_cache_384[i].y));
  28060. sp_cache_384[i].set = 1;
  28061. sp_cache_384[i].cnt = 1;
  28062. }
  28063. *cache = &sp_cache_384[i];
  28064. sp_cache_384_last = i;
  28065. }
  28066. #endif /* FP_ECC */
  28067. /* Multiply the base point of P384 by the scalar and return the result.
  28068. * If map is true then convert result to affine coordinates.
  28069. *
  28070. * r Resulting point.
  28071. * g Point to multiply.
  28072. * k Scalar to multiply by.
  28073. * map Indicates whether to convert result to affine.
  28074. * ct Constant time required.
  28075. * heap Heap to use for allocation.
  28076. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  28077. */
  28078. static int sp_384_ecc_mulmod_15(sp_point_384* r, const sp_point_384* g, const sp_digit* k,
  28079. int map, int ct, void* heap)
  28080. {
  28081. #ifndef FP_ECC
  28082. return sp_384_ecc_mulmod_win_add_sub_15(r, g, k, map, ct, heap);
  28083. #else
  28084. sp_digit tmp[2 * 15 * 7];
  28085. sp_cache_384_t* cache;
  28086. int err = MP_OKAY;
  28087. #ifndef HAVE_THREAD_LS
  28088. if (initCacheMutex_384 == 0) {
  28089. wc_InitMutex(&sp_cache_384_lock);
  28090. initCacheMutex_384 = 1;
  28091. }
  28092. if (wc_LockMutex(&sp_cache_384_lock) != 0)
  28093. err = BAD_MUTEX_E;
  28094. #endif /* HAVE_THREAD_LS */
  28095. if (err == MP_OKAY) {
  28096. sp_ecc_get_cache_384(g, &cache);
  28097. if (cache->cnt == 2)
  28098. sp_384_gen_stripe_table_15(g, cache->table, tmp, heap);
  28099. #ifndef HAVE_THREAD_LS
  28100. wc_UnLockMutex(&sp_cache_384_lock);
  28101. #endif /* HAVE_THREAD_LS */
  28102. if (cache->cnt < 2) {
  28103. err = sp_384_ecc_mulmod_win_add_sub_15(r, g, k, map, ct, heap);
  28104. }
  28105. else {
  28106. err = sp_384_ecc_mulmod_stripe_15(r, g, cache->table, k,
  28107. map, ct, heap);
  28108. }
  28109. }
  28110. return err;
  28111. #endif
  28112. }
  28113. #endif
  28114. /* Multiply the point by the scalar and return the result.
  28115. * If map is true then convert result to affine coordinates.
  28116. *
  28117. * km Scalar to multiply by.
  28118. * p Point to multiply.
  28119. * r Resulting point.
  28120. * map Indicates whether to convert result to affine.
  28121. * heap Heap to use for allocation.
  28122. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  28123. */
  28124. int sp_ecc_mulmod_384(const mp_int* km, const ecc_point* gm, ecc_point* r,
  28125. int map, void* heap)
  28126. {
  28127. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  28128. sp_point_384* point = NULL;
  28129. sp_digit* k = NULL;
  28130. #else
  28131. sp_point_384 point[1];
  28132. sp_digit k[15];
  28133. #endif
  28134. int err = MP_OKAY;
  28135. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  28136. point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap,
  28137. DYNAMIC_TYPE_ECC);
  28138. if (point == NULL)
  28139. err = MEMORY_E;
  28140. if (err == MP_OKAY) {
  28141. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15, heap,
  28142. DYNAMIC_TYPE_ECC);
  28143. if (k == NULL)
  28144. err = MEMORY_E;
  28145. }
  28146. #endif
  28147. if (err == MP_OKAY) {
  28148. sp_384_from_mp(k, 15, km);
  28149. sp_384_point_from_ecc_point_15(point, gm);
  28150. err = sp_384_ecc_mulmod_15(point, point, k, map, 1, heap);
  28151. }
  28152. if (err == MP_OKAY) {
  28153. err = sp_384_point_to_ecc_point_15(point, r);
  28154. }
  28155. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  28156. if (k != NULL)
  28157. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  28158. if (point != NULL)
  28159. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  28160. #endif
  28161. return err;
  28162. }
  28163. /* Multiply the point by the scalar, add point a and return the result.
  28164. * If map is true then convert result to affine coordinates.
  28165. *
  28166. * km Scalar to multiply by.
  28167. * p Point to multiply.
  28168. * am Point to add to scalar mulitply result.
  28169. * inMont Point to add is in montgomery form.
  28170. * r Resulting point.
  28171. * map Indicates whether to convert result to affine.
  28172. * heap Heap to use for allocation.
  28173. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  28174. */
  28175. int sp_ecc_mulmod_add_384(const mp_int* km, const ecc_point* gm,
  28176. const ecc_point* am, int inMont, ecc_point* r, int map, void* heap)
  28177. {
  28178. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  28179. sp_point_384* point = NULL;
  28180. sp_digit* k = NULL;
  28181. #else
  28182. sp_point_384 point[2];
  28183. sp_digit k[15 + 15 * 2 * 6];
  28184. #endif
  28185. sp_point_384* addP = NULL;
  28186. sp_digit* tmp = NULL;
  28187. int err = MP_OKAY;
  28188. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  28189. point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap,
  28190. DYNAMIC_TYPE_ECC);
  28191. if (point == NULL)
  28192. err = MEMORY_E;
  28193. if (err == MP_OKAY) {
  28194. k = (sp_digit*)XMALLOC(
  28195. sizeof(sp_digit) * (15 + 15 * 2 * 6), heap,
  28196. DYNAMIC_TYPE_ECC);
  28197. if (k == NULL)
  28198. err = MEMORY_E;
  28199. }
  28200. #endif
  28201. if (err == MP_OKAY) {
  28202. addP = point + 1;
  28203. tmp = k + 15;
  28204. sp_384_from_mp(k, 15, km);
  28205. sp_384_point_from_ecc_point_15(point, gm);
  28206. sp_384_point_from_ecc_point_15(addP, am);
  28207. }
  28208. if ((err == MP_OKAY) && (!inMont)) {
  28209. err = sp_384_mod_mul_norm_15(addP->x, addP->x, p384_mod);
  28210. }
  28211. if ((err == MP_OKAY) && (!inMont)) {
  28212. err = sp_384_mod_mul_norm_15(addP->y, addP->y, p384_mod);
  28213. }
  28214. if ((err == MP_OKAY) && (!inMont)) {
  28215. err = sp_384_mod_mul_norm_15(addP->z, addP->z, p384_mod);
  28216. }
  28217. if (err == MP_OKAY) {
  28218. err = sp_384_ecc_mulmod_15(point, point, k, 0, 0, heap);
  28219. }
  28220. if (err == MP_OKAY) {
  28221. sp_384_proj_point_add_15(point, point, addP, tmp);
  28222. if (map) {
  28223. sp_384_map_15(point, point, tmp);
  28224. }
  28225. err = sp_384_point_to_ecc_point_15(point, r);
  28226. }
  28227. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  28228. if (k != NULL)
  28229. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  28230. if (point != NULL)
  28231. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  28232. #endif
  28233. return err;
  28234. }
  28235. #ifdef WOLFSSL_SP_SMALL
  28236. /* Multiply the base point of P384 by the scalar and return the result.
  28237. * If map is true then convert result to affine coordinates.
  28238. *
  28239. * r Resulting point.
  28240. * k Scalar to multiply by.
  28241. * map Indicates whether to convert result to affine.
  28242. * heap Heap to use for allocation.
  28243. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  28244. */
  28245. static int sp_384_ecc_mulmod_base_15(sp_point_384* r, const sp_digit* k,
  28246. int map, int ct, void* heap)
  28247. {
  28248. /* No pre-computed values. */
  28249. return sp_384_ecc_mulmod_15(r, &p384_base, k, map, ct, heap);
  28250. }
  28251. #else
  28252. /* Striping precomputation table.
  28253. * 8 points combined into a table of 256 points.
  28254. * Distance of 48 between points.
  28255. */
  28256. static const sp_table_entry_384 p384_table[256] = {
  28257. /* 0 */
  28258. { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  28259. 0x00, 0x00, 0x00 },
  28260. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  28261. 0x00, 0x00, 0x00 } },
  28262. /* 1 */
  28263. { { 0x1c0b528,0x01d5992,0x0e383dd,0x38a835b,0x220e378,0x106d35b,
  28264. 0x1c3afc5,0x03bfe1e,0x28459a3,0x2d91521,0x214ede2,0x0bfdc8d,
  28265. 0x2151381,0x3708a67,0x004d3aa },
  28266. { 0x303a4fe,0x10f6b52,0x29ac230,0x2fdeed2,0x0a1bfa8,0x3a0ec14,
  28267. 0x2de7562,0x3ff662e,0x21968f4,0x031b0d4,0x3969a84,0x2000898,
  28268. 0x1c5e9dd,0x2f09685,0x002b78a } },
  28269. /* 2 */
  28270. { { 0x30c535b,0x191d4ca,0x2296298,0x14dc141,0x090dd69,0x05aae6b,
  28271. 0x0cd6b42,0x35da80e,0x3b7be12,0x2cf7e6d,0x1f347bd,0x3d365e1,
  28272. 0x1448913,0x32704fa,0x00222c5 },
  28273. { 0x280dc64,0x39e5bc9,0x24175f8,0x2dd60d4,0x0120e7c,0x041d02e,
  28274. 0x0b5d8ad,0x37b9895,0x2fb5337,0x1f0e2e3,0x14f0224,0x2230b86,
  28275. 0x1bc4cf6,0x17cdb09,0x007b5c7 } },
  28276. /* 3 */
  28277. { { 0x2dffea5,0x28f30e7,0x29fce26,0x070df5f,0x235bbfd,0x2f78fbd,
  28278. 0x27700d9,0x23d6bc3,0x3471a53,0x0c0e03a,0x05bf9eb,0x276a2ec,
  28279. 0x20c3e2e,0x31cc691,0x00dbb93 },
  28280. { 0x126b605,0x2e8983d,0x153737d,0x23bf5e1,0x295d497,0x35ca812,
  28281. 0x2d793ae,0x16c6893,0x3777600,0x089a520,0x1e681f8,0x3d55ee6,
  28282. 0x154ef99,0x155f592,0x00ae5f9 } },
  28283. /* 4 */
  28284. { { 0x26feef9,0x20315fc,0x1240244,0x250e838,0x3c31a26,0x1cf8af1,
  28285. 0x1002c32,0x3b531cd,0x1c53ef1,0x22310ba,0x3f4948e,0x22eafd9,
  28286. 0x3863202,0x3d0e2a5,0x006a502 },
  28287. { 0x34536fe,0x04e91ad,0x30ebf5f,0x2af62a7,0x01d218b,0x1c8c9da,
  28288. 0x336bcc3,0x23060c3,0x331576e,0x1b14c5e,0x1bbcb76,0x0755e9a,
  28289. 0x3d4dcef,0x24c2cf8,0x00917c4 } },
  28290. /* 5 */
  28291. { { 0x349ddd0,0x09b8bb8,0x0250114,0x3e66cbf,0x29f117e,0x3005d29,
  28292. 0x36b480e,0x2119bfc,0x2761845,0x253d2f7,0x0580604,0x0bb6db4,
  28293. 0x3ca922f,0x1744677,0x008adc7 },
  28294. { 0x3d5a7ce,0x27425ed,0x11e9a61,0x3968d10,0x3874275,0x3692d3b,
  28295. 0x03e0470,0x0763d50,0x3d97790,0x3cbaeab,0x2747170,0x18faf3a,
  28296. 0x180365e,0x2511fe7,0x0012a36 } },
  28297. /* 6 */
  28298. { { 0x3c52870,0x2701e93,0x296128f,0x120694e,0x1ce0b37,0x3860a36,
  28299. 0x10fa180,0x0896b55,0x2f76adb,0x22892ae,0x2e58a34,0x07b4295,
  28300. 0x2cb62d1,0x079a522,0x00f3d81 },
  28301. { 0x061ed22,0x2375dd3,0x3c9d861,0x3e602d1,0x10bb747,0x39ae156,
  28302. 0x3f796fd,0x087a48a,0x06d680a,0x37f7f47,0x2af2c9d,0x36c55dc,
  28303. 0x10f3dc0,0x279b07a,0x00a0937 } },
  28304. /* 7 */
  28305. { { 0x085c629,0x319bbf8,0x089a386,0x184256f,0x15fc2a4,0x00fd2d0,
  28306. 0x13d6312,0x363d44d,0x32b7e4b,0x25f2865,0x27df8ce,0x1dce02a,
  28307. 0x24ea3b0,0x0e27b9f,0x00d8a90 },
  28308. { 0x3b14461,0x1d371f9,0x0f781bc,0x0503271,0x0dc2cb0,0x13bc284,
  28309. 0x34b3a68,0x1ff894a,0x25d2032,0x16f79ba,0x260f961,0x07b10d5,
  28310. 0x18173b7,0x2812e2b,0x00eede5 } },
  28311. /* 8 */
  28312. { { 0x13b9a2d,0x132ece2,0x0c5d558,0x02c0214,0x1820c66,0x37cb50f,
  28313. 0x26d8267,0x3a00504,0x3f00109,0x33756ee,0x38172f1,0x2e4bb8c,
  28314. 0x030d985,0x3e4fcc5,0x00609d4 },
  28315. { 0x2daf9d6,0x16681fa,0x1fb01e0,0x1b03c49,0x370e653,0x183c839,
  28316. 0x2207515,0x0ea6b58,0x1ae7aaf,0x3a96522,0x24bae14,0x1c38bd9,
  28317. 0x082497b,0x1c05db4,0x000dd03 } },
  28318. /* 9 */
  28319. { { 0x110521f,0x04efa21,0x0c174cc,0x2a7dc93,0x387315b,0x14f7098,
  28320. 0x1d83bb3,0x2495ed2,0x2fe0c27,0x1e2d9df,0x093c953,0x0287073,
  28321. 0x02c9951,0x336291c,0x0033e30 },
  28322. { 0x208353f,0x3f22748,0x2b2bf0f,0x2373b50,0x10170fa,0x1b8a97d,
  28323. 0x0851ed2,0x0b25824,0x055ecb5,0x12049d9,0x3fe1adf,0x11b1385,
  28324. 0x28eab06,0x11fac21,0x00513f0 } },
  28325. /* 10 */
  28326. { { 0x35bdf53,0x1847d37,0x1a6dc07,0x29d62c4,0x045d331,0x313b8e5,
  28327. 0x165daf1,0x1e34562,0x3e75a58,0x16ea2fa,0x02dd302,0x3302862,
  28328. 0x3eb8bae,0x2266a48,0x00cf2a3 },
  28329. { 0x24fd048,0x324a074,0x025df98,0x1662eec,0x3841bfb,0x26ae754,
  28330. 0x1df8cec,0x0113ae3,0x0b67fef,0x094e293,0x2323666,0x0ab087c,
  28331. 0x2f06509,0x0e142d9,0x00a919d } },
  28332. /* 11 */
  28333. { { 0x1d480d8,0x00ed021,0x3a7d3db,0x1e46ca1,0x28cd9f4,0x2a3ceeb,
  28334. 0x24dc754,0x0624a3c,0x0003db4,0x1520bae,0x1c56e0f,0x2fe7ace,
  28335. 0x1dc6f38,0x0c826a4,0x008b977 },
  28336. { 0x209cfc2,0x2c16c9c,0x1b70a31,0x21416cb,0x34c49bf,0x186549e,
  28337. 0x062498d,0x146e959,0x0391fac,0x08ff944,0x2b4b834,0x013d57a,
  28338. 0x2eabffb,0x0370131,0x00c07c1 } },
  28339. /* 12 */
  28340. { { 0x332f048,0x0bf9336,0x16dfad2,0x2451d7b,0x35f23bf,0x299adb2,
  28341. 0x0ce0c0a,0x0170294,0x289f034,0x2b7d89e,0x395e2d6,0x1d20df7,
  28342. 0x2e64e36,0x16dae90,0x00081c9 },
  28343. { 0x31d6ceb,0x0f80db9,0x0271eba,0x33db1ac,0x1b45bcc,0x1a11c07,
  28344. 0x347e630,0x148fd9e,0x142e712,0x3183e3e,0x1cd47ad,0x108d1c9,
  28345. 0x09cbb82,0x35e61d9,0x0083027 } },
  28346. /* 13 */
  28347. { { 0x215b0b8,0x0a7a98d,0x2c41b39,0x3f69536,0x0b41441,0x16da8da,
  28348. 0x15d556b,0x3c17a26,0x129167e,0x3ea0351,0x2d25a27,0x2f2d285,
  28349. 0x15b68f6,0x2931ef5,0x00210d6 },
  28350. { 0x1351130,0x012aec9,0x37ebf38,0x26640f8,0x01d2df6,0x2130972,
  28351. 0x201efc0,0x23a457c,0x087a1c6,0x14c68a3,0x163f62a,0x36b494d,
  28352. 0x015d481,0x39c35b1,0x005dd6d } },
  28353. /* 14 */
  28354. { { 0x06612ce,0x11c3f61,0x199729f,0x3b36863,0x2986f3e,0x3cd2be1,
  28355. 0x04c1612,0x2be2dae,0x00846dd,0x3d7bc29,0x249e795,0x1016803,
  28356. 0x37a3714,0x2c5aa8b,0x005f491 },
  28357. { 0x341b38d,0x01eb936,0x3caac7f,0x27863ef,0x1ef7d11,0x1110ec6,
  28358. 0x18e0761,0x26498e8,0x01a79a1,0x390d5a1,0x22226fb,0x3d2a473,
  28359. 0x0872191,0x1230f32,0x00dc772 } },
  28360. /* 15 */
  28361. { { 0x0b1ec9d,0x03fc6b9,0x3706d57,0x03b9fbb,0x221d23e,0x2867821,
  28362. 0x1e40f4c,0x2c9c0f3,0x3c4cd4b,0x31f5948,0x3f13aa6,0x307c1b2,
  28363. 0x04b6016,0x116b453,0x005aa72 },
  28364. { 0x0b74de8,0x20519d1,0x134e37f,0x05d882a,0x1839e7a,0x3a2c6a8,
  28365. 0x0d14e8d,0x1d78bdd,0x251f30d,0x3a1e27e,0x081c261,0x2c9014b,
  28366. 0x165ee09,0x19e0cf1,0x00654e2 } },
  28367. /* 16 */
  28368. { { 0x39fbe67,0x081778b,0x0e44378,0x20dfdca,0x1c4afcb,0x20b803c,
  28369. 0x0ec06c6,0x1508f6f,0x1c3114d,0x3bca851,0x3a52463,0x07661d1,
  28370. 0x17b0aa0,0x16c5f5c,0x00fc093 },
  28371. { 0x0d01f95,0x0ef13f5,0x2d34965,0x2a25582,0x39aa83e,0x3e38fcf,
  28372. 0x3943dca,0x385bbdd,0x210e86f,0x3dc1dd2,0x3f9ffdc,0x18b9bc6,
  28373. 0x345c96b,0x0e79621,0x008a72f } },
  28374. /* 17 */
  28375. { { 0x341c342,0x3793688,0x042273a,0x153a9c1,0x3dd326e,0x1d073bc,
  28376. 0x2c7d983,0x05524cd,0x00d59e6,0x347abe8,0x3d9a3ef,0x0fb624a,
  28377. 0x2c7e4cd,0x09b3171,0x0003faf },
  28378. { 0x045f8ac,0x38bf3cc,0x1e73087,0x0c85d3c,0x314a655,0x382be69,
  28379. 0x384f28f,0x24d6cb3,0x2842cdc,0x1777f5e,0x2929c89,0x03c45ed,
  28380. 0x3cfcc4c,0x0b59322,0x0035657 } },
  28381. /* 18 */
  28382. { { 0x18c1bba,0x2eb005f,0x33d57ec,0x30e42c3,0x36058f9,0x1865f43,
  28383. 0x2116e3f,0x2c4a2bb,0x0684033,0x0f1375c,0x0209b98,0x2136e9b,
  28384. 0x1bc4af0,0x0b3e0c7,0x0097c7c },
  28385. { 0x16010e8,0x398777e,0x2a172f4,0x0814a7e,0x0d97e4e,0x274dfc8,
  28386. 0x2666606,0x1b5c93b,0x1ed3d36,0x3f3304e,0x13488e0,0x02dbb88,
  28387. 0x2d53369,0x3717ce9,0x007cad1 } },
  28388. /* 19 */
  28389. { { 0x257a41f,0x2a6a076,0x39b6660,0x04bb000,0x1e74a04,0x3876b45,
  28390. 0x343c6b5,0x0753108,0x3f54668,0x24a13cf,0x23749e8,0x0421fc5,
  28391. 0x32f13b5,0x0f31be7,0x00070f2 },
  28392. { 0x1186e14,0x0847697,0x0dff542,0x0dff76c,0x084748f,0x2c7d060,
  28393. 0x23aab4d,0x0b43906,0x27ba640,0x1497b59,0x02f5835,0x0a492a4,
  28394. 0x0a6892f,0x39f3e91,0x005844e } },
  28395. /* 20 */
  28396. { { 0x33b236f,0x02181cf,0x21dafab,0x0760788,0x019e9d4,0x249ed0a,
  28397. 0x36571e3,0x3c7dbcf,0x1337550,0x010d22a,0x285e62f,0x19ee65a,
  28398. 0x052bf71,0x1d65fd5,0x0062d43 },
  28399. { 0x2955926,0x3fae7bc,0x0353d85,0x07db7de,0x1440a56,0x328dad6,
  28400. 0x1668ec9,0x28058e2,0x1a1a22d,0x1014afc,0x3609325,0x3effdcb,
  28401. 0x209f3bd,0x3ca3888,0x0094e50 } },
  28402. /* 21 */
  28403. { { 0x062e8af,0x0b96ccc,0x136990b,0x1d7a28f,0x1a85723,0x0076dec,
  28404. 0x21b00b2,0x06a88ff,0x2f0ee65,0x1fa49b7,0x39b10ad,0x10b26fa,
  28405. 0x0be7465,0x026e8bf,0x00098e3 },
  28406. { 0x3f1d63f,0x37bacff,0x1374779,0x02882ff,0x323d0e8,0x1da3de5,
  28407. 0x12bb3b8,0x0a15a11,0x34d1f95,0x2b3dd6e,0x29ea3fa,0x39ad000,
  28408. 0x33a538f,0x390204d,0x0012bd3 } },
  28409. /* 22 */
  28410. { { 0x04cbba5,0x0de0344,0x1d4cc02,0x11fe8d7,0x36207e7,0x32a6da8,
  28411. 0x0239281,0x1ec40d7,0x3e89798,0x213fc66,0x0022eee,0x11daefe,
  28412. 0x3e74db8,0x28534ee,0x00aa0a4 },
  28413. { 0x07d4543,0x250cc46,0x206620f,0x1c1e7db,0x1321538,0x31fa0b8,
  28414. 0x30f74ea,0x01aae0e,0x3a2828f,0x3e9dd22,0x026ef35,0x3c0a62b,
  28415. 0x27dbdc5,0x01c23a6,0x000f0c5 } },
  28416. /* 23 */
  28417. { { 0x2f029dd,0x3091337,0x21b80c5,0x21e1419,0x13dabc6,0x3847660,
  28418. 0x12b865f,0x36eb666,0x38f6274,0x0ba6006,0x098da24,0x1398c64,
  28419. 0x13d08e5,0x246a469,0x009929a },
  28420. { 0x1285887,0x3ff5c8d,0x010237b,0x097c506,0x0bc7594,0x34b9b88,
  28421. 0x00cc35f,0x0bb964a,0x00cfbc4,0x29cd718,0x0837619,0x2b4a192,
  28422. 0x0c57bb7,0x08c69de,0x00a3627 } },
  28423. /* 24 */
  28424. { { 0x1361ed8,0x266d724,0x366cae7,0x1d5b18c,0x247d71b,0x2c9969a,
  28425. 0x0dd5211,0x1edd153,0x25998d7,0x0380856,0x3ab29db,0x09366de,
  28426. 0x1e53644,0x2b31ff6,0x008b0ff },
  28427. { 0x3b5d9ef,0x217448d,0x174746d,0x18afea4,0x15b106d,0x3e66e8b,
  28428. 0x0479f85,0x13793b4,0x1231d10,0x3c39bce,0x25e8983,0x2a13210,
  28429. 0x05a7083,0x382be04,0x00a9507 } },
  28430. /* 25 */
  28431. { { 0x0cf381c,0x1a29b85,0x31ccf6c,0x2f708b8,0x3af9d27,0x2a29732,
  28432. 0x168d4da,0x393488d,0x2c0e338,0x3f90c7b,0x0f52ad1,0x2a0a3fa,
  28433. 0x2cd80f1,0x15e7a1a,0x00db6a0 },
  28434. { 0x107832a,0x159cb91,0x1289288,0x17e21f9,0x073fc27,0x1584342,
  28435. 0x3802780,0x3d6c197,0x154075f,0x16366d1,0x09f712b,0x23a3ec4,
  28436. 0x29cf23a,0x3218baf,0x0039f0a } },
  28437. /* 26 */
  28438. { { 0x052edf5,0x2afde13,0x2e53d8f,0x3969626,0x3dcd737,0x1e46ac5,
  28439. 0x118bf0d,0x01b2652,0x156bcff,0x16d7ef6,0x1ca46d4,0x34c0cbb,
  28440. 0x3e486f6,0x1f85068,0x002cdff },
  28441. { 0x1f47ec8,0x12cee98,0x0608667,0x18fbbe1,0x08a8821,0x31a1fe4,
  28442. 0x17c7054,0x3c89e89,0x2edf6cd,0x1b8c32c,0x3f6ea84,0x1319329,
  28443. 0x3cd3c2c,0x05f331a,0x00186fa } },
  28444. /* 27 */
  28445. { { 0x1fcb91e,0x0fd4d87,0x358a48a,0x04d91b4,0x083595e,0x044a1e6,
  28446. 0x15827b9,0x1d5eaf4,0x2b82187,0x08f3984,0x21bd737,0x0c54285,
  28447. 0x2f56887,0x14c2d98,0x00f4684 },
  28448. { 0x01896f6,0x0e542d0,0x2090883,0x269dfcf,0x1e11cb8,0x239fd29,
  28449. 0x312cac4,0x19dfacb,0x369f606,0x0cc4f75,0x16579f9,0x33c22cc,
  28450. 0x0f22bfd,0x3b251ae,0x006429c } },
  28451. /* 28 */
  28452. { { 0x375f9a4,0x137552e,0x3570498,0x2e4a74e,0x24aef06,0x35b9307,
  28453. 0x384ca23,0x3bcd6d7,0x011b083,0x3c93187,0x392ca9f,0x129ce48,
  28454. 0x0a800ce,0x145d9cc,0x00865d6 },
  28455. { 0x22b4a2b,0x37f9d9c,0x3e0eca3,0x3e5ec20,0x112c04b,0x2e1ae29,
  28456. 0x3ce5b51,0x0f83200,0x32d6a7e,0x10ff1d8,0x081adbe,0x265c30b,
  28457. 0x216b1c8,0x0eb4483,0x003cbcd } },
  28458. /* 29 */
  28459. { { 0x030ce93,0x2d331fb,0x20a2fbf,0x1f6dc9c,0x010ed6c,0x1ed5540,
  28460. 0x275bf74,0x3df0fb1,0x103333f,0x0241c96,0x1075bfc,0x30e5cf9,
  28461. 0x0f31bc7,0x32c01eb,0x00b049e },
  28462. { 0x358839c,0x1dbabd3,0x1e4fb40,0x36a8ac1,0x2101896,0x2d0319b,
  28463. 0x2033b0a,0x192e8fd,0x2ebc8d8,0x2867ba7,0x07bf6d2,0x1b3c555,
  28464. 0x2477deb,0x198fe09,0x008e5a9 } },
  28465. /* 30 */
  28466. { { 0x3fbd5e1,0x18bf77d,0x2b1d69e,0x151da44,0x338ecfe,0x0768efe,
  28467. 0x1a3d56d,0x3c35211,0x10e1c86,0x2012525,0x3bc36ce,0x32b6fe4,
  28468. 0x0c8d183,0x15c93f3,0x0041fce },
  28469. { 0x332c144,0x24e70a0,0x246e05f,0x22c21c7,0x2b17f24,0x1ba2bfd,
  28470. 0x0534e26,0x318a4f6,0x1dc3b85,0x0c741bc,0x23131b7,0x01a8cba,
  28471. 0x364e5db,0x21362cf,0x00f2951 } },
  28472. /* 31 */
  28473. { { 0x2ddc103,0x14ffdcd,0x206fd96,0x0de57bd,0x025f43e,0x381b73a,
  28474. 0x2301fcf,0x3bafc27,0x34130b6,0x0216bc8,0x0ff56b2,0x2c4ad4c,
  28475. 0x23c6b79,0x1267fa6,0x009b4fb },
  28476. { 0x1d27ac2,0x13e2494,0x1389015,0x38d5b29,0x2d33167,0x3f01969,
  28477. 0x28ec1fa,0x1b26de0,0x2587f74,0x1c25668,0x0c44f83,0x23c6f8c,
  28478. 0x32fdbb1,0x045f104,0x00a7946 } },
  28479. /* 32 */
  28480. { { 0x23c647b,0x09addd7,0x1348c04,0x0e633c1,0x1bfcbd9,0x1cb034f,
  28481. 0x1312e31,0x11cdcc7,0x1e6ee75,0x057d27f,0x2da7ee6,0x154c3c1,
  28482. 0x3a5fb89,0x2c2ba2c,0x00cf281 },
  28483. { 0x1b8a543,0x125cd50,0x1d30fd1,0x29cc203,0x341a625,0x14e4233,
  28484. 0x3aae076,0x289e38a,0x036ba02,0x230f405,0x3b21b8f,0x34088b9,
  28485. 0x01297a0,0x03a75fb,0x00fdc27 } },
  28486. /* 33 */
  28487. { { 0x07f41d6,0x1cf032f,0x1641008,0x0f86deb,0x3d97611,0x0e110fe,
  28488. 0x136ff42,0x0b914a9,0x0e241e6,0x180c340,0x1f545fc,0x0ba619d,
  28489. 0x1208c53,0x04223a4,0x00cd033 },
  28490. { 0x397612c,0x0132665,0x34e2d1a,0x00bba99,0x1d4393e,0x065d0a8,
  28491. 0x2fa69ee,0x1643b55,0x08085f0,0x3774aad,0x08a2243,0x33bf149,
  28492. 0x03f41a5,0x1ed950e,0x0048cc6 } },
  28493. /* 34 */
  28494. { { 0x014ab48,0x010c3bf,0x2a744e5,0x13c99c1,0x2195b7f,0x32207fd,
  28495. 0x28a228c,0x004f4bf,0x0e2d945,0x2ec6e5a,0x0b92162,0x1aa95e5,
  28496. 0x2754a93,0x1adcd93,0x004fb76 },
  28497. { 0x1e1ff7f,0x24ef28c,0x269113f,0x32b393c,0x2696eb5,0x0ac2780,
  28498. 0x354bf8a,0x0ffe3fd,0x09ce58e,0x0163c4f,0x1678c0b,0x15cd1bc,
  28499. 0x292b3b7,0x036ea19,0x00d5420 } },
  28500. /* 35 */
  28501. { { 0x1da1265,0x0c2ef5b,0x18dd9a0,0x3f3a25c,0x0f7b4f3,0x0d8196e,
  28502. 0x24931f9,0x090729a,0x1875f72,0x1ef39cb,0x2577585,0x2ed472d,
  28503. 0x136756c,0x20553a6,0x00c7161 },
  28504. { 0x2e32189,0x283de4b,0x00b2e81,0x0989df7,0x3ef2fab,0x1c7d1a7,
  28505. 0x24f6feb,0x3e16679,0x233dfda,0x06d1233,0x3e6b5df,0x1707132,
  28506. 0x05f7b3f,0x2c00779,0x00fb8df } },
  28507. /* 36 */
  28508. { { 0x15bb921,0x117e9d3,0x267ec73,0x2f934ad,0x25c7e04,0x20b5e8f,
  28509. 0x2d3a802,0x2ca911f,0x3f87e47,0x39709dd,0x08488e2,0x2cec400,
  28510. 0x35b4589,0x1f0acba,0x009aad7 },
  28511. { 0x2ac34ae,0x06f29f6,0x3326d68,0x3949abe,0x02452e4,0x0687b85,
  28512. 0x0879244,0x1eb7832,0x0d4c240,0x31d0ec1,0x3c17a2a,0x17a666f,
  28513. 0x01a06cb,0x3e0929c,0x004dca2 } },
  28514. /* 37 */
  28515. { { 0x127bc1a,0x0c72984,0x13be68e,0x26c5fab,0x1a3edd5,0x097d685,
  28516. 0x36b645e,0x385799e,0x394a420,0x39d8885,0x0b1e872,0x13f60ed,
  28517. 0x2ce1b79,0x3c0ecb7,0x007cab3 },
  28518. { 0x29b3586,0x26fc572,0x0bd7711,0x0913494,0x0a55459,0x31af3c9,
  28519. 0x3633eac,0x3e2105c,0x0c2b1b6,0x0e6f4c2,0x047d38c,0x2b81bd5,
  28520. 0x1fe1c3b,0x04d7cd0,0x0054dcc } },
  28521. /* 38 */
  28522. { { 0x03caf0d,0x0d66365,0x313356d,0x2a4897f,0x2ce044e,0x18feb7a,
  28523. 0x1f6a7c5,0x3709e7b,0x14473e8,0x2d8cbae,0x3190dca,0x12d19f8,
  28524. 0x31e3181,0x3cc5b6e,0x002d4f4 },
  28525. { 0x143b7ca,0x2604728,0x39508d6,0x0cb79f3,0x24ec1ac,0x1ed7fa0,
  28526. 0x3ab5fd3,0x3c76488,0x2e49390,0x03a0985,0x3580461,0x3fd2c81,
  28527. 0x308f0ab,0x38561d6,0x0011b9b } },
  28528. /* 39 */
  28529. { { 0x3be682c,0x0c68f4e,0x32dd4ae,0x099d3bb,0x0bc7c5d,0x311f750,
  28530. 0x2fd10a3,0x2e7864a,0x23bc14a,0x13b1f82,0x32e495e,0x1b0f746,
  28531. 0x3cd856a,0x17a4c26,0x00085ee },
  28532. { 0x02e67fd,0x06a4223,0x2af2f38,0x2038987,0x132083a,0x1b7bb85,
  28533. 0x0d6a499,0x131e43f,0x3035e52,0x278ee3e,0x1d5b08b,0x30d8364,
  28534. 0x2719f8d,0x0b21fc9,0x003a06e } },
  28535. /* 40 */
  28536. { { 0x237cac0,0x27d6a1c,0x27945cd,0x2750d61,0x293f0b5,0x253db13,
  28537. 0x04a764e,0x20b4d0e,0x12bb627,0x160c13b,0x0de0601,0x236e2cf,
  28538. 0x2190f0b,0x354d76f,0x004336d },
  28539. { 0x2ab473a,0x10d54e4,0x1046574,0x1d6f97b,0x0031c72,0x06426a9,
  28540. 0x38678c2,0x0b76cf9,0x04f9920,0x152adf8,0x2977e63,0x1234819,
  28541. 0x198be26,0x061024c,0x00d427d } },
  28542. /* 41 */
  28543. { { 0x39b5a31,0x2123d43,0x362a822,0x1a2eab6,0x0bb0034,0x0d5d567,
  28544. 0x3a04723,0x3a10c8c,0x08079ae,0x0d27bda,0x2eb9e1e,0x2619e82,
  28545. 0x39a55a8,0x0c6c7db,0x00c1519 },
  28546. { 0x174251e,0x13ac2eb,0x295ed26,0x18d2afc,0x037b9b2,0x1258344,
  28547. 0x00921b0,0x1f702d8,0x1bc4da7,0x1c3794f,0x12b1869,0x366eacf,
  28548. 0x16ddf01,0x31ebdc5,0x00ad54e } },
  28549. /* 42 */
  28550. { { 0x1efdc58,0x1370d5e,0x0ddb8e7,0x1a53fda,0x1456bd3,0x0c825a9,
  28551. 0x0e74ccd,0x20f41c9,0x3423867,0x139073f,0x3c70d8a,0x131fc85,
  28552. 0x219a2a0,0x34bf986,0x0041199 },
  28553. { 0x1c05dd2,0x268f80a,0x3da9d38,0x1af9f8f,0x0535f2a,0x30ad37e,
  28554. 0x2cf72d7,0x14a509b,0x1f4fe74,0x259e09d,0x1d23f51,0x0672732,
  28555. 0x08fc463,0x00b6201,0x001e05a } },
  28556. /* 43 */
  28557. { { 0x0d5ffe8,0x3238bb5,0x17f275c,0x25b6fa8,0x2f8bb48,0x3b8f2d2,
  28558. 0x059790c,0x18594d4,0x285a47c,0x3d301bb,0x12935d2,0x23ffc96,
  28559. 0x3d7c7f9,0x15c8cbf,0x0034c4a },
  28560. { 0x20376a2,0x05201ba,0x1e02c4b,0x1413c45,0x02ea5e7,0x39575f0,
  28561. 0x2d76e21,0x113694c,0x011f310,0x0da3725,0x31b7799,0x1cb9195,
  28562. 0x0cfd592,0x22ee4ea,0x00adaa3 } },
  28563. /* 44 */
  28564. { { 0x14ed72a,0x031c49f,0x39a34bf,0x192e87d,0x0da0e92,0x130e7a9,
  28565. 0x00258bf,0x144e123,0x2d82a71,0x0294e53,0x3f06c66,0x3d4473a,
  28566. 0x037cd4a,0x3bbfb17,0x00fcebc },
  28567. { 0x39ae8c1,0x2dd6a9d,0x206ef23,0x332b479,0x2deff59,0x09d5720,
  28568. 0x3526fd2,0x33bf7cf,0x344bb32,0x359316a,0x115bdef,0x1b8468a,
  28569. 0x3813ea9,0x11a8450,0x00ab197 } },
  28570. /* 45 */
  28571. { { 0x0837d7d,0x1e1617b,0x0ba443c,0x2f2e3b8,0x2ca5b6f,0x176ed7b,
  28572. 0x2924d9d,0x07294d3,0x104bb4f,0x1cfd3e8,0x398640f,0x1162dc8,
  28573. 0x007ea15,0x2aa75fd,0x004231f },
  28574. { 0x16e6896,0x01987be,0x0f9d53e,0x1a740ec,0x1554e4c,0x31e1634,
  28575. 0x3cb07b9,0x013eb53,0x39352cb,0x1dfa549,0x0974e7f,0x17c55d2,
  28576. 0x157c85f,0x1561adb,0x002e3fa } },
  28577. /* 46 */
  28578. { { 0x29951a8,0x35200da,0x2ad042c,0x22109e4,0x3a8b15b,0x2eca69c,
  28579. 0x28bcf9a,0x0cfa063,0x0924099,0x12ff668,0x2fb88dc,0x028d653,
  28580. 0x2445876,0x218d01c,0x0014418 },
  28581. { 0x1caedc7,0x295bba6,0x01c9162,0x3364744,0x28fb12e,0x24c80b6,
  28582. 0x2719673,0x35e5ba9,0x04aa4cc,0x206ab23,0x1cf185a,0x2c140d8,
  28583. 0x1095a7d,0x1b3633f,0x000c9f8 } },
  28584. /* 47 */
  28585. { { 0x0b2a556,0x0a051c4,0x30b29a7,0x190c9ed,0x3767ca9,0x38de66d,
  28586. 0x2d9e125,0x3aca813,0x2dc22a3,0x319e074,0x0d9450a,0x3445bac,
  28587. 0x3e08a5b,0x07f29fa,0x00eccac },
  28588. { 0x02d6e94,0x21113f7,0x321bde6,0x0a4d7b3,0x03621f4,0x2780e8b,
  28589. 0x22d5432,0x1fc2853,0x0d57d3e,0x254f90b,0x33ed00b,0x289b025,
  28590. 0x12272bb,0x30e715f,0x0000297 } },
  28591. /* 48 */
  28592. { { 0x0243a7d,0x2aac42e,0x0c5b3aa,0x0fa3e96,0x06eeef9,0x2b9fdd9,
  28593. 0x26fca39,0x0134fe1,0x22661ab,0x1990416,0x03945d6,0x15e3628,
  28594. 0x3848ca3,0x0f91e46,0x00b08cd },
  28595. { 0x16d2411,0x3717e1d,0x128c45e,0x3669d54,0x0d4a790,0x2797da8,
  28596. 0x0f09634,0x2faab0b,0x27df649,0x3b19b49,0x0467039,0x39b65a2,
  28597. 0x3816f3c,0x31ad0bd,0x0050046 } },
  28598. /* 49 */
  28599. { { 0x2425043,0x3858099,0x389092a,0x3f7c236,0x11ff66a,0x3c58b39,
  28600. 0x2f5a7f8,0x1663ce1,0x2a0fcf5,0x38634b7,0x1a8ca18,0x0dcace8,
  28601. 0x0e6f778,0x03ae334,0x00df0d2 },
  28602. { 0x1bb4045,0x357875d,0x14b77ed,0x33ae5b6,0x2252a47,0x31899dd,
  28603. 0x3293582,0x040c6f6,0x14340dd,0x3614f0e,0x3d5f47f,0x326fb3d,
  28604. 0x0044a9d,0x00beeb9,0x0027c23 } },
  28605. /* 50 */
  28606. { { 0x32d49ce,0x34822a3,0x30a22d1,0x00858b7,0x10d91aa,0x2681fd9,
  28607. 0x1cce870,0x2404a71,0x38b8433,0x377c1c8,0x019442c,0x0a38b21,
  28608. 0x22aba50,0x0d61c81,0x002dcbd },
  28609. { 0x0680967,0x2f0f2f9,0x172cb5f,0x1167e4b,0x12a7bc6,0x05b0da7,
  28610. 0x2c76e11,0x3a36201,0x37a3177,0x1d71419,0x0569df5,0x0dce7ad,
  28611. 0x3f40b75,0x3bd8db0,0x002d481 } },
  28612. /* 51 */
  28613. { { 0x2a1103e,0x34e7f7f,0x1b171a2,0x24a57e0,0x2eaae55,0x166c992,
  28614. 0x10aa18f,0x0bb836f,0x01acb59,0x0e430e7,0x1750cca,0x18be036,
  28615. 0x3cc6cdf,0x0a0f7e5,0x00da4d8 },
  28616. { 0x2201067,0x374d187,0x1f6b0a6,0x165a7ec,0x31531f8,0x3580487,
  28617. 0x15e5521,0x0724522,0x2b04c04,0x202c86a,0x3cc1ccf,0x225b11a,
  28618. 0x1bde79d,0x0eccc50,0x00d24da } },
  28619. /* 52 */
  28620. { { 0x3b0a354,0x2814dd4,0x1cd8575,0x3d031b7,0x0392ff2,0x1855ee5,
  28621. 0x0e8cff5,0x203442e,0x3bd3b1b,0x141cf95,0x3fedee1,0x1d783c0,
  28622. 0x26f192a,0x0392aa3,0x0075238 },
  28623. { 0x158ffe9,0x3889f19,0x14151f4,0x06067b1,0x13a3486,0x1e65c21,
  28624. 0x382d5ef,0x1ab0aac,0x2ffddc4,0x3179b7a,0x3c8d094,0x05101e3,
  28625. 0x237c6e5,0x3947d83,0x00f674f } },
  28626. /* 53 */
  28627. { { 0x363408f,0x21eb96b,0x27376fb,0x2a735d6,0x1a39c36,0x3d31863,
  28628. 0x33313fc,0x32235e0,0x082f034,0x23ef351,0x39b3528,0x1a69d84,
  28629. 0x1d9c944,0x07159ad,0x0077a71 },
  28630. { 0x04f8d65,0x25771e5,0x2ba84a6,0x194586a,0x1e6da5f,0x118059a,
  28631. 0x14e9c32,0x1d24619,0x3f528ae,0x22f22e4,0x0f5580d,0x0747a0e,
  28632. 0x32cc85f,0x286b3a8,0x008ccf9 } },
  28633. /* 54 */
  28634. { { 0x196fee2,0x2c4431c,0x094528a,0x18e1d32,0x175799d,0x26bb6b7,
  28635. 0x2293482,0x23fd289,0x07b2be8,0x1a5c533,0x158d60d,0x04a4f3f,
  28636. 0x164e9f7,0x32ccca9,0x00da6b6 },
  28637. { 0x1d821c2,0x3f76c4f,0x323df43,0x17e4374,0x0f2f278,0x121227e,
  28638. 0x2464190,0x19d2644,0x326d24c,0x3185983,0x0803c15,0x0767a33,
  28639. 0x1c4c996,0x0563eab,0x00631c6 } },
  28640. /* 55 */
  28641. { { 0x1752366,0x0baf83f,0x288bacf,0x0384e6f,0x2b93c34,0x3c805e7,
  28642. 0x3664850,0x29e1663,0x254ff1d,0x3852080,0x0f85c16,0x1e389d9,
  28643. 0x3191352,0x3915eaa,0x00a246e },
  28644. { 0x3763b33,0x187ad14,0x3c0d438,0x3f11702,0x1c49f03,0x35ac7a8,
  28645. 0x3f16bca,0x27266bf,0x08b6fd4,0x0f38ce4,0x37fde8c,0x147a6ff,
  28646. 0x02c5e5c,0x28e7fc5,0x00076a7 } },
  28647. /* 56 */
  28648. { { 0x2338d10,0x0e77fa7,0x011b046,0x1bfd0ad,0x28ee699,0x21d73bc,
  28649. 0x0461d1a,0x342ea58,0x2d695b4,0x30415ed,0x2906e0b,0x18e494a,
  28650. 0x20f8a27,0x026b870,0x002c19f },
  28651. { 0x2f4c43d,0x3f0fc3b,0x0aa95b8,0x2a01ea1,0x3e2e1b1,0x0d74af6,
  28652. 0x0555288,0x0cb757d,0x24d2071,0x143d2bb,0x3907f67,0x3e0ce30,
  28653. 0x131f0e9,0x3724381,0x007a874 } },
  28654. /* 57 */
  28655. { { 0x3c27050,0x08b5165,0x0bf884b,0x3dd679c,0x3bd0b8d,0x25ce2e6,
  28656. 0x1674057,0x1f13ed3,0x1f5cd91,0x0d1fd35,0x13ce6e3,0x2671338,
  28657. 0x10f8b90,0x34e5487,0x00942bf },
  28658. { 0x03b566d,0x23c3da9,0x37de502,0x1a486ff,0x1af6e86,0x1108cb3,
  28659. 0x36f856c,0x01a6a0f,0x179f915,0x1595a01,0x2cfecb8,0x082568b,
  28660. 0x1ba16d1,0x1abb6c0,0x00cf7f0 } },
  28661. /* 58 */
  28662. { { 0x2f96c80,0x1b8f123,0x209c0f5,0x2ccf76d,0x1d521f2,0x3705143,
  28663. 0x2941027,0x07f88af,0x07102a9,0x38b4868,0x1efa37d,0x1bdd3e8,
  28664. 0x028a12e,0x02e055b,0x009a9a9 },
  28665. { 0x1c7dfcb,0x3aa7aa7,0x1d62c54,0x3f0b0b0,0x3c74e66,0x274f819,
  28666. 0x23f9674,0x0e2b67c,0x24654dd,0x0c71f0e,0x1946cee,0x0016211,
  28667. 0x0045dc7,0x0da1173,0x0089856 } },
  28668. /* 59 */
  28669. { { 0x0e73946,0x29f353f,0x056329d,0x2d48c5a,0x28f697d,0x2ea4bb1,
  28670. 0x235e9cc,0x34faa38,0x15f9f91,0x3557519,0x2a50a6c,0x1a27c8e,
  28671. 0x2a1a0f3,0x3098879,0x00dcf21 },
  28672. { 0x1b818bf,0x2f20b98,0x2243cff,0x25b691e,0x3c74a2f,0x2f06833,
  28673. 0x0e980a8,0x32db48d,0x2b57929,0x33cd7f5,0x2fe17d6,0x11a384b,
  28674. 0x2dafb81,0x2b9562c,0x00ddea6 } },
  28675. /* 60 */
  28676. { { 0x2787b2e,0x37a21df,0x310d294,0x07ce6a4,0x1258acc,0x3050997,
  28677. 0x19714aa,0x122824b,0x11c708b,0x0462d56,0x21abbf7,0x331aec3,
  28678. 0x307b927,0x3e8d5a0,0x00c0581 },
  28679. { 0x24d4d58,0x3d628fc,0x23279e0,0x2e38338,0x2febe9b,0x346f9c0,
  28680. 0x3d6a419,0x3264e47,0x245faca,0x3669f62,0x1e50d66,0x3028232,
  28681. 0x18201ab,0x0bdc192,0x0002c34 } },
  28682. /* 61 */
  28683. { { 0x17bdbc2,0x1c501c5,0x1605ccd,0x31ab438,0x372fa89,0x24a8057,
  28684. 0x13da2bb,0x3f95ac7,0x3cda0a3,0x1e2b679,0x24f0673,0x03b72f4,
  28685. 0x35be616,0x2ccd849,0x0079d4d },
  28686. { 0x33497c4,0x0c7f657,0x2fb0d3d,0x3b81064,0x38cafea,0x0e942bc,
  28687. 0x3ca7451,0x2ab9784,0x1678c85,0x3c62098,0x1eb556f,0x01b3aa2,
  28688. 0x149f3ce,0x2656f6d,0x002eef1 } },
  28689. /* 62 */
  28690. { { 0x0596edc,0x1f4fad4,0x03a28ed,0x18a4149,0x3aa3593,0x12db40a,
  28691. 0x12c2c2a,0x3b1a288,0x327c4fb,0x35847f5,0x384f733,0x02e3fde,
  28692. 0x1af0e8a,0x2e417c3,0x00d85a6 },
  28693. { 0x0091cf7,0x2267d75,0x276860e,0x19cbbfc,0x04fef2b,0x030ce59,
  28694. 0x3195cb1,0x1aa3f07,0x3699362,0x2a09d74,0x0d6c840,0x1e413d0,
  28695. 0x28acdc7,0x1ff5ea1,0x0088d8b } },
  28696. /* 63 */
  28697. { { 0x3d98425,0x08dc8de,0x154e85f,0x24b1c2c,0x2d44639,0x19a1e8b,
  28698. 0x300ee29,0x053f72e,0x3f7c832,0x12417f6,0x1359368,0x0674a4c,
  28699. 0x1218e20,0x0e4fbd4,0x000428c },
  28700. { 0x01e909a,0x1d88fe6,0x12da40c,0x215ef86,0x2925133,0x004241f,
  28701. 0x3e480f4,0x2d16523,0x07c3120,0x3375e86,0x21fd8f3,0x35dc0b6,
  28702. 0x0efc5c9,0x14ef8d6,0x0066e47 } },
  28703. /* 64 */
  28704. { { 0x2973cf4,0x34d3845,0x34f7070,0x22df93c,0x120aee0,0x3ae2b4a,
  28705. 0x1af9b95,0x177689a,0x036a6a4,0x0377828,0x23df41e,0x22d4a39,
  28706. 0x0df2aa1,0x06ca898,0x0003cc7 },
  28707. { 0x06b1dd7,0x19dc2a8,0x35d324a,0x0467499,0x25bfa9c,0x1a1110c,
  28708. 0x01e2a19,0x1b3c1cf,0x18d131a,0x10d9815,0x2ee7945,0x0a2720c,
  28709. 0x0ddcdb0,0x2c071b6,0x00a6aef } },
  28710. /* 65 */
  28711. { { 0x1ab5245,0x1192d00,0x13ffba1,0x1b71236,0x09b8d0b,0x0eb49cb,
  28712. 0x1867dc9,0x371de4e,0x05eae9f,0x36faf82,0x094ea8b,0x2b9440e,
  28713. 0x022e173,0x2268e6b,0x00740fc },
  28714. { 0x0e23b23,0x22c28ca,0x04d05e2,0x0bb84c4,0x1235272,0x0289903,
  28715. 0x267a18b,0x0df0fd1,0x32e49bb,0x2ab1d29,0x281e183,0x3dcd3c3,
  28716. 0x1c0eb79,0x2db0ff6,0x00bffe5 } },
  28717. /* 66 */
  28718. { { 0x2a2123f,0x0d63d71,0x1f6db1a,0x257f8a3,0x1927b2d,0x06674be,
  28719. 0x302753f,0x20b7225,0x14c1a3f,0x0429cdd,0x377affe,0x0f40a75,
  28720. 0x2d34d06,0x05fb6b9,0x0054398 },
  28721. { 0x38b83c4,0x1e7bbda,0x1682f79,0x0527651,0x2615cb2,0x1795fab,
  28722. 0x0e4facc,0x11f763c,0x1b81130,0x2010ae2,0x13f3650,0x20d5b72,
  28723. 0x1f32f88,0x34617f4,0x00bf008 } },
  28724. /* 67 */
  28725. { { 0x28068db,0x0aa8913,0x1a47801,0x10695ca,0x1c72cc6,0x0fc1a47,
  28726. 0x33df2c4,0x0517cf0,0x3471d92,0x1be815c,0x397f794,0x3f03cbe,
  28727. 0x121bfae,0x172cbe0,0x00813d7 },
  28728. { 0x383bba6,0x04f1c90,0x0b3f056,0x1c29089,0x2a924ce,0x3c85e69,
  28729. 0x1cecbe5,0x0ad8796,0x0aa79f6,0x25e38ba,0x13ad807,0x30b30ed,
  28730. 0x0fa963a,0x35c763d,0x0055518 } },
  28731. /* 68 */
  28732. { { 0x0623f3b,0x3ca4880,0x2bff03c,0x0457ca7,0x3095c71,0x02a9a08,
  28733. 0x1722478,0x302c10b,0x3a17458,0x001131e,0x0959ec2,0x18bdfbc,
  28734. 0x2929fca,0x2adfe32,0x0040ae2 },
  28735. { 0x127b102,0x14ddeaa,0x1771b8c,0x283700c,0x2398a86,0x085a901,
  28736. 0x108f9dc,0x0cc0012,0x33a918d,0x26d08e9,0x20b9473,0x12c3fc7,
  28737. 0x1f69763,0x1c94b5a,0x00e29de } },
  28738. /* 69 */
  28739. { { 0x035af04,0x3450021,0x12da744,0x077fb06,0x25f255b,0x0db7150,
  28740. 0x17dc123,0x1a2a07c,0x2a7636a,0x3972430,0x3704ca1,0x0327add,
  28741. 0x3d65a96,0x3c79bec,0x009de8c },
  28742. { 0x11d3d06,0x3fb8354,0x12c7c60,0x04fe7ad,0x0466e23,0x01ac245,
  28743. 0x3c0f5f2,0x2a935d0,0x3ac2191,0x090bd56,0x3febdbc,0x3f1f23f,
  28744. 0x0ed1cce,0x02079ba,0x00d4fa6 } },
  28745. /* 70 */
  28746. { { 0x0ab9645,0x10174ec,0x3711b5e,0x26357c7,0x2aeec7f,0x2170a9b,
  28747. 0x1423115,0x1a5122b,0x39e512c,0x18116b2,0x290db1c,0x041b13a,
  28748. 0x26563ae,0x0f56263,0x00b89f3 },
  28749. { 0x3ed2ce4,0x01f365f,0x1b2043b,0x05f7605,0x1f9934e,0x2a068d2,
  28750. 0x38d4d50,0x201859d,0x2de5291,0x0a7985a,0x17e6711,0x01b6c1b,
  28751. 0x08091fa,0x33c6212,0x001da23 } },
  28752. /* 71 */
  28753. { { 0x2f2c4b5,0x311acd0,0x1e47821,0x3bd9816,0x1931513,0x1bd4334,
  28754. 0x30ae436,0x2c49dc0,0x2c943e7,0x010ed4d,0x1fca536,0x189633d,
  28755. 0x17abf00,0x39e5ad5,0x00e4e3e },
  28756. { 0x0c8b22f,0x2ce4009,0x1054bb6,0x307f2fc,0x32eb5e2,0x19d24ab,
  28757. 0x3b18c95,0x0e55e4d,0x2e4acf5,0x1bc250c,0x1dbf3a5,0x17d6a74,
  28758. 0x087cf58,0x07f6f82,0x00f8675 } },
  28759. /* 72 */
  28760. { { 0x110e0b2,0x0e672e7,0x11b7157,0x1598371,0x01c0d59,0x3d60c24,
  28761. 0x096b8a1,0x0121075,0x0268859,0x219962f,0x03213f2,0x3022adc,
  28762. 0x18de488,0x3dcdeb9,0x008d2e0 },
  28763. { 0x06cfee6,0x26f2552,0x3c579b7,0x31fa796,0x2036a26,0x362ba5e,
  28764. 0x103601c,0x012506b,0x387ff3a,0x101a41f,0x2c7eb58,0x23d2efc,
  28765. 0x10a5a07,0x2fd5fa3,0x00e3731 } },
  28766. /* 73 */
  28767. { { 0x1cd0abe,0x08a0af8,0x2fa272f,0x17a1fbf,0x1d4f901,0x30e0d2f,
  28768. 0x1898066,0x273b674,0x0c1b8a2,0x3272337,0x3ee82eb,0x006e7d3,
  28769. 0x2a75606,0x0af1c81,0x0037105 },
  28770. { 0x2f32562,0x2842491,0x1bb476f,0x1305cd4,0x1daad53,0x0d8daed,
  28771. 0x164c37b,0x138030f,0x05145d5,0x300e2a3,0x32c09e7,0x0798600,
  28772. 0x3515130,0x2b9e55c,0x009764e } },
  28773. /* 74 */
  28774. { { 0x3d5256a,0x06c67f2,0x3a3b879,0x3c9b284,0x04007e0,0x33c1a41,
  28775. 0x3794604,0x1d6240e,0x022b6c1,0x22c62a7,0x01d4590,0x32df5f6,
  28776. 0x368f1a1,0x2a7486e,0x006e13f },
  28777. { 0x31e6e16,0x20f18a9,0x09ed471,0x23b861d,0x15cf0ef,0x397b502,
  28778. 0x1c7f9b2,0x05f84b2,0x2cce6e1,0x3c10bba,0x13fb5a7,0x1b52058,
  28779. 0x1feb1b8,0x03b7279,0x00ea1cf } },
  28780. /* 75 */
  28781. { { 0x2a4cc9b,0x15cf273,0x08f36e6,0x076bf3b,0x2541796,0x10e2dbd,
  28782. 0x0bf02aa,0x3aa2201,0x03cdcd4,0x3ee252c,0x3799571,0x3e01fa4,
  28783. 0x156e8d0,0x1fd6188,0x003466a },
  28784. { 0x2515664,0x166b355,0x2b0b51e,0x0f28f17,0x355b0f9,0x2909e76,
  28785. 0x206b026,0x3823a12,0x179c5fa,0x0972141,0x2663a1a,0x01ee36e,
  28786. 0x3fc8dcf,0x2ef3d1b,0x0049a36 } },
  28787. /* 76 */
  28788. { { 0x2d93106,0x3d6b311,0x3c9ce47,0x382aa25,0x265b7ad,0x0b5f92f,
  28789. 0x0f4c941,0x32aa4df,0x380d4b2,0x0e8aba6,0x260357a,0x1f38273,
  28790. 0x0d5f95e,0x199f23b,0x0029f77 },
  28791. { 0x0a0b1c5,0x21a3d6a,0x0ad8df6,0x33d8a5e,0x1240858,0x30000a8,
  28792. 0x3ac101d,0x2a8143d,0x1d7ffe9,0x1c74a2a,0x1b962c9,0x1261359,
  28793. 0x0c8b274,0x002cf4a,0x00a8a7c } },
  28794. /* 77 */
  28795. { { 0x211a338,0x22a14ab,0x16e77c5,0x3c746be,0x3a78613,0x0d5731c,
  28796. 0x1767d25,0x0b799fa,0x009792a,0x09ae8dc,0x124386b,0x183d860,
  28797. 0x176747d,0x14c4445,0x00ab09b },
  28798. { 0x0eb9dd0,0x0121066,0x032895a,0x330541c,0x1e6c17a,0x2271b92,
  28799. 0x06da454,0x054c2bf,0x20abb21,0x0ead169,0x3d7ea93,0x2359649,
  28800. 0x242c6c5,0x3194255,0x00a3ef3 } },
  28801. /* 78 */
  28802. { { 0x3010879,0x1083a77,0x217989d,0x174e55d,0x29d2525,0x0e544ed,
  28803. 0x1efd50e,0x30c4e73,0x05bd5d1,0x0793bf9,0x3f7af77,0x052779c,
  28804. 0x2b06bc0,0x13d0d02,0x0055a6b },
  28805. { 0x3eaf771,0x094947a,0x0288f13,0x0a21e35,0x22ab441,0x23816bf,
  28806. 0x15832e1,0x2d8aff3,0x348cc1f,0x2bbd4a8,0x01c4792,0x34209d3,
  28807. 0x06dc72b,0x211a1df,0x00345c5 } },
  28808. /* 79 */
  28809. { { 0x2a65e90,0x173ac2f,0x199cde1,0x0ac905b,0x00987f7,0x3618f7b,
  28810. 0x1b578df,0x0d5e113,0x34bac6a,0x27d85ed,0x1b48e99,0x18af5eb,
  28811. 0x1a1be9e,0x3987aac,0x00877ca },
  28812. { 0x2358610,0x3776a8e,0x2b0723a,0x344c978,0x22fc4d6,0x1615d53,
  28813. 0x3198f51,0x2d61225,0x12cb392,0x07dd061,0x355f7de,0x09e0132,
  28814. 0x0efae99,0x13b46aa,0x00e9e6c } },
  28815. /* 80 */
  28816. { { 0x0683186,0x36d8e66,0x0ea9867,0x0937731,0x1fb5cf4,0x13c39ef,
  28817. 0x1a7ffed,0x27dfb32,0x31c7a77,0x09f15fd,0x16b25ef,0x1dd01e7,
  28818. 0x0168090,0x240ed02,0x0090eae },
  28819. { 0x2e1fceb,0x2ab9783,0x1a1fdf2,0x093a1b0,0x33ff1da,0x2864fb7,
  28820. 0x3587d6c,0x275aa03,0x123dc9b,0x0e95a55,0x0592030,0x2102402,
  28821. 0x1bdef7b,0x37f2e9b,0x001efa4 } },
  28822. /* 81 */
  28823. { { 0x0540015,0x20e3e78,0x37dcfbd,0x11b0e41,0x02c3239,0x3586449,
  28824. 0x1fb9e6a,0x0baa22c,0x00c0ca6,0x3e58491,0x2dbe00f,0x366d4b0,
  28825. 0x176439a,0x2a86b86,0x00f52ab },
  28826. { 0x0ac32ad,0x226250b,0x0f91d0e,0x1098aa6,0x3dfb79e,0x1dbd572,
  28827. 0x052ecf2,0x0f84995,0x0d27ad2,0x036c6b0,0x1e4986f,0x2317dab,
  28828. 0x2327df6,0x0dee0b3,0x00389ac } },
  28829. /* 82 */
  28830. { { 0x0e60f5b,0x0622d3e,0x2ada511,0x05522a8,0x27fe670,0x206af28,
  28831. 0x333cb83,0x3f25f6c,0x19ddaf3,0x0ec579b,0x36aabc0,0x093dbac,
  28832. 0x348b44b,0x277dca9,0x00c5978 },
  28833. { 0x1cf5279,0x32e294a,0x1a6c26f,0x3f006b6,0x37a3c6b,0x2e2eb26,
  28834. 0x2cf88d4,0x3410619,0x1899c80,0x23d3226,0x30add14,0x2810905,
  28835. 0x01a41f0,0x11e5176,0x005a02f } },
  28836. /* 83 */
  28837. { { 0x1c90202,0x321df30,0x3570fa5,0x103e2b1,0x3d099d4,0x05e207d,
  28838. 0x0a5b1bd,0x0075d0a,0x3db5b25,0x2d87899,0x32e4465,0x226fc13,
  28839. 0x24cb8f8,0x3821daa,0x004da3a },
  28840. { 0x3e66861,0x03f89b8,0x386d3ef,0x14ccc62,0x35e7729,0x11ce5b7,
  28841. 0x035fbc7,0x3f4df0f,0x29c439f,0x1144568,0x32d7037,0x312f65e,
  28842. 0x06b9dbf,0x03a9589,0x0008863 } },
  28843. /* 84 */
  28844. { { 0x0a9e8c9,0x1a19b6e,0x091ecd9,0x2e16ee0,0x2a11963,0x116cf34,
  28845. 0x390d530,0x194131f,0x2b580f3,0x31d569c,0x21d3751,0x3e2ce64,
  28846. 0x193de46,0x32454f0,0x004bffd },
  28847. { 0x09554e7,0x170126e,0x2be6cd1,0x153de89,0x0353c67,0x350765c,
  28848. 0x202370b,0x1db01e5,0x30b12b1,0x3778591,0x00c8809,0x2e845d5,
  28849. 0x1fb1e56,0x170f90d,0x00e2db3 } },
  28850. /* 85 */
  28851. { { 0x328e33f,0x392aad8,0x36d1d71,0x0aebe04,0x1548678,0x1b55c8c,
  28852. 0x24995f8,0x2a5a01e,0x1bd1651,0x37c7c29,0x36803b6,0x3716c91,
  28853. 0x1a935a5,0x32f10b7,0x005c587 },
  28854. { 0x2e8b4c0,0x336ccae,0x11382b6,0x22ec4cc,0x066d159,0x35fa585,
  28855. 0x23b2d25,0x3017528,0x2a674a8,0x3a4f900,0x1a7ce82,0x2b2539b,
  28856. 0x3d46545,0x0a07918,0x00eb9f8 } },
  28857. /* 86 */
  28858. { { 0x2cf5b9b,0x03e747f,0x166a34e,0x0afc81a,0x0a115b1,0x3aa814d,
  28859. 0x11cf3b1,0x163e556,0x3cbfb15,0x157c0a4,0x1bc703a,0x2141e90,
  28860. 0x01f811c,0x207218b,0x0092e6b },
  28861. { 0x1af24e3,0x3af19b3,0x3c70cc9,0x335cbf3,0x068917e,0x055ee92,
  28862. 0x09a9308,0x2cac9b7,0x008b06a,0x1175097,0x36e929c,0x0be339c,
  28863. 0x0932436,0x15f18ba,0x0009f6f } },
  28864. /* 87 */
  28865. { { 0x29375fb,0x35ade34,0x11571c7,0x07b8d74,0x3fabd85,0x090fa91,
  28866. 0x362dcd4,0x02c3fdb,0x0608fe3,0x2477649,0x3fc6e70,0x059b7eb,
  28867. 0x1e6a708,0x1a4c220,0x00c6c4c },
  28868. { 0x2a53fb0,0x1a3e1f5,0x11f9203,0x27e7ad3,0x038718e,0x3f5f9e4,
  28869. 0x308acda,0x0a8700f,0x34472fe,0x3420d7a,0x08076e5,0x014240e,
  28870. 0x0e7317e,0x197a98e,0x00538f7 } },
  28871. /* 88 */
  28872. { { 0x2663b4b,0x0927670,0x38dd0e0,0x16d1f34,0x3e700ab,0x3119567,
  28873. 0x12559d2,0x399b6c6,0x0a84bcd,0x163e7dd,0x3e2aced,0x058548c,
  28874. 0x03a5bad,0x011cf74,0x00c155c },
  28875. { 0x3e454eb,0x2a1e64e,0x1ccd346,0x36e0edf,0x266ee94,0x2e74aaf,
  28876. 0x2d8378a,0x3cd547d,0x1d27733,0x0928e5b,0x353553c,0x26f502b,
  28877. 0x1d94341,0x2635cc7,0x00d0ead } },
  28878. /* 89 */
  28879. { { 0x0142408,0x382c3bb,0x3310908,0x2e50452,0x398943c,0x1d0ac75,
  28880. 0x1bf7d81,0x04bd00f,0x36b6934,0x3349c37,0x0f69e20,0x0195252,
  28881. 0x243a1c5,0x030da5f,0x00a76a9 },
  28882. { 0x224825a,0x28ce111,0x34c2e0f,0x02e2b30,0x382e48c,0x26853ca,
  28883. 0x24bd14e,0x0200dec,0x1e24db3,0x0d3d775,0x132da0a,0x1dea79e,
  28884. 0x253dc0c,0x03c9d31,0x0020db9 } },
  28885. /* 90 */
  28886. { { 0x26c5fd9,0x05e6dc3,0x2eea261,0x08db260,0x2f8bec1,0x1255edf,
  28887. 0x283338d,0x3d9a91d,0x2640a72,0x03311f9,0x1bad935,0x152fda8,
  28888. 0x0e95abd,0x31abd15,0x00dfbf4 },
  28889. { 0x107f4fa,0x29ebe9a,0x27353f7,0x3821972,0x27311fa,0x2925ab6,
  28890. 0x337ab82,0x2de6c91,0x1f115fe,0x044f909,0x21b93c2,0x3a5f142,
  28891. 0x13eb5e9,0x3ab1377,0x00b26b6 } },
  28892. /* 91 */
  28893. { { 0x22e5f2b,0x2ae7d4a,0x1ac481c,0x0a6fce1,0x2f93caf,0x242658e,
  28894. 0x3f35c3c,0x050f3d2,0x30074c9,0x142079c,0x0281b4c,0x295fea3,
  28895. 0x007413e,0x01726cd,0x00e4979 },
  28896. { 0x1ab3cfb,0x1b76295,0x36adf55,0x1ad4636,0x1d444b9,0x3bd2e55,
  28897. 0x35425a5,0x1aa8cd3,0x3acecd2,0x1f769e8,0x1a655e9,0x1f6846f,
  28898. 0x24c70b5,0x3bff080,0x0002da3 } },
  28899. /* 92 */
  28900. { { 0x081d0d9,0x2c00d99,0x1fe2e24,0x396063f,0x03740db,0x243f680,
  28901. 0x3c1f451,0x1ff7b07,0x2803cf2,0x38ca724,0x2934f43,0x0d72d4d,
  28902. 0x0e8fe74,0x2975e21,0x002b505 },
  28903. { 0x11adcc9,0x331a99c,0x21e16cf,0x1714c78,0x1f03432,0x2caa2a6,
  28904. 0x34a9679,0x2f7fe8b,0x0423c21,0x1a757ce,0x31b57d6,0x171e044,
  28905. 0x093b9b2,0x13602e0,0x00db534 } },
  28906. /* 93 */
  28907. { { 0x250a2f5,0x0b999eb,0x21d10d7,0x22b92a1,0x39b7f8d,0x0c37c72,
  28908. 0x29f70f3,0x3bf0e84,0x1d7e04f,0x07a42a9,0x272c3ae,0x1587b2f,
  28909. 0x155faff,0x10a336e,0x000d8fb },
  28910. { 0x3663784,0x0d7dcf5,0x056ad22,0x319f8b1,0x0c05bae,0x2b6ff33,
  28911. 0x0292e42,0x0435797,0x188efb1,0x0d3f45e,0x119d49f,0x395dcd3,
  28912. 0x279fe27,0x133a13d,0x00188ac } },
  28913. /* 94 */
  28914. { { 0x396c53e,0x0d133e9,0x009b7ee,0x13421a0,0x1bbf607,0x1d284a5,
  28915. 0x1594f74,0x18cb47c,0x2dcac11,0x2999ddb,0x04e2fa5,0x1889e2c,
  28916. 0x0a89a18,0x33cb215,0x0052665 },
  28917. { 0x104ab58,0x1d91920,0x3d6d7e3,0x04dc813,0x1167759,0x13a8466,
  28918. 0x0a06a54,0x103761b,0x25b1c92,0x26a8fdd,0x2474614,0x21406a4,
  28919. 0x251d75f,0x38c3734,0x007b982 } },
  28920. /* 95 */
  28921. { { 0x15f3060,0x3a7bf30,0x3be6e44,0x0baa1fa,0x05ad62f,0x1e54035,
  28922. 0x099d41c,0x2a744d9,0x1c0336f,0x3e99b5b,0x1afd3b1,0x2bf1255,
  28923. 0x1822bf8,0x2c93972,0x001d8cc },
  28924. { 0x1d7584b,0x0508ade,0x20dd403,0x203a8fc,0x1c54a05,0x1611a31,
  28925. 0x037c8f9,0x1dcd4fe,0x110fbea,0x30f60bc,0x3dffe2f,0x26a1de1,
  28926. 0x0480367,0x18ec81c,0x0048eba } },
  28927. /* 96 */
  28928. { { 0x346e2f6,0x0435077,0x036789b,0x3e06545,0x313ab57,0x351a721,
  28929. 0x3372b91,0x15e6019,0x2fa4f6c,0x3c30656,0x272c9ac,0x10e84a8,
  28930. 0x2bdacea,0x232d9e2,0x009dadd },
  28931. { 0x182579a,0x15b1af8,0x02d8cce,0x36cb49b,0x086feba,0x2911d17,
  28932. 0x268ee12,0x011e871,0x18698dc,0x35602b3,0x11b9ec2,0x0ade731,
  28933. 0x0f6a05a,0x1821015,0x00007da } },
  28934. /* 97 */
  28935. { { 0x3b00dd0,0x328d485,0x27a69e3,0x32c3a06,0x1046779,0x120b61c,
  28936. 0x19fef3d,0x0fef2e6,0x134d923,0x039bce0,0x348cd0e,0x0b0c007,
  28937. 0x066ae11,0x15d8f1b,0x00934e7 },
  28938. { 0x33234dc,0x353f0f5,0x2fc1b44,0x18a193a,0x2fcae20,0x1afbc86,
  28939. 0x3afe252,0x17f7e10,0x107f3b7,0x2d84d54,0x394c2e6,0x19e96a9,
  28940. 0x0a37283,0x26c6152,0x003d262 } },
  28941. /* 98 */
  28942. { { 0x37cfaf8,0x01863d0,0x0299623,0x32c80cb,0x25b8742,0x0a4d90e,
  28943. 0x1f72472,0x13de652,0x31a0946,0x0ee0103,0x0f25414,0x2518b49,
  28944. 0x07e7604,0x1488d9b,0x00abd6b },
  28945. { 0x1338f55,0x2ce4af5,0x1a0c119,0x3380525,0x21a80a9,0x235d4df,
  28946. 0x118ca7f,0x2dd8bcc,0x1c26bf4,0x32dc56b,0x28482b6,0x1418596,
  28947. 0x3c84d24,0x1f1a5a9,0x00d958d } },
  28948. /* 99 */
  28949. { { 0x1c21f31,0x22aa1ef,0x258c9ad,0x2d2018f,0x0adb3ca,0x01f75ee,
  28950. 0x186283b,0x31ad3bf,0x3621be7,0x3b1ee6d,0x015582d,0x3d61d04,
  28951. 0x2ddf32e,0x14b8a66,0x00c970c },
  28952. { 0x2f24d66,0x00b8a88,0x100a78f,0x041d330,0x2efec1d,0x24c5b86,
  28953. 0x2a6a390,0x37526bc,0x2055849,0x3339f08,0x16bffc4,0x07f9d72,
  28954. 0x06ec09c,0x3f49ee8,0x00cad98 } },
  28955. /* 100 */
  28956. { { 0x248b73e,0x1b8b42d,0x285eed7,0x39473f4,0x1a9f92c,0x3b44f78,
  28957. 0x086c062,0x06a4ea3,0x34ea519,0x3c74e95,0x1ad1b8b,0x1737e2c,
  28958. 0x2cfe338,0x0a291f4,0x00bbecc },
  28959. { 0x1cec548,0x0c9b01a,0x20b298d,0x377c902,0x24f5bc1,0x2415c8d,
  28960. 0x1a70622,0x2529090,0x1c5c682,0x283f1ba,0x2319f17,0x0120e2e,
  28961. 0x01c6f4d,0x33c67ff,0x008b612 } },
  28962. /* 101 */
  28963. { { 0x03830eb,0x02d4053,0x10c59bb,0x0f23b83,0x13d08f8,0x26ea4e2,
  28964. 0x2626427,0x0a45292,0x0449cbc,0x0175750,0x074c46f,0x27ae0f8,
  28965. 0x2d7d6ae,0x163dd3a,0x0063bb7 },
  28966. { 0x2bb29e0,0x034bab1,0x341e1c4,0x21d2c0b,0x295aa2d,0x0f2c666,
  28967. 0x1891755,0x13db64a,0x2fe5158,0x337646e,0x31a1aae,0x057bee4,
  28968. 0x00f9e37,0x396d19e,0x00c1b6a } },
  28969. /* 102 */
  28970. { { 0x2772f41,0x34f92d0,0x39d1cde,0x174ef2d,0x03a700d,0x03fbb98,
  28971. 0x30d50e8,0x352ed10,0x1fcf5e5,0x3d113bc,0x26e358f,0x180653f,
  28972. 0x1b43cc6,0x3cc9aa4,0x00e68a2 },
  28973. { 0x37fe4d2,0x09dd725,0x01eb584,0x171f8a9,0x278fdef,0x3e37c03,
  28974. 0x3bec02f,0x149757c,0x0cd5852,0x37d2e10,0x0e6988b,0x1c120e9,
  28975. 0x0b83708,0x38e7319,0x0039499 } },
  28976. /* 103 */
  28977. { { 0x08df5fe,0x177a02c,0x0362fc0,0x1f18ee8,0x00c1295,0x173c50a,
  28978. 0x379414d,0x1885ba8,0x32a54ef,0x2315644,0x39e65cf,0x357c4be,
  28979. 0x1d66333,0x09e05a5,0x0009c60 },
  28980. { 0x1f7a2fb,0x073b518,0x2eb83ac,0x11353d7,0x1dd8384,0x0c63f2b,
  28981. 0x238c6c8,0x2a1920a,0x2e5e9f1,0x1cc56f8,0x042daf4,0x1ed5dc5,
  28982. 0x25f9e31,0x012a56a,0x0081b59 } },
  28983. /* 104 */
  28984. { { 0x321d232,0x2c71422,0x3a756b6,0x30230b2,0x387f3db,0x3a7c3eb,
  28985. 0x274b46a,0x201e69f,0x185bb7b,0x140da82,0x0d974a2,0x0616e42,
  28986. 0x35ec94f,0x3bc366b,0x005aa7c },
  28987. { 0x3dcfffc,0x19a9c15,0x3225e05,0x36ae114,0x16ea311,0x0cda2aa,
  28988. 0x2a1a8d2,0x154b5cb,0x08348cd,0x17b66c8,0x080ea43,0x21e59f3,
  28989. 0x04173b9,0x31d5b04,0x00ad735 } },
  28990. /* 105 */
  28991. { { 0x2e76ef4,0x216acf3,0x2b93aea,0x112bc74,0x3449974,0x2b2e48f,
  28992. 0x11929be,0x2f03021,0x19051e3,0x0ac202d,0x19be68a,0x3b87619,
  28993. 0x26cdac4,0x086592c,0x00f00de },
  28994. { 0x2e90d4d,0x3ed703c,0x2c648d7,0x29ddf67,0x000e219,0x3471247,
  28995. 0x26febd5,0x1161713,0x3541a8f,0x302038d,0x08d2af9,0x26e1b21,
  28996. 0x398514a,0x36dad99,0x002ed70 } },
  28997. /* 106 */
  28998. { { 0x06f25cb,0x1104596,0x370faee,0x07e83f3,0x0f7b686,0x228d43a,
  28999. 0x12cd201,0x0a1bd57,0x3e592dc,0x1e186fc,0x2226aba,0x2c63fe9,
  29000. 0x17b039a,0x1efaa61,0x00d1582 },
  29001. { 0x2e6acef,0x07d51e4,0x3ac326c,0x322b07e,0x1422c63,0x32ff5c7,
  29002. 0x18760df,0x048928b,0x139b251,0x04d7da9,0x048d1a2,0x2a23e84,
  29003. 0x199dbba,0x2fa7afe,0x0049f1a } },
  29004. /* 107 */
  29005. { { 0x3492b73,0x27d3d3d,0x2b1a16f,0x07b2ce4,0x0cf28ec,0x2729bff,
  29006. 0x3130d46,0x3e96116,0x140b72e,0x14a2ea3,0x1ca066f,0x3a61f1d,
  29007. 0x022ebac,0x09192b4,0x003e399 },
  29008. { 0x12555bb,0x0b6139d,0x239463a,0x12a70ab,0x2aaa93b,0x2254e72,
  29009. 0x00424ec,0x26a6736,0x26daa11,0x25b5ad6,0x379f262,0x140cd30,
  29010. 0x0c7d3bd,0x097bbcf,0x00899e9 } },
  29011. /* 108 */
  29012. { { 0x3825dc4,0x3cd946f,0x0462b7f,0x31102e7,0x30f741c,0x3313ed6,
  29013. 0x1ff5a95,0x15bf9dc,0x09b47fd,0x0f2e7a7,0x1626c0d,0x3c14f6d,
  29014. 0x14098bd,0x19d7df8,0x00a97ce },
  29015. { 0x0934f5e,0x3f968db,0x046f68a,0x12333bf,0x26cd5e1,0x1ea2161,
  29016. 0x358570d,0x235031d,0x35edd55,0x05265e3,0x24ae00c,0x3542229,
  29017. 0x25bb2a1,0x1c83c75,0x0058f2a } },
  29018. /* 109 */
  29019. { { 0x24daedb,0x376928f,0x305266f,0x0499746,0x038318c,0x312efd7,
  29020. 0x1910a24,0x33450a3,0x1c478a9,0x39d8bf9,0x12cc0ae,0x397aeab,
  29021. 0x0654c08,0x095f283,0x00d2cdf },
  29022. { 0x0b717d2,0x1f162c2,0x107a48f,0x128e1b3,0x2380718,0x39f4044,
  29023. 0x00f626a,0x05ec0c9,0x21bc439,0x200fa4d,0x20aea01,0x186a1d8,
  29024. 0x26372f2,0x1a91f87,0x0053f55 } },
  29025. /* 110 */
  29026. { { 0x3512a90,0x33b958b,0x29f1c84,0x0106c3a,0x224b3c0,0x09b307a,
  29027. 0x215d2de,0x3bdf43b,0x22cf0c9,0x176121d,0x1534143,0x09ba717,
  29028. 0x16b3110,0x0f73f6c,0x008f5b7 },
  29029. { 0x2c75d95,0x26fbcb4,0x0dda1f6,0x206f819,0x28d33d5,0x1fb4d79,
  29030. 0x024c125,0x30a0630,0x1f9c309,0x0fe350d,0x1696019,0x0a54187,
  29031. 0x09541fd,0x35e3a79,0x0066618 } },
  29032. /* 111 */
  29033. { { 0x0e382de,0x33f5163,0x0dde571,0x3bb7a40,0x1175806,0x12ae8ed,
  29034. 0x0499653,0x3b25586,0x38ade7a,0x3fa265d,0x3f4aa97,0x3c03dbb,
  29035. 0x30c6de8,0x32d4042,0x00ae971 },
  29036. { 0x2f788f1,0x1fbaf0e,0x3e2d182,0x3ff904f,0x0d46229,0x1d0726d,
  29037. 0x15455b4,0x093ae28,0x290f8e4,0x097c0b9,0x1ae8771,0x28480bb,
  29038. 0x04f6d40,0x3689925,0x0049b3b } },
  29039. /* 112 */
  29040. { { 0x35b2d69,0x31819c0,0x11b0d63,0x035afb6,0x2b50715,0x2bece6c,
  29041. 0x35f82f7,0x0ad987c,0x0011601,0x02e6f67,0x2d0a5f5,0x365e583,
  29042. 0x2f7c900,0x11449c5,0x00ed705 },
  29043. { 0x27abdb4,0x1bbfd04,0x301c157,0x263c079,0x36850d6,0x3f21f8b,
  29044. 0x27d7493,0x0f9227e,0x06fb0ce,0x002daf3,0x37d8c1c,0x3ef87d7,
  29045. 0x19cc6f4,0x0c3809c,0x00cf752 } },
  29046. /* 113 */
  29047. { { 0x22d94ed,0x075b09c,0x020e676,0x084dc62,0x2d1ec3f,0x17439f1,
  29048. 0x240b702,0x33cc596,0x30ebaf3,0x0359fe0,0x393ea43,0x0ece01e,
  29049. 0x16c6963,0x03a82f2,0x0017faa },
  29050. { 0x3866b98,0x3cd20b7,0x12d4e6b,0x3a6a76d,0x1205c1e,0x3e6ae1a,
  29051. 0x2f9bbdf,0x2e61547,0x2d175ee,0x28e18f6,0x13cf442,0x085b0ef,
  29052. 0x0e321ef,0x238fe72,0x003fb22 } },
  29053. /* 114 */
  29054. { { 0x360ac07,0x26dc301,0x3f4d94f,0x2ba75e6,0x1f3c9cc,0x17ff20f,
  29055. 0x0ea084c,0x30e39cf,0x143dc49,0x03bd43e,0x3c9e733,0x19e8aba,
  29056. 0x27fbaf4,0x12d913a,0x005ee53 },
  29057. { 0x3609e7f,0x2d89c80,0x09f020c,0x1558bf7,0x3098443,0x3c515fd,
  29058. 0x1c8e580,0x16506bd,0x26cb4b2,0x1747d42,0x2ec8239,0x32c91f0,
  29059. 0x1ca3377,0x079768f,0x00a5f3e } },
  29060. /* 115 */
  29061. { { 0x185fa94,0x122759f,0x0e47023,0x0dcb6e7,0x10ba405,0x3b5eab4,
  29062. 0x1f7a1fa,0x32d003f,0x1739a4c,0x3295ec3,0x1b18967,0x3f3b265,
  29063. 0x34d2448,0x2dbadc9,0x00f30b5 },
  29064. { 0x01c5338,0x2d1dcf2,0x2bd07cc,0x39a8fb5,0x2b85639,0x355bab6,
  29065. 0x1df95f1,0x01eb5f6,0x17f0a16,0x1b895b5,0x157574d,0x29fff72,
  29066. 0x3a8c46d,0x0118071,0x0065f84 } },
  29067. /* 116 */
  29068. { { 0x3a1e7f1,0x17432f2,0x1f648d4,0x3000ad5,0x2ef0a08,0x1f86624,
  29069. 0x1ca31b1,0x241f9dc,0x2cb4885,0x2b8610f,0x364ce16,0x1e5faf0,
  29070. 0x0b33867,0x2cb637d,0x00816d2 },
  29071. { 0x1aa8671,0x02c394e,0x35f5e87,0x393040a,0x39f0db3,0x1c831a5,
  29072. 0x2966591,0x034a8d0,0x09e613c,0x042b532,0x018ddd6,0x3e402c9,
  29073. 0x2e20e1a,0x29cb4cd,0x00e087c } },
  29074. /* 117 */
  29075. { { 0x3a10079,0x20c7fea,0x3ff2222,0x1edb593,0x00dc5f8,0x3a32ccc,
  29076. 0x1479073,0x0cfed11,0x2a2702a,0x17a056a,0x1fba321,0x235acb9,
  29077. 0x149c833,0x172de7d,0x000f753 },
  29078. { 0x2e95923,0x3b365cb,0x009f471,0x0df1b47,0x21e868b,0x199bbd3,
  29079. 0x07b8ecc,0x12ff0af,0x189808a,0x3bd5059,0x3fbc4d2,0x0fa7b88,
  29080. 0x1125bf2,0x0db0b5d,0x0043572 } },
  29081. /* 118 */
  29082. { { 0x29cdb1b,0x1db656e,0x391efe1,0x004be09,0x245a1ca,0x3793328,
  29083. 0x254af24,0x2f2e65d,0x10e5cc4,0x2af6fe7,0x2d97ac0,0x29f7d42,
  29084. 0x19fd6f6,0x0ac184d,0x00c5211 },
  29085. { 0x305eae3,0x36738d3,0x2c2b696,0x00ba50e,0x3903adc,0x2122f85,
  29086. 0x0753470,0x1cf96a4,0x1702a39,0x247883c,0x2feb67e,0x2ab3071,
  29087. 0x3c6b9e1,0x30cb85a,0x002ca0a } },
  29088. /* 119 */
  29089. { { 0x3871eb5,0x284b93b,0x0a7affe,0x176a2fc,0x294c2f2,0x204d3aa,
  29090. 0x1e4c2a7,0x3ec4134,0x2fb0360,0x3847b45,0x05fc11b,0x0a6db6e,
  29091. 0x390fa40,0x2adfd34,0x005e9f7 },
  29092. { 0x0646612,0x1b5cbcc,0x10d8507,0x0777687,0x3a0afed,0x1687440,
  29093. 0x0222578,0x1af34a4,0x2174e27,0x372d267,0x11246c3,0x34769c5,
  29094. 0x2044316,0x1b4d626,0x00c72d5 } },
  29095. /* 120 */
  29096. { { 0x2e5bb45,0x3ff1d36,0x16dcdf5,0x128986f,0x399068c,0x2a63b1e,
  29097. 0x0afa7aa,0x3a5b770,0x200f121,0x33b74bb,0x1414045,0x0f31ef8,
  29098. 0x2f50e16,0x2f38cd6,0x00b0b1b },
  29099. { 0x1a06293,0x035e140,0x2644d44,0x1f1954b,0x2cdebab,0x31d5f91,
  29100. 0x0b8dbc8,0x38f2d23,0x3783cab,0x2a07e73,0x3123f59,0x3409846,
  29101. 0x3784ddd,0x223bbac,0x003dc7b } },
  29102. /* 121 */
  29103. { { 0x0741456,0x234e631,0x2121e1b,0x00980ca,0x3a9dfa9,0x098c916,
  29104. 0x3fc86d1,0x1c63072,0x3625244,0x13d0471,0x05b0fc5,0x1487550,
  29105. 0x2498596,0x11bb6ea,0x001afab },
  29106. { 0x274b4ad,0x240aea1,0x3d12a75,0x2b56b61,0x1486b43,0x1b83426,
  29107. 0x31c7363,0x35b59ca,0x207bb6c,0x38e6243,0x19bace4,0x0a26671,
  29108. 0x35e3381,0x0c2ded4,0x00d8da4 } },
  29109. /* 122 */
  29110. { { 0x2b75791,0x19590b1,0x2bfb39f,0x2988601,0x0050947,0x0d8bbe1,
  29111. 0x23e3701,0x08e4432,0x2ed8c3d,0x326f182,0x332e1dd,0x12219c5,
  29112. 0x2e0779b,0x367aa63,0x0012d10 },
  29113. { 0x251b7dc,0x0a08b4d,0x1138b6f,0x2ea02af,0x06345a5,0x1cb4f21,
  29114. 0x0332624,0x1d49d88,0x140acc5,0x2f55287,0x024447c,0x291ace9,
  29115. 0x1a4966e,0x015cbec,0x005bc41 } },
  29116. /* 123 */
  29117. { { 0x351cd0e,0x315e8e9,0x07d6e70,0x067ae8f,0x2190d84,0x351f556,
  29118. 0x03bee79,0x31b62c7,0x266f912,0x1b6a504,0x007a6ad,0x3a6ab31,
  29119. 0x3891112,0x3c45ba0,0x00d6ce5 },
  29120. { 0x0e1f2ce,0x32a5edc,0x1434063,0x1ca084f,0x2a3e47c,0x137e042,
  29121. 0x16e2418,0x2069280,0x3b0dfd8,0x35a22b5,0x289bf0a,0x1f667f2,
  29122. 0x02d23a3,0x0ce688f,0x00d8e3f } },
  29123. /* 124 */
  29124. { { 0x10bed6f,0x14c58dd,0x0b0abdf,0x0ca0f9a,0x3808abc,0x2ec228c,
  29125. 0x2366275,0x12afa16,0x20f6b0e,0x37dca8e,0x3af0c6a,0x1c5b467,
  29126. 0x1b25ff7,0x00814de,0x0022dcc },
  29127. { 0x1a56e11,0x02fe37e,0x3f21740,0x35d5a91,0x06cb8ba,0x29bad91,
  29128. 0x17176f7,0x2d919f2,0x0f7d1f5,0x13a3f61,0x04ddb05,0x0c82a51,
  29129. 0x286f598,0x2e8c777,0x0007071 } },
  29130. /* 125 */
  29131. { { 0x0f8fcb9,0x3e83966,0x170c6fd,0x3825343,0x089cec8,0x01b482a,
  29132. 0x0993971,0x3327282,0x39aba8a,0x32456fe,0x1507e01,0x1c3252d,
  29133. 0x21ffb13,0x29822a0,0x0083246 },
  29134. { 0x23c378f,0x1cea7ef,0x1be9a82,0x224d689,0x37e5447,0x3764a75,
  29135. 0x3a49724,0x361e1b3,0x19d365b,0x3a61ffb,0x1c29a7a,0x20ab251,
  29136. 0x17ec549,0x175d777,0x004589a } },
  29137. /* 126 */
  29138. { { 0x15540a9,0x2ec5d2a,0x05b09fa,0x1bc058b,0x07cfb88,0x28f7b86,
  29139. 0x3e766be,0x189305e,0x01fe88e,0x23fdf69,0x0b919c3,0x02dc7ae,
  29140. 0x3f9a9ad,0x0b83cc7,0x0086a52 },
  29141. { 0x28bc259,0x39bdca1,0x39e4bc8,0x0e0f33b,0x16130c6,0x2919955,
  29142. 0x31f4549,0x2fed027,0x30919b2,0x0a39b03,0x0ca7bb2,0x1711b24,
  29143. 0x3b67b94,0x05a136b,0x00acd87 } },
  29144. /* 127 */
  29145. { { 0x0c53841,0x31cb284,0x3ced090,0x06d5693,0x1c20ae0,0x0408d2b,
  29146. 0x37ebd5e,0x081900f,0x26a8589,0x0acfd0a,0x34a1472,0x2f0c302,
  29147. 0x124ccbd,0x10de328,0x00971bc },
  29148. { 0x17ff2ff,0x27d1b54,0x147b6f7,0x38bb2ea,0x26a9c96,0x0a49448,
  29149. 0x39f2f46,0x247c579,0x3b16a4e,0x28c2a5a,0x2d4c72d,0x11f248c,
  29150. 0x1e4df11,0x047d604,0x0065bc3 } },
  29151. /* 128 */
  29152. { { 0x39b3239,0x1f75f44,0x3bae87c,0x139360c,0x18b5782,0x3ffc005,
  29153. 0x3c48789,0x2bc6af2,0x38b909e,0x223ff3b,0x31443a7,0x017d3bb,
  29154. 0x0bfed99,0x128b857,0x00020dd },
  29155. { 0x306d695,0x25a7b28,0x2f60ca2,0x2b6e4f2,0x1df940c,0x1fa9b8e,
  29156. 0x37fab78,0x13f959f,0x10ff98c,0x38343b8,0x019cb91,0x11a1e6b,
  29157. 0x17ab4c6,0x1431f47,0x004b4ea } },
  29158. /* 129 */
  29159. { { 0x20db57e,0x102515e,0x170219e,0x2b66a32,0x1e6017c,0x2f973fe,
  29160. 0x3739e51,0x0e28b6f,0x3cda7a9,0x30d91ac,0x28350df,0x1444215,
  29161. 0x098b504,0x1bcd5b8,0x00ad3bd },
  29162. { 0x22e3e3e,0x3aeaffb,0x26cb935,0x0091ce4,0x2fbd017,0x3a7ed6a,
  29163. 0x335b029,0x3bfc1f1,0x3852e3f,0x2b14a86,0x046b405,0x266af4c,
  29164. 0x3997191,0x33b0e40,0x00e306f } },
  29165. /* 130 */
  29166. { { 0x3e4712c,0x26bb208,0x18eed6d,0x1b30f06,0x27ca837,0x06faf62,
  29167. 0x1831873,0x3fbcf9b,0x3f3d88b,0x1fb55eb,0x0f44edc,0x29917bb,
  29168. 0x3151772,0x342d72e,0x00d4e63 },
  29169. { 0x2ee0ecf,0x39e8733,0x2e8e98c,0x0cd4e0f,0x08f0126,0x1ad157a,
  29170. 0x079078a,0x23018ee,0x196c765,0x2b2f34f,0x0783336,0x075bf9c,
  29171. 0x3713672,0x098d699,0x00f21a7 } },
  29172. /* 131 */
  29173. { { 0x186ba11,0x22cf365,0x048019d,0x2ca2970,0x0d9e0ae,0x08c3bd7,
  29174. 0x261dbf2,0x2fc2790,0x1ee02e6,0x10256a7,0x00dc778,0x18dc8f2,
  29175. 0x157b189,0x2ebc514,0x005c97d },
  29176. { 0x3c4503e,0x1d10d12,0x337097e,0x0c6169a,0x30fb1cb,0x3481752,
  29177. 0x0df2bec,0x19768fa,0x1bcf8f7,0x2925f74,0x2c988a1,0x3be571d,
  29178. 0x04cfa92,0x2ea9937,0x003f924 } },
  29179. /* 132 */
  29180. { { 0x268b448,0x06e375c,0x1b946bf,0x287bf5e,0x3d4c28b,0x138d547,
  29181. 0x21f8c8e,0x21ea4be,0x2d45c91,0x35da78e,0x00326c0,0x210ed35,
  29182. 0x1d66928,0x0251435,0x00fefc8 },
  29183. { 0x0339366,0x216ff64,0x2c3a30c,0x3c5733d,0x04eeb56,0x2333477,
  29184. 0x32b1492,0x25e3839,0x1b5f2ce,0x0dcfba1,0x3165bb2,0x3acafcc,
  29185. 0x10abfcd,0x248d390,0x008106c } },
  29186. /* 133 */
  29187. { { 0x102f4ee,0x3c0585f,0x1225c8d,0x11c6388,0x08a7815,0x2b3e790,
  29188. 0x2895eb6,0x18cf53a,0x0b56e5a,0x2e2c003,0x3e981ff,0x0761b55,
  29189. 0x1bc32f3,0x0a7111d,0x00f5c80 },
  29190. { 0x3568973,0x1587386,0x16ec764,0x20698a6,0x02f809b,0x2821502,
  29191. 0x113d64d,0x38c2679,0x15de61c,0x0309f60,0x272999e,0x29bfe64,
  29192. 0x173f70d,0x1de7fab,0x00bd284 } },
  29193. /* 134 */
  29194. { { 0x31cdf2b,0x0f0be66,0x2151603,0x01af17e,0x32a99cf,0x085dece,
  29195. 0x27d2591,0x1520df4,0x273c448,0x1ec7c54,0x102e229,0x355f604,
  29196. 0x2acb75f,0x005f1fd,0x003d43e },
  29197. { 0x270eb28,0x22ec2ce,0x306b41a,0x238fa02,0x167de2d,0x030a379,
  29198. 0x245a417,0x1808c24,0x0b1a7b2,0x3ab5f6f,0x2cbc6c1,0x2c228d4,
  29199. 0x3041f70,0x2d9a6cc,0x00b504f } },
  29200. /* 135 */
  29201. { { 0x17a27c2,0x216ad7e,0x011ba8e,0x22f0428,0x16ac5ec,0x3ef3c58,
  29202. 0x345533f,0x0298155,0x2856579,0x0005e03,0x19ee75b,0x146fe16,
  29203. 0x29881e4,0x18ece70,0x008907a },
  29204. { 0x20189ed,0x119ce09,0x35cb76d,0x0d91ef4,0x2284a44,0x032ad87,
  29205. 0x0e8c402,0x3c82b5d,0x38c416c,0x398992f,0x1fd820c,0x169b255,
  29206. 0x3b5fcfa,0x1343c92,0x00fa715 } },
  29207. /* 136 */
  29208. { { 0x33f5034,0x20b3b26,0x28fd184,0x16b3679,0x3962d44,0x15d1bc8,
  29209. 0x2fb1d69,0x1292c99,0x25a58c9,0x1b19ab7,0x2d68a5b,0x2f6a09b,
  29210. 0x0d6aedb,0x2935eac,0x0005664 },
  29211. { 0x25e32fc,0x13f9440,0x3252bcd,0x2fea5b7,0x161a5ae,0x0564a8c,
  29212. 0x0a07e23,0x1545f62,0x0de9890,0x1d76765,0x1fd440e,0x2ed0041,
  29213. 0x3db4c96,0x1e8ba01,0x001b0c4 } },
  29214. /* 137 */
  29215. { { 0x0223878,0x29ab202,0x15585c2,0x1a79969,0x1ba08c2,0x2ef09ff,
  29216. 0x2b1b9b9,0x181f748,0x1bf72b9,0x224645c,0x2588dc5,0x2d157e7,
  29217. 0x22d939a,0x05b88d9,0x006d549 },
  29218. { 0x31de0c1,0x23a4e0e,0x278f8da,0x1aa013c,0x1a84d18,0x0d185a5,
  29219. 0x0988ccd,0x2c32efd,0x3bee10e,0x37d7ab8,0x3f2a66e,0x3e2da3e,
  29220. 0x1b5701f,0x3d9f0c1,0x00a68da } },
  29221. /* 138 */
  29222. { { 0x0b2e045,0x0133fd1,0x05d4c10,0x0d92c70,0x391b5e1,0x2292281,
  29223. 0x2e40908,0x2ec694e,0x195ea11,0x29cfeca,0x3d93a4e,0x01215c0,
  29224. 0x08a5f32,0x37a0eff,0x00cce45 },
  29225. { 0x2b3106e,0x12a5fb0,0x0b4faff,0x0c2da12,0x09069c6,0x35d8907,
  29226. 0x2837a6e,0x3db3fb6,0x3136cc3,0x222836b,0x3da018a,0x2741274,
  29227. 0x13ba319,0x1ac7642,0x00f867c } },
  29228. /* 139 */
  29229. { { 0x2527296,0x10a9595,0x178de4d,0x0f739c4,0x0ae26c7,0x3094599,
  29230. 0x20adac6,0x2b875c2,0x3ae5dc0,0x3e04d20,0x1aab2da,0x1d3ab37,
  29231. 0x15f4f75,0x0b730b5,0x00c56b5 },
  29232. { 0x1f32923,0x2f059e5,0x2a89872,0x2056f74,0x04be175,0x1da67c0,
  29233. 0x17f1e7a,0x3780a6d,0x0723ac2,0x257f367,0x1237773,0x2bcee86,
  29234. 0x0b97f83,0x38aff14,0x00a64d4 } },
  29235. /* 140 */
  29236. { { 0x2552b40,0x0b6b883,0x12e8217,0x0974d35,0x062f497,0x1e563e6,
  29237. 0x30ee400,0x375d1e4,0x290751f,0x0d5b68a,0x353e48c,0x064a0d3,
  29238. 0x3c343f1,0x309a394,0x0034d2a },
  29239. { 0x3111286,0x0f08604,0x1827107,0x0536a76,0x0201dac,0x3a574de,
  29240. 0x2c29dbe,0x382c7b0,0x1191f3e,0x324c5bc,0x144ce71,0x24327c1,
  29241. 0x1212778,0x22bc9d8,0x00d7713 } },
  29242. /* 141 */
  29243. { { 0x34ad1cd,0x1179b4e,0x1bc1780,0x1392a92,0x2cd86b9,0x359de85,
  29244. 0x251f1df,0x0da5d5f,0x135fa61,0x0f64a42,0x34f4d89,0x0fe564c,
  29245. 0x3cf9b7a,0x122d757,0x008c9c2 },
  29246. { 0x370d4e9,0x0e9209b,0x0ae99f2,0x1518c64,0x0172734,0x2c20692,
  29247. 0x1d7c135,0x149c52f,0x38928d6,0x3c78b78,0x25841d1,0x2eaa897,
  29248. 0x372e50b,0x29e5d19,0x00c4c18 } },
  29249. /* 142 */
  29250. { { 0x13375ac,0x389a056,0x211310e,0x2f9f757,0x04f3288,0x103cd4e,
  29251. 0x17b2fb2,0x2c78a6a,0x09f1de6,0x23e8442,0x1351bc5,0x1b69588,
  29252. 0x285b551,0x0464b7e,0x00573b6 },
  29253. { 0x0ba7df5,0x259a0db,0x2b4089e,0x05630a2,0x3f299be,0x350ff2f,
  29254. 0x1c9348a,0x3becfa4,0x3cc9a1c,0x17a6ef1,0x338b277,0x2b761d9,
  29255. 0x2aa01c8,0x3cb9dd7,0x006e3b1 } },
  29256. /* 143 */
  29257. { { 0x277788b,0x16a222d,0x173c036,0x310ff58,0x2634ae8,0x392636f,
  29258. 0x0987619,0x1e6acc1,0x26dc8f7,0x242310f,0x0c09aca,0x22b8e11,
  29259. 0x0d17006,0x1c2c806,0x002380c },
  29260. { 0x297c5ec,0x1fef0e8,0x3948cf7,0x14f2915,0x2dacbc8,0x0dafb1f,
  29261. 0x10de043,0x31184da,0x06414ee,0x3c9aeeb,0x1f713ab,0x308f1f8,
  29262. 0x1569ed1,0x3f379bf,0x00f08bb } },
  29263. /* 144 */
  29264. { { 0x0770ee3,0x058fd21,0x17065f8,0x251d128,0x10e0c7f,0x06cb51b,
  29265. 0x0f05f7e,0x3666a72,0x3e7d01f,0x2d05fab,0x11440e5,0x28577d4,
  29266. 0x2fbcf2b,0x14aa469,0x00dc5c5 },
  29267. { 0x270f721,0x1c75d28,0x085b862,0x1d68011,0x132c0a0,0x37be81d,
  29268. 0x1a87e38,0x083fa74,0x3acbf0d,0x16d6429,0x0feda1f,0x031070a,
  29269. 0x2ec2443,0x21e563d,0x00454d2 } },
  29270. /* 145 */
  29271. { { 0x0525435,0x1e98d5f,0x3dbc52b,0x1fcdf12,0x13d9ef5,0x3ff311d,
  29272. 0x393e9ed,0x3cef8ae,0x2987710,0x3bdee2e,0x21b727d,0x3ba1b68,
  29273. 0x10d0142,0x3c64b92,0x0055ac3 },
  29274. { 0x0c1c390,0x38e9bb0,0x1e7b487,0x11511b3,0x1036fb3,0x25aba54,
  29275. 0x1eb2764,0x048d022,0x0d971ed,0x1bb7fb5,0x100f0b4,0x06c3756,
  29276. 0x2f0d366,0x3c6e160,0x0011bd6 } },
  29277. /* 146 */
  29278. { { 0x36bc9d1,0x24d43c1,0x12c35cf,0x2fb3cf3,0x015d903,0x16bc0c7,
  29279. 0x0fc8c22,0x3195c87,0x2488b1c,0x1f82b4c,0x30014e8,0x27ee58d,
  29280. 0x31658dd,0x1684a5f,0x00f0f3a },
  29281. { 0x1f703aa,0x023eebc,0x20babb9,0x080bd9d,0x12f9cc4,0x1a8e2d4,
  29282. 0x0eec666,0x1176803,0x33005d6,0x1137b68,0x37de339,0x33d71cb,
  29283. 0x0c906b9,0x14086b5,0x00aeef6 } },
  29284. /* 147 */
  29285. { { 0x219045d,0x0f22c5e,0x024c058,0x00b414a,0x0ae7c31,0x3db3e96,
  29286. 0x234979f,0x0cf00a8,0x3c962c7,0x27fa77f,0x1c0c4b0,0x1fe8942,
  29287. 0x218053a,0x1eed3f8,0x0051643 },
  29288. { 0x2a23ddb,0x138f570,0x104e945,0x21ca270,0x30726d8,0x3f45490,
  29289. 0x37d9184,0x242ea25,0x33f6d77,0x3f15679,0x065af85,0x34fa1f5,
  29290. 0x2e46b8f,0x31d17fb,0x00a2615 } },
  29291. /* 148 */
  29292. { { 0x335167d,0x181ea10,0x0887c8d,0x01383d7,0x18b42d8,0x263447e,
  29293. 0x1f13df3,0x0319d7e,0x0872074,0x2d6aa94,0x23d9234,0x36a69aa,
  29294. 0x0bad183,0x3138a95,0x00bd3a5 },
  29295. { 0x1b0f658,0x0e4530b,0x373add1,0x1b968fc,0x329dcb6,0x09169ca,
  29296. 0x162df55,0x0211eff,0x02391e4,0x3867460,0x3136b1a,0x37dd36e,
  29297. 0x3bc5bd9,0x2dacfe4,0x0072a06 } },
  29298. /* 149 */
  29299. { { 0x119d96f,0x067b0eb,0x00996da,0x293eca9,0x2b342da,0x1889c7a,
  29300. 0x21633a6,0x0152c39,0x281ce8c,0x18ef3b3,0x0bd62dc,0x3238186,
  29301. 0x38d8b7c,0x3867b95,0x00ae189 },
  29302. { 0x0ed1eed,0x1e89777,0x13ab73e,0x029e1d7,0x2c1257f,0x33fbc09,
  29303. 0x32d5a21,0x3d870b2,0x39bb1fd,0x33663bc,0x24e83e6,0x239bda4,
  29304. 0x3088bcd,0x01db1ed,0x00d71e7 } },
  29305. /* 150 */
  29306. { { 0x14245bf,0x0da0c27,0x153b339,0x05cab0a,0x122d962,0x1b0f0f3,
  29307. 0x3f5a825,0x267a2ce,0x2910d06,0x254326f,0x0f36645,0x025118e,
  29308. 0x37c35ec,0x36e944e,0x006c056 },
  29309. { 0x05ab0e3,0x29aa0c1,0x1295687,0x1fd1172,0x08d40b5,0x05bd655,
  29310. 0x345048a,0x02a1c3c,0x2393d8f,0x0992d71,0x1f71c5e,0x18d4e8a,
  29311. 0x30dd410,0x11d61d3,0x00dd58b } },
  29312. /* 151 */
  29313. { { 0x2230c72,0x30213d8,0x05e367e,0x329204e,0x0f14f6c,0x3369ddd,
  29314. 0x0bb4074,0x2edafd6,0x1b1aa2d,0x0785404,0x0c035ab,0x220da74,
  29315. 0x1f2fdd4,0x092a091,0x00ef83c },
  29316. { 0x3dc2538,0x1cca3e7,0x246afb5,0x24c647f,0x0798082,0x0bb7952,
  29317. 0x0f5c443,0x008b38a,0x299ea1a,0x3c6cf36,0x3df2ec7,0x398e6dc,
  29318. 0x29a1839,0x1cadd83,0x0077b62 } },
  29319. /* 152 */
  29320. { { 0x25d56d5,0x3546f69,0x16e02b1,0x3e5fa9a,0x03a9b71,0x2413d31,
  29321. 0x250ecc9,0x1d2de54,0x2ebe757,0x2a2f135,0x2aeeb9a,0x0d0fe2b,
  29322. 0x204cb0e,0x07464c3,0x00c473c },
  29323. { 0x24cd8ae,0x0c86c41,0x221c282,0x0795588,0x1f4b437,0x06fc488,
  29324. 0x0c81ecd,0x020bf07,0x3a9e2c8,0x2294a81,0x3a64a95,0x0363966,
  29325. 0x32c9a35,0x0f79bec,0x0029e4f } },
  29326. /* 153 */
  29327. { { 0x289aaa5,0x2755b2e,0x059e0aa,0x3031318,0x0f0208a,0x35b7729,
  29328. 0x00d9c6b,0x3dd29d0,0x075f2c2,0x0ece139,0x31562dd,0x04187f2,
  29329. 0x13b8d4c,0x0920b85,0x003924e },
  29330. { 0x09808ab,0x2e36621,0x2a36f38,0x1829246,0x229bf32,0x20883b7,
  29331. 0x159ada8,0x3108a14,0x15bbe5b,0x1e2d1e4,0x1730096,0x0d35cbb,
  29332. 0x15d0da9,0x0e60b94,0x00c4f30 } },
  29333. /* 154 */
  29334. { { 0x31de38b,0x27b9086,0x2760e3e,0x169098d,0x2a124e2,0x00596c6,
  29335. 0x3f73c09,0x0d31642,0x2341464,0x248600a,0x2e1fa10,0x2aa0fc8,
  29336. 0x051e954,0x00f3b67,0x001d4bd },
  29337. { 0x18751e6,0x25a8e1e,0x07f5c2d,0x17e30d4,0x0ed2723,0x23093e2,
  29338. 0x3b80e2c,0x13de2d7,0x2fad37f,0x1be1cfb,0x3224ba9,0x0a7f5d3,
  29339. 0x1714972,0x06667b7,0x009dcd9 } },
  29340. /* 155 */
  29341. { { 0x294f22a,0x3e06993,0x0341ee9,0x24bdc7b,0x2e56098,0x2660a13,
  29342. 0x018ddda,0x2c261b2,0x2953b54,0x267f51c,0x0e8a7cc,0x29ab00c,
  29343. 0x3a38247,0x397ac81,0x00de684 },
  29344. { 0x36b956b,0x347b34a,0x35834bd,0x053c06c,0x0090844,0x148cec5,
  29345. 0x380b325,0x2f17b8b,0x054ef5e,0x09683fb,0x3f8b29a,0x33c979a,
  29346. 0x1e01474,0x3e81fca,0x001c757 } },
  29347. /* 156 */
  29348. { { 0x30fdfe4,0x2d712ba,0x13671bc,0x2cfc226,0x3d7c649,0x16f020e,
  29349. 0x368e3f0,0x2981ebb,0x246a78a,0x115e81b,0x21223a4,0x04dbb30,
  29350. 0x1a50ba2,0x12114bd,0x0089bd6 },
  29351. { 0x055f15a,0x1046e51,0x00fd724,0x1c022a7,0x323dfa9,0x36d8efb,
  29352. 0x0da4d16,0x0910dec,0x2c1fb16,0x2dbe29f,0x298284f,0x2b273bb,
  29353. 0x26022c1,0x20accd5,0x00085a5 } },
  29354. /* 157 */
  29355. { { 0x01f138a,0x2d87e7b,0x0c2815c,0x0c19a3c,0x311c9a2,0x3e4fce3,
  29356. 0x029729d,0x21236b2,0x2984048,0x3f3bc95,0x2bba8fb,0x1a1b680,
  29357. 0x0619a3f,0x29e0447,0x00ed5fe },
  29358. { 0x2d1c833,0x3dcef35,0x3f809b4,0x01a1b9e,0x1509516,0x10ac754,
  29359. 0x2735080,0x27b0a8a,0x2495fb8,0x0a7bdba,0x1ef8b89,0x00233a5,
  29360. 0x0568bf1,0x1a126ba,0x0078a7e } },
  29361. /* 158 */
  29362. { { 0x0470cd8,0x20e9f04,0x30003fe,0x20be1b7,0x1927346,0x2a5026d,
  29363. 0x1ac06bd,0x2717ed7,0x2609493,0x3079ea5,0x1cc116d,0x31b0541,
  29364. 0x2c8ccde,0x10219ae,0x001a52b },
  29365. { 0x2864045,0x0e8d95b,0x2fc1530,0x0aa44e7,0x345eae7,0x3cc7553,
  29366. 0x3ec6466,0x229b60e,0x06f6e95,0x00bed2a,0x0ff4403,0x181c639,
  29367. 0x2e0df67,0x1f8fa46,0x0000811 } },
  29368. /* 159 */
  29369. { { 0x04310a2,0x20cee8e,0x09fc5d5,0x3707f5b,0x0bdfb4e,0x12713ee,
  29370. 0x24f1028,0x0787ee6,0x39a581c,0x3797ec8,0x10a9746,0x112cb9f,
  29371. 0x142b9ba,0x1da0ef6,0x0078f7b },
  29372. { 0x07607ae,0x3232872,0x2a7e076,0x0bb572a,0x182b23c,0x1d8f918,
  29373. 0x181f392,0x37c45a9,0x24a3886,0x0b2a297,0x264e7f2,0x1fa433c,
  29374. 0x0fcfcc8,0x21c0857,0x0004f74 } },
  29375. /* 160 */
  29376. { { 0x01d161c,0x1744585,0x2d17528,0x03a4f13,0x267cd2e,0x30d861f,
  29377. 0x062a647,0x213284b,0x139ed25,0x27d4ca5,0x02fbbd6,0x31ddf11,
  29378. 0x3c50ac4,0x1dd86f7,0x00107de },
  29379. { 0x16beebd,0x1b7317a,0x2151997,0x256a196,0x3be2aff,0x3621cab,
  29380. 0x0a9da19,0x05f3038,0x23da63c,0x3178d5e,0x215cc67,0x07f7f63,
  29381. 0x0c6d8d3,0x3bf5e5c,0x00c44bb } },
  29382. /* 161 */
  29383. { { 0x00c62f1,0x3e0f893,0x1572703,0x3b93865,0x19b1e28,0x389b33b,
  29384. 0x02858bf,0x0e3e9aa,0x04bc436,0x234e072,0x25ba43d,0x3dca19e,
  29385. 0x0274394,0x20f442e,0x003b4a7 },
  29386. { 0x176451e,0x2b5ed5d,0x35c8ee1,0x25c52da,0x0c3d0b5,0x32b306e,
  29387. 0x030954f,0x275ecf7,0x10e472c,0x21577c4,0x02f8a32,0x321bb5c,
  29388. 0x0098f97,0x104e237,0x00d0433 } },
  29389. /* 162 */
  29390. { { 0x0a8f2fe,0x034548b,0x141f1a6,0x121246f,0x1616409,0x237f80d,
  29391. 0x2e29a55,0x1218db6,0x3ea278e,0x1669856,0x1ad7c8e,0x36d11de,
  29392. 0x2c2fcbb,0x18c0b3a,0x001c706 },
  29393. { 0x1699b4b,0x2d531a6,0x17e85e2,0x1b48e78,0x2b509ca,0x2818ea0,
  29394. 0x0165fee,0x0b809ca,0x09db6a2,0x3dad798,0x326ee1d,0x204e416,
  29395. 0x091fa12,0x1c890e5,0x0007b9f } },
  29396. /* 163 */
  29397. { { 0x0ff4e49,0x0bb0512,0x0129159,0x05db591,0x03e4e9f,0x055ab30,
  29398. 0x0f82881,0x0ac2deb,0x3a8bb09,0x356a8d2,0x3d38393,0x03e4089,
  29399. 0x38187cd,0x1377a93,0x0041672 },
  29400. { 0x0139e73,0x3990730,0x187d3c4,0x33e4793,0x2e0fe46,0x2ad87e2,
  29401. 0x33c792c,0x21d4fb6,0x1e4d386,0x2932d1b,0x20f1098,0x1270874,
  29402. 0x0ea6ee4,0x0167d6e,0x005e5fd } },
  29403. /* 164 */
  29404. { { 0x1856031,0x2b7519d,0x3bd07fc,0x337abcb,0x089c7a4,0x2a1f120,
  29405. 0x3523ce7,0x2ba406b,0x09561d9,0x1797f04,0x3cdb95f,0x2d6193e,
  29406. 0x32c7d3f,0x223aed6,0x00beb51 },
  29407. { 0x2e65825,0x158f0ce,0x16413d1,0x310395f,0x3116854,0x250baf4,
  29408. 0x373d341,0x156cc47,0x104c069,0x0893716,0x195a0a6,0x035320e,
  29409. 0x37b7d8a,0x21b5755,0x00fb26b } },
  29410. /* 165 */
  29411. { { 0x286ae17,0x04239f1,0x1a56c53,0x0e74707,0x29090d7,0x2bb142b,
  29412. 0x03b0139,0x1aac916,0x08ba49a,0x0376682,0x3382f85,0x064bbab,
  29413. 0x2910e28,0x1d5bd7f,0x00cc8df },
  29414. { 0x0ab7630,0x208e8e7,0x3fc1877,0x26bee39,0x264984a,0x192ff05,
  29415. 0x08ef9c3,0x0aa6951,0x071c44e,0x26eed3e,0x035c95e,0x06906ad,
  29416. 0x10a0690,0x397eaa9,0x00c6c23 } },
  29417. /* 166 */
  29418. { { 0x034d8dd,0x005b064,0x279bb78,0x12c2c4f,0x1856bb4,0x0c90681,
  29419. 0x06409ab,0x3b48617,0x19a2d78,0x0a34bf8,0x326eddf,0x31f09b5,
  29420. 0x04f04dc,0x3d7c944,0x003ccaf },
  29421. { 0x321f843,0x35fb71a,0x1e4c397,0x377a5d7,0x2da88e4,0x3d6ada7,
  29422. 0x33d3964,0x1b30149,0x0e39aae,0x054dda0,0x3e6f946,0x1273394,
  29423. 0x3ffd3f7,0x2f6655e,0x00021dd } },
  29424. /* 167 */
  29425. { { 0x37233cf,0x11617dd,0x26f07b6,0x3d8250a,0x0fe6771,0x3f9bbbc,
  29426. 0x2aba7ad,0x200a58d,0x3568603,0x198eefa,0x1e8fcf3,0x3b9610b,
  29427. 0x20524ac,0x2a67528,0x0048d9a },
  29428. { 0x1a5e57a,0x1e9d303,0x16c9cff,0x0f39527,0x3c23259,0x03c8a1e,
  29429. 0x104bccf,0x182d5a1,0x18dbc83,0x05b5f42,0x1b402f4,0x317c525,
  29430. 0x11bf1ea,0x3c46e1f,0x0061936 } },
  29431. /* 168 */
  29432. { { 0x0153a9d,0x36859ee,0x2cf0aa9,0x2b27a0f,0x0a49fe3,0x2d984e1,
  29433. 0x018f8e1,0x1378453,0x1ab3843,0x1987093,0x283dae9,0x25cf0e8,
  29434. 0x14fc93d,0x280609d,0x00c99ba },
  29435. { 0x026b1e3,0x34663d3,0x2202477,0x21a9d45,0x212e8e1,0x18ab77e,
  29436. 0x2e52f63,0x0a14ce1,0x295c396,0x00c7a3d,0x2aaedb6,0x30abc4d,
  29437. 0x374acde,0x1318a73,0x00fcfdb } },
  29438. /* 169 */
  29439. { { 0x0a40298,0x3ba5633,0x11956b3,0x14fcbd7,0x3c38781,0x34bab96,
  29440. 0x165630e,0x1f3c831,0x37e3a69,0x2b4226c,0x2d5029e,0x3b4ab1e,
  29441. 0x1da6ac2,0x3eb43c3,0x007e5cd },
  29442. { 0x1b86202,0x109b7f6,0x2054f98,0x2c50cd7,0x2ed1960,0x3c518e7,
  29443. 0x1b02463,0x319c07f,0x1c30db6,0x045fdc2,0x373421e,0x31a1eb9,
  29444. 0x1a8acbf,0x31289b0,0x0013fef } },
  29445. /* 170 */
  29446. { { 0x3fa0a5f,0x068661f,0x2109e36,0x00b18ff,0x1f4b261,0x31d3844,
  29447. 0x0acbc56,0x3aebc99,0x1fa77ab,0x152bd11,0x24cddb7,0x2313f74,
  29448. 0x06eea44,0x15f5114,0x000b131 },
  29449. { 0x2e9993d,0x1ac565c,0x2cbe22a,0x3921797,0x12c3c57,0x360f868,
  29450. 0x33560bf,0x320ee99,0x382c3b8,0x39af88f,0x00bbe38,0x2c4ea59,
  29451. 0x3399b40,0x00ceb45,0x0066eea } },
  29452. /* 171 */
  29453. { { 0x0c6c693,0x31ba56d,0x3d3849f,0x378dabd,0x0efc735,0x17f90bf,
  29454. 0x13343d3,0x2df0f81,0x27c6a9a,0x13c2a90,0x0a0fcb2,0x27c10d9,
  29455. 0x3bc50c7,0x090e4fa,0x0016287 },
  29456. { 0x2927e1e,0x35af405,0x184c5c3,0x3499cee,0x240158e,0x33522e6,
  29457. 0x386fc84,0x0a0b69f,0x1a660ea,0x34590fb,0x22a1bee,0x2ce4fab,
  29458. 0x31a9445,0x0e78655,0x00664c8 } },
  29459. /* 172 */
  29460. { { 0x3eeaf94,0x115d409,0x21e7577,0x097aa67,0x22875c9,0x021ab7a,
  29461. 0x27e7ba5,0x1093f04,0x2a086fe,0x05d9494,0x2b6c028,0x10f31b0,
  29462. 0x1312d11,0x262759c,0x00c9bb2 },
  29463. { 0x1acb0a5,0x30cdf14,0x0f78880,0x0574f18,0x1a37109,0x098adbb,
  29464. 0x2113c09,0x2060925,0x1f89ce4,0x1974976,0x3381358,0x2dab5ca,
  29465. 0x2159c53,0x3af1303,0x000ea3b } },
  29466. /* 173 */
  29467. { { 0x1e49bea,0x29142b1,0x1a59cab,0x055f017,0x0684e54,0x39eb0db,
  29468. 0x29cab9d,0x255ee8b,0x35f2e6f,0x05329e6,0x09b817b,0x1ec091c,
  29469. 0x1df0fef,0x2641f62,0x00eb304 },
  29470. { 0x2fe5096,0x3dcc1d1,0x2aaf508,0x3a0b813,0x0695810,0x144bddb,
  29471. 0x2f1bd93,0x281ae23,0x3513ebc,0x1ddd984,0x0cf158b,0x35218eb,
  29472. 0x257daf7,0x391253b,0x00b2a81 } },
  29473. /* 174 */
  29474. { { 0x153e6ba,0x22396db,0x0ea2ff2,0x2a45121,0x0a90de1,0x34cf23b,
  29475. 0x2db60ce,0x1a900be,0x2f328b6,0x355e75b,0x2c24372,0x0b75b77,
  29476. 0x2ec7d4f,0x3f24759,0x00e9e33 },
  29477. { 0x39eab6e,0x2267480,0x3b5e110,0x1e8fa5e,0x2a31a66,0x3f739a3,
  29478. 0x00166dc,0x3552d88,0x3ae5137,0x3efa0fa,0x0800acd,0x17df61d,
  29479. 0x38c8608,0x04cc31b,0x00cf4ab } },
  29480. /* 175 */
  29481. { { 0x31e08fb,0x1961164,0x22c003f,0x078541b,0x3643855,0x30da587,
  29482. 0x11f0dc9,0x324595e,0x329e3dc,0x29a041e,0x3495d2c,0x0908dd3,
  29483. 0x1895b83,0x198dbb9,0x00d8cfb },
  29484. { 0x0349b1b,0x383c5a8,0x2b86525,0x1b1283e,0x133cd2c,0x2be376a,
  29485. 0x012ee82,0x1eb4d1b,0x0ba71e9,0x01f3109,0x37621eb,0x1d9b77c,
  29486. 0x0d39069,0x3d5a97c,0x0095565 } },
  29487. /* 176 */
  29488. { { 0x20f5e94,0x1eefc86,0x1327e0e,0x054760b,0x2f771e1,0x3ac447e,
  29489. 0x033e3dc,0x198e040,0x04dd342,0x1b49a5d,0x00d01ef,0x3cb6768,
  29490. 0x1ceafbd,0x31c6812,0x001cb80 },
  29491. { 0x221c677,0x060ca27,0x398b17f,0x0146723,0x36452af,0x02d9e65,
  29492. 0x39c5f78,0x3cf50d6,0x0be40f8,0x2970b87,0x26d667c,0x3e45959,
  29493. 0x16e7943,0x01673e7,0x009faaa } },
  29494. /* 177 */
  29495. { { 0x2078fe6,0x0918602,0x11dd8ad,0x399193f,0x0f6cc73,0x0f8dd12,
  29496. 0x2ce34dc,0x06d7d34,0x0c5e327,0x0989254,0x2fc5af7,0x2443d7b,
  29497. 0x32bc662,0x2fe2a84,0x008b585 },
  29498. { 0x039327f,0x08e616a,0x252f117,0x1f52ab0,0x234e2d2,0x0a5b313,
  29499. 0x2f59ef6,0x0f7a500,0x15c4705,0x2c02b81,0x28b4f09,0x08aa5c8,
  29500. 0x0180efc,0x0993e83,0x00a9e86 } },
  29501. /* 178 */
  29502. { { 0x0310ecc,0x2d8892f,0x14ed0b7,0x3c59fe8,0x08a1a74,0x0850e57,
  29503. 0x1d09607,0x044a21f,0x109f5c9,0x237c6cf,0x06b264a,0x3fc8f1a,
  29504. 0x0d4c539,0x2740f96,0x00dc2d4 },
  29505. { 0x1d6f501,0x0adf4ea,0x14f7215,0x0930102,0x3f4c32e,0x24e2643,
  29506. 0x366596d,0x081ff18,0x38f94fb,0x2c21341,0x328594c,0x267c75c,
  29507. 0x196b3fd,0x29932cb,0x0036def } },
  29508. /* 179 */
  29509. { { 0x3ed7cbe,0x26de044,0x3d0e461,0x0565e12,0x295e500,0x31dc17f,
  29510. 0x32251c2,0x3420ca8,0x3995f0d,0x2e8ddab,0x0361a45,0x10971b0,
  29511. 0x11e7b55,0x33bc7ca,0x00812d2 },
  29512. { 0x3d94972,0x1606817,0x0383ccf,0x0e795b7,0x026e20e,0x0f6fefc,
  29513. 0x13685d6,0x315d402,0x0cc36b8,0x1c7f059,0x390ef5e,0x316ae04,
  29514. 0x08c66b9,0x2fac9a4,0x0040086 } },
  29515. /* 180 */
  29516. { { 0x3e3c115,0x153de4d,0x1a8ae5e,0x2330511,0x169b8ee,0x1d965c2,
  29517. 0x2edff2b,0x3ef99e6,0x1631b46,0x1f8a238,0x118d7bb,0x12113c3,
  29518. 0x26424db,0x0f4122a,0x00e0ea2 },
  29519. { 0x3d80a73,0x30393bc,0x0f98714,0x278ef59,0x087a0aa,0x3b18c20,
  29520. 0x04b8a82,0x2068e21,0x030255d,0x3382b27,0x055397f,0x05448dd,
  29521. 0x2015586,0x1190be0,0x000b979 } },
  29522. /* 181 */
  29523. { { 0x2e03080,0x2895692,0x09fb127,0x2d1602a,0x1232306,0x105bd4e,
  29524. 0x28cd6a6,0x0a83813,0x1ee13b0,0x2abadc3,0x0c09684,0x00e33e1,
  29525. 0x033eea3,0x30f0a39,0x00a710e },
  29526. { 0x01b1f7d,0x1c959da,0x017077a,0x254bf0a,0x086fbce,0x15cd6b2,
  29527. 0x008683f,0x23a4f4d,0x22a6bd6,0x14e8c93,0x0027d15,0x31d0d4f,
  29528. 0x271777e,0x1533510,0x00ab603 } },
  29529. /* 182 */
  29530. { { 0x34c209d,0x14d0abb,0x270432a,0x1d02358,0x22ba752,0x209757f,
  29531. 0x34af6fc,0x1ffc52e,0x1ced28e,0x1870e46,0x1e0340f,0x3f0bf73,
  29532. 0x33ba91d,0x2ebca7c,0x00c6580 },
  29533. { 0x1d442cb,0x0879d50,0x24e4ae1,0x3f4e91c,0x04c7727,0x093cd1d,
  29534. 0x16d6a45,0x10a8b95,0x0c77856,0x361f84f,0x217845f,0x0bbeec6,
  29535. 0x0485718,0x33c5385,0x00dcec0 } },
  29536. /* 183 */
  29537. { { 0x1539819,0x225507a,0x1bf11cb,0x13e7653,0x0c8cb3b,0x05f695e,
  29538. 0x353f634,0x2827874,0x3fb8053,0x22de9a5,0x035d8b7,0x2105cc7,
  29539. 0x2a7a98d,0x35bed95,0x0085748 },
  29540. { 0x1859c5d,0x00e51f0,0x22a21fd,0x3054d74,0x06ce965,0x328eab7,
  29541. 0x26a13e0,0x13bfc65,0x01d4fb1,0x36600b9,0x36dd3fc,0x01232ed,
  29542. 0x15bbaa9,0x0ad7a51,0x0089b18 } },
  29543. /* 184 */
  29544. { { 0x3360710,0x1eb5a90,0x136bd77,0x3bd57a6,0x0841287,0x12886c9,
  29545. 0x35c6700,0x21bc6eb,0x25f35ad,0x3bcb01c,0x0707e72,0x23e9943,
  29546. 0x03e5233,0x34bb622,0x002bf8e },
  29547. { 0x16e0d6a,0x04b3d2d,0x290cb02,0x049a10c,0x350537e,0x22cf71b,
  29548. 0x3184a19,0x2dc8b62,0x2350210,0x3b4afa6,0x159781e,0x1d01b6d,
  29549. 0x1853440,0x16442f0,0x005a78d } },
  29550. /* 185 */
  29551. { { 0x348b02c,0x1ea8ab5,0x3b954d5,0x14684ac,0x0be5b34,0x11c4496,
  29552. 0x0a7a456,0x14f6eb7,0x11a3221,0x2d65f82,0x32eb1ea,0x09c4018,
  29553. 0x3f301f3,0x32e8a1c,0x00bd9ad },
  29554. { 0x0543f7f,0x31e744e,0x1fefd1d,0x24a486c,0x1000220,0x3977e3b,
  29555. 0x1b3ef51,0x2512a1b,0x2049e6b,0x122232b,0x391a32b,0x2f4a7b1,
  29556. 0x1c13e71,0x081a9b4,0x00d3516 } },
  29557. /* 186 */
  29558. { { 0x1924f43,0x1ae5495,0x28d52ef,0x2b93e77,0x2d2f401,0x371a010,
  29559. 0x33e8d7a,0x06ed3f1,0x30c0d9d,0x2589fa9,0x3bf3567,0x2ecf8fa,
  29560. 0x2dee4c3,0x152b620,0x007e8a2 },
  29561. { 0x1924407,0x01bd42d,0x044a089,0x18686b5,0x2f14a0e,0x17cdce3,
  29562. 0x0efa216,0x3c586a8,0x1d6ae71,0x375831f,0x3175894,0x20e43eb,
  29563. 0x34c009e,0x3480527,0x00d115c } },
  29564. /* 187 */
  29565. { { 0x12abf77,0x38b0769,0x25682f2,0x295508c,0x0c2a0dc,0x1259b73,
  29566. 0x023ea25,0x340e7b5,0x3c7cd0d,0x1f92324,0x176405c,0x1528894,
  29567. 0x18f2e1e,0x2c59c35,0x001efb5 },
  29568. { 0x0fb1471,0x07e7665,0x141da75,0x07d9f4a,0x0fdb31e,0x0dccda6,
  29569. 0x074eb25,0x3d92a9b,0x11189a0,0x1b4c557,0x24b8d2b,0x0533f92,
  29570. 0x0e9e344,0x2fa3dea,0x008d5a4 } },
  29571. /* 188 */
  29572. { { 0x2669e98,0x1ad3514,0x2a035c9,0x08a3f50,0x24547f9,0x0a145d3,
  29573. 0x1c1319d,0x3fe833d,0x1ae064b,0x1e01734,0x246d27e,0x3a2f13c,
  29574. 0x01e1150,0x263f55e,0x00f89ef },
  29575. { 0x2e0b63f,0x3e57db7,0x23a4b4f,0x11c8899,0x0ad8500,0x348f3a7,
  29576. 0x2918604,0x27d6409,0x1ce5001,0x38f94c2,0x29a508a,0x39bdc89,
  29577. 0x3a52c27,0x194899e,0x00e9376 } },
  29578. /* 189 */
  29579. { { 0x0368708,0x34a2730,0x2e1da04,0x0bd78c1,0x2c45887,0x0c44bfa,
  29580. 0x3a23de3,0x390b9db,0x1746efd,0x05c638e,0x1d20609,0x3263370,
  29581. 0x31987f0,0x2988529,0x005fa3c },
  29582. { 0x0aa9f2a,0x20622f7,0x060deee,0x0c9626a,0x3312cc7,0x18ebac7,
  29583. 0x008dd6c,0x0ad4fe6,0x3db4ea6,0x1dc3f50,0x090b6e9,0x0aff8d2,
  29584. 0x26aa62c,0x18f3e90,0x00105f8 } },
  29585. /* 190 */
  29586. { { 0x38059ad,0x25e576c,0x3ea00b2,0x1fa4191,0x25686b7,0x2d1ce8f,
  29587. 0x30470ed,0x3478bbf,0x340f9b6,0x1c9e348,0x3d594ec,0x2ffe56e,
  29588. 0x3f23deb,0x0cd34e9,0x00f4b72 },
  29589. { 0x1a83f0b,0x2166029,0x28b32a2,0x06a5c5a,0x20786c4,0x0944604,
  29590. 0x0901bd2,0x379b84e,0x221e2fe,0x0346d54,0x1f4eb59,0x01b8993,
  29591. 0x2462e08,0x25f9d8b,0x006c4c8 } },
  29592. /* 191 */
  29593. { { 0x0b41d9d,0x2e417ed,0x265bd10,0x199148e,0x3826ca4,0x1a67e8d,
  29594. 0x1bbd13b,0x23e414d,0x3d773bc,0x356e64c,0x0d2118a,0x0cb587f,
  29595. 0x25fd093,0x24fb529,0x00158c6 },
  29596. { 0x2806e63,0x3ecaa39,0x251b4dd,0x3b2d779,0x2e31ed3,0x066f1a6,
  29597. 0x060e518,0x2c7e3e5,0x0d62c76,0x0d88a70,0x101970a,0x1e3c8c6,
  29598. 0x272b8bb,0x083e73b,0x0031f38 } },
  29599. /* 192 */
  29600. { { 0x09e1c72,0x072bcb0,0x0cf4e93,0x2604a64,0x00715f2,0x10c98b6,
  29601. 0x2ad81d9,0x234fcce,0x37a7304,0x1974a4a,0x1c7415f,0x14aaa93,
  29602. 0x19587b1,0x3f643f4,0x00c3d10 },
  29603. { 0x1ddadd0,0x2cd715d,0x294cf76,0x14479ed,0x19f5f4a,0x0198c09,
  29604. 0x1ab7ebc,0x182c0bc,0x0879202,0x1807273,0x05d39da,0x2c7d868,
  29605. 0x29c4ec4,0x1b13ad2,0x006dcd7 } },
  29606. /* 193 */
  29607. { { 0x1c83f01,0x0245bff,0x24f90ba,0x112554f,0x2354c8b,0x3f17988,
  29608. 0x0c511af,0x39e1e9b,0x26ae95b,0x0ae551c,0x35b41a6,0x0120455,
  29609. 0x1e989cb,0x1b37aff,0x00fa2ae },
  29610. { 0x324659a,0x1aef1c3,0x1c43637,0x3f530a2,0x313a999,0x326af62,
  29611. 0x134184e,0x2ac131c,0x3f6a789,0x30a300a,0x13e526e,0x2107af3,
  29612. 0x093a8ff,0x2479902,0x00442b1 } },
  29613. /* 194 */
  29614. { { 0x22b6e20,0x31b18be,0x18614ca,0x26fdb5a,0x197f29e,0x325b44b,
  29615. 0x0ab1dbb,0x042348a,0x3275e8e,0x15bae44,0x0077124,0x2cf5345,
  29616. 0x2803ad4,0x188f2a2,0x0061b20 },
  29617. { 0x2a560b1,0x3ced069,0x3cf42c2,0x100e167,0x3879e1d,0x0936ff0,
  29618. 0x1b51450,0x14c55f3,0x3153bfa,0x2957423,0x2a93823,0x15f5dce,
  29619. 0x2c9a22f,0x16731a8,0x00a97f2 } },
  29620. /* 195 */
  29621. { { 0x18edbbb,0x18c5ef9,0x1f13c30,0x071e77f,0x225ade5,0x1b60f75,
  29622. 0x1beaf11,0x3e495ad,0x2441dd8,0x2fa00e2,0x32a87b6,0x00050f2,
  29623. 0x038de7f,0x0037d6d,0x00a885d },
  29624. { 0x39e48bd,0x1d9e433,0x2768e9f,0x3c29458,0x3f0bdf9,0x35ed5f2,
  29625. 0x36709fa,0x176dc10,0x012f7c1,0x2df8547,0x1d90ee3,0x053c089,
  29626. 0x21a8d35,0x200cb0d,0x002e84e } },
  29627. /* 196 */
  29628. { { 0x23ec8d8,0x1d81f55,0x0cb7227,0x07f8e4d,0x2a66181,0x163f577,
  29629. 0x272e7af,0x131a8f2,0x2046229,0x25e6276,0x36bbefe,0x2cdc22f,
  29630. 0x17c8288,0x33dd4fb,0x000d524 },
  29631. { 0x330c073,0x1a6728b,0x1cf369f,0x12e7707,0x2f0fa26,0x17c2abd,
  29632. 0x0a45680,0x26ebd13,0x3c7d19b,0x1c3d6c8,0x2abd110,0x064fd07,
  29633. 0x09b8339,0x02b4a9f,0x009e3e1 } },
  29634. /* 197 */
  29635. { { 0x0ae972f,0x2093c35,0x06e7a90,0x0af1ba1,0x243eef0,0x2748582,
  29636. 0x0606122,0x13a45f9,0x0acfe60,0x08a685e,0x0eb184b,0x015bc11,
  29637. 0x0cdf423,0x157fad5,0x004fcad },
  29638. { 0x2728d15,0x3e5bceb,0x0331a0f,0x31b1a80,0x28a2680,0x3b94955,
  29639. 0x04cae07,0x176b57e,0x03ac5a6,0x3d7918b,0x22d23f4,0x0ae077f,
  29640. 0x1eb075d,0x006f16c,0x006e473 } },
  29641. /* 198 */
  29642. { { 0x38219b9,0x0475a2b,0x107a774,0x39946c6,0x1cb883c,0x004e0ed,
  29643. 0x087e571,0x25c3497,0x059982f,0x0a71f66,0x118305d,0x1aaf294,
  29644. 0x3a5dbaa,0x34be404,0x00725fe },
  29645. { 0x3abd109,0x336ebea,0x2528487,0x15a1d61,0x0c0f8cf,0x2b56095,
  29646. 0x2591e68,0x3549a80,0x1d1debb,0x0701c6c,0x161e7e3,0x1f7fa2e,
  29647. 0x3dfe192,0x17e6498,0x0055f89 } },
  29648. /* 199 */
  29649. { { 0x175645b,0x26c036c,0x0b92f89,0x09ed96d,0x351f3a6,0x19ce67b,
  29650. 0x33ac8db,0x2f0828b,0x27fe400,0x0b9c5e1,0x1967b95,0x3324080,
  29651. 0x11de142,0x1d44fb3,0x003d596 },
  29652. { 0x3979775,0x3af37b6,0x3e88d41,0x2f1a8b9,0x299ba61,0x085413c,
  29653. 0x1149a53,0x0beb40e,0x31427ba,0x239f708,0x357d836,0x1558c22,
  29654. 0x280a79f,0x1b255f6,0x002b6d1 } },
  29655. /* 200 */
  29656. { { 0x39ad982,0x3d79d89,0x01a684a,0x0b6722e,0x39bb4c9,0x39a6399,
  29657. 0x1ad44e0,0x3059f5e,0x048265f,0x33a2fa4,0x0c3a4cc,0x0d7df98,
  29658. 0x23a33f1,0x34e2e21,0x00a0a10 },
  29659. { 0x386efd9,0x1c91f34,0x06c2e19,0x3e6d48d,0x00eefd3,0x2181ef2,
  29660. 0x2415f97,0x1d33b08,0x0625086,0x1e8aa3e,0x08c9d60,0x0ab427b,
  29661. 0x2764fa7,0x3b7943e,0x00cd9f0 } },
  29662. /* 201 */
  29663. { { 0x1a46d4d,0x0e471f4,0x1693063,0x0467ac0,0x22df51c,0x127a0f7,
  29664. 0x0498008,0x20e0b16,0x1aa8ad0,0x1923f42,0x2a74273,0x01761ce,
  29665. 0x1600ca4,0x187b87e,0x00ee49e },
  29666. { 0x0c76f73,0x19daf92,0x0b2ad76,0x3d8049d,0x1d9c100,0x0fe1c63,
  29667. 0x0bb67c8,0x035cc44,0x02002fc,0x37b2169,0x344656a,0x1127879,
  29668. 0x1939bc0,0x0dd8df6,0x0028ce7 } },
  29669. /* 202 */
  29670. { { 0x0544ac7,0x26bdc91,0x042697e,0x356e804,0x1f2c658,0x2ceb7ef,
  29671. 0x2dec39f,0x02c1dcc,0x391a2df,0x2344beb,0x2171e20,0x3099c94,
  29672. 0x0fa548a,0x37216c9,0x00f820c },
  29673. { 0x0f4cf77,0x29bbaa5,0x33c6307,0x34a5128,0x118c783,0x2dd06b1,
  29674. 0x139d4c0,0x2db912e,0x1153ffb,0x1075eb3,0x3a255e4,0x2892161,
  29675. 0x36d5006,0x125338c,0x0014fbc } },
  29676. /* 203 */
  29677. { { 0x1584e3c,0x0830314,0x00279b9,0x167df95,0x2c7733c,0x2108aef,
  29678. 0x0ce1398,0x35aaf89,0x012523b,0x3c46b6a,0x388e6de,0x01a2002,
  29679. 0x0582dde,0x19c7fa3,0x007b872 },
  29680. { 0x1e53510,0x11bca1f,0x19684e7,0x267de5c,0x2492f8b,0x364a2b0,
  29681. 0x080bc77,0x2c6d47b,0x248432e,0x3ace44f,0x32028f6,0x0212198,
  29682. 0x2f38bad,0x20d63f0,0x00122bb } },
  29683. /* 204 */
  29684. { { 0x30b29c3,0x3cec78e,0x01510a9,0x0c93e91,0x3837b64,0x1eca3a9,
  29685. 0x105c921,0x05d42e6,0x1379845,0x07ce6f2,0x0e8b6da,0x0e0f093,
  29686. 0x220b2cd,0x1f6c041,0x00299f5 },
  29687. { 0x0afdce3,0x2b0e596,0x2f477b6,0x2ccf417,0x3a15206,0x26ec0bf,
  29688. 0x2e37e2b,0x2593282,0x0ab9db3,0x2841dd8,0x27954be,0x277a681,
  29689. 0x03f82e2,0x2b610c7,0x00446a1 } },
  29690. /* 205 */
  29691. { { 0x06b8195,0x3b3a817,0x31b9c6f,0x317d279,0x3d744a7,0x1de9eb9,
  29692. 0x296acc1,0x1ce9ea3,0x06c3587,0x246815d,0x3756736,0x0588518,
  29693. 0x1c971a4,0x1fde1f4,0x00aa021 },
  29694. { 0x3fd3226,0x274561d,0x00be61e,0x01393d8,0x30f6f23,0x29b7fc1,
  29695. 0x04cebc7,0x0a892a7,0x20109f1,0x27456be,0x0c863ee,0x2eb6c8a,
  29696. 0x38c782b,0x039397a,0x00a2829 } },
  29697. /* 206 */
  29698. { { 0x29de330,0x21fe80f,0x145b55b,0x1986570,0x012b260,0x2482fbc,
  29699. 0x0536e0a,0x16b7382,0x32c4d19,0x1deffdb,0x145f418,0x0c67a76,
  29700. 0x2ce477f,0x218fe24,0x00f9848 },
  29701. { 0x3e37657,0x3f074d3,0x245ad0e,0x20973c3,0x23c58de,0x2c332ef,
  29702. 0x2ad21a8,0x0bf1589,0x208af95,0x1f4a8c4,0x2b43735,0x1e46657,
  29703. 0x15d4f81,0x0c3e63a,0x005f19d } },
  29704. /* 207 */
  29705. { { 0x26865bb,0x20f6683,0x16a672e,0x0efd8d1,0x222f5af,0x18f2367,
  29706. 0x1e9c734,0x25c3902,0x178dfe6,0x2903a79,0x311b91c,0x1adbbe9,
  29707. 0x225a387,0x0b3e509,0x0089551 },
  29708. { 0x34e462b,0x23b6a32,0x27c884c,0x129104b,0x384c015,0x3adedc7,
  29709. 0x325db1c,0x021dc10,0x1e366f7,0x3054df7,0x1992b9a,0x2824e64,
  29710. 0x0ae77f3,0x181b526,0x00a7316 } },
  29711. /* 208 */
  29712. { { 0x2d260f5,0x2434bf2,0x28c0139,0x0a7bb03,0x176c3be,0x3def5f5,
  29713. 0x05bee00,0x3692df7,0x3d2efeb,0x3a6f859,0x1122b87,0x38f779a,
  29714. 0x1415ccc,0x2c260ad,0x0075a28 },
  29715. { 0x04607a6,0x042f37a,0x3f0df68,0x0a1bd36,0x3c6d581,0x2d36bfa,
  29716. 0x2d577d1,0x0a3affa,0x0b2066b,0x2e6f110,0x0b17e84,0x3c76a5e,
  29717. 0x1a57553,0x012f36a,0x0004595 } },
  29718. /* 209 */
  29719. { { 0x29e5836,0x0e6808c,0x269d13e,0x147dc5c,0x32c9e7d,0x09b258e,
  29720. 0x2c58d6f,0x1efd716,0x0437996,0x34ec31b,0x15908d9,0x2efa8fd,
  29721. 0x09ad160,0x079fc1f,0x00d8481 },
  29722. { 0x3d20e4a,0x18269d6,0x3aa8fe7,0x34829c2,0x2e4325d,0x0d800e1,
  29723. 0x11f370b,0x10c08dc,0x22fd092,0x1a5fe55,0x0acc443,0x037030d,
  29724. 0x1cdd404,0x097379e,0x00fd6d7 } },
  29725. /* 210 */
  29726. { { 0x313eafb,0x3f438f3,0x2e5fb3e,0x2ed6a82,0x121009c,0x240889e,
  29727. 0x00c5537,0x269b792,0x334b2fc,0x1dd573c,0x07096ae,0x19296fc,
  29728. 0x3813985,0x2742f48,0x00ddd64 },
  29729. { 0x2045041,0x3842c62,0x1572d0d,0x04f255f,0x06e05b4,0x383ec97,
  29730. 0x1ff8064,0x18bed71,0x39b6411,0x2764cc5,0x257439f,0x3521217,
  29731. 0x172aa42,0x342a2a3,0x0070c5b } },
  29732. /* 211 */
  29733. { { 0x3bdf646,0x1c5ce25,0x1f7ca76,0x2d2acca,0x3aa1485,0x23c97f7,
  29734. 0x3e11d6f,0x0609338,0x07ec622,0x01da8ff,0x3392474,0x17ca07f,
  29735. 0x13a9a04,0x353a5b4,0x0024557 },
  29736. { 0x14c27cd,0x32012f7,0x3fea875,0x3d03d71,0x211c5f0,0x3157fdf,
  29737. 0x0c880bd,0x3c406b2,0x2c51103,0x24ab377,0x399faa8,0x0d06887,
  29738. 0x16b5738,0x28b33a7,0x00c7b67 } },
  29739. /* 212 */
  29740. { { 0x2357586,0x35c93e3,0x0da09a0,0x3d77d92,0x11d7f4f,0x37b98a9,
  29741. 0x3e6c9bf,0x2cdca70,0x2f00389,0x2412673,0x18eab87,0x0101436,
  29742. 0x11617e9,0x06d9b01,0x00e8eef },
  29743. { 0x37e3ca9,0x16ffaf0,0x391debf,0x1b69382,0x07c5e94,0x312fa8a,
  29744. 0x0973142,0x2cadde4,0x109ee67,0x3a07db0,0x1afc5ed,0x08df66f,
  29745. 0x304c7af,0x0804aae,0x00d2e60 } },
  29746. /* 213 */
  29747. { { 0x24f57bf,0x1818322,0x182a615,0x25bfc44,0x0f97586,0x0a5bbc0,
  29748. 0x36773c6,0x1a2660c,0x3ceff66,0x3270152,0x319cd11,0x2845845,
  29749. 0x1acfad6,0x19076f8,0x009824a },
  29750. { 0x289fd01,0x2de97ee,0x39d80b7,0x026227d,0x0f8d3b8,0x15e0a17,
  29751. 0x21ea08f,0x20a2317,0x136ae6d,0x3deb1d1,0x3521ef5,0x0de8801,
  29752. 0x0a25d5d,0x0612c98,0x005ecc4 } },
  29753. /* 214 */
  29754. { { 0x308c8d3,0x3aec669,0x01ecddc,0x13f18fe,0x1e63ed0,0x061cfe5,
  29755. 0x05f5a01,0x1db5741,0x14479f2,0x0ced6b5,0x025ae5b,0x09ca8f5,
  29756. 0x2160581,0x1404433,0x008bfeb },
  29757. { 0x08228bf,0x0e02722,0x37df423,0x33ecabf,0x34bd82a,0x32f529f,
  29758. 0x28f1800,0x0c8f671,0x1246b44,0x1ff35dc,0x091db95,0x303f3da,
  29759. 0x28f7f60,0x3624136,0x00cfbb4 } },
  29760. /* 215 */
  29761. { { 0x326139a,0x2977e4e,0x3eb89a6,0x20ecb31,0x13e076a,0x2a592f3,
  29762. 0x28e82d5,0x235ad1e,0x239b927,0x262938a,0x2444354,0x141b263,
  29763. 0x0d56693,0x2a3fc78,0x0006497 },
  29764. { 0x31efa05,0x3a3664a,0x3e333de,0x2a114e4,0x12da63c,0x3c15e6b,
  29765. 0x2f7277c,0x363aa92,0x2393236,0x16bd2d1,0x32b617f,0x32b656c,
  29766. 0x3b1246c,0x22e2e22,0x00ce76d } },
  29767. /* 216 */
  29768. { { 0x03843dc,0x094de82,0x13b463d,0x0507905,0x089eb35,0x2a6bf25,
  29769. 0x35ebc4e,0x2bb5d45,0x1808ed1,0x1de9949,0x185e829,0x0a55847,
  29770. 0x0b73d67,0x1a2ed61,0x008dd2d },
  29771. { 0x133c3a4,0x04e7980,0x38ea237,0x2ad2f49,0x19de838,0x018bf36,
  29772. 0x29b072c,0x21c1ba0,0x14f63ba,0x31c1cc3,0x13cd05e,0x20120ff,
  29773. 0x1f84d60,0x16e0321,0x00872ab } },
  29774. /* 217 */
  29775. { { 0x19d4d49,0x1ddb4e6,0x05e7fc0,0x37bb0fd,0x1a3eb59,0x36b87f0,
  29776. 0x190e440,0x1c7fef2,0x31ea153,0x14cd65a,0x1bc7ab2,0x11f72ca,
  29777. 0x39582d4,0x0fa4d65,0x00cd5b6 },
  29778. { 0x3d1ff11,0x0d9be9d,0x2903ae3,0x017b7b9,0x259f28f,0x110cefc,
  29779. 0x03fed1a,0x38039bd,0x09bdf9c,0x3055027,0x2ca9c5d,0x2d737b6,
  29780. 0x3bdb421,0x16560b5,0x00f9f33 } },
  29781. /* 218 */
  29782. { { 0x022c792,0x110de25,0x38bf959,0x08f2562,0x1239ea9,0x3c1d950,
  29783. 0x21a247d,0x315112d,0x285bb9f,0x2534a73,0x0b42455,0x1a4a99c,
  29784. 0x069009a,0x1680392,0x006e0ca },
  29785. { 0x1b3bece,0x269e0a1,0x18926b7,0x0e7187e,0x241f35e,0x39d1fe0,
  29786. 0x02099aa,0x1675bfe,0x23fd0ca,0x3d6322b,0x19406b5,0x324c38a,
  29787. 0x242434a,0x3ae677c,0x002ce04 } },
  29788. /* 219 */
  29789. { { 0x2c37b82,0x1ae6506,0x0d83436,0x23496c1,0x0ff0c72,0x2711edf,
  29790. 0x1513611,0x04f9c7d,0x1edbeff,0x376fcb5,0x212a683,0x23bf547,
  29791. 0x0f9c4f7,0x16e6627,0x0082cd8 },
  29792. { 0x0cb5d37,0x31b6db8,0x1a15e23,0x2f5cbb8,0x0818aee,0x21dc6c5,
  29793. 0x12aafd2,0x205f608,0x1d91def,0x3def088,0x1445c51,0x3100e8a,
  29794. 0x3746bda,0x145c4b0,0x00711b0 } },
  29795. /* 220 */
  29796. { { 0x2a99ecc,0x27b5217,0x35e10ed,0x036e32a,0x0f79950,0x15c32f7,
  29797. 0x2c87dcb,0x3ebb2a3,0x2c2d35d,0x114b3ec,0x2e4d80a,0x0c7eb89,
  29798. 0x2abe58d,0x3727737,0x00e6a37 },
  29799. { 0x1eca452,0x1968d07,0x344e5d3,0x29435a2,0x109a5f8,0x181d12c,
  29800. 0x238ea5a,0x127a564,0x00dbb42,0x0fcbfb7,0x2909b2e,0x2571d3a,
  29801. 0x08250e3,0x0694e4e,0x00e156d } },
  29802. /* 221 */
  29803. { { 0x3181ae9,0x1acf411,0x3808d79,0x2a11065,0x0baf44b,0x133cfeb,
  29804. 0x1330943,0x1711b9a,0x2dec3bd,0x1906a9a,0x2ed947c,0x369d763,
  29805. 0x1a5254f,0x104a7a9,0x00acd9d },
  29806. { 0x030301b,0x31568f5,0x2a4965c,0x33ded4b,0x03c9a5b,0x16541fc,
  29807. 0x1319cf1,0x2a3748b,0x1b5de74,0x18bb82e,0x077ac2b,0x309a87a,
  29808. 0x3c31420,0x0f6a4b9,0x00387d7 } },
  29809. /* 222 */
  29810. { { 0x0d3fdac,0x120cfa3,0x1b8e13c,0x1ccccb9,0x376fcd4,0x0bf87f4,
  29811. 0x271b4be,0x363b3fd,0x28b5d98,0x0535cd3,0x114bbc1,0x3ab4f19,
  29812. 0x10494b1,0x2161ece,0x00d14ca },
  29813. { 0x12d37e9,0x110ebd7,0x062295a,0x1cc0119,0x073c6ea,0x15d5411,
  29814. 0x0aeb4b1,0x23fba91,0x175fab5,0x3ee8fe1,0x1c680a6,0x1e76f27,
  29815. 0x3ddfc97,0x3d69ecd,0x00e1ee5 } },
  29816. /* 223 */
  29817. { { 0x2d29f46,0x2d19204,0x3137cd0,0x02c3b54,0x193295b,0x02fbdb2,
  29818. 0x2260948,0x22c02ff,0x3885424,0x1299595,0x00e7f9c,0x310ff2a,
  29819. 0x01ea169,0x0deef85,0x0021908 },
  29820. { 0x1b26cfb,0x38566a8,0x2852875,0x21debff,0x290ca9f,0x0b29663,
  29821. 0x26550d9,0x2b44457,0x05d1938,0x1f8f825,0x366ef93,0x1d8daec,
  29822. 0x069e5ef,0x342ece6,0x00b6034 } },
  29823. /* 224 */
  29824. { { 0x2d8356e,0x1578c09,0x226f4d2,0x3b74c51,0x0f83666,0x0323b59,
  29825. 0x1ddf61d,0x1ed8508,0x3c52667,0x0e5b91c,0x1e9b18b,0x352bdfa,
  29826. 0x13f75da,0x352aa4e,0x00fceff },
  29827. { 0x1c731d5,0x04e2844,0x01d9843,0x286cbc5,0x105bcb3,0x05edd9c,
  29828. 0x21fa956,0x3b1ec83,0x01288cc,0x22fbf3a,0x10f1b56,0x081cf72,
  29829. 0x15cb758,0x18687c1,0x00f5722 } },
  29830. /* 225 */
  29831. { { 0x2973088,0x1209dcd,0x3980f31,0x0221aa7,0x1c008e7,0x011b098,
  29832. 0x395947e,0x2f2806d,0x27dca76,0x037c79a,0x31acddf,0x2bf6219,
  29833. 0x0d8f4ab,0x13644d9,0x00ff705 },
  29834. { 0x2260594,0x18d51f8,0x277e2cf,0x1cb5cec,0x2468a53,0x3e6f4d7,
  29835. 0x019e24e,0x0f30f1d,0x0202404,0x34ad287,0x090b39c,0x23c11ea,
  29836. 0x1a2e3a2,0x3a851be,0x00dca2c } },
  29837. /* 226 */
  29838. { { 0x3277538,0x221cd94,0x3738ab7,0x0973da5,0x1a734e2,0x2c8b8b0,
  29839. 0x2e1d1e6,0x348499b,0x389ebe1,0x18b1854,0x02bb076,0x1b2b500,
  29840. 0x0f207f3,0x170cf99,0x0012088 },
  29841. { 0x0fbfec2,0x1df55a4,0x34ae59e,0x2ab5e95,0x3f9e781,0x3411794,
  29842. 0x1410b05,0x17c3a00,0x0aaa91b,0x074ed7c,0x3fbb352,0x3477c01,
  29843. 0x3ee9ab3,0x0cfb1ca,0x0011c4b } },
  29844. /* 227 */
  29845. { { 0x3c3a7f3,0x2e60ca0,0x2354d32,0x33e2362,0x28083ab,0x03d3b16,
  29846. 0x3164045,0x0a41f7a,0x3f0641e,0x38635d1,0x31bbf03,0x225e2bb,
  29847. 0x0cd894e,0x1f72228,0x0093244 },
  29848. { 0x33d5897,0x383faf3,0x0e6d561,0x0bc4d80,0x3fc3a68,0x05a9adc,
  29849. 0x0b9d73d,0x3d6031e,0x2ded29b,0x339c4ff,0x08d69e5,0x089488c,
  29850. 0x3fda40a,0x295c7fd,0x003a924 } },
  29851. /* 228 */
  29852. { { 0x0093bee,0x115532d,0x2ec0fb6,0x0969631,0x3a6d65a,0x0f43b4d,
  29853. 0x26994d4,0x0b51104,0x2515515,0x3695a26,0x284caa8,0x397aa30,
  29854. 0x25538b8,0x353f47c,0x0033f05 },
  29855. { 0x3615d6e,0x37f8246,0x07dae0f,0x23dc154,0x02ded7e,0x1eef320,
  29856. 0x1631e51,0x3447f75,0x13e267f,0x353e1d1,0x3f89d62,0x369c8ff,
  29857. 0x1a21dc6,0x2b8b8f3,0x0055cbc } },
  29858. /* 229 */
  29859. { { 0x34e84f3,0x2f2539a,0x2c35336,0x0c53bdc,0x1728630,0x3ad5fe6,
  29860. 0x05fdeee,0x3386db6,0x272a42e,0x29fd38c,0x36f0320,0x21b2ed4,
  29861. 0x331e67f,0x28ae48c,0x00f09b6 },
  29862. { 0x2778435,0x0fb3c55,0x32d221d,0x2660c8e,0x32977ba,0x1c12f03,
  29863. 0x1b57fb1,0x01229a8,0x38b389f,0x375ddf3,0x2c6b42c,0x3885d3e,
  29864. 0x2c55a9c,0x2ffc279,0x00404e2 } },
  29865. /* 230 */
  29866. { { 0x04c5ddb,0x2c4d788,0x150e9b9,0x110fbfd,0x29dbfe0,0x30ef83d,
  29867. 0x2ab4bfe,0x395bcd7,0x30d0a43,0x0e2d30f,0x0e73f9b,0x07199cc,
  29868. 0x0c9054c,0x22f4b1e,0x0092ed3 },
  29869. { 0x386e27c,0x00fdaa8,0x0507c70,0x1beb3b6,0x0b9c4f4,0x277d519,
  29870. 0x024ec85,0x1cbaba8,0x1524295,0x112be58,0x21fc119,0x273578b,
  29871. 0x2358c27,0x280ca07,0x00aa376 } },
  29872. /* 231 */
  29873. { { 0x0dbc95c,0x16488cf,0x337a078,0x1abbcb8,0x0aae1aa,0x1caa151,
  29874. 0x00108d4,0x1edf701,0x3e68d03,0x1203214,0x0c7eee2,0x084c572,
  29875. 0x07752d2,0x215a3b9,0x00195d3 },
  29876. { 0x2cd7fbe,0x06e80f6,0x052bd4b,0x07b4f83,0x24b5ac6,0x2aaded4,
  29877. 0x13c0526,0x0ffa9a3,0x08c660e,0x13c35c9,0x3145efb,0x36cfe24,
  29878. 0x0936daf,0x268e3d0,0x00a73fd } },
  29879. /* 232 */
  29880. { { 0x31b17ce,0x2e7bcee,0x3f31891,0x19f1849,0x1140236,0x015487f,
  29881. 0x32e58d3,0x202204a,0x049e350,0x1ce91f9,0x3f75150,0x27f212f,
  29882. 0x0d16ee4,0x1c894c4,0x004023f },
  29883. { 0x33399fa,0x2397b6d,0x2a3ea60,0x36354ca,0x1f12632,0x117a105,
  29884. 0x22758e8,0x361844e,0x3851fc2,0x0ab92db,0x339d02f,0x1e7d6c4,
  29885. 0x19ebd38,0x0a9a036,0x00446d2 } },
  29886. /* 233 */
  29887. { { 0x3e164f1,0x008c092,0x19200f5,0x35a22e0,0x38d09d2,0x212b3bf,
  29888. 0x0056f19,0x3a03545,0x1f075e9,0x0e97137,0x1f496a9,0x32d1f9b,
  29889. 0x36bf738,0x35ace37,0x00899e1 },
  29890. { 0x19eb2a6,0x21fa22d,0x338b69e,0x18e6d1f,0x1280d9d,0x1953a55,
  29891. 0x1411ea3,0x2960566,0x0fd969a,0x1f3e375,0x130742a,0x170aebd,
  29892. 0x33085ff,0x14d868d,0x00a4391 } },
  29893. /* 234 */
  29894. { { 0x0a4bdd2,0x39ca8ea,0x37026ac,0x346da3b,0x0c656cd,0x03136b6,
  29895. 0x233e7e9,0x0714352,0x08a9d95,0x192bb38,0x085d68e,0x20016b8,
  29896. 0x102b8ea,0x1f5dbdd,0x00fdd7a },
  29897. { 0x0d6fa45,0x3ec29a6,0x2b8cce6,0x1c84413,0x0228f86,0x28275f7,
  29898. 0x3d8787d,0x0c19748,0x28b2ae9,0x1954850,0x2a56c36,0x3eae8f7,
  29899. 0x0aca595,0x00e42a2,0x00edbe5 } },
  29900. /* 235 */
  29901. { { 0x3b26c82,0x3682b6f,0x2f9cd64,0x0f254b0,0x0e5d70b,0x1f9dfda,
  29902. 0x28f365f,0x35a57d7,0x00208f2,0x19c8d38,0x112e7be,0x3e403bb,
  29903. 0x3734efa,0x24d12b3,0x0027dc6 },
  29904. { 0x260a46a,0x13fd7b0,0x1c2880e,0x338b70c,0x27da5eb,0x29a7d54,
  29905. 0x1c5d73c,0x2130921,0x32969cc,0x2b37eda,0x2d6d4ec,0x0716bfb,
  29906. 0x0763703,0x1320889,0x00c7bbf } },
  29907. /* 236 */
  29908. { { 0x1fe01b2,0x2dcb1d2,0x11b89d5,0x219e4ea,0x0347851,0x3d1810e,
  29909. 0x3a3c54c,0x06dbe8e,0x03d3ab2,0x2dcfa39,0x3e57b8a,0x337a382,
  29910. 0x0426450,0x0e9f748,0x006488b },
  29911. { 0x1dc4582,0x0e62cf7,0x06fea9e,0x2a56fb1,0x31698c1,0x15b4e10,
  29912. 0x1446ef1,0x0a689fc,0x1d87703,0x20ff497,0x2c71066,0x2c48868,
  29913. 0x2e6cf05,0x30aa9cb,0x0065b2d } },
  29914. /* 237 */
  29915. { { 0x1021d63,0x2217df3,0x1f0821a,0x057fa98,0x23f344b,0x173dcf9,
  29916. 0x1ba6ddc,0x22c8eb5,0x18f227a,0x0455343,0x1c55931,0x1d0dcf3,
  29917. 0x20fa19b,0x1c56618,0x004feab },
  29918. { 0x19ec924,0x224e39f,0x2550509,0x179b51f,0x284d54a,0x2d85d41,
  29919. 0x2d1bdc1,0x1a29068,0x3826158,0x1267f85,0x3005a92,0x0769e00,
  29920. 0x379b617,0x17b5f63,0x00a70bf } },
  29921. /* 238 */
  29922. { { 0x22216c5,0x049437f,0x33510bc,0x141d806,0x22c37e2,0x1bc1adf,
  29923. 0x300175d,0x2e6ded8,0x0a18bfe,0x35377a3,0x382f843,0x08410ca,
  29924. 0x00afd4f,0x0be6c6b,0x008d70e },
  29925. { 0x2e91abb,0x1cede2a,0x28f225c,0x28e18c0,0x30230dc,0x173cc2d,
  29926. 0x123ecfe,0x3c9962e,0x2c25506,0x27b5d53,0x329a5e3,0x106e231,
  29927. 0x3889b8e,0x3b0aeaf,0x00ee67c } },
  29928. /* 239 */
  29929. { { 0x3e46c65,0x0eb3d46,0x1d7ae18,0x23f9d59,0x2978953,0x2589ed3,
  29930. 0x073391d,0x2461e1e,0x0c19f1d,0x22fd2b1,0x0691f5c,0x2e67d8d,
  29931. 0x1fb985d,0x200dd28,0x00a68df },
  29932. { 0x392b5fa,0x123b46f,0x1c323c4,0x104f82f,0x0a098c8,0x26fc05b,
  29933. 0x34cd557,0x0913639,0x09c115e,0x3977c34,0x3410b66,0x062b404,
  29934. 0x0213094,0x132c5e8,0x008b612 } },
  29935. /* 240 */
  29936. { { 0x26e3392,0x3b0ebf0,0x2e00425,0x1c285c8,0x3c07f84,0x08d5ad0,
  29937. 0x028190e,0x1669b73,0x1ffb1ef,0x053b65f,0x063028c,0x0aceb47,
  29938. 0x18988c2,0x0f09a30,0x0007072 },
  29939. { 0x0f49e7d,0x28c0bd3,0x252270d,0x24cfc4a,0x0c5e87c,0x2165052,
  29940. 0x2cdd1d1,0x04931d2,0x3abca74,0x22b57dc,0x169fd47,0x0b928fb,
  29941. 0x17cc3e7,0x21a1ec4,0x0061593 } },
  29942. /* 241 */
  29943. { { 0x1aa0486,0x2e55dea,0x15577b7,0x0d6818f,0x36e41fb,0x2a411f5,
  29944. 0x17d5c7d,0x1eea6c0,0x28068a8,0x0e31d20,0x1f08ad9,0x117e973,
  29945. 0x08a28ab,0x085d30a,0x00cd9fb },
  29946. { 0x347843d,0x1119095,0x11e3595,0x1b29584,0x134d64c,0x2ff3a35,
  29947. 0x247ea14,0x099fc4b,0x2056169,0x145dd03,0x2ed03fb,0x1250e3b,
  29948. 0x3f5135c,0x2b753f0,0x009da30 } },
  29949. /* 242 */
  29950. { { 0x0fa5200,0x214a0b3,0x313dc4e,0x23da866,0x3270760,0x15c9b8b,
  29951. 0x39a53df,0x1f79772,0x3c9e942,0x2984901,0x154d582,0x1685f87,
  29952. 0x2e1183e,0x1f79956,0x00b9987 },
  29953. { 0x15254de,0x3a5cac0,0x37c56f0,0x2c7c29b,0x292a56d,0x195be2c,
  29954. 0x17e4e1a,0x0660f4a,0x052ad98,0x1267f80,0x07cfed8,0x194b4bc,
  29955. 0x01738d3,0x14ba10f,0x00c7843 } },
  29956. /* 243 */
  29957. { { 0x29b2d8a,0x242bc1f,0x19646ee,0x0615f3c,0x0ac8d70,0x07ca3bf,
  29958. 0x2d90317,0x2c83bdb,0x1a96812,0x39fdc35,0x31c61ee,0x2d55fd3,
  29959. 0x2375827,0x355f189,0x00f1c9b },
  29960. { 0x21a6194,0x1f4050a,0x2b845cf,0x02c6242,0x2dd614e,0x3a4f0a9,
  29961. 0x39de100,0x24714fb,0x175e0cd,0x0be633d,0x14befc3,0x13b0318,
  29962. 0x1d68c50,0x299989e,0x00d0513 } },
  29963. /* 244 */
  29964. { { 0x059fb6a,0x2b6eb6a,0x3666a8e,0x39f6ca0,0x1cf8346,0x388b8d5,
  29965. 0x35e61a3,0x271adec,0x22c9963,0x20a4fb3,0x16f241c,0x0058b89,
  29966. 0x21ddafa,0x1ee6fde,0x00d2e6c },
  29967. { 0x0075e63,0x39894d0,0x0286d0d,0x187e7b2,0x02405aa,0x3f91525,
  29968. 0x37830a8,0x2723088,0x2c7364e,0x013f406,0x104ba75,0x270f486,
  29969. 0x3520b4d,0x3852bc6,0x00d589b } },
  29970. /* 245 */
  29971. { { 0x262e53b,0x1da93d1,0x3676135,0x147e41d,0x335ec2f,0x1f02be5,
  29972. 0x297d139,0x22d6198,0x1fe9e59,0x13b4c80,0x1e70f60,0x2f1d4a9,
  29973. 0x2d95149,0x14d6ec4,0x00b54af },
  29974. { 0x12c1c76,0x2930ac8,0x0dfd36e,0x31fac94,0x218f5bb,0x2828691,
  29975. 0x1466cc9,0x3645e83,0x1a4dac2,0x1549593,0x0e95fab,0x19567d2,
  29976. 0x27a3320,0x0642729,0x007487c } },
  29977. /* 246 */
  29978. { { 0x1e98e9c,0x2ff8df7,0x119975a,0x098a904,0x099b90b,0x336c7df,
  29979. 0x010996d,0x159d46d,0x3118b3b,0x3aacd1b,0x31f8ae1,0x214864f,
  29980. 0x398c104,0x089dae2,0x001ec4d },
  29981. { 0x1452baa,0x2f24991,0x2572ba3,0x162b312,0x2387d18,0x147c5c7,
  29982. 0x38eff6e,0x0700251,0x37d931e,0x23cd5c1,0x254c8ca,0x3b9df37,
  29983. 0x1c9a4ff,0x0bfd547,0x00fb489 } },
  29984. /* 247 */
  29985. { { 0x1b8dff8,0x2f6b40b,0x05a25b1,0x3f5688a,0x1d462f4,0x2802d18,
  29986. 0x2aad8ed,0x1b46c75,0x3cf4130,0x250fefb,0x2a13fe1,0x23a1bcd,
  29987. 0x0940442,0x04605fe,0x00c8b2f },
  29988. { 0x0d51afb,0x14a2abc,0x1d06762,0x291526c,0x2a3e2fe,0x28f77d9,
  29989. 0x3ad8f2e,0x3481a1b,0x04b4fbd,0x2836733,0x0189ff5,0x3a5f533,
  29990. 0x319a6cd,0x0f58667,0x00c3679 } },
  29991. /* 248 */
  29992. { { 0x1b85197,0x22426d4,0x2895ea3,0x342d324,0x3ffb17d,0x376cfcf,
  29993. 0x30878b1,0x3c3c83a,0x0ffc57c,0x0ac174a,0x1abd57e,0x2f78b9c,
  29994. 0x01b20d8,0x0a37103,0x007f2be },
  29995. { 0x19a2d48,0x137288a,0x182d655,0x0ba0dde,0x25130ba,0x01c65c6,
  29996. 0x23205f1,0x2097621,0x2827cf2,0x2c57b98,0x03748f2,0x2db15fc,
  29997. 0x385a0d4,0x13690c0,0x00a9e3f } },
  29998. /* 249 */
  29999. { { 0x3fbc9c6,0x2df3b20,0x377e33e,0x31d1505,0x024a311,0x3c1d9ff,
  30000. 0x1377f74,0x00b6b20,0x2364ab7,0x184ab6b,0x2a77969,0x3f2db6c,
  30001. 0x2a6adb7,0x0a10073,0x004a6fb },
  30002. { 0x1fc73de,0x2c74ab3,0x3d325e8,0x2346c0b,0x1d0efae,0x2076146,
  30003. 0x19c190d,0x225c4fe,0x3fafc80,0x2cf063d,0x11b7ae7,0x3dc4f9d,
  30004. 0x3c3f841,0x10d7c1f,0x000a4b3 } },
  30005. /* 250 */
  30006. { { 0x19b7d2e,0x28f1300,0x0b897dd,0x06b5371,0x0631c8d,0x336cc4f,
  30007. 0x09cd6e1,0x2ec1952,0x1104c07,0x07512bb,0x35f000d,0x25f84e9,
  30008. 0x1df4d8f,0x193f769,0x000e9ee },
  30009. { 0x2346910,0x267cecf,0x0ad7eaa,0x087e8a5,0x1622f69,0x342cbfa,
  30010. 0x2aa20d0,0x206e88a,0x3991e58,0x093fb4b,0x0157180,0x3cecb5b,
  30011. 0x2e17c9a,0x1ea371f,0x00919e6 } },
  30012. /* 251 */
  30013. { { 0x2250533,0x13f931d,0x3ef8c72,0x395f605,0x18a2080,0x1cb25d4,
  30014. 0x2fb0f41,0x1c0ba8a,0x1eb17c0,0x266c433,0x09b7e3e,0x0e5d78f,
  30015. 0x0cdc5bf,0x1f7c734,0x0020611 },
  30016. { 0x205ebd5,0x127986f,0x02c0fb0,0x1705b1e,0x1eb0bb5,0x2dffb42,
  30017. 0x2331b8a,0x18fc04e,0x31d6328,0x17db162,0x0d3b619,0x193bdb9,
  30018. 0x3f11662,0x2d8e694,0x0092c51 } },
  30019. /* 252 */
  30020. { { 0x08b364d,0x31ef20a,0x25c4a57,0x021ed07,0x14a562e,0x262a684,
  30021. 0x1d21c66,0x126e5a6,0x181f3f8,0x2a93b65,0x1eb726b,0x08fbbce,
  30022. 0x084f9a2,0x308f30a,0x0013159 },
  30023. { 0x23f4963,0x0c7960e,0x2a81739,0x2242b69,0x3965003,0x2aca542,
  30024. 0x28a1c65,0x2ad48fb,0x149775f,0x1bbb7d2,0x0f2671b,0x3594b85,
  30025. 0x22f5563,0x2470f13,0x00fed44 } },
  30026. /* 253 */
  30027. { { 0x0eb453e,0x3ab70fd,0x1a5b335,0x18f2b74,0x25ff74b,0x3612a46,
  30028. 0x33d0d75,0x28cdda4,0x2b9b49b,0x22728fb,0x004c15b,0x1beb33b,
  30029. 0x1a7e41f,0x0c9b702,0x004ef19 },
  30030. { 0x1ca3233,0x0b4c90f,0x1d4b53d,0x2428896,0x20ee405,0x151bc00,
  30031. 0x022edb5,0x1adc463,0x00109ea,0x06490a6,0x30e91e6,0x3682b76,
  30032. 0x23c50aa,0x3bd2665,0x005fe53 } },
  30033. /* 254 */
  30034. { { 0x0c28c65,0x3741ae4,0x247d372,0x0b04673,0x2176524,0x2c8bf20,
  30035. 0x01fb806,0x3330701,0x307b0a7,0x3999fb7,0x1261bec,0x256679c,
  30036. 0x3f22ac7,0x26e8673,0x00bc69d },
  30037. { 0x3c06819,0x35df344,0x379d009,0x2bb8a0a,0x0635a66,0x096c6fa,
  30038. 0x1ac4a62,0x023e53b,0x0e45240,0x115f53d,0x3056af8,0x0a66b16,
  30039. 0x3c386ee,0x1130e82,0x00cc384 } },
  30040. /* 255 */
  30041. { { 0x14c2356,0x190ec73,0x07be490,0x145d415,0x0740a48,0x1251301,
  30042. 0x3eaf29d,0x2628190,0x079299a,0x26e95c9,0x2e05fdf,0x2ca7c5b,
  30043. 0x32d7b48,0x3d84226,0x0033fb4 },
  30044. { 0x150f955,0x01240aa,0x3ddf867,0x137fb70,0x297e103,0x17eeda8,
  30045. 0x1320b60,0x266ec84,0x13f4322,0x0c8f5ee,0x0590e4a,0x386815e,
  30046. 0x00ce61f,0x161bd63,0x008e1d0 } },
  30047. };
  30048. /* Multiply the base point of P384 by the scalar and return the result.
  30049. * If map is true then convert result to affine coordinates.
  30050. *
  30051. * Stripe implementation.
  30052. * Pre-generated: 2^0, 2^48, ...
  30053. * Pre-generated: products of all combinations of above.
  30054. * 8 doubles and adds (with qz=1)
  30055. *
  30056. * r Resulting point.
  30057. * k Scalar to multiply by.
  30058. * map Indicates whether to convert result to affine.
  30059. * ct Constant time required.
  30060. * heap Heap to use for allocation.
  30061. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  30062. */
  30063. static int sp_384_ecc_mulmod_base_15(sp_point_384* r, const sp_digit* k,
  30064. int map, int ct, void* heap)
  30065. {
  30066. return sp_384_ecc_mulmod_stripe_15(r, &p384_base, p384_table,
  30067. k, map, ct, heap);
  30068. }
  30069. #endif
  30070. /* Multiply the base point of P384 by the scalar and return the result.
  30071. * If map is true then convert result to affine coordinates.
  30072. *
  30073. * km Scalar to multiply by.
  30074. * r Resulting point.
  30075. * map Indicates whether to convert result to affine.
  30076. * heap Heap to use for allocation.
  30077. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  30078. */
  30079. int sp_ecc_mulmod_base_384(const mp_int* km, ecc_point* r, int map, void* heap)
  30080. {
  30081. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  30082. sp_point_384* point = NULL;
  30083. sp_digit* k = NULL;
  30084. #else
  30085. sp_point_384 point[1];
  30086. sp_digit k[15];
  30087. #endif
  30088. int err = MP_OKAY;
  30089. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  30090. point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap,
  30091. DYNAMIC_TYPE_ECC);
  30092. if (point == NULL)
  30093. err = MEMORY_E;
  30094. if (err == MP_OKAY) {
  30095. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15, heap,
  30096. DYNAMIC_TYPE_ECC);
  30097. if (k == NULL)
  30098. err = MEMORY_E;
  30099. }
  30100. #endif
  30101. if (err == MP_OKAY) {
  30102. sp_384_from_mp(k, 15, km);
  30103. err = sp_384_ecc_mulmod_base_15(point, k, map, 1, heap);
  30104. }
  30105. if (err == MP_OKAY) {
  30106. err = sp_384_point_to_ecc_point_15(point, r);
  30107. }
  30108. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  30109. if (k != NULL)
  30110. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  30111. if (point != NULL)
  30112. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  30113. #endif
  30114. return err;
  30115. }
  30116. /* Multiply the base point of P384 by the scalar, add point a and return
  30117. * the result. If map is true then convert result to affine coordinates.
  30118. *
  30119. * km Scalar to multiply by.
  30120. * am Point to add to scalar mulitply result.
  30121. * inMont Point to add is in montgomery form.
  30122. * r Resulting point.
  30123. * map Indicates whether to convert result to affine.
  30124. * heap Heap to use for allocation.
  30125. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  30126. */
  30127. int sp_ecc_mulmod_base_add_384(const mp_int* km, const ecc_point* am,
  30128. int inMont, ecc_point* r, int map, void* heap)
  30129. {
  30130. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  30131. sp_point_384* point = NULL;
  30132. sp_digit* k = NULL;
  30133. #else
  30134. sp_point_384 point[2];
  30135. sp_digit k[15 + 15 * 2 * 6];
  30136. #endif
  30137. sp_point_384* addP = NULL;
  30138. sp_digit* tmp = NULL;
  30139. int err = MP_OKAY;
  30140. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  30141. point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap,
  30142. DYNAMIC_TYPE_ECC);
  30143. if (point == NULL)
  30144. err = MEMORY_E;
  30145. if (err == MP_OKAY) {
  30146. k = (sp_digit*)XMALLOC(
  30147. sizeof(sp_digit) * (15 + 15 * 2 * 6),
  30148. heap, DYNAMIC_TYPE_ECC);
  30149. if (k == NULL)
  30150. err = MEMORY_E;
  30151. }
  30152. #endif
  30153. if (err == MP_OKAY) {
  30154. addP = point + 1;
  30155. tmp = k + 15;
  30156. sp_384_from_mp(k, 15, km);
  30157. sp_384_point_from_ecc_point_15(addP, am);
  30158. }
  30159. if ((err == MP_OKAY) && (!inMont)) {
  30160. err = sp_384_mod_mul_norm_15(addP->x, addP->x, p384_mod);
  30161. }
  30162. if ((err == MP_OKAY) && (!inMont)) {
  30163. err = sp_384_mod_mul_norm_15(addP->y, addP->y, p384_mod);
  30164. }
  30165. if ((err == MP_OKAY) && (!inMont)) {
  30166. err = sp_384_mod_mul_norm_15(addP->z, addP->z, p384_mod);
  30167. }
  30168. if (err == MP_OKAY) {
  30169. err = sp_384_ecc_mulmod_base_15(point, k, 0, 0, heap);
  30170. }
  30171. if (err == MP_OKAY) {
  30172. sp_384_proj_point_add_15(point, point, addP, tmp);
  30173. if (map) {
  30174. sp_384_map_15(point, point, tmp);
  30175. }
  30176. err = sp_384_point_to_ecc_point_15(point, r);
  30177. }
  30178. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  30179. if (k != NULL)
  30180. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  30181. if (point)
  30182. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  30183. #endif
  30184. return err;
  30185. }
  30186. #if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
  30187. defined(HAVE_ECC_VERIFY)
  30188. #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
  30189. /* Add 1 to a. (a = a + 1)
  30190. *
  30191. * r A single precision integer.
  30192. * a A single precision integer.
  30193. */
  30194. SP_NOINLINE static void sp_384_add_one_15(sp_digit* a)
  30195. {
  30196. a[0]++;
  30197. sp_384_norm_15(a);
  30198. }
  30199. /* Read big endian unsigned byte array into r.
  30200. *
  30201. * r A single precision integer.
  30202. * size Maximum number of bytes to convert
  30203. * a Byte array.
  30204. * n Number of bytes in array to read.
  30205. */
  30206. static void sp_384_from_bin(sp_digit* r, int size, const byte* a, int n)
  30207. {
  30208. int i;
  30209. int j = 0;
  30210. word32 s = 0;
  30211. r[0] = 0;
  30212. for (i = n-1; i >= 0; i--) {
  30213. r[j] |= (((sp_digit)a[i]) << s);
  30214. if (s >= 18U) {
  30215. r[j] &= 0x3ffffff;
  30216. s = 26U - s;
  30217. if (j + 1 >= size) {
  30218. break;
  30219. }
  30220. r[++j] = (sp_digit)a[i] >> s;
  30221. s = 8U - s;
  30222. }
  30223. else {
  30224. s += 8U;
  30225. }
  30226. }
  30227. for (j++; j < size; j++) {
  30228. r[j] = 0;
  30229. }
  30230. }
  30231. /* Generates a scalar that is in the range 1..order-1.
  30232. *
  30233. * rng Random number generator.
  30234. * k Scalar value.
  30235. * returns RNG failures, MEMORY_E when memory allocation fails and
  30236. * MP_OKAY on success.
  30237. */
  30238. static int sp_384_ecc_gen_k_15(WC_RNG* rng, sp_digit* k)
  30239. {
  30240. int err;
  30241. byte buf[48];
  30242. do {
  30243. err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf));
  30244. if (err == 0) {
  30245. sp_384_from_bin(k, 15, buf, (int)sizeof(buf));
  30246. if (sp_384_cmp_15(k, p384_order2) <= 0) {
  30247. sp_384_add_one_15(k);
  30248. break;
  30249. }
  30250. }
  30251. }
  30252. while (err == 0);
  30253. return err;
  30254. }
  30255. /* Makes a random EC key pair.
  30256. *
  30257. * rng Random number generator.
  30258. * priv Generated private value.
  30259. * pub Generated public point.
  30260. * heap Heap to use for allocation.
  30261. * returns ECC_INF_E when the point does not have the correct order, RNG
  30262. * failures, MEMORY_E when memory allocation fails and MP_OKAY on success.
  30263. */
  30264. int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap)
  30265. {
  30266. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  30267. sp_point_384* point = NULL;
  30268. sp_digit* k = NULL;
  30269. #else
  30270. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  30271. sp_point_384 point[2];
  30272. #else
  30273. sp_point_384 point[1];
  30274. #endif
  30275. sp_digit k[15];
  30276. #endif
  30277. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  30278. sp_point_384* infinity = NULL;
  30279. #endif
  30280. int err = MP_OKAY;
  30281. (void)heap;
  30282. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  30283. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  30284. point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, DYNAMIC_TYPE_ECC);
  30285. #else
  30286. point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC);
  30287. #endif
  30288. if (point == NULL)
  30289. err = MEMORY_E;
  30290. if (err == MP_OKAY) {
  30291. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15, heap,
  30292. DYNAMIC_TYPE_ECC);
  30293. if (k == NULL)
  30294. err = MEMORY_E;
  30295. }
  30296. #endif
  30297. if (err == MP_OKAY) {
  30298. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  30299. infinity = point + 1;
  30300. #endif
  30301. err = sp_384_ecc_gen_k_15(rng, k);
  30302. }
  30303. if (err == MP_OKAY) {
  30304. err = sp_384_ecc_mulmod_base_15(point, k, 1, 1, NULL);
  30305. }
  30306. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  30307. if (err == MP_OKAY) {
  30308. err = sp_384_ecc_mulmod_15(infinity, point, p384_order, 1, 1, NULL);
  30309. }
  30310. if (err == MP_OKAY) {
  30311. if (sp_384_iszero_15(point->x) || sp_384_iszero_15(point->y)) {
  30312. err = ECC_INF_E;
  30313. }
  30314. }
  30315. #endif
  30316. if (err == MP_OKAY) {
  30317. err = sp_384_to_mp(k, priv);
  30318. }
  30319. if (err == MP_OKAY) {
  30320. err = sp_384_point_to_ecc_point_15(point, pub);
  30321. }
  30322. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  30323. if (k != NULL)
  30324. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  30325. if (point != NULL) {
  30326. /* point is not sensitive, so no need to zeroize */
  30327. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  30328. }
  30329. #endif
  30330. return err;
  30331. }
  30332. #ifdef HAVE_ECC_DHE
  30333. /* Write r as big endian to byte array.
  30334. * Fixed length number of bytes written: 48
  30335. *
  30336. * r A single precision integer.
  30337. * a Byte array.
  30338. */
  30339. static void sp_384_to_bin_15(sp_digit* r, byte* a)
  30340. {
  30341. int i;
  30342. int j;
  30343. int s = 0;
  30344. int b;
  30345. for (i=0; i<14; i++) {
  30346. r[i+1] += r[i] >> 26;
  30347. r[i] &= 0x3ffffff;
  30348. }
  30349. j = 391 / 8 - 1;
  30350. a[j] = 0;
  30351. for (i=0; i<15 && j>=0; i++) {
  30352. b = 0;
  30353. /* lint allow cast of mismatch sp_digit and int */
  30354. a[j--] |= (byte)(r[i] << s); /*lint !e9033*/
  30355. b += 8 - s;
  30356. if (j < 0) {
  30357. break;
  30358. }
  30359. while (b < 26) {
  30360. a[j--] = (byte)(r[i] >> b);
  30361. b += 8;
  30362. if (j < 0) {
  30363. break;
  30364. }
  30365. }
  30366. s = 8 - (b - 26);
  30367. if (j >= 0) {
  30368. a[j] = 0;
  30369. }
  30370. if (s != 0) {
  30371. j++;
  30372. }
  30373. }
  30374. }
  30375. /* Multiply the point by the scalar and serialize the X ordinate.
  30376. * The number is 0 padded to maximum size on output.
  30377. *
  30378. * priv Scalar to multiply the point by.
  30379. * pub Point to multiply.
  30380. * out Buffer to hold X ordinate.
  30381. * outLen On entry, size of the buffer in bytes.
  30382. * On exit, length of data in buffer in bytes.
  30383. * heap Heap to use for allocation.
  30384. * returns BUFFER_E if the buffer is to small for output size,
  30385. * MEMORY_E when memory allocation fails and MP_OKAY on success.
  30386. */
  30387. int sp_ecc_secret_gen_384(const mp_int* priv, const ecc_point* pub, byte* out,
  30388. word32* outLen, void* heap)
  30389. {
  30390. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  30391. sp_point_384* point = NULL;
  30392. sp_digit* k = NULL;
  30393. #else
  30394. sp_point_384 point[1];
  30395. sp_digit k[15];
  30396. #endif
  30397. int err = MP_OKAY;
  30398. if (*outLen < 48U) {
  30399. err = BUFFER_E;
  30400. }
  30401. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  30402. if (err == MP_OKAY) {
  30403. point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap,
  30404. DYNAMIC_TYPE_ECC);
  30405. if (point == NULL)
  30406. err = MEMORY_E;
  30407. }
  30408. if (err == MP_OKAY) {
  30409. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15, heap,
  30410. DYNAMIC_TYPE_ECC);
  30411. if (k == NULL)
  30412. err = MEMORY_E;
  30413. }
  30414. #endif
  30415. if (err == MP_OKAY) {
  30416. sp_384_from_mp(k, 15, priv);
  30417. sp_384_point_from_ecc_point_15(point, pub);
  30418. err = sp_384_ecc_mulmod_15(point, point, k, 1, 1, heap);
  30419. }
  30420. if (err == MP_OKAY) {
  30421. sp_384_to_bin_15(point->x, out);
  30422. *outLen = 48;
  30423. }
  30424. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  30425. if (k != NULL)
  30426. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  30427. if (point != NULL)
  30428. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  30429. #endif
  30430. return err;
  30431. }
  30432. #endif /* HAVE_ECC_DHE */
  30433. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  30434. #endif
  30435. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  30436. SP_NOINLINE static void sp_384_rshift_15(sp_digit* r, const sp_digit* a,
  30437. byte n)
  30438. {
  30439. int i;
  30440. #ifdef WOLFSSL_SP_SMALL
  30441. for (i=0; i<14; i++) {
  30442. r[i] = ((a[i] >> n) | (a[i + 1] << (26 - n))) & 0x3ffffff;
  30443. }
  30444. #else
  30445. for (i=0; i<8; i += 8) {
  30446. r[i+0] = (a[i+0] >> n) | ((a[i+1] << (26 - n)) & 0x3ffffff);
  30447. r[i+1] = (a[i+1] >> n) | ((a[i+2] << (26 - n)) & 0x3ffffff);
  30448. r[i+2] = (a[i+2] >> n) | ((a[i+3] << (26 - n)) & 0x3ffffff);
  30449. r[i+3] = (a[i+3] >> n) | ((a[i+4] << (26 - n)) & 0x3ffffff);
  30450. r[i+4] = (a[i+4] >> n) | ((a[i+5] << (26 - n)) & 0x3ffffff);
  30451. r[i+5] = (a[i+5] >> n) | ((a[i+6] << (26 - n)) & 0x3ffffff);
  30452. r[i+6] = (a[i+6] >> n) | ((a[i+7] << (26 - n)) & 0x3ffffff);
  30453. r[i+7] = (a[i+7] >> n) | ((a[i+8] << (26 - n)) & 0x3ffffff);
  30454. }
  30455. r[8] = (a[8] >> n) | ((a[9] << (26 - n)) & 0x3ffffff);
  30456. r[9] = (a[9] >> n) | ((a[10] << (26 - n)) & 0x3ffffff);
  30457. r[10] = (a[10] >> n) | ((a[11] << (26 - n)) & 0x3ffffff);
  30458. r[11] = (a[11] >> n) | ((a[12] << (26 - n)) & 0x3ffffff);
  30459. r[12] = (a[12] >> n) | ((a[13] << (26 - n)) & 0x3ffffff);
  30460. r[13] = (a[13] >> n) | ((a[14] << (26 - n)) & 0x3ffffff);
  30461. #endif /* WOLFSSL_SP_SMALL */
  30462. r[14] = a[14] >> n;
  30463. }
  30464. /* Multiply a by scalar b into r. (r = a * b)
  30465. *
  30466. * r A single precision integer.
  30467. * a A single precision integer.
  30468. * b A scalar.
  30469. */
  30470. SP_NOINLINE static void sp_384_mul_d_15(sp_digit* r, const sp_digit* a,
  30471. sp_digit b)
  30472. {
  30473. #ifdef WOLFSSL_SP_SMALL
  30474. sp_int64 tb = b;
  30475. sp_int64 t = 0;
  30476. int i;
  30477. for (i = 0; i < 15; i++) {
  30478. t += tb * a[i];
  30479. r[i] = (sp_digit)(t & 0x3ffffff);
  30480. t >>= 26;
  30481. }
  30482. r[15] = (sp_digit)t;
  30483. #else
  30484. sp_int64 tb = b;
  30485. sp_int64 t[15];
  30486. t[ 0] = tb * a[ 0];
  30487. t[ 1] = tb * a[ 1];
  30488. t[ 2] = tb * a[ 2];
  30489. t[ 3] = tb * a[ 3];
  30490. t[ 4] = tb * a[ 4];
  30491. t[ 5] = tb * a[ 5];
  30492. t[ 6] = tb * a[ 6];
  30493. t[ 7] = tb * a[ 7];
  30494. t[ 8] = tb * a[ 8];
  30495. t[ 9] = tb * a[ 9];
  30496. t[10] = tb * a[10];
  30497. t[11] = tb * a[11];
  30498. t[12] = tb * a[12];
  30499. t[13] = tb * a[13];
  30500. t[14] = tb * a[14];
  30501. r[ 0] = (sp_digit) (t[ 0] & 0x3ffffff);
  30502. r[ 1] = (sp_digit)((t[ 0] >> 26) + (t[ 1] & 0x3ffffff));
  30503. r[ 2] = (sp_digit)((t[ 1] >> 26) + (t[ 2] & 0x3ffffff));
  30504. r[ 3] = (sp_digit)((t[ 2] >> 26) + (t[ 3] & 0x3ffffff));
  30505. r[ 4] = (sp_digit)((t[ 3] >> 26) + (t[ 4] & 0x3ffffff));
  30506. r[ 5] = (sp_digit)((t[ 4] >> 26) + (t[ 5] & 0x3ffffff));
  30507. r[ 6] = (sp_digit)((t[ 5] >> 26) + (t[ 6] & 0x3ffffff));
  30508. r[ 7] = (sp_digit)((t[ 6] >> 26) + (t[ 7] & 0x3ffffff));
  30509. r[ 8] = (sp_digit)((t[ 7] >> 26) + (t[ 8] & 0x3ffffff));
  30510. r[ 9] = (sp_digit)((t[ 8] >> 26) + (t[ 9] & 0x3ffffff));
  30511. r[10] = (sp_digit)((t[ 9] >> 26) + (t[10] & 0x3ffffff));
  30512. r[11] = (sp_digit)((t[10] >> 26) + (t[11] & 0x3ffffff));
  30513. r[12] = (sp_digit)((t[11] >> 26) + (t[12] & 0x3ffffff));
  30514. r[13] = (sp_digit)((t[12] >> 26) + (t[13] & 0x3ffffff));
  30515. r[14] = (sp_digit)((t[13] >> 26) + (t[14] & 0x3ffffff));
  30516. r[15] = (sp_digit) (t[14] >> 26);
  30517. #endif /* WOLFSSL_SP_SMALL */
  30518. }
  30519. SP_NOINLINE static void sp_384_lshift_30(sp_digit* r, const sp_digit* a,
  30520. byte n)
  30521. {
  30522. #ifdef WOLFSSL_SP_SMALL
  30523. int i;
  30524. r[30] = a[29] >> (26 - n);
  30525. for (i=29; i>0; i--) {
  30526. r[i] = ((a[i] << n) | (a[i-1] >> (26 - n))) & 0x3ffffff;
  30527. }
  30528. #else
  30529. sp_int_digit s;
  30530. sp_int_digit t;
  30531. s = (sp_int_digit)a[29];
  30532. r[30] = s >> (26U - n);
  30533. s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]);
  30534. r[29] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30535. s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]);
  30536. r[28] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30537. s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]);
  30538. r[27] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30539. s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]);
  30540. r[26] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30541. s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]);
  30542. r[25] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30543. s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]);
  30544. r[24] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30545. s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]);
  30546. r[23] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30547. s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]);
  30548. r[22] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30549. s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]);
  30550. r[21] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30551. s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]);
  30552. r[20] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30553. s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]);
  30554. r[19] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30555. s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]);
  30556. r[18] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30557. s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]);
  30558. r[17] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30559. s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]);
  30560. r[16] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30561. s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]);
  30562. r[15] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30563. s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]);
  30564. r[14] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30565. s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]);
  30566. r[13] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30567. s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]);
  30568. r[12] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30569. s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]);
  30570. r[11] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30571. s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]);
  30572. r[10] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30573. s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]);
  30574. r[9] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30575. s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]);
  30576. r[8] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30577. s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]);
  30578. r[7] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30579. s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]);
  30580. r[6] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30581. s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]);
  30582. r[5] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30583. s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]);
  30584. r[4] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30585. s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]);
  30586. r[3] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30587. s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]);
  30588. r[2] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30589. s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]);
  30590. r[1] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
  30591. #endif /* WOLFSSL_SP_SMALL */
  30592. r[0] = (a[0] << n) & 0x3ffffff;
  30593. }
  30594. /* Divide d in a and put remainder into r (m*d + r = a)
  30595. * m is not calculated as it is not needed at this time.
  30596. *
  30597. * Simplified based on top word of divisor being (1 << 26) - 1
  30598. *
  30599. * a Number to be divided.
  30600. * d Number to divide with.
  30601. * m Multiplier result.
  30602. * r Remainder from the division.
  30603. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  30604. */
  30605. static int sp_384_div_15(const sp_digit* a, const sp_digit* d,
  30606. const sp_digit* m, sp_digit* r)
  30607. {
  30608. int i;
  30609. sp_digit r1;
  30610. sp_digit mask;
  30611. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  30612. sp_digit* t1 = NULL;
  30613. #else
  30614. sp_digit t1[4 * 15 + 3];
  30615. #endif
  30616. sp_digit* t2 = NULL;
  30617. sp_digit* sd = NULL;
  30618. int err = MP_OKAY;
  30619. (void)m;
  30620. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  30621. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 15 + 3), NULL,
  30622. DYNAMIC_TYPE_TMP_BUFFER);
  30623. if (t1 == NULL)
  30624. err = MEMORY_E;
  30625. #endif
  30626. (void)m;
  30627. if (err == MP_OKAY) {
  30628. t2 = t1 + 30 + 1;
  30629. sd = t2 + 15 + 1;
  30630. sp_384_mul_d_15(sd, d, (sp_digit)1 << 6);
  30631. sp_384_lshift_30(t1, a, 6);
  30632. t1[15 + 15] += t1[15 + 15 - 1] >> 26;
  30633. t1[15 + 15 - 1] &= 0x3ffffff;
  30634. for (i=14; i>=0; i--) {
  30635. r1 = t1[15 + i];
  30636. sp_384_mul_d_15(t2, sd, r1);
  30637. (void)sp_384_sub_15(&t1[i], &t1[i], t2);
  30638. t1[15 + i] -= t2[15];
  30639. sp_384_norm_15(&t1[i + 1]);
  30640. mask = ~((t1[15 + i] - 1) >> 31);
  30641. sp_384_cond_sub_15(t1 + i, t1 + i, sd, mask);
  30642. sp_384_norm_15(&t1[i + 1]);
  30643. }
  30644. sp_384_norm_15(t1);
  30645. sp_384_rshift_15(r, t1, 6);
  30646. }
  30647. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  30648. if (t1 != NULL)
  30649. XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  30650. #endif
  30651. return err;
  30652. }
  30653. /* Reduce a modulo m into r. (r = a mod m)
  30654. *
  30655. * r A single precision number that is the reduced result.
  30656. * a A single precision number that is to be reduced.
  30657. * m A single precision number that is the modulus to reduce with.
  30658. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  30659. */
  30660. static int sp_384_mod_15(sp_digit* r, const sp_digit* a, const sp_digit* m)
  30661. {
  30662. return sp_384_div_15(a, m, NULL, r);
  30663. }
  30664. #endif
  30665. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  30666. /* Multiply two number mod the order of P384 curve. (r = a * b mod order)
  30667. *
  30668. * r Result of the multiplication.
  30669. * a First operand of the multiplication.
  30670. * b Second operand of the multiplication.
  30671. */
  30672. static void sp_384_mont_mul_order_15(sp_digit* r, const sp_digit* a, const sp_digit* b)
  30673. {
  30674. sp_384_mul_15(r, a, b);
  30675. sp_384_mont_reduce_order_15(r, p384_order, p384_mp_order);
  30676. }
  30677. #if defined(HAVE_ECC_SIGN) || (defined(HAVE_ECC_VERIFY) && defined(WOLFSSL_SP_SMALL))
  30678. #ifdef WOLFSSL_SP_SMALL
  30679. /* Order-2 for the P384 curve. */
  30680. static const uint32_t p384_order_minus_2[12] = {
  30681. 0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U,
  30682. 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU
  30683. };
  30684. #else
  30685. /* The low half of the order-2 of the P384 curve. */
  30686. static const uint32_t p384_order_low[6] = {
  30687. 0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U
  30688. };
  30689. #endif /* WOLFSSL_SP_SMALL */
  30690. /* Square number mod the order of P384 curve. (r = a * a mod order)
  30691. *
  30692. * r Result of the squaring.
  30693. * a Number to square.
  30694. */
  30695. static void sp_384_mont_sqr_order_15(sp_digit* r, const sp_digit* a)
  30696. {
  30697. sp_384_sqr_15(r, a);
  30698. sp_384_mont_reduce_order_15(r, p384_order, p384_mp_order);
  30699. }
  30700. #ifndef WOLFSSL_SP_SMALL
  30701. /* Square number mod the order of P384 curve a number of times.
  30702. * (r = a ^ n mod order)
  30703. *
  30704. * r Result of the squaring.
  30705. * a Number to square.
  30706. */
  30707. static void sp_384_mont_sqr_n_order_15(sp_digit* r, const sp_digit* a, int n)
  30708. {
  30709. int i;
  30710. sp_384_mont_sqr_order_15(r, a);
  30711. for (i=1; i<n; i++) {
  30712. sp_384_mont_sqr_order_15(r, r);
  30713. }
  30714. }
  30715. #endif /* !WOLFSSL_SP_SMALL */
  30716. /* Invert the number, in Montgomery form, modulo the order of the P384 curve.
  30717. * (r = 1 / a mod order)
  30718. *
  30719. * r Inverse result.
  30720. * a Number to invert.
  30721. * td Temporary data.
  30722. */
  30723. #ifdef WOLFSSL_SP_NONBLOCK
  30724. typedef struct sp_384_mont_inv_order_15_ctx {
  30725. int state;
  30726. int i;
  30727. } sp_384_mont_inv_order_15_ctx;
  30728. static int sp_384_mont_inv_order_15_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a,
  30729. sp_digit* t)
  30730. {
  30731. int err = FP_WOULDBLOCK;
  30732. sp_384_mont_inv_order_15_ctx* ctx = (sp_384_mont_inv_order_15_ctx*)sp_ctx;
  30733. typedef char ctx_size_test[sizeof(sp_384_mont_inv_order_15_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  30734. (void)sizeof(ctx_size_test);
  30735. switch (ctx->state) {
  30736. case 0:
  30737. XMEMCPY(t, a, sizeof(sp_digit) * 15);
  30738. ctx->i = 382;
  30739. ctx->state = 1;
  30740. break;
  30741. case 1:
  30742. sp_384_mont_sqr_order_15(t, t);
  30743. ctx->state = 2;
  30744. break;
  30745. case 2:
  30746. if ((p384_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) {
  30747. sp_384_mont_mul_order_15(t, t, a);
  30748. }
  30749. ctx->i--;
  30750. ctx->state = (ctx->i == 0) ? 3 : 1;
  30751. break;
  30752. case 3:
  30753. XMEMCPY(r, t, sizeof(sp_digit) * 15U);
  30754. err = MP_OKAY;
  30755. break;
  30756. }
  30757. return err;
  30758. }
  30759. #endif /* WOLFSSL_SP_NONBLOCK */
  30760. static void sp_384_mont_inv_order_15(sp_digit* r, const sp_digit* a,
  30761. sp_digit* td)
  30762. {
  30763. #ifdef WOLFSSL_SP_SMALL
  30764. sp_digit* t = td;
  30765. int i;
  30766. XMEMCPY(t, a, sizeof(sp_digit) * 15);
  30767. for (i=382; i>=0; i--) {
  30768. sp_384_mont_sqr_order_15(t, t);
  30769. if ((p384_order_minus_2[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
  30770. sp_384_mont_mul_order_15(t, t, a);
  30771. }
  30772. }
  30773. XMEMCPY(r, t, sizeof(sp_digit) * 15U);
  30774. #else
  30775. sp_digit* t = td;
  30776. sp_digit* t2 = td + 2 * 15;
  30777. sp_digit* t3 = td + 4 * 15;
  30778. int i;
  30779. /* t = a^2 */
  30780. sp_384_mont_sqr_order_15(t, a);
  30781. /* t = a^3 = t * a */
  30782. sp_384_mont_mul_order_15(t, t, a);
  30783. /* t2= a^c = t ^ 2 ^ 2 */
  30784. sp_384_mont_sqr_n_order_15(t2, t, 2);
  30785. /* t = a^f = t2 * t */
  30786. sp_384_mont_mul_order_15(t, t2, t);
  30787. /* t2= a^f0 = t ^ 2 ^ 4 */
  30788. sp_384_mont_sqr_n_order_15(t2, t, 4);
  30789. /* t = a^ff = t2 * t */
  30790. sp_384_mont_mul_order_15(t, t2, t);
  30791. /* t2= a^ff00 = t ^ 2 ^ 8 */
  30792. sp_384_mont_sqr_n_order_15(t2, t, 8);
  30793. /* t3= a^ffff = t2 * t */
  30794. sp_384_mont_mul_order_15(t3, t2, t);
  30795. /* t2= a^ffff0000 = t3 ^ 2 ^ 16 */
  30796. sp_384_mont_sqr_n_order_15(t2, t3, 16);
  30797. /* t = a^ffffffff = t2 * t3 */
  30798. sp_384_mont_mul_order_15(t, t2, t3);
  30799. /* t2= a^ffffffff0000 = t ^ 2 ^ 16 */
  30800. sp_384_mont_sqr_n_order_15(t2, t, 16);
  30801. /* t = a^ffffffffffff = t2 * t3 */
  30802. sp_384_mont_mul_order_15(t, t2, t3);
  30803. /* t2= a^ffffffffffff000000000000 = t ^ 2 ^ 48 */
  30804. sp_384_mont_sqr_n_order_15(t2, t, 48);
  30805. /* t= a^fffffffffffffffffffffffff = t2 * t */
  30806. sp_384_mont_mul_order_15(t, t2, t);
  30807. /* t2= a^ffffffffffffffffffffffff000000000000000000000000 */
  30808. sp_384_mont_sqr_n_order_15(t2, t, 96);
  30809. /* t2= a^ffffffffffffffffffffffffffffffffffffffffffffffff = t2 * t */
  30810. sp_384_mont_mul_order_15(t2, t2, t);
  30811. for (i=191; i>=1; i--) {
  30812. sp_384_mont_sqr_order_15(t2, t2);
  30813. if ((p384_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
  30814. sp_384_mont_mul_order_15(t2, t2, a);
  30815. }
  30816. }
  30817. sp_384_mont_sqr_order_15(t2, t2);
  30818. sp_384_mont_mul_order_15(r, t2, a);
  30819. #endif /* WOLFSSL_SP_SMALL */
  30820. }
  30821. #endif /* HAVE_ECC_SIGN || (HAVE_ECC_VERIFY && WOLFSSL_SP_SMALL) */
  30822. #endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
  30823. #ifdef HAVE_ECC_SIGN
  30824. #ifndef SP_ECC_MAX_SIG_GEN
  30825. #define SP_ECC_MAX_SIG_GEN 64
  30826. #endif
  30827. /* Calculate second signature value S from R, k and private value.
  30828. *
  30829. * s = (r * x + e) / k
  30830. *
  30831. * s Signature value.
  30832. * r First signature value.
  30833. * k Ephemeral private key.
  30834. * x Private key as a number.
  30835. * e Hash of message as a number.
  30836. * tmp Temporary storage for intermediate numbers.
  30837. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  30838. */
  30839. static int sp_384_calc_s_15(sp_digit* s, const sp_digit* r, sp_digit* k,
  30840. sp_digit* x, const sp_digit* e, sp_digit* tmp)
  30841. {
  30842. int err;
  30843. sp_digit carry;
  30844. sp_int32 c;
  30845. sp_digit* kInv = k;
  30846. /* Conv k to Montgomery form (mod order) */
  30847. sp_384_mul_15(k, k, p384_norm_order);
  30848. err = sp_384_mod_15(k, k, p384_order);
  30849. if (err == MP_OKAY) {
  30850. sp_384_norm_15(k);
  30851. /* kInv = 1/k mod order */
  30852. sp_384_mont_inv_order_15(kInv, k, tmp);
  30853. sp_384_norm_15(kInv);
  30854. /* s = r * x + e */
  30855. sp_384_mul_15(x, x, r);
  30856. err = sp_384_mod_15(x, x, p384_order);
  30857. }
  30858. if (err == MP_OKAY) {
  30859. sp_384_norm_15(x);
  30860. carry = sp_384_add_15(s, e, x);
  30861. sp_384_cond_sub_15(s, s, p384_order, 0 - carry);
  30862. sp_384_norm_15(s);
  30863. c = sp_384_cmp_15(s, p384_order);
  30864. sp_384_cond_sub_15(s, s, p384_order,
  30865. (sp_digit)0 - (sp_digit)(c >= 0));
  30866. sp_384_norm_15(s);
  30867. /* s = s * k^-1 mod order */
  30868. sp_384_mont_mul_order_15(s, s, kInv);
  30869. sp_384_norm_15(s);
  30870. }
  30871. return err;
  30872. }
  30873. /* Sign the hash using the private key.
  30874. * e = [hash, 384 bits] from binary
  30875. * r = (k.G)->x mod order
  30876. * s = (r * x + e) / k mod order
  30877. * The hash is truncated to the first 384 bits.
  30878. *
  30879. * hash Hash to sign.
  30880. * hashLen Length of the hash data.
  30881. * rng Random number generator.
  30882. * priv Private part of key - scalar.
  30883. * rm First part of result as an mp_int.
  30884. * sm Sirst part of result as an mp_int.
  30885. * heap Heap to use for allocation.
  30886. * returns RNG failures, MEMORY_E when memory allocation fails and
  30887. * MP_OKAY on success.
  30888. */
  30889. #ifdef WOLFSSL_SP_NONBLOCK
  30890. typedef struct sp_ecc_sign_384_ctx {
  30891. int state;
  30892. union {
  30893. sp_384_ecc_mulmod_15_ctx mulmod_ctx;
  30894. sp_384_mont_inv_order_15_ctx mont_inv_order_ctx;
  30895. };
  30896. sp_digit e[2*15];
  30897. sp_digit x[2*15];
  30898. sp_digit k[2*15];
  30899. sp_digit r[2*15];
  30900. sp_digit tmp[3 * 2*15];
  30901. sp_point_384 point;
  30902. sp_digit* s;
  30903. sp_digit* kInv;
  30904. int i;
  30905. } sp_ecc_sign_384_ctx;
  30906. int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng,
  30907. mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
  30908. {
  30909. int err = FP_WOULDBLOCK;
  30910. sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data;
  30911. typedef char ctx_size_test[sizeof(sp_ecc_sign_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  30912. (void)sizeof(ctx_size_test);
  30913. (void)heap;
  30914. switch (ctx->state) {
  30915. case 0: /* INIT */
  30916. ctx->s = ctx->e;
  30917. ctx->kInv = ctx->k;
  30918. ctx->i = SP_ECC_MAX_SIG_GEN;
  30919. ctx->state = 1;
  30920. break;
  30921. case 1: /* GEN */
  30922. /* New random point. */
  30923. if (km == NULL || mp_iszero(km)) {
  30924. err = sp_384_ecc_gen_k_15(rng, ctx->k);
  30925. }
  30926. else {
  30927. sp_384_from_mp(ctx->k, 15, km);
  30928. mp_zero(km);
  30929. }
  30930. XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
  30931. ctx->state = 2;
  30932. break;
  30933. case 2: /* MULMOD */
  30934. err = sp_384_ecc_mulmod_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
  30935. &ctx->point, &p384_base, ctx->k, 1, 1, heap);
  30936. if (err == MP_OKAY) {
  30937. ctx->state = 3;
  30938. }
  30939. break;
  30940. case 3: /* MODORDER */
  30941. {
  30942. sp_int32 c;
  30943. /* r = point->x mod order */
  30944. XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 15U);
  30945. sp_384_norm_15(ctx->r);
  30946. c = sp_384_cmp_15(ctx->r, p384_order);
  30947. sp_384_cond_sub_15(ctx->r, ctx->r, p384_order,
  30948. (sp_digit)0 - (sp_digit)(c >= 0));
  30949. sp_384_norm_15(ctx->r);
  30950. if (hashLen > 48U) {
  30951. hashLen = 48U;
  30952. }
  30953. sp_384_from_mp(ctx->x, 15, priv);
  30954. sp_384_from_bin(ctx->e, 15, hash, (int)hashLen);
  30955. ctx->state = 4;
  30956. break;
  30957. }
  30958. case 4: /* KMODORDER */
  30959. /* Conv k to Montgomery form (mod order) */
  30960. sp_384_mul_15(ctx->k, ctx->k, p384_norm_order);
  30961. err = sp_384_mod_15(ctx->k, ctx->k, p384_order);
  30962. if (err == MP_OKAY) {
  30963. sp_384_norm_15(ctx->k);
  30964. XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
  30965. ctx->state = 5;
  30966. }
  30967. break;
  30968. case 5: /* KINV */
  30969. /* kInv = 1/k mod order */
  30970. err = sp_384_mont_inv_order_15_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp);
  30971. if (err == MP_OKAY) {
  30972. XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
  30973. ctx->state = 6;
  30974. }
  30975. break;
  30976. case 6: /* KINVNORM */
  30977. sp_384_norm_15(ctx->kInv);
  30978. ctx->state = 7;
  30979. break;
  30980. case 7: /* R */
  30981. /* s = r * x + e */
  30982. sp_384_mul_15(ctx->x, ctx->x, ctx->r);
  30983. ctx->state = 8;
  30984. break;
  30985. case 8: /* S1 */
  30986. err = sp_384_mod_15(ctx->x, ctx->x, p384_order);
  30987. if (err == MP_OKAY)
  30988. ctx->state = 9;
  30989. break;
  30990. case 9: /* S2 */
  30991. {
  30992. sp_digit carry;
  30993. sp_int32 c;
  30994. sp_384_norm_15(ctx->x);
  30995. carry = sp_384_add_15(ctx->s, ctx->e, ctx->x);
  30996. sp_384_cond_sub_15(ctx->s, ctx->s,
  30997. p384_order, 0 - carry);
  30998. sp_384_norm_15(ctx->s);
  30999. c = sp_384_cmp_15(ctx->s, p384_order);
  31000. sp_384_cond_sub_15(ctx->s, ctx->s, p384_order,
  31001. (sp_digit)0 - (sp_digit)(c >= 0));
  31002. sp_384_norm_15(ctx->s);
  31003. /* s = s * k^-1 mod order */
  31004. sp_384_mont_mul_order_15(ctx->s, ctx->s, ctx->kInv);
  31005. sp_384_norm_15(ctx->s);
  31006. /* Check that signature is usable. */
  31007. if (sp_384_iszero_15(ctx->s) == 0) {
  31008. ctx->state = 10;
  31009. break;
  31010. }
  31011. #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
  31012. ctx->i = 1;
  31013. #endif
  31014. /* not usable gen, try again */
  31015. ctx->i--;
  31016. if (ctx->i == 0) {
  31017. err = RNG_FAILURE_E;
  31018. }
  31019. ctx->state = 1;
  31020. break;
  31021. }
  31022. case 10: /* RES */
  31023. err = sp_384_to_mp(ctx->r, rm);
  31024. if (err == MP_OKAY) {
  31025. err = sp_384_to_mp(ctx->s, sm);
  31026. }
  31027. break;
  31028. }
  31029. if (err == MP_OKAY && ctx->state != 10) {
  31030. err = FP_WOULDBLOCK;
  31031. }
  31032. if (err != FP_WOULDBLOCK) {
  31033. XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 15U);
  31034. XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 15U);
  31035. XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 15U);
  31036. XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 15U);
  31037. XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 15U);
  31038. }
  31039. return err;
  31040. }
  31041. #endif /* WOLFSSL_SP_NONBLOCK */
  31042. int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng,
  31043. const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
  31044. {
  31045. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31046. sp_digit* e = NULL;
  31047. sp_point_384* point = NULL;
  31048. #else
  31049. sp_digit e[7 * 2 * 15];
  31050. sp_point_384 point[1];
  31051. #endif
  31052. sp_digit* x = NULL;
  31053. sp_digit* k = NULL;
  31054. sp_digit* r = NULL;
  31055. sp_digit* tmp = NULL;
  31056. sp_digit* s = NULL;
  31057. sp_int32 c;
  31058. int err = MP_OKAY;
  31059. int i;
  31060. (void)heap;
  31061. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31062. if (err == MP_OKAY) {
  31063. point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap,
  31064. DYNAMIC_TYPE_ECC);
  31065. if (point == NULL)
  31066. err = MEMORY_E;
  31067. }
  31068. if (err == MP_OKAY) {
  31069. e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 15, heap,
  31070. DYNAMIC_TYPE_ECC);
  31071. if (e == NULL)
  31072. err = MEMORY_E;
  31073. }
  31074. #endif
  31075. if (err == MP_OKAY) {
  31076. x = e + 2 * 15;
  31077. k = e + 4 * 15;
  31078. r = e + 6 * 15;
  31079. tmp = e + 8 * 15;
  31080. s = e;
  31081. if (hashLen > 48U) {
  31082. hashLen = 48U;
  31083. }
  31084. }
  31085. for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) {
  31086. /* New random point. */
  31087. if (km == NULL || mp_iszero(km)) {
  31088. err = sp_384_ecc_gen_k_15(rng, k);
  31089. }
  31090. else {
  31091. sp_384_from_mp(k, 15, km);
  31092. mp_zero(km);
  31093. }
  31094. if (err == MP_OKAY) {
  31095. err = sp_384_ecc_mulmod_base_15(point, k, 1, 1, heap);
  31096. }
  31097. if (err == MP_OKAY) {
  31098. /* r = point->x mod order */
  31099. XMEMCPY(r, point->x, sizeof(sp_digit) * 15U);
  31100. sp_384_norm_15(r);
  31101. c = sp_384_cmp_15(r, p384_order);
  31102. sp_384_cond_sub_15(r, r, p384_order,
  31103. (sp_digit)0 - (sp_digit)(c >= 0));
  31104. sp_384_norm_15(r);
  31105. sp_384_from_mp(x, 15, priv);
  31106. sp_384_from_bin(e, 15, hash, (int)hashLen);
  31107. err = sp_384_calc_s_15(s, r, k, x, e, tmp);
  31108. }
  31109. /* Check that signature is usable. */
  31110. if ((err == MP_OKAY) && (sp_384_iszero_15(s) == 0)) {
  31111. break;
  31112. }
  31113. #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
  31114. i = 1;
  31115. #endif
  31116. }
  31117. if (i == 0) {
  31118. err = RNG_FAILURE_E;
  31119. }
  31120. if (err == MP_OKAY) {
  31121. err = sp_384_to_mp(r, rm);
  31122. }
  31123. if (err == MP_OKAY) {
  31124. err = sp_384_to_mp(s, sm);
  31125. }
  31126. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31127. if (e != NULL)
  31128. #endif
  31129. {
  31130. ForceZero(e, sizeof(sp_digit) * 7 * 2 * 15);
  31131. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31132. XFREE(e, heap, DYNAMIC_TYPE_ECC);
  31133. #endif
  31134. }
  31135. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31136. if (point != NULL)
  31137. #endif
  31138. {
  31139. ForceZero(point, sizeof(sp_point_384));
  31140. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31141. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  31142. #endif
  31143. }
  31144. return err;
  31145. }
  31146. #endif /* HAVE_ECC_SIGN */
  31147. #ifndef WOLFSSL_SP_SMALL
  31148. static const char sp_384_tab32_15[32] = {
  31149. 1, 10, 2, 11, 14, 22, 3, 30,
  31150. 12, 15, 17, 19, 23, 26, 4, 31,
  31151. 9, 13, 21, 29, 16, 18, 25, 8,
  31152. 20, 28, 24, 7, 27, 6, 5, 32};
  31153. static int sp_384_num_bits_26_15(sp_digit v)
  31154. {
  31155. v |= v >> 1;
  31156. v |= v >> 2;
  31157. v |= v >> 4;
  31158. v |= v >> 8;
  31159. v |= v >> 16;
  31160. return sp_384_tab32_15[(uint32_t)(v*0x07C4ACDD) >> 27];
  31161. }
  31162. static int sp_384_num_bits_15(const sp_digit* a)
  31163. {
  31164. int i;
  31165. int r = 0;
  31166. for (i = 14; i >= 0; i--) {
  31167. if (a[i] != 0) {
  31168. r = sp_384_num_bits_26_15(a[i]);
  31169. r += i * 26;
  31170. break;
  31171. }
  31172. }
  31173. return r;
  31174. }
  31175. /* Non-constant time modular inversion.
  31176. *
  31177. * @param [out] r Resulting number.
  31178. * @param [in] a Number to invert.
  31179. * @param [in] m Modulus.
  31180. * @return MP_OKAY on success.
  31181. * @return MEMEORY_E when dynamic memory allocation fails.
  31182. */
  31183. static int sp_384_mod_inv_15(sp_digit* r, const sp_digit* a, const sp_digit* m)
  31184. {
  31185. int err = MP_OKAY;
  31186. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31187. sp_digit* u = NULL;
  31188. #else
  31189. sp_digit u[15 * 4];
  31190. #endif
  31191. sp_digit* v = NULL;
  31192. sp_digit* b = NULL;
  31193. sp_digit* d = NULL;
  31194. int ut;
  31195. int vt;
  31196. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31197. u = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15 * 4, NULL,
  31198. DYNAMIC_TYPE_ECC);
  31199. if (u == NULL)
  31200. err = MEMORY_E;
  31201. #endif
  31202. if (err == MP_OKAY) {
  31203. v = u + 15;
  31204. b = u + 2 * 15;
  31205. d = u + 3 * 15;
  31206. XMEMCPY(u, m, sizeof(sp_digit) * 15);
  31207. XMEMCPY(v, a, sizeof(sp_digit) * 15);
  31208. ut = sp_384_num_bits_15(u);
  31209. vt = sp_384_num_bits_15(v);
  31210. XMEMSET(b, 0, sizeof(sp_digit) * 15);
  31211. if ((v[0] & 1) == 0) {
  31212. sp_384_rshift1_15(v, v);
  31213. XMEMCPY(d, m, sizeof(sp_digit) * 15);
  31214. d[0]++;
  31215. sp_384_rshift1_15(d, d);
  31216. vt--;
  31217. while ((v[0] & 1) == 0) {
  31218. sp_384_rshift1_15(v, v);
  31219. if (d[0] & 1)
  31220. sp_384_add_15(d, d, m);
  31221. sp_384_rshift1_15(d, d);
  31222. vt--;
  31223. }
  31224. }
  31225. else {
  31226. XMEMSET(d+1, 0, sizeof(sp_digit) * (15 - 1));
  31227. d[0] = 1;
  31228. }
  31229. while (ut > 1 && vt > 1) {
  31230. if (ut > vt || (ut == vt &&
  31231. sp_384_cmp_15(u, v) >= 0)) {
  31232. sp_384_sub_15(u, u, v);
  31233. sp_384_norm_15(u);
  31234. sp_384_sub_15(b, b, d);
  31235. sp_384_norm_15(b);
  31236. if (b[14] < 0)
  31237. sp_384_add_15(b, b, m);
  31238. sp_384_norm_15(b);
  31239. ut = sp_384_num_bits_15(u);
  31240. do {
  31241. sp_384_rshift1_15(u, u);
  31242. if (b[0] & 1)
  31243. sp_384_add_15(b, b, m);
  31244. sp_384_rshift1_15(b, b);
  31245. ut--;
  31246. }
  31247. while (ut > 0 && (u[0] & 1) == 0);
  31248. }
  31249. else {
  31250. sp_384_sub_15(v, v, u);
  31251. sp_384_norm_15(v);
  31252. sp_384_sub_15(d, d, b);
  31253. sp_384_norm_15(d);
  31254. if (d[14] < 0)
  31255. sp_384_add_15(d, d, m);
  31256. sp_384_norm_15(d);
  31257. vt = sp_384_num_bits_15(v);
  31258. do {
  31259. sp_384_rshift1_15(v, v);
  31260. if (d[0] & 1)
  31261. sp_384_add_15(d, d, m);
  31262. sp_384_rshift1_15(d, d);
  31263. vt--;
  31264. }
  31265. while (vt > 0 && (v[0] & 1) == 0);
  31266. }
  31267. }
  31268. if (ut == 1)
  31269. XMEMCPY(r, b, sizeof(sp_digit) * 15);
  31270. else
  31271. XMEMCPY(r, d, sizeof(sp_digit) * 15);
  31272. }
  31273. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31274. if (u != NULL)
  31275. XFREE(u, NULL, DYNAMIC_TYPE_ECC);
  31276. #endif
  31277. return err;
  31278. }
  31279. #endif /* WOLFSSL_SP_SMALL */
  31280. /* Add point p1 into point p2. Handles p1 == p2 and result at infinity.
  31281. *
  31282. * p1 First point to add and holds result.
  31283. * p2 Second point to add.
  31284. * tmp Temporary storage for intermediate numbers.
  31285. */
  31286. static void sp_384_add_points_15(sp_point_384* p1, const sp_point_384* p2,
  31287. sp_digit* tmp)
  31288. {
  31289. sp_384_proj_point_add_15(p1, p1, p2, tmp);
  31290. if (sp_384_iszero_15(p1->z)) {
  31291. if (sp_384_iszero_15(p1->x) && sp_384_iszero_15(p1->y)) {
  31292. sp_384_proj_point_dbl_15(p1, p2, tmp);
  31293. }
  31294. else {
  31295. /* Y ordinate is not used from here - don't set. */
  31296. p1->x[0] = 0;
  31297. p1->x[1] = 0;
  31298. p1->x[2] = 0;
  31299. p1->x[3] = 0;
  31300. p1->x[4] = 0;
  31301. p1->x[5] = 0;
  31302. p1->x[6] = 0;
  31303. p1->x[7] = 0;
  31304. p1->x[8] = 0;
  31305. p1->x[9] = 0;
  31306. p1->x[10] = 0;
  31307. p1->x[11] = 0;
  31308. p1->x[12] = 0;
  31309. p1->x[13] = 0;
  31310. p1->x[14] = 0;
  31311. XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod));
  31312. }
  31313. }
  31314. }
  31315. /* Calculate the verification point: [e/s]G + [r/s]Q
  31316. *
  31317. * p1 Calculated point.
  31318. * p2 Public point and temporary.
  31319. * s Second part of signature as a number.
  31320. * u1 Temporary number.
  31321. * u2 Temproray number.
  31322. * heap Heap to use for allocation.
  31323. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  31324. */
  31325. static int sp_384_calc_vfy_point_15(sp_point_384* p1, sp_point_384* p2,
  31326. sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap)
  31327. {
  31328. int err;
  31329. #ifndef WOLFSSL_SP_SMALL
  31330. err = sp_384_mod_inv_15(s, s, p384_order);
  31331. if (err == MP_OKAY)
  31332. #endif /* !WOLFSSL_SP_SMALL */
  31333. {
  31334. sp_384_mul_15(s, s, p384_norm_order);
  31335. err = sp_384_mod_15(s, s, p384_order);
  31336. }
  31337. if (err == MP_OKAY) {
  31338. sp_384_norm_15(s);
  31339. #ifdef WOLFSSL_SP_SMALL
  31340. {
  31341. sp_384_mont_inv_order_15(s, s, tmp);
  31342. sp_384_mont_mul_order_15(u1, u1, s);
  31343. sp_384_mont_mul_order_15(u2, u2, s);
  31344. }
  31345. #else
  31346. {
  31347. sp_384_mont_mul_order_15(u1, u1, s);
  31348. sp_384_mont_mul_order_15(u2, u2, s);
  31349. }
  31350. #endif /* WOLFSSL_SP_SMALL */
  31351. {
  31352. err = sp_384_ecc_mulmod_base_15(p1, u1, 0, 0, heap);
  31353. }
  31354. }
  31355. if ((err == MP_OKAY) && sp_384_iszero_15(p1->z)) {
  31356. p1->infinity = 1;
  31357. }
  31358. if (err == MP_OKAY) {
  31359. err = sp_384_ecc_mulmod_15(p2, p2, u2, 0, 0, heap);
  31360. }
  31361. if ((err == MP_OKAY) && sp_384_iszero_15(p2->z)) {
  31362. p2->infinity = 1;
  31363. }
  31364. if (err == MP_OKAY) {
  31365. sp_384_add_points_15(p1, p2, tmp);
  31366. }
  31367. return err;
  31368. }
  31369. #ifdef HAVE_ECC_VERIFY
  31370. /* Verify the signature values with the hash and public key.
  31371. * e = Truncate(hash, 384)
  31372. * u1 = e/s mod order
  31373. * u2 = r/s mod order
  31374. * r == (u1.G + u2.Q)->x mod order
  31375. * Optimization: Leave point in projective form.
  31376. * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z')
  31377. * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x'
  31378. * The hash is truncated to the first 384 bits.
  31379. *
  31380. * hash Hash to sign.
  31381. * hashLen Length of the hash data.
  31382. * rng Random number generator.
  31383. * priv Private part of key - scalar.
  31384. * rm First part of result as an mp_int.
  31385. * sm Sirst part of result as an mp_int.
  31386. * heap Heap to use for allocation.
  31387. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  31388. */
  31389. #ifdef WOLFSSL_SP_NONBLOCK
  31390. typedef struct sp_ecc_verify_384_ctx {
  31391. int state;
  31392. union {
  31393. sp_384_ecc_mulmod_15_ctx mulmod_ctx;
  31394. sp_384_mont_inv_order_15_ctx mont_inv_order_ctx;
  31395. sp_384_proj_point_dbl_15_ctx dbl_ctx;
  31396. sp_384_proj_point_add_15_ctx add_ctx;
  31397. };
  31398. sp_digit u1[2*15];
  31399. sp_digit u2[2*15];
  31400. sp_digit s[2*15];
  31401. sp_digit tmp[2*15 * 6];
  31402. sp_point_384 p1;
  31403. sp_point_384 p2;
  31404. } sp_ecc_verify_384_ctx;
  31405. int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash,
  31406. word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ,
  31407. const mp_int* rm, const mp_int* sm, int* res, void* heap)
  31408. {
  31409. int err = FP_WOULDBLOCK;
  31410. sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data;
  31411. typedef char ctx_size_test[sizeof(sp_ecc_verify_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  31412. (void)sizeof(ctx_size_test);
  31413. switch (ctx->state) {
  31414. case 0: /* INIT */
  31415. if (hashLen > 48U) {
  31416. hashLen = 48U;
  31417. }
  31418. sp_384_from_bin(ctx->u1, 15, hash, (int)hashLen);
  31419. sp_384_from_mp(ctx->u2, 15, rm);
  31420. sp_384_from_mp(ctx->s, 15, sm);
  31421. sp_384_from_mp(ctx->p2.x, 15, pX);
  31422. sp_384_from_mp(ctx->p2.y, 15, pY);
  31423. sp_384_from_mp(ctx->p2.z, 15, pZ);
  31424. ctx->state = 1;
  31425. break;
  31426. case 1: /* NORMS0 */
  31427. sp_384_mul_15(ctx->s, ctx->s, p384_norm_order);
  31428. err = sp_384_mod_15(ctx->s, ctx->s, p384_order);
  31429. if (err == MP_OKAY)
  31430. ctx->state = 2;
  31431. break;
  31432. case 2: /* NORMS1 */
  31433. sp_384_norm_15(ctx->s);
  31434. XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
  31435. ctx->state = 3;
  31436. break;
  31437. case 3: /* NORMS2 */
  31438. err = sp_384_mont_inv_order_15_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp);
  31439. if (err == MP_OKAY) {
  31440. ctx->state = 4;
  31441. }
  31442. break;
  31443. case 4: /* NORMS3 */
  31444. sp_384_mont_mul_order_15(ctx->u1, ctx->u1, ctx->s);
  31445. ctx->state = 5;
  31446. break;
  31447. case 5: /* NORMS4 */
  31448. sp_384_mont_mul_order_15(ctx->u2, ctx->u2, ctx->s);
  31449. XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
  31450. ctx->state = 6;
  31451. break;
  31452. case 6: /* MULBASE */
  31453. err = sp_384_ecc_mulmod_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p384_base, ctx->u1, 0, 0, heap);
  31454. if (err == MP_OKAY) {
  31455. if (sp_384_iszero_15(ctx->p1.z)) {
  31456. ctx->p1.infinity = 1;
  31457. }
  31458. XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
  31459. ctx->state = 7;
  31460. }
  31461. break;
  31462. case 7: /* MULMOD */
  31463. err = sp_384_ecc_mulmod_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, 0, heap);
  31464. if (err == MP_OKAY) {
  31465. if (sp_384_iszero_15(ctx->p2.z)) {
  31466. ctx->p2.infinity = 1;
  31467. }
  31468. XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx));
  31469. ctx->state = 8;
  31470. }
  31471. break;
  31472. case 8: /* ADD */
  31473. err = sp_384_proj_point_add_15_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp);
  31474. if (err == MP_OKAY)
  31475. ctx->state = 9;
  31476. break;
  31477. case 9: /* MONT */
  31478. /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
  31479. /* Reload r and convert to Montgomery form. */
  31480. sp_384_from_mp(ctx->u2, 15, rm);
  31481. err = sp_384_mod_mul_norm_15(ctx->u2, ctx->u2, p384_mod);
  31482. if (err == MP_OKAY)
  31483. ctx->state = 10;
  31484. break;
  31485. case 10: /* SQR */
  31486. /* u1 = r.z'.z' mod prime */
  31487. sp_384_mont_sqr_15(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod);
  31488. ctx->state = 11;
  31489. break;
  31490. case 11: /* MUL */
  31491. sp_384_mont_mul_15(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod);
  31492. ctx->state = 12;
  31493. break;
  31494. case 12: /* RES */
  31495. {
  31496. sp_int32 c = 0;
  31497. err = MP_OKAY; /* math okay, now check result */
  31498. *res = (int)(sp_384_cmp_15(ctx->p1.x, ctx->u1) == 0);
  31499. if (*res == 0) {
  31500. sp_digit carry;
  31501. /* Reload r and add order. */
  31502. sp_384_from_mp(ctx->u2, 15, rm);
  31503. carry = sp_384_add_15(ctx->u2, ctx->u2, p384_order);
  31504. /* Carry means result is greater than mod and is not valid. */
  31505. if (carry == 0) {
  31506. sp_384_norm_15(ctx->u2);
  31507. /* Compare with mod and if greater or equal then not valid. */
  31508. c = sp_384_cmp_15(ctx->u2, p384_mod);
  31509. }
  31510. }
  31511. if ((*res == 0) && (c < 0)) {
  31512. /* Convert to Montogomery form */
  31513. err = sp_384_mod_mul_norm_15(ctx->u2, ctx->u2, p384_mod);
  31514. if (err == MP_OKAY) {
  31515. /* u1 = (r + 1*order).z'.z' mod prime */
  31516. sp_384_mont_mul_15(ctx->u1, ctx->u2, ctx->p1.z, p384_mod,
  31517. p384_mp_mod);
  31518. *res = (int)(sp_384_cmp_15(ctx->p1.x, ctx->u1) == 0);
  31519. }
  31520. }
  31521. break;
  31522. }
  31523. } /* switch */
  31524. if (err == MP_OKAY && ctx->state != 12) {
  31525. err = FP_WOULDBLOCK;
  31526. }
  31527. return err;
  31528. }
  31529. #endif /* WOLFSSL_SP_NONBLOCK */
  31530. int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX,
  31531. const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm,
  31532. int* res, void* heap)
  31533. {
  31534. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31535. sp_digit* u1 = NULL;
  31536. sp_point_384* p1 = NULL;
  31537. #else
  31538. sp_digit u1[18 * 15];
  31539. sp_point_384 p1[2];
  31540. #endif
  31541. sp_digit* u2 = NULL;
  31542. sp_digit* s = NULL;
  31543. sp_digit* tmp = NULL;
  31544. sp_point_384* p2 = NULL;
  31545. sp_digit carry;
  31546. sp_int32 c = 0;
  31547. int err = MP_OKAY;
  31548. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31549. if (err == MP_OKAY) {
  31550. p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap,
  31551. DYNAMIC_TYPE_ECC);
  31552. if (p1 == NULL)
  31553. err = MEMORY_E;
  31554. }
  31555. if (err == MP_OKAY) {
  31556. u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 15, heap,
  31557. DYNAMIC_TYPE_ECC);
  31558. if (u1 == NULL)
  31559. err = MEMORY_E;
  31560. }
  31561. #endif
  31562. if (err == MP_OKAY) {
  31563. u2 = u1 + 2 * 15;
  31564. s = u1 + 4 * 15;
  31565. tmp = u1 + 6 * 15;
  31566. p2 = p1 + 1;
  31567. if (hashLen > 48U) {
  31568. hashLen = 48U;
  31569. }
  31570. sp_384_from_bin(u1, 15, hash, (int)hashLen);
  31571. sp_384_from_mp(u2, 15, rm);
  31572. sp_384_from_mp(s, 15, sm);
  31573. sp_384_from_mp(p2->x, 15, pX);
  31574. sp_384_from_mp(p2->y, 15, pY);
  31575. sp_384_from_mp(p2->z, 15, pZ);
  31576. err = sp_384_calc_vfy_point_15(p1, p2, s, u1, u2, tmp, heap);
  31577. }
  31578. if (err == MP_OKAY) {
  31579. /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
  31580. /* Reload r and convert to Montgomery form. */
  31581. sp_384_from_mp(u2, 15, rm);
  31582. err = sp_384_mod_mul_norm_15(u2, u2, p384_mod);
  31583. }
  31584. if (err == MP_OKAY) {
  31585. /* u1 = r.z'.z' mod prime */
  31586. sp_384_mont_sqr_15(p1->z, p1->z, p384_mod, p384_mp_mod);
  31587. sp_384_mont_mul_15(u1, u2, p1->z, p384_mod, p384_mp_mod);
  31588. *res = (int)(sp_384_cmp_15(p1->x, u1) == 0);
  31589. if (*res == 0) {
  31590. /* Reload r and add order. */
  31591. sp_384_from_mp(u2, 15, rm);
  31592. carry = sp_384_add_15(u2, u2, p384_order);
  31593. /* Carry means result is greater than mod and is not valid. */
  31594. if (carry == 0) {
  31595. sp_384_norm_15(u2);
  31596. /* Compare with mod and if greater or equal then not valid. */
  31597. c = sp_384_cmp_15(u2, p384_mod);
  31598. }
  31599. }
  31600. if ((*res == 0) && (c < 0)) {
  31601. /* Convert to Montogomery form */
  31602. err = sp_384_mod_mul_norm_15(u2, u2, p384_mod);
  31603. if (err == MP_OKAY) {
  31604. /* u1 = (r + 1*order).z'.z' mod prime */
  31605. {
  31606. sp_384_mont_mul_15(u1, u2, p1->z, p384_mod, p384_mp_mod);
  31607. }
  31608. *res = (sp_384_cmp_15(p1->x, u1) == 0);
  31609. }
  31610. }
  31611. }
  31612. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31613. if (u1 != NULL)
  31614. XFREE(u1, heap, DYNAMIC_TYPE_ECC);
  31615. if (p1 != NULL)
  31616. XFREE(p1, heap, DYNAMIC_TYPE_ECC);
  31617. #endif
  31618. return err;
  31619. }
  31620. #endif /* HAVE_ECC_VERIFY */
  31621. #ifdef HAVE_ECC_CHECK_KEY
  31622. /* Check that the x and y oridinates are a valid point on the curve.
  31623. *
  31624. * point EC point.
  31625. * heap Heap to use if dynamically allocating.
  31626. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  31627. * not on the curve and MP_OKAY otherwise.
  31628. */
  31629. static int sp_384_ecc_is_point_15(const sp_point_384* point,
  31630. void* heap)
  31631. {
  31632. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31633. sp_digit* t1 = NULL;
  31634. #else
  31635. sp_digit t1[15 * 4];
  31636. #endif
  31637. sp_digit* t2 = NULL;
  31638. int err = MP_OKAY;
  31639. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31640. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15 * 4, heap, DYNAMIC_TYPE_ECC);
  31641. if (t1 == NULL)
  31642. err = MEMORY_E;
  31643. #endif
  31644. (void)heap;
  31645. if (err == MP_OKAY) {
  31646. t2 = t1 + 2 * 15;
  31647. sp_384_sqr_15(t1, point->y);
  31648. (void)sp_384_mod_15(t1, t1, p384_mod);
  31649. sp_384_sqr_15(t2, point->x);
  31650. (void)sp_384_mod_15(t2, t2, p384_mod);
  31651. sp_384_mul_15(t2, t2, point->x);
  31652. (void)sp_384_mod_15(t2, t2, p384_mod);
  31653. (void)sp_384_sub_15(t2, p384_mod, t2);
  31654. sp_384_mont_add_15(t1, t1, t2, p384_mod);
  31655. sp_384_mont_add_15(t1, t1, point->x, p384_mod);
  31656. sp_384_mont_add_15(t1, t1, point->x, p384_mod);
  31657. sp_384_mont_add_15(t1, t1, point->x, p384_mod);
  31658. if (sp_384_cmp_15(t1, p384_b) != 0) {
  31659. err = MP_VAL;
  31660. }
  31661. }
  31662. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31663. if (t1 != NULL)
  31664. XFREE(t1, heap, DYNAMIC_TYPE_ECC);
  31665. #endif
  31666. return err;
  31667. }
  31668. /* Check that the x and y oridinates are a valid point on the curve.
  31669. *
  31670. * pX X ordinate of EC point.
  31671. * pY Y ordinate of EC point.
  31672. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  31673. * not on the curve and MP_OKAY otherwise.
  31674. */
  31675. int sp_ecc_is_point_384(const mp_int* pX, const mp_int* pY)
  31676. {
  31677. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31678. sp_point_384* pub = NULL;
  31679. #else
  31680. sp_point_384 pub[1];
  31681. #endif
  31682. const byte one[1] = { 1 };
  31683. int err = MP_OKAY;
  31684. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31685. pub = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL,
  31686. DYNAMIC_TYPE_ECC);
  31687. if (pub == NULL)
  31688. err = MEMORY_E;
  31689. #endif
  31690. if (err == MP_OKAY) {
  31691. sp_384_from_mp(pub->x, 15, pX);
  31692. sp_384_from_mp(pub->y, 15, pY);
  31693. sp_384_from_bin(pub->z, 15, one, (int)sizeof(one));
  31694. err = sp_384_ecc_is_point_15(pub, NULL);
  31695. }
  31696. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31697. if (pub != NULL)
  31698. XFREE(pub, NULL, DYNAMIC_TYPE_ECC);
  31699. #endif
  31700. return err;
  31701. }
  31702. /* Check that the private scalar generates the EC point (px, py), the point is
  31703. * on the curve and the point has the correct order.
  31704. *
  31705. * pX X ordinate of EC point.
  31706. * pY Y ordinate of EC point.
  31707. * privm Private scalar that generates EC point.
  31708. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  31709. * not on the curve, ECC_INF_E if the point does not have the correct order,
  31710. * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
  31711. * MP_OKAY otherwise.
  31712. */
  31713. int sp_ecc_check_key_384(const mp_int* pX, const mp_int* pY,
  31714. const mp_int* privm, void* heap)
  31715. {
  31716. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31717. sp_digit* priv = NULL;
  31718. sp_point_384* pub = NULL;
  31719. #else
  31720. sp_digit priv[15];
  31721. sp_point_384 pub[2];
  31722. #endif
  31723. sp_point_384* p = NULL;
  31724. const byte one[1] = { 1 };
  31725. int err = MP_OKAY;
  31726. /* Quick check the lengs of public key ordinates and private key are in
  31727. * range. Proper check later.
  31728. */
  31729. if (((mp_count_bits(pX) > 384) ||
  31730. (mp_count_bits(pY) > 384) ||
  31731. ((privm != NULL) && (mp_count_bits(privm) > 384)))) {
  31732. err = ECC_OUT_OF_RANGE_E;
  31733. }
  31734. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31735. if (err == MP_OKAY) {
  31736. pub = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap,
  31737. DYNAMIC_TYPE_ECC);
  31738. if (pub == NULL)
  31739. err = MEMORY_E;
  31740. }
  31741. if (err == MP_OKAY && privm) {
  31742. priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15, heap,
  31743. DYNAMIC_TYPE_ECC);
  31744. if (priv == NULL)
  31745. err = MEMORY_E;
  31746. }
  31747. #endif
  31748. if (err == MP_OKAY) {
  31749. p = pub + 1;
  31750. sp_384_from_mp(pub->x, 15, pX);
  31751. sp_384_from_mp(pub->y, 15, pY);
  31752. sp_384_from_bin(pub->z, 15, one, (int)sizeof(one));
  31753. if (privm)
  31754. sp_384_from_mp(priv, 15, privm);
  31755. /* Check point at infinitiy. */
  31756. if ((sp_384_iszero_15(pub->x) != 0) &&
  31757. (sp_384_iszero_15(pub->y) != 0)) {
  31758. err = ECC_INF_E;
  31759. }
  31760. }
  31761. /* Check range of X and Y */
  31762. if ((err == MP_OKAY) &&
  31763. ((sp_384_cmp_15(pub->x, p384_mod) >= 0) ||
  31764. (sp_384_cmp_15(pub->y, p384_mod) >= 0))) {
  31765. err = ECC_OUT_OF_RANGE_E;
  31766. }
  31767. if (err == MP_OKAY) {
  31768. /* Check point is on curve */
  31769. err = sp_384_ecc_is_point_15(pub, heap);
  31770. }
  31771. if (err == MP_OKAY) {
  31772. /* Point * order = infinity */
  31773. err = sp_384_ecc_mulmod_15(p, pub, p384_order, 1, 1, heap);
  31774. }
  31775. /* Check result is infinity */
  31776. if ((err == MP_OKAY) && ((sp_384_iszero_15(p->x) == 0) ||
  31777. (sp_384_iszero_15(p->y) == 0))) {
  31778. err = ECC_INF_E;
  31779. }
  31780. if (privm) {
  31781. if (err == MP_OKAY) {
  31782. /* Base * private = point */
  31783. err = sp_384_ecc_mulmod_base_15(p, priv, 1, 1, heap);
  31784. }
  31785. /* Check result is public key */
  31786. if ((err == MP_OKAY) &&
  31787. ((sp_384_cmp_15(p->x, pub->x) != 0) ||
  31788. (sp_384_cmp_15(p->y, pub->y) != 0))) {
  31789. err = ECC_PRIV_KEY_E;
  31790. }
  31791. }
  31792. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31793. if (pub != NULL)
  31794. XFREE(pub, heap, DYNAMIC_TYPE_ECC);
  31795. if (priv != NULL)
  31796. XFREE(priv, heap, DYNAMIC_TYPE_ECC);
  31797. #endif
  31798. return err;
  31799. }
  31800. #endif
  31801. #ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL
  31802. /* Add two projective EC points together.
  31803. * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ)
  31804. *
  31805. * pX First EC point's X ordinate.
  31806. * pY First EC point's Y ordinate.
  31807. * pZ First EC point's Z ordinate.
  31808. * qX Second EC point's X ordinate.
  31809. * qY Second EC point's Y ordinate.
  31810. * qZ Second EC point's Z ordinate.
  31811. * rX Resultant EC point's X ordinate.
  31812. * rY Resultant EC point's Y ordinate.
  31813. * rZ Resultant EC point's Z ordinate.
  31814. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  31815. */
  31816. int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ,
  31817. mp_int* qX, mp_int* qY, mp_int* qZ,
  31818. mp_int* rX, mp_int* rY, mp_int* rZ)
  31819. {
  31820. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31821. sp_digit* tmp = NULL;
  31822. sp_point_384* p = NULL;
  31823. #else
  31824. sp_digit tmp[2 * 15 * 6];
  31825. sp_point_384 p[2];
  31826. #endif
  31827. sp_point_384* q = NULL;
  31828. int err = MP_OKAY;
  31829. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31830. if (err == MP_OKAY) {
  31831. p = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, NULL,
  31832. DYNAMIC_TYPE_ECC);
  31833. if (p == NULL)
  31834. err = MEMORY_E;
  31835. }
  31836. if (err == MP_OKAY) {
  31837. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 6, NULL,
  31838. DYNAMIC_TYPE_ECC);
  31839. if (tmp == NULL) {
  31840. err = MEMORY_E;
  31841. }
  31842. }
  31843. #endif
  31844. if (err == MP_OKAY) {
  31845. q = p + 1;
  31846. sp_384_from_mp(p->x, 15, pX);
  31847. sp_384_from_mp(p->y, 15, pY);
  31848. sp_384_from_mp(p->z, 15, pZ);
  31849. sp_384_from_mp(q->x, 15, qX);
  31850. sp_384_from_mp(q->y, 15, qY);
  31851. sp_384_from_mp(q->z, 15, qZ);
  31852. p->infinity = sp_384_iszero_15(p->x) &
  31853. sp_384_iszero_15(p->y);
  31854. q->infinity = sp_384_iszero_15(q->x) &
  31855. sp_384_iszero_15(q->y);
  31856. sp_384_proj_point_add_15(p, p, q, tmp);
  31857. }
  31858. if (err == MP_OKAY) {
  31859. err = sp_384_to_mp(p->x, rX);
  31860. }
  31861. if (err == MP_OKAY) {
  31862. err = sp_384_to_mp(p->y, rY);
  31863. }
  31864. if (err == MP_OKAY) {
  31865. err = sp_384_to_mp(p->z, rZ);
  31866. }
  31867. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31868. if (tmp != NULL)
  31869. XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
  31870. if (p != NULL)
  31871. XFREE(p, NULL, DYNAMIC_TYPE_ECC);
  31872. #endif
  31873. return err;
  31874. }
  31875. /* Double a projective EC point.
  31876. * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ)
  31877. *
  31878. * pX EC point's X ordinate.
  31879. * pY EC point's Y ordinate.
  31880. * pZ EC point's Z ordinate.
  31881. * rX Resultant EC point's X ordinate.
  31882. * rY Resultant EC point's Y ordinate.
  31883. * rZ Resultant EC point's Z ordinate.
  31884. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  31885. */
  31886. int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ,
  31887. mp_int* rX, mp_int* rY, mp_int* rZ)
  31888. {
  31889. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31890. sp_digit* tmp = NULL;
  31891. sp_point_384* p = NULL;
  31892. #else
  31893. sp_digit tmp[2 * 15 * 2];
  31894. sp_point_384 p[1];
  31895. #endif
  31896. int err = MP_OKAY;
  31897. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31898. if (err == MP_OKAY) {
  31899. p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL,
  31900. DYNAMIC_TYPE_ECC);
  31901. if (p == NULL)
  31902. err = MEMORY_E;
  31903. }
  31904. if (err == MP_OKAY) {
  31905. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 2, NULL,
  31906. DYNAMIC_TYPE_ECC);
  31907. if (tmp == NULL)
  31908. err = MEMORY_E;
  31909. }
  31910. #endif
  31911. if (err == MP_OKAY) {
  31912. sp_384_from_mp(p->x, 15, pX);
  31913. sp_384_from_mp(p->y, 15, pY);
  31914. sp_384_from_mp(p->z, 15, pZ);
  31915. p->infinity = sp_384_iszero_15(p->x) &
  31916. sp_384_iszero_15(p->y);
  31917. sp_384_proj_point_dbl_15(p, p, tmp);
  31918. }
  31919. if (err == MP_OKAY) {
  31920. err = sp_384_to_mp(p->x, rX);
  31921. }
  31922. if (err == MP_OKAY) {
  31923. err = sp_384_to_mp(p->y, rY);
  31924. }
  31925. if (err == MP_OKAY) {
  31926. err = sp_384_to_mp(p->z, rZ);
  31927. }
  31928. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31929. if (tmp != NULL)
  31930. XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
  31931. if (p != NULL)
  31932. XFREE(p, NULL, DYNAMIC_TYPE_ECC);
  31933. #endif
  31934. return err;
  31935. }
  31936. /* Map a projective EC point to affine in place.
  31937. * pZ will be one.
  31938. *
  31939. * pX EC point's X ordinate.
  31940. * pY EC point's Y ordinate.
  31941. * pZ EC point's Z ordinate.
  31942. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  31943. */
  31944. int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ)
  31945. {
  31946. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31947. sp_digit* tmp = NULL;
  31948. sp_point_384* p = NULL;
  31949. #else
  31950. sp_digit tmp[2 * 15 * 6];
  31951. sp_point_384 p[1];
  31952. #endif
  31953. int err = MP_OKAY;
  31954. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31955. if (err == MP_OKAY) {
  31956. p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL,
  31957. DYNAMIC_TYPE_ECC);
  31958. if (p == NULL)
  31959. err = MEMORY_E;
  31960. }
  31961. if (err == MP_OKAY) {
  31962. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 6, NULL,
  31963. DYNAMIC_TYPE_ECC);
  31964. if (tmp == NULL)
  31965. err = MEMORY_E;
  31966. }
  31967. #endif
  31968. if (err == MP_OKAY) {
  31969. sp_384_from_mp(p->x, 15, pX);
  31970. sp_384_from_mp(p->y, 15, pY);
  31971. sp_384_from_mp(p->z, 15, pZ);
  31972. p->infinity = sp_384_iszero_15(p->x) &
  31973. sp_384_iszero_15(p->y);
  31974. sp_384_map_15(p, p, tmp);
  31975. }
  31976. if (err == MP_OKAY) {
  31977. err = sp_384_to_mp(p->x, pX);
  31978. }
  31979. if (err == MP_OKAY) {
  31980. err = sp_384_to_mp(p->y, pY);
  31981. }
  31982. if (err == MP_OKAY) {
  31983. err = sp_384_to_mp(p->z, pZ);
  31984. }
  31985. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  31986. if (tmp != NULL)
  31987. XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
  31988. if (p != NULL)
  31989. XFREE(p, NULL, DYNAMIC_TYPE_ECC);
  31990. #endif
  31991. return err;
  31992. }
  31993. #endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */
  31994. #ifdef HAVE_COMP_KEY
  31995. /* Find the square root of a number mod the prime of the curve.
  31996. *
  31997. * y The number to operate on and the result.
  31998. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  31999. */
  32000. static int sp_384_mont_sqrt_15(sp_digit* y)
  32001. {
  32002. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  32003. sp_digit* t1 = NULL;
  32004. #else
  32005. sp_digit t1[5 * 2 * 15];
  32006. #endif
  32007. sp_digit* t2 = NULL;
  32008. sp_digit* t3 = NULL;
  32009. sp_digit* t4 = NULL;
  32010. sp_digit* t5 = NULL;
  32011. int err = MP_OKAY;
  32012. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  32013. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 15, NULL, DYNAMIC_TYPE_ECC);
  32014. if (t1 == NULL)
  32015. err = MEMORY_E;
  32016. #endif
  32017. if (err == MP_OKAY) {
  32018. t2 = t1 + 2 * 15;
  32019. t3 = t1 + 4 * 15;
  32020. t4 = t1 + 6 * 15;
  32021. t5 = t1 + 8 * 15;
  32022. {
  32023. /* t2 = y ^ 0x2 */
  32024. sp_384_mont_sqr_15(t2, y, p384_mod, p384_mp_mod);
  32025. /* t1 = y ^ 0x3 */
  32026. sp_384_mont_mul_15(t1, t2, y, p384_mod, p384_mp_mod);
  32027. /* t5 = y ^ 0xc */
  32028. sp_384_mont_sqr_n_15(t5, t1, 2, p384_mod, p384_mp_mod);
  32029. /* t1 = y ^ 0xf */
  32030. sp_384_mont_mul_15(t1, t1, t5, p384_mod, p384_mp_mod);
  32031. /* t2 = y ^ 0x1e */
  32032. sp_384_mont_sqr_15(t2, t1, p384_mod, p384_mp_mod);
  32033. /* t3 = y ^ 0x1f */
  32034. sp_384_mont_mul_15(t3, t2, y, p384_mod, p384_mp_mod);
  32035. /* t2 = y ^ 0x3e0 */
  32036. sp_384_mont_sqr_n_15(t2, t3, 5, p384_mod, p384_mp_mod);
  32037. /* t1 = y ^ 0x3ff */
  32038. sp_384_mont_mul_15(t1, t3, t2, p384_mod, p384_mp_mod);
  32039. /* t2 = y ^ 0x7fe0 */
  32040. sp_384_mont_sqr_n_15(t2, t1, 5, p384_mod, p384_mp_mod);
  32041. /* t3 = y ^ 0x7fff */
  32042. sp_384_mont_mul_15(t3, t3, t2, p384_mod, p384_mp_mod);
  32043. /* t2 = y ^ 0x3fff800 */
  32044. sp_384_mont_sqr_n_15(t2, t3, 15, p384_mod, p384_mp_mod);
  32045. /* t4 = y ^ 0x3ffffff */
  32046. sp_384_mont_mul_15(t4, t3, t2, p384_mod, p384_mp_mod);
  32047. /* t2 = y ^ 0xffffffc000000 */
  32048. sp_384_mont_sqr_n_15(t2, t4, 30, p384_mod, p384_mp_mod);
  32049. /* t1 = y ^ 0xfffffffffffff */
  32050. sp_384_mont_mul_15(t1, t4, t2, p384_mod, p384_mp_mod);
  32051. /* t2 = y ^ 0xfffffffffffffff000000000000000 */
  32052. sp_384_mont_sqr_n_15(t2, t1, 60, p384_mod, p384_mp_mod);
  32053. /* t1 = y ^ 0xffffffffffffffffffffffffffffff */
  32054. sp_384_mont_mul_15(t1, t1, t2, p384_mod, p384_mp_mod);
  32055. /* t2 = y ^ 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */
  32056. sp_384_mont_sqr_n_15(t2, t1, 120, p384_mod, p384_mp_mod);
  32057. /* t1 = y ^ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */
  32058. sp_384_mont_mul_15(t1, t1, t2, p384_mod, p384_mp_mod);
  32059. /* t2 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */
  32060. sp_384_mont_sqr_n_15(t2, t1, 15, p384_mod, p384_mp_mod);
  32061. /* t1 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */
  32062. sp_384_mont_mul_15(t1, t3, t2, p384_mod, p384_mp_mod);
  32063. /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000 */
  32064. sp_384_mont_sqr_n_15(t2, t1, 31, p384_mod, p384_mp_mod);
  32065. /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff */
  32066. sp_384_mont_mul_15(t1, t4, t2, p384_mod, p384_mp_mod);
  32067. /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff0 */
  32068. sp_384_mont_sqr_n_15(t2, t1, 4, p384_mod, p384_mp_mod);
  32069. /* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc */
  32070. sp_384_mont_mul_15(t1, t5, t2, p384_mod, p384_mp_mod);
  32071. /* t2 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000 */
  32072. sp_384_mont_sqr_n_15(t2, t1, 62, p384_mod, p384_mp_mod);
  32073. /* t1 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000001 */
  32074. sp_384_mont_mul_15(t1, y, t2, p384_mod, p384_mp_mod);
  32075. /* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc00000000000000040000000 */
  32076. sp_384_mont_sqr_n_15(y, t1, 30, p384_mod, p384_mp_mod);
  32077. }
  32078. }
  32079. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  32080. if (t1 != NULL)
  32081. XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
  32082. #endif
  32083. return err;
  32084. }
  32085. /* Uncompress the point given the X ordinate.
  32086. *
  32087. * xm X ordinate.
  32088. * odd Whether the Y ordinate is odd.
  32089. * ym Calculated Y ordinate.
  32090. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  32091. */
  32092. int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym)
  32093. {
  32094. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  32095. sp_digit* x = NULL;
  32096. #else
  32097. sp_digit x[4 * 15];
  32098. #endif
  32099. sp_digit* y = NULL;
  32100. int err = MP_OKAY;
  32101. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  32102. x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 15, NULL, DYNAMIC_TYPE_ECC);
  32103. if (x == NULL)
  32104. err = MEMORY_E;
  32105. #endif
  32106. if (err == MP_OKAY) {
  32107. y = x + 2 * 15;
  32108. sp_384_from_mp(x, 15, xm);
  32109. err = sp_384_mod_mul_norm_15(x, x, p384_mod);
  32110. }
  32111. if (err == MP_OKAY) {
  32112. /* y = x^3 */
  32113. {
  32114. sp_384_mont_sqr_15(y, x, p384_mod, p384_mp_mod);
  32115. sp_384_mont_mul_15(y, y, x, p384_mod, p384_mp_mod);
  32116. }
  32117. /* y = x^3 - 3x */
  32118. sp_384_mont_sub_15(y, y, x, p384_mod);
  32119. sp_384_mont_sub_15(y, y, x, p384_mod);
  32120. sp_384_mont_sub_15(y, y, x, p384_mod);
  32121. /* y = x^3 - 3x + b */
  32122. err = sp_384_mod_mul_norm_15(x, p384_b, p384_mod);
  32123. }
  32124. if (err == MP_OKAY) {
  32125. sp_384_mont_add_15(y, y, x, p384_mod);
  32126. /* y = sqrt(x^3 - 3x + b) */
  32127. err = sp_384_mont_sqrt_15(y);
  32128. }
  32129. if (err == MP_OKAY) {
  32130. XMEMSET(y + 15, 0, 15U * sizeof(sp_digit));
  32131. sp_384_mont_reduce_15(y, p384_mod, p384_mp_mod);
  32132. if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) {
  32133. sp_384_mont_sub_15(y, p384_mod, y, p384_mod);
  32134. }
  32135. err = sp_384_to_mp(y, ym);
  32136. }
  32137. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  32138. if (x != NULL)
  32139. XFREE(x, NULL, DYNAMIC_TYPE_ECC);
  32140. #endif
  32141. return err;
  32142. }
  32143. #endif
  32144. #endif /* WOLFSSL_SP_384 */
  32145. #ifdef WOLFSSL_SP_521
  32146. /* Point structure to use. */
  32147. typedef struct sp_point_521 {
  32148. /* X ordinate of point. */
  32149. sp_digit x[2 * 21];
  32150. /* Y ordinate of point. */
  32151. sp_digit y[2 * 21];
  32152. /* Z ordinate of point. */
  32153. sp_digit z[2 * 21];
  32154. /* Indicates point is at infinity. */
  32155. int infinity;
  32156. } sp_point_521;
  32157. /* The modulus (prime) of the curve P521. */
  32158. static const sp_digit p521_mod[21] = {
  32159. 0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,
  32160. 0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,
  32161. 0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x01fffff
  32162. };
  32163. /* The Montgomery normalizer for modulus of the curve P521. */
  32164. static const sp_digit p521_norm_mod[21] = {
  32165. 0x0000001,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
  32166. 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
  32167. 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000
  32168. };
  32169. /* The Montgomery multiplier for modulus of the curve P521. */
  32170. static sp_digit p521_mp_mod = 0x000001;
  32171. #if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
  32172. defined(HAVE_ECC_VERIFY)
  32173. /* The order of the curve P521. */
  32174. static const sp_digit p521_order[21] = {
  32175. 0x1386409,0x1db8f48,0x1ebaedb,0x1113388,0x1bb5c9b,0x04d2e81,0x00523dc,
  32176. 0x0d6ff98,0x1bf2f96,0x0c343c1,0x1fffe94,0x1ffffff,0x1ffffff,0x1ffffff,
  32177. 0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x01fffff
  32178. };
  32179. #endif
  32180. /* The order of the curve P521 minus 2. */
  32181. static const sp_digit p521_order2[21] = {
  32182. 0x1386407,0x1db8f48,0x1ebaedb,0x1113388,0x1bb5c9b,0x04d2e81,0x00523dc,
  32183. 0x0d6ff98,0x1bf2f96,0x0c343c1,0x1fffe94,0x1ffffff,0x1ffffff,0x1ffffff,
  32184. 0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x01fffff
  32185. };
  32186. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  32187. /* The Montgomery normalizer for order of the curve P521. */
  32188. static const sp_digit p521_norm_order[21] = {
  32189. 0x0c79bf7,0x02470b7,0x0145124,0x0eecc77,0x044a364,0x1b2d17e,0x1fadc23,
  32190. 0x1290067,0x040d069,0x13cbc3e,0x000016b,0x0000000,0x0000000,0x0000000,
  32191. 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000
  32192. };
  32193. #endif
  32194. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  32195. /* The Montgomery multiplier for order of the curve P521. */
  32196. static sp_digit p521_mp_order = 0x1a995c7;
  32197. #endif
  32198. /* The base point of curve P521. */
  32199. static const sp_point_521 p521_base = {
  32200. /* X ordinate */
  32201. {
  32202. 0x0e5bd66,0x13f18e1,0x0a6fe5f,0x030ad48,0x1348b3c,0x1fd46f1,0x1049e8b,
  32203. 0x051fc3b,0x1efe759,0x0a5af3b,0x14f6ea8,0x1ec0d69,0x01f828a,0x029fda9,
  32204. 0x19204e4,0x1688538,0x1662395,0x0cf1f65,0x1013a73,0x1c0d6e0,0x00c6858,
  32205. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  32206. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  32207. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  32208. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  32209. (sp_digit)0
  32210. },
  32211. /* Y ordinate */
  32212. {
  32213. 0x1d16650,0x14a3b4f,0x090222f,0x0d44e58,0x153c708,0x1683b09,0x0e404fe,
  32214. 0x0818aa1,0x15ef426,0x1f7394c,0x1998b25,0x1a2e4e7,0x0817afb,0x0bcda23,
  32215. 0x1d51125,0x037b331,0x1b42c7d,0x02e452f,0x08ef001,0x12d4f13,0x0118392,
  32216. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  32217. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  32218. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  32219. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  32220. (sp_digit)0
  32221. },
  32222. /* Z ordinate */
  32223. {
  32224. 0x0000001,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
  32225. 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
  32226. 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
  32227. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  32228. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  32229. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  32230. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  32231. (sp_digit)0
  32232. },
  32233. /* infinity */
  32234. 0
  32235. };
  32236. #if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY)
  32237. static const sp_digit p521_b[21] = {
  32238. 0x1503f00,0x08fea35,0x13c7bd1,0x107a586,0x1573df8,0x18df839,0x102f4ee,
  32239. 0x0f62ca5,0x1ec7e93,0x10c9ca8,0x0427855,0x13231de,0x13b8b48,0x0cd98af,
  32240. 0x169c96e,0x081dd45,0x1a0b685,0x1c94d10,0x1872687,0x1d72c31,0x0051953
  32241. };
  32242. #endif
  32243. #ifdef WOLFSSL_SP_SMALL
  32244. /* Multiply a and b into r. (r = a * b)
  32245. *
  32246. * r A single precision integer.
  32247. * a A single precision integer.
  32248. * b A single precision integer.
  32249. */
  32250. SP_NOINLINE static void sp_521_mul_21(sp_digit* r, const sp_digit* a,
  32251. const sp_digit* b)
  32252. {
  32253. int i;
  32254. int imax;
  32255. int k;
  32256. sp_uint64 c;
  32257. sp_uint64 lo;
  32258. c = ((sp_uint64)a[20]) * b[20];
  32259. r[41] = (sp_digit)(c >> 25);
  32260. c &= 0x1ffffff;
  32261. for (k = 39; k >= 0; k--) {
  32262. if (k >= 21) {
  32263. i = k - 20;
  32264. imax = 20;
  32265. }
  32266. else {
  32267. i = 0;
  32268. imax = k;
  32269. }
  32270. lo = 0;
  32271. for (; i <= imax; i++) {
  32272. lo += ((sp_uint64)a[i]) * b[k - i];
  32273. }
  32274. c += lo >> 25;
  32275. r[k + 2] += (sp_digit)(c >> 25);
  32276. r[k + 1] = (sp_digit)(c & 0x1ffffff);
  32277. c = lo & 0x1ffffff;
  32278. }
  32279. r[0] = (sp_digit)c;
  32280. }
  32281. #else
  32282. /* Multiply a and b into r. (r = a * b)
  32283. *
  32284. * r A single precision integer.
  32285. * a A single precision integer.
  32286. * b A single precision integer.
  32287. */
  32288. SP_NOINLINE static void sp_521_mul_21(sp_digit* r, const sp_digit* a,
  32289. const sp_digit* b)
  32290. {
  32291. int i;
  32292. int j;
  32293. sp_int64 t[42];
  32294. XMEMSET(t, 0, sizeof(t));
  32295. for (i=0; i<21; i++) {
  32296. for (j=0; j<21; j++) {
  32297. t[i+j] += ((sp_int64)a[i]) * b[j];
  32298. }
  32299. }
  32300. for (i=0; i<41; i++) {
  32301. r[i] = t[i] & 0x1ffffff;
  32302. t[i+1] += t[i] >> 25;
  32303. }
  32304. r[41] = (sp_digit)t[41];
  32305. }
  32306. #endif /* WOLFSSL_SP_SMALL */
  32307. #ifdef WOLFSSL_SP_SMALL
  32308. /* Square a and put result in r. (r = a * a)
  32309. *
  32310. * r A single precision integer.
  32311. * a A single precision integer.
  32312. */
  32313. SP_NOINLINE static void sp_521_sqr_21(sp_digit* r, const sp_digit* a)
  32314. {
  32315. int i;
  32316. int imax;
  32317. int k;
  32318. sp_uint64 c;
  32319. sp_uint64 t;
  32320. c = ((sp_uint64)a[20]) * a[20];
  32321. r[41] = (sp_digit)(c >> 25);
  32322. c = (c & 0x1ffffff) << 25;
  32323. for (k = 39; k >= 0; k--) {
  32324. i = (k + 1) / 2;
  32325. if ((k & 1) == 0) {
  32326. c += ((sp_uint64)a[i]) * a[i];
  32327. i++;
  32328. }
  32329. if (k < 20) {
  32330. imax = k;
  32331. }
  32332. else {
  32333. imax = 20;
  32334. }
  32335. t = 0;
  32336. for (; i <= imax; i++) {
  32337. t += ((sp_uint64)a[i]) * a[k - i];
  32338. }
  32339. c += t * 2;
  32340. r[k + 2] += (sp_digit) (c >> 50);
  32341. r[k + 1] = (sp_digit)((c >> 25) & 0x1ffffff);
  32342. c = (c & 0x1ffffff) << 25;
  32343. }
  32344. r[0] = (sp_digit)(c >> 25);
  32345. }
  32346. #else
  32347. /* Square a and put result in r. (r = a * a)
  32348. *
  32349. * r A single precision integer.
  32350. * a A single precision integer.
  32351. */
  32352. SP_NOINLINE static void sp_521_sqr_21(sp_digit* r, const sp_digit* a)
  32353. {
  32354. int i;
  32355. int j;
  32356. sp_int64 t[42];
  32357. XMEMSET(t, 0, sizeof(t));
  32358. for (i=0; i<21; i++) {
  32359. for (j=0; j<i; j++) {
  32360. t[i+j] += (((sp_int64)a[i]) * a[j]) * 2;
  32361. }
  32362. t[i+i] += ((sp_int64)a[i]) * a[i];
  32363. }
  32364. for (i=0; i<41; i++) {
  32365. r[i] = t[i] & 0x1ffffff;
  32366. t[i+1] += t[i] >> 25;
  32367. }
  32368. r[41] = (sp_digit)t[41];
  32369. }
  32370. #endif /* WOLFSSL_SP_SMALL */
  32371. #ifdef WOLFSSL_SP_SMALL
  32372. /* Add b to a into r. (r = a + b)
  32373. *
  32374. * r A single precision integer.
  32375. * a A single precision integer.
  32376. * b A single precision integer.
  32377. */
  32378. SP_NOINLINE static int sp_521_add_21(sp_digit* r, const sp_digit* a,
  32379. const sp_digit* b)
  32380. {
  32381. int i;
  32382. for (i = 0; i < 21; i++) {
  32383. r[i] = a[i] + b[i];
  32384. }
  32385. return 0;
  32386. }
  32387. #else
  32388. /* Add b to a into r. (r = a + b)
  32389. *
  32390. * r A single precision integer.
  32391. * a A single precision integer.
  32392. * b A single precision integer.
  32393. */
  32394. SP_NOINLINE static int sp_521_add_21(sp_digit* r, const sp_digit* a,
  32395. const sp_digit* b)
  32396. {
  32397. int i;
  32398. for (i = 0; i < 16; i += 8) {
  32399. r[i + 0] = a[i + 0] + b[i + 0];
  32400. r[i + 1] = a[i + 1] + b[i + 1];
  32401. r[i + 2] = a[i + 2] + b[i + 2];
  32402. r[i + 3] = a[i + 3] + b[i + 3];
  32403. r[i + 4] = a[i + 4] + b[i + 4];
  32404. r[i + 5] = a[i + 5] + b[i + 5];
  32405. r[i + 6] = a[i + 6] + b[i + 6];
  32406. r[i + 7] = a[i + 7] + b[i + 7];
  32407. }
  32408. r[16] = a[16] + b[16];
  32409. r[17] = a[17] + b[17];
  32410. r[18] = a[18] + b[18];
  32411. r[19] = a[19] + b[19];
  32412. r[20] = a[20] + b[20];
  32413. return 0;
  32414. }
  32415. #endif /* WOLFSSL_SP_SMALL */
  32416. #ifdef WOLFSSL_SP_SMALL
  32417. /* Sub b from a into r. (r = a - b)
  32418. *
  32419. * r A single precision integer.
  32420. * a A single precision integer.
  32421. * b A single precision integer.
  32422. */
  32423. SP_NOINLINE static int sp_521_sub_21(sp_digit* r, const sp_digit* a,
  32424. const sp_digit* b)
  32425. {
  32426. int i;
  32427. for (i = 0; i < 21; i++) {
  32428. r[i] = a[i] - b[i];
  32429. }
  32430. return 0;
  32431. }
  32432. #else
  32433. /* Sub b from a into r. (r = a - b)
  32434. *
  32435. * r A single precision integer.
  32436. * a A single precision integer.
  32437. * b A single precision integer.
  32438. */
  32439. SP_NOINLINE static int sp_521_sub_21(sp_digit* r, const sp_digit* a,
  32440. const sp_digit* b)
  32441. {
  32442. int i;
  32443. for (i = 0; i < 16; i += 8) {
  32444. r[i + 0] = a[i + 0] - b[i + 0];
  32445. r[i + 1] = a[i + 1] - b[i + 1];
  32446. r[i + 2] = a[i + 2] - b[i + 2];
  32447. r[i + 3] = a[i + 3] - b[i + 3];
  32448. r[i + 4] = a[i + 4] - b[i + 4];
  32449. r[i + 5] = a[i + 5] - b[i + 5];
  32450. r[i + 6] = a[i + 6] - b[i + 6];
  32451. r[i + 7] = a[i + 7] - b[i + 7];
  32452. }
  32453. r[16] = a[16] - b[16];
  32454. r[17] = a[17] - b[17];
  32455. r[18] = a[18] - b[18];
  32456. r[19] = a[19] - b[19];
  32457. r[20] = a[20] - b[20];
  32458. return 0;
  32459. }
  32460. #endif /* WOLFSSL_SP_SMALL */
  32461. /* Convert an mp_int to an array of sp_digit.
  32462. *
  32463. * r A single precision integer.
  32464. * size Maximum number of bytes to convert
  32465. * a A multi-precision integer.
  32466. */
  32467. static void sp_521_from_mp(sp_digit* r, int size, const mp_int* a)
  32468. {
  32469. #if DIGIT_BIT == 25
  32470. int j;
  32471. XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
  32472. for (j = a->used; j < size; j++) {
  32473. r[j] = 0;
  32474. }
  32475. #elif DIGIT_BIT > 25
  32476. int i;
  32477. int j = 0;
  32478. word32 s = 0;
  32479. r[0] = 0;
  32480. for (i = 0; i < a->used && j < size; i++) {
  32481. r[j] |= ((sp_digit)a->dp[i] << s);
  32482. r[j] &= 0x1ffffff;
  32483. s = 25U - s;
  32484. if (j + 1 >= size) {
  32485. break;
  32486. }
  32487. /* lint allow cast of mismatch word32 and mp_digit */
  32488. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  32489. while ((s + 25U) <= (word32)DIGIT_BIT) {
  32490. s += 25U;
  32491. r[j] &= 0x1ffffff;
  32492. if (j + 1 >= size) {
  32493. break;
  32494. }
  32495. if (s < (word32)DIGIT_BIT) {
  32496. /* lint allow cast of mismatch word32 and mp_digit */
  32497. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  32498. }
  32499. else {
  32500. r[++j] = (sp_digit)0;
  32501. }
  32502. }
  32503. s = (word32)DIGIT_BIT - s;
  32504. }
  32505. for (j++; j < size; j++) {
  32506. r[j] = 0;
  32507. }
  32508. #else
  32509. int i;
  32510. int j = 0;
  32511. int s = 0;
  32512. r[0] = 0;
  32513. for (i = 0; i < a->used && j < size; i++) {
  32514. r[j] |= ((sp_digit)a->dp[i]) << s;
  32515. if (s + DIGIT_BIT >= 25) {
  32516. r[j] &= 0x1ffffff;
  32517. if (j + 1 >= size) {
  32518. break;
  32519. }
  32520. s = 25 - s;
  32521. if (s == DIGIT_BIT) {
  32522. r[++j] = 0;
  32523. s = 0;
  32524. }
  32525. else {
  32526. r[++j] = a->dp[i] >> s;
  32527. s = DIGIT_BIT - s;
  32528. }
  32529. }
  32530. else {
  32531. s += DIGIT_BIT;
  32532. }
  32533. }
  32534. for (j++; j < size; j++) {
  32535. r[j] = 0;
  32536. }
  32537. #endif
  32538. }
  32539. /* Convert a point of type ecc_point to type sp_point_521.
  32540. *
  32541. * p Point of type sp_point_521 (result).
  32542. * pm Point of type ecc_point.
  32543. */
  32544. static void sp_521_point_from_ecc_point_21(sp_point_521* p,
  32545. const ecc_point* pm)
  32546. {
  32547. XMEMSET(p->x, 0, sizeof(p->x));
  32548. XMEMSET(p->y, 0, sizeof(p->y));
  32549. XMEMSET(p->z, 0, sizeof(p->z));
  32550. sp_521_from_mp(p->x, 21, pm->x);
  32551. sp_521_from_mp(p->y, 21, pm->y);
  32552. sp_521_from_mp(p->z, 21, pm->z);
  32553. p->infinity = 0;
  32554. }
  32555. /* Convert an array of sp_digit to an mp_int.
  32556. *
  32557. * a A single precision integer.
  32558. * r A multi-precision integer.
  32559. */
  32560. static int sp_521_to_mp(const sp_digit* a, mp_int* r)
  32561. {
  32562. int err;
  32563. err = mp_grow(r, (521 + DIGIT_BIT - 1) / DIGIT_BIT);
  32564. if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
  32565. #if DIGIT_BIT == 25
  32566. XMEMCPY(r->dp, a, sizeof(sp_digit) * 21);
  32567. r->used = 21;
  32568. mp_clamp(r);
  32569. #elif DIGIT_BIT < 25
  32570. int i;
  32571. int j = 0;
  32572. int s = 0;
  32573. r->dp[0] = 0;
  32574. for (i = 0; i < 21; i++) {
  32575. r->dp[j] |= (mp_digit)(a[i] << s);
  32576. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  32577. s = DIGIT_BIT - s;
  32578. r->dp[++j] = (mp_digit)(a[i] >> s);
  32579. while (s + DIGIT_BIT <= 25) {
  32580. s += DIGIT_BIT;
  32581. r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  32582. if (s == SP_WORD_SIZE) {
  32583. r->dp[j] = 0;
  32584. }
  32585. else {
  32586. r->dp[j] = (mp_digit)(a[i] >> s);
  32587. }
  32588. }
  32589. s = 25 - s;
  32590. }
  32591. r->used = (521 + DIGIT_BIT - 1) / DIGIT_BIT;
  32592. mp_clamp(r);
  32593. #else
  32594. int i;
  32595. int j = 0;
  32596. int s = 0;
  32597. r->dp[0] = 0;
  32598. for (i = 0; i < 21; i++) {
  32599. r->dp[j] |= ((mp_digit)a[i]) << s;
  32600. if (s + 25 >= DIGIT_BIT) {
  32601. #if DIGIT_BIT != 32 && DIGIT_BIT != 64
  32602. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  32603. #endif
  32604. s = DIGIT_BIT - s;
  32605. r->dp[++j] = a[i] >> s;
  32606. s = 25 - s;
  32607. }
  32608. else {
  32609. s += 25;
  32610. }
  32611. }
  32612. r->used = (521 + DIGIT_BIT - 1) / DIGIT_BIT;
  32613. mp_clamp(r);
  32614. #endif
  32615. }
  32616. return err;
  32617. }
  32618. /* Convert a point of type sp_point_521 to type ecc_point.
  32619. *
  32620. * p Point of type sp_point_521.
  32621. * pm Point of type ecc_point (result).
  32622. * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
  32623. * MP_OKAY.
  32624. */
  32625. static int sp_521_point_to_ecc_point_21(const sp_point_521* p, ecc_point* pm)
  32626. {
  32627. int err;
  32628. err = sp_521_to_mp(p->x, pm->x);
  32629. if (err == MP_OKAY) {
  32630. err = sp_521_to_mp(p->y, pm->y);
  32631. }
  32632. if (err == MP_OKAY) {
  32633. err = sp_521_to_mp(p->z, pm->z);
  32634. }
  32635. return err;
  32636. }
  32637. /* Normalize the values in each word to 25 bits.
  32638. *
  32639. * a Array of sp_digit to normalize.
  32640. */
  32641. static void sp_521_norm_21(sp_digit* a)
  32642. {
  32643. #ifdef WOLFSSL_SP_SMALL
  32644. int i;
  32645. for (i = 0; i < 20; i++) {
  32646. a[i+1] += a[i] >> 25;
  32647. a[i] &= 0x1ffffff;
  32648. }
  32649. #else
  32650. int i;
  32651. for (i = 0; i < 16; i += 8) {
  32652. a[i+1] += a[i+0] >> 25; a[i+0] &= 0x1ffffff;
  32653. a[i+2] += a[i+1] >> 25; a[i+1] &= 0x1ffffff;
  32654. a[i+3] += a[i+2] >> 25; a[i+2] &= 0x1ffffff;
  32655. a[i+4] += a[i+3] >> 25; a[i+3] &= 0x1ffffff;
  32656. a[i+5] += a[i+4] >> 25; a[i+4] &= 0x1ffffff;
  32657. a[i+6] += a[i+5] >> 25; a[i+5] &= 0x1ffffff;
  32658. a[i+7] += a[i+6] >> 25; a[i+6] &= 0x1ffffff;
  32659. a[i+8] += a[i+7] >> 25; a[i+7] &= 0x1ffffff;
  32660. }
  32661. a[17] += a[16] >> 25; a[16] &= 0x1ffffff;
  32662. a[18] += a[17] >> 25; a[17] &= 0x1ffffff;
  32663. a[19] += a[18] >> 25; a[18] &= 0x1ffffff;
  32664. a[20] += a[19] >> 25; a[19] &= 0x1ffffff;
  32665. #endif /* WOLFSSL_SP_SMALL */
  32666. }
  32667. /* Reduce the number back to 521 bits using Montgomery reduction.
  32668. *
  32669. * a A single precision number to reduce in place.
  32670. * m The single precision number representing the modulus.
  32671. * mp The digit representing the negative inverse of m mod 2^n.
  32672. */
  32673. static void sp_521_mont_reduce_21(sp_digit* a, const sp_digit* m, sp_digit mp)
  32674. {
  32675. int i;
  32676. (void)m;
  32677. (void)mp;
  32678. for (i = 0; i < 20; i++) {
  32679. a[i] += ((a[20 + i] >> 21) + (a[20 + i + 1] << 4)) & 0x1ffffff;
  32680. }
  32681. a[20] &= 0x1fffff;
  32682. a[20] += ((a[40] >> 21) + (a[41] << 4)) & 0x1ffffff;
  32683. sp_521_norm_21(a);
  32684. a[0] += a[20] >> 21;
  32685. a[20] &= 0x1fffff;
  32686. }
  32687. /* Compare a with b in constant time.
  32688. *
  32689. * a A single precision integer.
  32690. * b A single precision integer.
  32691. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  32692. * respectively.
  32693. */
  32694. static sp_digit sp_521_cmp_21(const sp_digit* a, const sp_digit* b)
  32695. {
  32696. sp_digit r = 0;
  32697. #ifdef WOLFSSL_SP_SMALL
  32698. int i;
  32699. for (i=20; i>=0; i--) {
  32700. r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 24);
  32701. }
  32702. #else
  32703. int i;
  32704. r |= (a[20] - b[20]) & (0 - (sp_digit)1);
  32705. r |= (a[19] - b[19]) & ~(((sp_digit)0 - r) >> 24);
  32706. r |= (a[18] - b[18]) & ~(((sp_digit)0 - r) >> 24);
  32707. r |= (a[17] - b[17]) & ~(((sp_digit)0 - r) >> 24);
  32708. r |= (a[16] - b[16]) & ~(((sp_digit)0 - r) >> 24);
  32709. for (i = 8; i >= 0; i -= 8) {
  32710. r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 24);
  32711. r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 24);
  32712. r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 24);
  32713. r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 24);
  32714. r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 24);
  32715. r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 24);
  32716. r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 24);
  32717. r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 24);
  32718. }
  32719. #endif /* WOLFSSL_SP_SMALL */
  32720. return r;
  32721. }
  32722. /* Conditionally subtract b from a using the mask m.
  32723. * m is -1 to subtract and 0 when not.
  32724. *
  32725. * r A single precision number representing condition subtract result.
  32726. * a A single precision number to subtract from.
  32727. * b A single precision number to subtract.
  32728. * m Mask value to apply.
  32729. */
  32730. static void sp_521_cond_sub_21(sp_digit* r, const sp_digit* a,
  32731. const sp_digit* b, const sp_digit m)
  32732. {
  32733. #ifdef WOLFSSL_SP_SMALL
  32734. int i;
  32735. for (i = 0; i < 21; i++) {
  32736. r[i] = a[i] - (b[i] & m);
  32737. }
  32738. #else
  32739. int i;
  32740. for (i = 0; i < 16; i += 8) {
  32741. r[i + 0] = a[i + 0] - (b[i + 0] & m);
  32742. r[i + 1] = a[i + 1] - (b[i + 1] & m);
  32743. r[i + 2] = a[i + 2] - (b[i + 2] & m);
  32744. r[i + 3] = a[i + 3] - (b[i + 3] & m);
  32745. r[i + 4] = a[i + 4] - (b[i + 4] & m);
  32746. r[i + 5] = a[i + 5] - (b[i + 5] & m);
  32747. r[i + 6] = a[i + 6] - (b[i + 6] & m);
  32748. r[i + 7] = a[i + 7] - (b[i + 7] & m);
  32749. }
  32750. r[16] = a[16] - (b[16] & m);
  32751. r[17] = a[17] - (b[17] & m);
  32752. r[18] = a[18] - (b[18] & m);
  32753. r[19] = a[19] - (b[19] & m);
  32754. r[20] = a[20] - (b[20] & m);
  32755. #endif /* WOLFSSL_SP_SMALL */
  32756. }
  32757. /* Mul a by scalar b and add into r. (r += a * b)
  32758. *
  32759. * r A single precision integer.
  32760. * a A single precision integer.
  32761. * b A scalar.
  32762. */
  32763. SP_NOINLINE static void sp_521_mul_add_21(sp_digit* r, const sp_digit* a,
  32764. const sp_digit b)
  32765. {
  32766. #ifdef WOLFSSL_SP_SMALL
  32767. sp_int64 tb = b;
  32768. sp_int64 t[4];
  32769. int i;
  32770. t[0] = 0;
  32771. for (i = 0; i < 20; i += 4) {
  32772. t[0] += (tb * a[i+0]) + r[i+0];
  32773. t[1] = (tb * a[i+1]) + r[i+1];
  32774. t[2] = (tb * a[i+2]) + r[i+2];
  32775. t[3] = (tb * a[i+3]) + r[i+3];
  32776. r[i+0] = t[0] & 0x1ffffff;
  32777. t[1] += t[0] >> 25;
  32778. r[i+1] = t[1] & 0x1ffffff;
  32779. t[2] += t[1] >> 25;
  32780. r[i+2] = t[2] & 0x1ffffff;
  32781. t[3] += t[2] >> 25;
  32782. r[i+3] = t[3] & 0x1ffffff;
  32783. t[0] = t[3] >> 25;
  32784. }
  32785. t[0] += (tb * a[20]) + r[20];
  32786. r[20] = t[0] & 0x1ffffff;
  32787. r[21] += (sp_digit)(t[0] >> 25);
  32788. #else
  32789. sp_int64 tb = b;
  32790. sp_int64 t[8];
  32791. int i;
  32792. t[0] = tb * a[0]; r[0] += (sp_digit)(t[0] & 0x1ffffff);
  32793. for (i = 0; i < 16; i += 8) {
  32794. t[1] = tb * a[i+1];
  32795. r[i+1] += (sp_digit)((t[0] >> 25) + (t[1] & 0x1ffffff));
  32796. t[2] = tb * a[i+2];
  32797. r[i+2] += (sp_digit)((t[1] >> 25) + (t[2] & 0x1ffffff));
  32798. t[3] = tb * a[i+3];
  32799. r[i+3] += (sp_digit)((t[2] >> 25) + (t[3] & 0x1ffffff));
  32800. t[4] = tb * a[i+4];
  32801. r[i+4] += (sp_digit)((t[3] >> 25) + (t[4] & 0x1ffffff));
  32802. t[5] = tb * a[i+5];
  32803. r[i+5] += (sp_digit)((t[4] >> 25) + (t[5] & 0x1ffffff));
  32804. t[6] = tb * a[i+6];
  32805. r[i+6] += (sp_digit)((t[5] >> 25) + (t[6] & 0x1ffffff));
  32806. t[7] = tb * a[i+7];
  32807. r[i+7] += (sp_digit)((t[6] >> 25) + (t[7] & 0x1ffffff));
  32808. t[0] = tb * a[i+8];
  32809. r[i+8] += (sp_digit)((t[7] >> 25) + (t[0] & 0x1ffffff));
  32810. }
  32811. t[1] = tb * a[17];
  32812. r[17] += (sp_digit)((t[0] >> 25) + (t[1] & 0x1ffffff));
  32813. t[2] = tb * a[18];
  32814. r[18] += (sp_digit)((t[1] >> 25) + (t[2] & 0x1ffffff));
  32815. t[3] = tb * a[19];
  32816. r[19] += (sp_digit)((t[2] >> 25) + (t[3] & 0x1ffffff));
  32817. t[4] = tb * a[20];
  32818. r[20] += (sp_digit)((t[3] >> 25) + (t[4] & 0x1ffffff));
  32819. r[21] += (sp_digit)(t[4] >> 25);
  32820. #endif /* WOLFSSL_SP_SMALL */
  32821. }
  32822. /* Shift the result in the high 521 bits down to the bottom.
  32823. *
  32824. * r A single precision number.
  32825. * a A single precision number.
  32826. */
  32827. static void sp_521_mont_shift_21(sp_digit* r, const sp_digit* a)
  32828. {
  32829. #ifdef WOLFSSL_SP_SMALL
  32830. int i;
  32831. sp_digit n;
  32832. sp_digit s;
  32833. s = a[21];
  32834. n = a[20] >> 21;
  32835. for (i = 0; i < 20; i++) {
  32836. n += (s & 0x1ffffff) << 4;
  32837. r[i] = n & 0x1ffffff;
  32838. n >>= 25;
  32839. s = a[22 + i] + (s >> 25);
  32840. }
  32841. n += s << 4;
  32842. r[20] = n;
  32843. #else
  32844. sp_digit n;
  32845. sp_digit s;
  32846. int i;
  32847. s = a[21]; n = a[20] >> 21;
  32848. for (i = 0; i < 16; i += 8) {
  32849. n += (s & 0x1ffffff) << 4; r[i+0] = n & 0x1ffffff;
  32850. n >>= 25; s = a[i+22] + (s >> 25);
  32851. n += (s & 0x1ffffff) << 4; r[i+1] = n & 0x1ffffff;
  32852. n >>= 25; s = a[i+23] + (s >> 25);
  32853. n += (s & 0x1ffffff) << 4; r[i+2] = n & 0x1ffffff;
  32854. n >>= 25; s = a[i+24] + (s >> 25);
  32855. n += (s & 0x1ffffff) << 4; r[i+3] = n & 0x1ffffff;
  32856. n >>= 25; s = a[i+25] + (s >> 25);
  32857. n += (s & 0x1ffffff) << 4; r[i+4] = n & 0x1ffffff;
  32858. n >>= 25; s = a[i+26] + (s >> 25);
  32859. n += (s & 0x1ffffff) << 4; r[i+5] = n & 0x1ffffff;
  32860. n >>= 25; s = a[i+27] + (s >> 25);
  32861. n += (s & 0x1ffffff) << 4; r[i+6] = n & 0x1ffffff;
  32862. n >>= 25; s = a[i+28] + (s >> 25);
  32863. n += (s & 0x1ffffff) << 4; r[i+7] = n & 0x1ffffff;
  32864. n >>= 25; s = a[i+29] + (s >> 25);
  32865. }
  32866. n += (s & 0x1ffffff) << 4; r[16] = n & 0x1ffffff;
  32867. n >>= 25; s = a[38] + (s >> 25);
  32868. n += (s & 0x1ffffff) << 4; r[17] = n & 0x1ffffff;
  32869. n >>= 25; s = a[39] + (s >> 25);
  32870. n += (s & 0x1ffffff) << 4; r[18] = n & 0x1ffffff;
  32871. n >>= 25; s = a[40] + (s >> 25);
  32872. n += (s & 0x1ffffff) << 4; r[19] = n & 0x1ffffff;
  32873. n >>= 25; s = a[41] + (s >> 25);
  32874. n += s << 4; r[20] = n;
  32875. #endif /* WOLFSSL_SP_SMALL */
  32876. XMEMSET(&r[21], 0, sizeof(*r) * 21U);
  32877. }
  32878. /* Reduce the number back to 521 bits using Montgomery reduction.
  32879. *
  32880. * a A single precision number to reduce in place.
  32881. * m The single precision number representing the modulus.
  32882. * mp The digit representing the negative inverse of m mod 2^n.
  32883. */
  32884. static void sp_521_mont_reduce_order_21(sp_digit* a, const sp_digit* m, sp_digit mp)
  32885. {
  32886. int i;
  32887. sp_digit mu;
  32888. sp_digit over;
  32889. sp_521_norm_21(a + 21);
  32890. for (i=0; i<20; i++) {
  32891. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1ffffff;
  32892. sp_521_mul_add_21(a+i, m, mu);
  32893. a[i+1] += a[i] >> 25;
  32894. }
  32895. mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffL;
  32896. sp_521_mul_add_21(a+i, m, mu);
  32897. a[i+1] += a[i] >> 25;
  32898. a[i] &= 0x1ffffff;
  32899. sp_521_mont_shift_21(a, a);
  32900. over = a[20] >> 21;
  32901. sp_521_cond_sub_21(a, a, m, ~((over - 1) >> 31));
  32902. sp_521_norm_21(a);
  32903. }
  32904. /* Multiply two Montgomery form numbers mod the modulus (prime).
  32905. * (r = a * b mod m)
  32906. *
  32907. * r Result of multiplication.
  32908. * a First number to multiply in Montgomery form.
  32909. * b Second number to multiply in Montgomery form.
  32910. * m Modulus (prime).
  32911. * mp Montgomery mulitplier.
  32912. */
  32913. SP_NOINLINE static void sp_521_mont_mul_21(sp_digit* r, const sp_digit* a,
  32914. const sp_digit* b, const sp_digit* m, sp_digit mp)
  32915. {
  32916. sp_521_mul_21(r, a, b);
  32917. sp_521_mont_reduce_21(r, m, mp);
  32918. }
  32919. /* Square the Montgomery form number. (r = a * a mod m)
  32920. *
  32921. * r Result of squaring.
  32922. * a Number to square in Montgomery form.
  32923. * m Modulus (prime).
  32924. * mp Montgomery mulitplier.
  32925. */
  32926. SP_NOINLINE static void sp_521_mont_sqr_21(sp_digit* r, const sp_digit* a,
  32927. const sp_digit* m, sp_digit mp)
  32928. {
  32929. sp_521_sqr_21(r, a);
  32930. sp_521_mont_reduce_21(r, m, mp);
  32931. }
  32932. #if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY)
  32933. /* Square the Montgomery form number a number of times. (r = a ^ n mod m)
  32934. *
  32935. * r Result of squaring.
  32936. * a Number to square in Montgomery form.
  32937. * n Number of times to square.
  32938. * m Modulus (prime).
  32939. * mp Montgomery mulitplier.
  32940. */
  32941. static void sp_521_mont_sqr_n_21(sp_digit* r, const sp_digit* a, int n,
  32942. const sp_digit* m, sp_digit mp)
  32943. {
  32944. sp_521_mont_sqr_21(r, a, m, mp);
  32945. for (; n > 1; n--) {
  32946. sp_521_mont_sqr_21(r, r, m, mp);
  32947. }
  32948. }
  32949. #endif /* !WOLFSSL_SP_SMALL | HAVE_COMP_KEY */
  32950. #ifdef WOLFSSL_SP_SMALL
  32951. /* Mod-2 for the P521 curve. */
  32952. static const uint32_t p521_mod_minus_2[17] = {
  32953. 0xfffffffdU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,
  32954. 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,
  32955. 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0x000001ffU
  32956. };
  32957. #endif /* !WOLFSSL_SP_SMALL */
  32958. /* Invert the number, in Montgomery form, modulo the modulus (prime) of the
  32959. * P521 curve. (r = 1 / a mod m)
  32960. *
  32961. * r Inverse result.
  32962. * a Number to invert.
  32963. * td Temporary data.
  32964. */
  32965. static void sp_521_mont_inv_21(sp_digit* r, const sp_digit* a, sp_digit* td)
  32966. {
  32967. #ifdef WOLFSSL_SP_SMALL
  32968. sp_digit* t = td;
  32969. int i;
  32970. XMEMCPY(t, a, sizeof(sp_digit) * 21);
  32971. for (i=519; i>=0; i--) {
  32972. sp_521_mont_sqr_21(t, t, p521_mod, p521_mp_mod);
  32973. if (p521_mod_minus_2[i / 32] & ((sp_digit)1 << (i % 32)))
  32974. sp_521_mont_mul_21(t, t, a, p521_mod, p521_mp_mod);
  32975. }
  32976. XMEMCPY(r, t, sizeof(sp_digit) * 21);
  32977. #else
  32978. sp_digit* t1 = td;
  32979. sp_digit* t2 = td + 2 * 21;
  32980. sp_digit* t3 = td + 4 * 21;
  32981. /* 0x2 */
  32982. sp_521_mont_sqr_21(t1, a, p521_mod, p521_mp_mod);
  32983. /* 0x3 */
  32984. sp_521_mont_mul_21(t2, t1, a, p521_mod, p521_mp_mod);
  32985. /* 0x6 */
  32986. sp_521_mont_sqr_21(t1, t2, p521_mod, p521_mp_mod);
  32987. /* 0x7 */
  32988. sp_521_mont_mul_21(t3, t1, a, p521_mod, p521_mp_mod);
  32989. /* 0xc */
  32990. sp_521_mont_sqr_n_21(t1, t2, 2, p521_mod, p521_mp_mod);
  32991. /* 0xf */
  32992. sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod);
  32993. /* 0x78 */
  32994. sp_521_mont_sqr_n_21(t1, t2, 3, p521_mod, p521_mp_mod);
  32995. /* 0x7f */
  32996. sp_521_mont_mul_21(t3, t3, t1, p521_mod, p521_mp_mod);
  32997. /* 0xf0 */
  32998. sp_521_mont_sqr_n_21(t1, t2, 4, p521_mod, p521_mp_mod);
  32999. /* 0xff */
  33000. sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod);
  33001. /* 0xff00 */
  33002. sp_521_mont_sqr_n_21(t1, t2, 8, p521_mod, p521_mp_mod);
  33003. /* 0xffff */
  33004. sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod);
  33005. /* 0xffff0000 */
  33006. sp_521_mont_sqr_n_21(t1, t2, 16, p521_mod, p521_mp_mod);
  33007. /* 0xffffffff */
  33008. sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod);
  33009. /* 0xffffffff00000000 */
  33010. sp_521_mont_sqr_n_21(t1, t2, 32, p521_mod, p521_mp_mod);
  33011. /* 0xffffffffffffffff */
  33012. sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod);
  33013. /* 0xffffffffffffffff0000000000000000 */
  33014. sp_521_mont_sqr_n_21(t1, t2, 64, p521_mod, p521_mp_mod);
  33015. /* 0xffffffffffffffffffffffffffffffff */
  33016. sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod);
  33017. /* 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000 */
  33018. sp_521_mont_sqr_n_21(t1, t2, 128, p521_mod, p521_mp_mod);
  33019. /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */
  33020. sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod);
  33021. /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000 */
  33022. sp_521_mont_sqr_n_21(t1, t2, 256, p521_mod, p521_mp_mod);
  33023. /* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */
  33024. sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod);
  33025. /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80 */
  33026. sp_521_mont_sqr_n_21(t1, t2, 7, p521_mod, p521_mp_mod);
  33027. /* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */
  33028. sp_521_mont_mul_21(t2, t3, t1, p521_mod, p521_mp_mod);
  33029. /* 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc */
  33030. sp_521_mont_sqr_n_21(t1, t2, 2, p521_mod, p521_mp_mod);
  33031. /* 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd */
  33032. sp_521_mont_mul_21(r, t1, a, p521_mod, p521_mp_mod);
  33033. #endif /* WOLFSSL_SP_SMALL */
  33034. }
  33035. /* Map the Montgomery form projective coordinate point to an affine point.
  33036. *
  33037. * r Resulting affine coordinate point.
  33038. * p Montgomery form projective coordinate point.
  33039. * t Temporary ordinate data.
  33040. */
  33041. static void sp_521_map_21(sp_point_521* r, const sp_point_521* p,
  33042. sp_digit* t)
  33043. {
  33044. sp_digit* t1 = t;
  33045. sp_digit* t2 = t + 2*21;
  33046. sp_int32 n;
  33047. sp_521_mont_inv_21(t1, p->z, t + 2*21);
  33048. sp_521_mont_sqr_21(t2, t1, p521_mod, p521_mp_mod);
  33049. sp_521_mont_mul_21(t1, t2, t1, p521_mod, p521_mp_mod);
  33050. /* x /= z^2 */
  33051. sp_521_mont_mul_21(r->x, p->x, t2, p521_mod, p521_mp_mod);
  33052. XMEMSET(r->x + 21, 0, sizeof(r->x) / 2U);
  33053. sp_521_mont_reduce_21(r->x, p521_mod, p521_mp_mod);
  33054. /* Reduce x to less than modulus */
  33055. n = sp_521_cmp_21(r->x, p521_mod);
  33056. sp_521_cond_sub_21(r->x, r->x, p521_mod, ~(n >> 24));
  33057. sp_521_norm_21(r->x);
  33058. /* y /= z^3 */
  33059. sp_521_mont_mul_21(r->y, p->y, t1, p521_mod, p521_mp_mod);
  33060. XMEMSET(r->y + 21, 0, sizeof(r->y) / 2U);
  33061. sp_521_mont_reduce_21(r->y, p521_mod, p521_mp_mod);
  33062. /* Reduce y to less than modulus */
  33063. n = sp_521_cmp_21(r->y, p521_mod);
  33064. sp_521_cond_sub_21(r->y, r->y, p521_mod, ~(n >> 24));
  33065. sp_521_norm_21(r->y);
  33066. XMEMSET(r->z, 0, sizeof(r->z) / 2);
  33067. r->z[0] = 1;
  33068. }
  33069. /* Add two Montgomery form numbers (r = a + b % m).
  33070. *
  33071. * r Result of addition.
  33072. * a First number to add in Montgomery form.
  33073. * b Second number to add in Montgomery form.
  33074. * m Modulus (prime).
  33075. */
  33076. static void sp_521_mont_add_21(sp_digit* r, const sp_digit* a, const sp_digit* b,
  33077. const sp_digit* m)
  33078. {
  33079. sp_digit over;
  33080. (void)sp_521_add_21(r, a, b);
  33081. sp_521_norm_21(r);
  33082. over = r[20] >> 21;
  33083. sp_521_cond_sub_21(r, r, m, ~((over - 1) >> 31));
  33084. sp_521_norm_21(r);
  33085. }
  33086. /* Double a Montgomery form number (r = a + a % m).
  33087. *
  33088. * r Result of doubling.
  33089. * a Number to double in Montgomery form.
  33090. * m Modulus (prime).
  33091. */
  33092. static void sp_521_mont_dbl_21(sp_digit* r, const sp_digit* a, const sp_digit* m)
  33093. {
  33094. sp_digit over;
  33095. (void)sp_521_add_21(r, a, a);
  33096. sp_521_norm_21(r);
  33097. over = r[20] >> 21;
  33098. sp_521_cond_sub_21(r, r, m, ~((over - 1) >> 31));
  33099. sp_521_norm_21(r);
  33100. }
  33101. /* Triple a Montgomery form number (r = a + a + a % m).
  33102. *
  33103. * r Result of Tripling.
  33104. * a Number to triple in Montgomery form.
  33105. * m Modulus (prime).
  33106. */
  33107. static void sp_521_mont_tpl_21(sp_digit* r, const sp_digit* a, const sp_digit* m)
  33108. {
  33109. sp_digit over;
  33110. (void)sp_521_add_21(r, a, a);
  33111. sp_521_norm_21(r);
  33112. over = r[20] >> 21;
  33113. sp_521_cond_sub_21(r, r, m, ~((over - 1) >> 31));
  33114. sp_521_norm_21(r);
  33115. (void)sp_521_add_21(r, r, a);
  33116. sp_521_norm_21(r);
  33117. over = r[20] >> 21;
  33118. sp_521_cond_sub_21(r, r, m, ~((over - 1) >> 31));
  33119. sp_521_norm_21(r);
  33120. }
  33121. #ifdef WOLFSSL_SP_SMALL
  33122. /* Conditionally add a and b using the mask m.
  33123. * m is -1 to add and 0 when not.
  33124. *
  33125. * r A single precision number representing conditional add result.
  33126. * a A single precision number to add with.
  33127. * b A single precision number to add.
  33128. * m Mask value to apply.
  33129. */
  33130. static void sp_521_cond_add_21(sp_digit* r, const sp_digit* a,
  33131. const sp_digit* b, const sp_digit m)
  33132. {
  33133. int i;
  33134. for (i = 0; i < 21; i++) {
  33135. r[i] = a[i] + (b[i] & m);
  33136. }
  33137. }
  33138. #endif /* WOLFSSL_SP_SMALL */
  33139. #ifndef WOLFSSL_SP_SMALL
  33140. /* Conditionally add a and b using the mask m.
  33141. * m is -1 to add and 0 when not.
  33142. *
  33143. * r A single precision number representing conditional add result.
  33144. * a A single precision number to add with.
  33145. * b A single precision number to add.
  33146. * m Mask value to apply.
  33147. */
  33148. static void sp_521_cond_add_21(sp_digit* r, const sp_digit* a,
  33149. const sp_digit* b, const sp_digit m)
  33150. {
  33151. int i;
  33152. for (i = 0; i < 16; i += 8) {
  33153. r[i + 0] = a[i + 0] + (b[i + 0] & m);
  33154. r[i + 1] = a[i + 1] + (b[i + 1] & m);
  33155. r[i + 2] = a[i + 2] + (b[i + 2] & m);
  33156. r[i + 3] = a[i + 3] + (b[i + 3] & m);
  33157. r[i + 4] = a[i + 4] + (b[i + 4] & m);
  33158. r[i + 5] = a[i + 5] + (b[i + 5] & m);
  33159. r[i + 6] = a[i + 6] + (b[i + 6] & m);
  33160. r[i + 7] = a[i + 7] + (b[i + 7] & m);
  33161. }
  33162. r[16] = a[16] + (b[16] & m);
  33163. r[17] = a[17] + (b[17] & m);
  33164. r[18] = a[18] + (b[18] & m);
  33165. r[19] = a[19] + (b[19] & m);
  33166. r[20] = a[20] + (b[20] & m);
  33167. }
  33168. #endif /* !WOLFSSL_SP_SMALL */
  33169. /* Subtract two Montgomery form numbers (r = a - b % m).
  33170. *
  33171. * r Result of subtration.
  33172. * a Number to subtract from in Montgomery form.
  33173. * b Number to subtract with in Montgomery form.
  33174. * m Modulus (prime).
  33175. */
  33176. static void sp_521_mont_sub_21(sp_digit* r, const sp_digit* a, const sp_digit* b,
  33177. const sp_digit* m)
  33178. {
  33179. (void)sp_521_sub_21(r, a, b);
  33180. sp_521_norm_21(r);
  33181. sp_521_cond_add_21(r, r, m, r[20] >> 21);
  33182. sp_521_norm_21(r);
  33183. }
  33184. #define sp_521_mont_sub_lower_21 sp_521_mont_sub_21
  33185. /* Shift number left one bit.
  33186. * Bottom bit is lost.
  33187. *
  33188. * r Result of shift.
  33189. * a Number to shift.
  33190. */
  33191. SP_NOINLINE static void sp_521_rshift1_21(sp_digit* r, const sp_digit* a)
  33192. {
  33193. #ifdef WOLFSSL_SP_SMALL
  33194. int i;
  33195. for (i=0; i<20; i++) {
  33196. r[i] = (a[i] >> 1) + ((a[i + 1] << 24) & 0x1ffffff);
  33197. }
  33198. #else
  33199. r[0] = (a[0] >> 1) + ((a[1] << 24) & 0x1ffffff);
  33200. r[1] = (a[1] >> 1) + ((a[2] << 24) & 0x1ffffff);
  33201. r[2] = (a[2] >> 1) + ((a[3] << 24) & 0x1ffffff);
  33202. r[3] = (a[3] >> 1) + ((a[4] << 24) & 0x1ffffff);
  33203. r[4] = (a[4] >> 1) + ((a[5] << 24) & 0x1ffffff);
  33204. r[5] = (a[5] >> 1) + ((a[6] << 24) & 0x1ffffff);
  33205. r[6] = (a[6] >> 1) + ((a[7] << 24) & 0x1ffffff);
  33206. r[7] = (a[7] >> 1) + ((a[8] << 24) & 0x1ffffff);
  33207. r[8] = (a[8] >> 1) + ((a[9] << 24) & 0x1ffffff);
  33208. r[9] = (a[9] >> 1) + ((a[10] << 24) & 0x1ffffff);
  33209. r[10] = (a[10] >> 1) + ((a[11] << 24) & 0x1ffffff);
  33210. r[11] = (a[11] >> 1) + ((a[12] << 24) & 0x1ffffff);
  33211. r[12] = (a[12] >> 1) + ((a[13] << 24) & 0x1ffffff);
  33212. r[13] = (a[13] >> 1) + ((a[14] << 24) & 0x1ffffff);
  33213. r[14] = (a[14] >> 1) + ((a[15] << 24) & 0x1ffffff);
  33214. r[15] = (a[15] >> 1) + ((a[16] << 24) & 0x1ffffff);
  33215. r[16] = (a[16] >> 1) + ((a[17] << 24) & 0x1ffffff);
  33216. r[17] = (a[17] >> 1) + ((a[18] << 24) & 0x1ffffff);
  33217. r[18] = (a[18] >> 1) + ((a[19] << 24) & 0x1ffffff);
  33218. r[19] = (a[19] >> 1) + ((a[20] << 24) & 0x1ffffff);
  33219. #endif
  33220. r[20] = a[20] >> 1;
  33221. }
  33222. /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
  33223. *
  33224. * r Result of division by 2.
  33225. * a Number to divide.
  33226. * m Modulus (prime).
  33227. */
  33228. static void sp_521_div2_21(sp_digit* r, const sp_digit* a, const sp_digit* m)
  33229. {
  33230. sp_521_cond_add_21(r, a, m, 0 - (a[0] & 1));
  33231. sp_521_norm_21(r);
  33232. sp_521_rshift1_21(r, r);
  33233. }
  33234. /* Double the Montgomery form projective point p.
  33235. *
  33236. * r Result of doubling point.
  33237. * p Point to double.
  33238. * t Temporary ordinate data.
  33239. */
  33240. #ifdef WOLFSSL_SP_NONBLOCK
  33241. typedef struct sp_521_proj_point_dbl_21_ctx {
  33242. int state;
  33243. sp_digit* t1;
  33244. sp_digit* t2;
  33245. sp_digit* x;
  33246. sp_digit* y;
  33247. sp_digit* z;
  33248. } sp_521_proj_point_dbl_21_ctx;
  33249. static int sp_521_proj_point_dbl_21_nb(sp_ecc_ctx_t* sp_ctx, sp_point_521* r, const sp_point_521* p, sp_digit* t)
  33250. {
  33251. int err = FP_WOULDBLOCK;
  33252. sp_521_proj_point_dbl_21_ctx* ctx = (sp_521_proj_point_dbl_21_ctx*)sp_ctx->data;
  33253. typedef char ctx_size_test[sizeof(sp_521_proj_point_dbl_21_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  33254. (void)sizeof(ctx_size_test);
  33255. switch (ctx->state) {
  33256. case 0:
  33257. ctx->t1 = t;
  33258. ctx->t2 = t + 2*21;
  33259. ctx->x = r->x;
  33260. ctx->y = r->y;
  33261. ctx->z = r->z;
  33262. /* Put infinity into result. */
  33263. if (r != p) {
  33264. r->infinity = p->infinity;
  33265. }
  33266. ctx->state = 1;
  33267. break;
  33268. case 1:
  33269. /* T1 = Z * Z */
  33270. sp_521_mont_sqr_21(ctx->t1, p->z, p521_mod, p521_mp_mod);
  33271. ctx->state = 2;
  33272. break;
  33273. case 2:
  33274. /* Z = Y * Z */
  33275. sp_521_mont_mul_21(ctx->z, p->y, p->z, p521_mod, p521_mp_mod);
  33276. ctx->state = 3;
  33277. break;
  33278. case 3:
  33279. /* Z = 2Z */
  33280. sp_521_mont_dbl_21(ctx->z, ctx->z, p521_mod);
  33281. ctx->state = 4;
  33282. break;
  33283. case 4:
  33284. /* T2 = X - T1 */
  33285. sp_521_mont_sub_21(ctx->t2, p->x, ctx->t1, p521_mod);
  33286. ctx->state = 5;
  33287. break;
  33288. case 5:
  33289. /* T1 = X + T1 */
  33290. sp_521_mont_add_21(ctx->t1, p->x, ctx->t1, p521_mod);
  33291. ctx->state = 6;
  33292. break;
  33293. case 6:
  33294. /* T2 = T1 * T2 */
  33295. sp_521_mont_mul_21(ctx->t2, ctx->t1, ctx->t2, p521_mod, p521_mp_mod);
  33296. ctx->state = 7;
  33297. break;
  33298. case 7:
  33299. /* T1 = 3T2 */
  33300. sp_521_mont_tpl_21(ctx->t1, ctx->t2, p521_mod);
  33301. ctx->state = 8;
  33302. break;
  33303. case 8:
  33304. /* Y = 2Y */
  33305. sp_521_mont_dbl_21(ctx->y, p->y, p521_mod);
  33306. ctx->state = 9;
  33307. break;
  33308. case 9:
  33309. /* Y = Y * Y */
  33310. sp_521_mont_sqr_21(ctx->y, ctx->y, p521_mod, p521_mp_mod);
  33311. ctx->state = 10;
  33312. break;
  33313. case 10:
  33314. /* T2 = Y * Y */
  33315. sp_521_mont_sqr_21(ctx->t2, ctx->y, p521_mod, p521_mp_mod);
  33316. ctx->state = 11;
  33317. break;
  33318. case 11:
  33319. /* T2 = T2/2 */
  33320. sp_521_div2_21(ctx->t2, ctx->t2, p521_mod);
  33321. ctx->state = 12;
  33322. break;
  33323. case 12:
  33324. /* Y = Y * X */
  33325. sp_521_mont_mul_21(ctx->y, ctx->y, p->x, p521_mod, p521_mp_mod);
  33326. ctx->state = 13;
  33327. break;
  33328. case 13:
  33329. /* X = T1 * T1 */
  33330. sp_521_mont_sqr_21(ctx->x, ctx->t1, p521_mod, p521_mp_mod);
  33331. ctx->state = 14;
  33332. break;
  33333. case 14:
  33334. /* X = X - Y */
  33335. sp_521_mont_sub_21(ctx->x, ctx->x, ctx->y, p521_mod);
  33336. ctx->state = 15;
  33337. break;
  33338. case 15:
  33339. /* X = X - Y */
  33340. sp_521_mont_sub_21(ctx->x, ctx->x, ctx->y, p521_mod);
  33341. ctx->state = 16;
  33342. break;
  33343. case 16:
  33344. /* Y = Y - X */
  33345. sp_521_mont_sub_lower_21(ctx->y, ctx->y, ctx->x, p521_mod);
  33346. ctx->state = 17;
  33347. break;
  33348. case 17:
  33349. /* Y = Y * T1 */
  33350. sp_521_mont_mul_21(ctx->y, ctx->y, ctx->t1, p521_mod, p521_mp_mod);
  33351. ctx->state = 18;
  33352. break;
  33353. case 18:
  33354. /* Y = Y - T2 */
  33355. sp_521_mont_sub_21(ctx->y, ctx->y, ctx->t2, p521_mod);
  33356. ctx->state = 19;
  33357. /* fall-through */
  33358. case 19:
  33359. err = MP_OKAY;
  33360. break;
  33361. }
  33362. if (err == MP_OKAY && ctx->state != 19) {
  33363. err = FP_WOULDBLOCK;
  33364. }
  33365. return err;
  33366. }
  33367. #endif /* WOLFSSL_SP_NONBLOCK */
  33368. static void sp_521_proj_point_dbl_21(sp_point_521* r, const sp_point_521* p,
  33369. sp_digit* t)
  33370. {
  33371. sp_digit* t1 = t;
  33372. sp_digit* t2 = t + 2*21;
  33373. sp_digit* x;
  33374. sp_digit* y;
  33375. sp_digit* z;
  33376. x = r->x;
  33377. y = r->y;
  33378. z = r->z;
  33379. /* Put infinity into result. */
  33380. if (r != p) {
  33381. r->infinity = p->infinity;
  33382. }
  33383. /* T1 = Z * Z */
  33384. sp_521_mont_sqr_21(t1, p->z, p521_mod, p521_mp_mod);
  33385. /* Z = Y * Z */
  33386. sp_521_mont_mul_21(z, p->y, p->z, p521_mod, p521_mp_mod);
  33387. /* Z = 2Z */
  33388. sp_521_mont_dbl_21(z, z, p521_mod);
  33389. /* T2 = X - T1 */
  33390. sp_521_mont_sub_21(t2, p->x, t1, p521_mod);
  33391. /* T1 = X + T1 */
  33392. sp_521_mont_add_21(t1, p->x, t1, p521_mod);
  33393. /* T2 = T1 * T2 */
  33394. sp_521_mont_mul_21(t2, t1, t2, p521_mod, p521_mp_mod);
  33395. /* T1 = 3T2 */
  33396. sp_521_mont_tpl_21(t1, t2, p521_mod);
  33397. /* Y = 2Y */
  33398. sp_521_mont_dbl_21(y, p->y, p521_mod);
  33399. /* Y = Y * Y */
  33400. sp_521_mont_sqr_21(y, y, p521_mod, p521_mp_mod);
  33401. /* T2 = Y * Y */
  33402. sp_521_mont_sqr_21(t2, y, p521_mod, p521_mp_mod);
  33403. /* T2 = T2/2 */
  33404. sp_521_div2_21(t2, t2, p521_mod);
  33405. /* Y = Y * X */
  33406. sp_521_mont_mul_21(y, y, p->x, p521_mod, p521_mp_mod);
  33407. /* X = T1 * T1 */
  33408. sp_521_mont_sqr_21(x, t1, p521_mod, p521_mp_mod);
  33409. /* X = X - Y */
  33410. sp_521_mont_sub_21(x, x, y, p521_mod);
  33411. /* X = X - Y */
  33412. sp_521_mont_sub_21(x, x, y, p521_mod);
  33413. /* Y = Y - X */
  33414. sp_521_mont_sub_lower_21(y, y, x, p521_mod);
  33415. /* Y = Y * T1 */
  33416. sp_521_mont_mul_21(y, y, t1, p521_mod, p521_mp_mod);
  33417. /* Y = Y - T2 */
  33418. sp_521_mont_sub_21(y, y, t2, p521_mod);
  33419. }
  33420. /* Compare two numbers to determine if they are equal.
  33421. * Constant time implementation.
  33422. *
  33423. * a First number to compare.
  33424. * b Second number to compare.
  33425. * returns 1 when equal and 0 otherwise.
  33426. */
  33427. static int sp_521_cmp_equal_21(const sp_digit* a, const sp_digit* b)
  33428. {
  33429. return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) |
  33430. (a[3] ^ b[3]) | (a[4] ^ b[4]) | (a[5] ^ b[5]) |
  33431. (a[6] ^ b[6]) | (a[7] ^ b[7]) | (a[8] ^ b[8]) |
  33432. (a[9] ^ b[9]) | (a[10] ^ b[10]) | (a[11] ^ b[11]) |
  33433. (a[12] ^ b[12]) | (a[13] ^ b[13]) | (a[14] ^ b[14]) |
  33434. (a[15] ^ b[15]) | (a[16] ^ b[16]) | (a[17] ^ b[17]) |
  33435. (a[18] ^ b[18]) | (a[19] ^ b[19]) | (a[20] ^ b[20])) == 0;
  33436. }
  33437. /* Returns 1 if the number of zero.
  33438. * Implementation is constant time.
  33439. *
  33440. * a Number to check.
  33441. * returns 1 if the number is zero and 0 otherwise.
  33442. */
  33443. static int sp_521_iszero_21(const sp_digit* a)
  33444. {
  33445. return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] |
  33446. a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14] | a[15] |
  33447. a[16] | a[17] | a[18] | a[19] | a[20]) == 0;
  33448. }
  33449. /* Add two Montgomery form projective points.
  33450. *
  33451. * r Result of addition.
  33452. * p First point to add.
  33453. * q Second point to add.
  33454. * t Temporary ordinate data.
  33455. */
  33456. #ifdef WOLFSSL_SP_NONBLOCK
  33457. typedef struct sp_521_proj_point_add_21_ctx {
  33458. int state;
  33459. sp_521_proj_point_dbl_21_ctx dbl_ctx;
  33460. const sp_point_521* ap[2];
  33461. sp_point_521* rp[2];
  33462. sp_digit* t1;
  33463. sp_digit* t2;
  33464. sp_digit* t3;
  33465. sp_digit* t4;
  33466. sp_digit* t5;
  33467. sp_digit* t6;
  33468. sp_digit* x;
  33469. sp_digit* y;
  33470. sp_digit* z;
  33471. } sp_521_proj_point_add_21_ctx;
  33472. static int sp_521_proj_point_add_21_nb(sp_ecc_ctx_t* sp_ctx, sp_point_521* r,
  33473. const sp_point_521* p, const sp_point_521* q, sp_digit* t)
  33474. {
  33475. int err = FP_WOULDBLOCK;
  33476. sp_521_proj_point_add_21_ctx* ctx = (sp_521_proj_point_add_21_ctx*)sp_ctx->data;
  33477. /* Ensure only the first point is the same as the result. */
  33478. if (q == r) {
  33479. const sp_point_521* a = p;
  33480. p = q;
  33481. q = a;
  33482. }
  33483. typedef char ctx_size_test[sizeof(sp_521_proj_point_add_21_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  33484. (void)sizeof(ctx_size_test);
  33485. switch (ctx->state) {
  33486. case 0: /* INIT */
  33487. ctx->t1 = t;
  33488. ctx->t2 = t + 2*21;
  33489. ctx->t3 = t + 4*21;
  33490. ctx->t4 = t + 6*21;
  33491. ctx->t5 = t + 8*21;
  33492. ctx->t6 = t + 10*21;
  33493. ctx->x = ctx->t6;
  33494. ctx->y = ctx->t1;
  33495. ctx->z = ctx->t2;
  33496. ctx->state = 1;
  33497. break;
  33498. case 1:
  33499. /* Check double */
  33500. (void)sp_521_sub_21(ctx->t1, p521_mod, q->y);
  33501. sp_521_norm_21(ctx->t1);
  33502. if ((~p->infinity & ~q->infinity &
  33503. sp_521_cmp_equal_21(p->x, q->x) & sp_521_cmp_equal_21(p->z, q->z) &
  33504. (sp_521_cmp_equal_21(p->y, q->y) | sp_521_cmp_equal_21(p->y, ctx->t1))) != 0)
  33505. {
  33506. XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
  33507. ctx->state = 2;
  33508. }
  33509. else {
  33510. ctx->state = 3;
  33511. }
  33512. break;
  33513. case 2:
  33514. err = sp_521_proj_point_dbl_21_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t);
  33515. if (err == MP_OKAY)
  33516. ctx->state = 27; /* done */
  33517. break;
  33518. case 3:
  33519. {
  33520. ctx->state = 4;
  33521. break;
  33522. }
  33523. case 4:
  33524. /* U1 = X1*Z2^2 */
  33525. sp_521_mont_sqr_21(ctx->t1, q->z, p521_mod, p521_mp_mod);
  33526. ctx->state = 5;
  33527. break;
  33528. case 5:
  33529. sp_521_mont_mul_21(ctx->t3, ctx->t1, q->z, p521_mod, p521_mp_mod);
  33530. ctx->state = 6;
  33531. break;
  33532. case 6:
  33533. sp_521_mont_mul_21(ctx->t1, ctx->t1, p->x, p521_mod, p521_mp_mod);
  33534. ctx->state = 7;
  33535. break;
  33536. case 7:
  33537. /* U2 = X2*Z1^2 */
  33538. sp_521_mont_sqr_21(ctx->t2, p->z, p521_mod, p521_mp_mod);
  33539. ctx->state = 8;
  33540. break;
  33541. case 8:
  33542. sp_521_mont_mul_21(ctx->t4, ctx->t2, p->z, p521_mod, p521_mp_mod);
  33543. ctx->state = 9;
  33544. break;
  33545. case 9:
  33546. sp_521_mont_mul_21(ctx->t2, ctx->t2, q->x, p521_mod, p521_mp_mod);
  33547. ctx->state = 10;
  33548. break;
  33549. case 10:
  33550. /* S1 = Y1*Z2^3 */
  33551. sp_521_mont_mul_21(ctx->t3, ctx->t3, p->y, p521_mod, p521_mp_mod);
  33552. ctx->state = 11;
  33553. break;
  33554. case 11:
  33555. /* S2 = Y2*Z1^3 */
  33556. sp_521_mont_mul_21(ctx->t4, ctx->t4, q->y, p521_mod, p521_mp_mod);
  33557. ctx->state = 12;
  33558. break;
  33559. case 12:
  33560. /* H = U2 - U1 */
  33561. sp_521_mont_sub_21(ctx->t2, ctx->t2, ctx->t1, p521_mod);
  33562. ctx->state = 13;
  33563. break;
  33564. case 13:
  33565. /* R = S2 - S1 */
  33566. sp_521_mont_sub_21(ctx->t4, ctx->t4, ctx->t3, p521_mod);
  33567. ctx->state = 14;
  33568. break;
  33569. case 14:
  33570. /* X3 = R^2 - H^3 - 2*U1*H^2 */
  33571. sp_521_mont_sqr_21(ctx->t5, ctx->t2, p521_mod, p521_mp_mod);
  33572. ctx->state = 15;
  33573. break;
  33574. case 15:
  33575. sp_521_mont_mul_21(ctx->y, ctx->t1, ctx->t5, p521_mod, p521_mp_mod);
  33576. ctx->state = 16;
  33577. break;
  33578. case 16:
  33579. sp_521_mont_mul_21(ctx->t5, ctx->t5, ctx->t2, p521_mod, p521_mp_mod);
  33580. ctx->state = 17;
  33581. break;
  33582. case 17:
  33583. /* Z3 = H*Z1*Z2 */
  33584. sp_521_mont_mul_21(ctx->z, p->z, ctx->t2, p521_mod, p521_mp_mod);
  33585. ctx->state = 18;
  33586. break;
  33587. case 18:
  33588. sp_521_mont_mul_21(ctx->z, ctx->z, q->z, p521_mod, p521_mp_mod);
  33589. ctx->state = 19;
  33590. break;
  33591. case 19:
  33592. sp_521_mont_sqr_21(ctx->x, ctx->t4, p521_mod, p521_mp_mod);
  33593. ctx->state = 20;
  33594. break;
  33595. case 20:
  33596. sp_521_mont_sub_21(ctx->x, ctx->x, ctx->t5, p521_mod);
  33597. ctx->state = 21;
  33598. break;
  33599. case 21:
  33600. sp_521_mont_mul_21(ctx->t5, ctx->t5, ctx->t3, p521_mod, p521_mp_mod);
  33601. ctx->state = 22;
  33602. break;
  33603. case 22:
  33604. sp_521_mont_dbl_21(ctx->t3, ctx->y, p521_mod);
  33605. ctx->state = 23;
  33606. break;
  33607. case 23:
  33608. sp_521_mont_sub_21(ctx->x, ctx->x, ctx->t3, p521_mod);
  33609. ctx->state = 24;
  33610. break;
  33611. case 24:
  33612. /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
  33613. sp_521_mont_sub_lower_21(ctx->y, ctx->y, ctx->x, p521_mod);
  33614. ctx->state = 25;
  33615. break;
  33616. case 25:
  33617. sp_521_mont_mul_21(ctx->y, ctx->y, ctx->t4, p521_mod, p521_mp_mod);
  33618. ctx->state = 26;
  33619. break;
  33620. case 26:
  33621. sp_521_mont_sub_21(ctx->y, ctx->y, ctx->t5, p521_mod);
  33622. ctx->state = 27;
  33623. /* fall-through */
  33624. case 27:
  33625. {
  33626. int i;
  33627. sp_digit maskp = 0 - (q->infinity & (!p->infinity));
  33628. sp_digit maskq = 0 - (p->infinity & (!q->infinity));
  33629. sp_digit maskt = ~(maskp | maskq);
  33630. for (i = 0; i < 21; i++) {
  33631. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) |
  33632. (ctx->x[i] & maskt);
  33633. }
  33634. for (i = 0; i < 21; i++) {
  33635. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) |
  33636. (ctx->y[i] & maskt);
  33637. }
  33638. for (i = 0; i < 21; i++) {
  33639. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) |
  33640. (ctx->z[i] & maskt);
  33641. }
  33642. r->z[0] |= p->infinity & q->infinity;
  33643. r->infinity = p->infinity & q->infinity;
  33644. err = MP_OKAY;
  33645. break;
  33646. }
  33647. }
  33648. if (err == MP_OKAY && ctx->state != 27) {
  33649. err = FP_WOULDBLOCK;
  33650. }
  33651. return err;
  33652. }
  33653. #endif /* WOLFSSL_SP_NONBLOCK */
  33654. static void sp_521_proj_point_add_21(sp_point_521* r,
  33655. const sp_point_521* p, const sp_point_521* q, sp_digit* t)
  33656. {
  33657. sp_digit* t1 = t;
  33658. sp_digit* t2 = t + 2*21;
  33659. sp_digit* t3 = t + 4*21;
  33660. sp_digit* t4 = t + 6*21;
  33661. sp_digit* t5 = t + 8*21;
  33662. sp_digit* t6 = t + 10*21;
  33663. /* Check double */
  33664. (void)sp_521_sub_21(t1, p521_mod, q->y);
  33665. sp_521_norm_21(t1);
  33666. if ((~p->infinity & ~q->infinity &
  33667. sp_521_cmp_equal_21(p->x, q->x) & sp_521_cmp_equal_21(p->z, q->z) &
  33668. (sp_521_cmp_equal_21(p->y, q->y) | sp_521_cmp_equal_21(p->y, t1))) != 0) {
  33669. sp_521_proj_point_dbl_21(r, p, t);
  33670. }
  33671. else {
  33672. sp_digit maskp;
  33673. sp_digit maskq;
  33674. sp_digit maskt;
  33675. sp_digit* x = t6;
  33676. sp_digit* y = t1;
  33677. sp_digit* z = t2;
  33678. int i;
  33679. maskp = 0 - (q->infinity & (!p->infinity));
  33680. maskq = 0 - (p->infinity & (!q->infinity));
  33681. maskt = ~(maskp | maskq);
  33682. /* U1 = X1*Z2^2 */
  33683. sp_521_mont_sqr_21(t1, q->z, p521_mod, p521_mp_mod);
  33684. sp_521_mont_mul_21(t3, t1, q->z, p521_mod, p521_mp_mod);
  33685. sp_521_mont_mul_21(t1, t1, p->x, p521_mod, p521_mp_mod);
  33686. /* U2 = X2*Z1^2 */
  33687. sp_521_mont_sqr_21(t2, p->z, p521_mod, p521_mp_mod);
  33688. sp_521_mont_mul_21(t4, t2, p->z, p521_mod, p521_mp_mod);
  33689. sp_521_mont_mul_21(t2, t2, q->x, p521_mod, p521_mp_mod);
  33690. /* S1 = Y1*Z2^3 */
  33691. sp_521_mont_mul_21(t3, t3, p->y, p521_mod, p521_mp_mod);
  33692. /* S2 = Y2*Z1^3 */
  33693. sp_521_mont_mul_21(t4, t4, q->y, p521_mod, p521_mp_mod);
  33694. /* H = U2 - U1 */
  33695. sp_521_mont_sub_21(t2, t2, t1, p521_mod);
  33696. /* R = S2 - S1 */
  33697. sp_521_mont_sub_21(t4, t4, t3, p521_mod);
  33698. if (~p->infinity & ~q->infinity &
  33699. sp_521_iszero_21(t2) & sp_521_iszero_21(t4) & maskt) {
  33700. sp_521_proj_point_dbl_21(r, p, t);
  33701. }
  33702. else {
  33703. /* X3 = R^2 - H^3 - 2*U1*H^2 */
  33704. sp_521_mont_sqr_21(t5, t2, p521_mod, p521_mp_mod);
  33705. sp_521_mont_mul_21(y, t1, t5, p521_mod, p521_mp_mod);
  33706. sp_521_mont_mul_21(t5, t5, t2, p521_mod, p521_mp_mod);
  33707. /* Z3 = H*Z1*Z2 */
  33708. sp_521_mont_mul_21(z, p->z, t2, p521_mod, p521_mp_mod);
  33709. sp_521_mont_mul_21(z, z, q->z, p521_mod, p521_mp_mod);
  33710. sp_521_mont_sqr_21(x, t4, p521_mod, p521_mp_mod);
  33711. sp_521_mont_sub_21(x, x, t5, p521_mod);
  33712. sp_521_mont_mul_21(t5, t5, t3, p521_mod, p521_mp_mod);
  33713. sp_521_mont_dbl_21(t3, y, p521_mod);
  33714. sp_521_mont_sub_21(x, x, t3, p521_mod);
  33715. /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
  33716. sp_521_mont_sub_lower_21(y, y, x, p521_mod);
  33717. sp_521_mont_mul_21(y, y, t4, p521_mod, p521_mp_mod);
  33718. sp_521_mont_sub_21(y, y, t5, p521_mod);
  33719. for (i = 0; i < 21; i++) {
  33720. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) |
  33721. (x[i] & maskt);
  33722. }
  33723. for (i = 0; i < 21; i++) {
  33724. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) |
  33725. (y[i] & maskt);
  33726. }
  33727. for (i = 0; i < 21; i++) {
  33728. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) |
  33729. (z[i] & maskt);
  33730. }
  33731. r->z[0] |= p->infinity & q->infinity;
  33732. r->infinity = p->infinity & q->infinity;
  33733. }
  33734. }
  33735. }
  33736. /* Multiply a number by Montgomery normalizer mod modulus (prime).
  33737. *
  33738. * r The resulting Montgomery form number.
  33739. * a The number to convert.
  33740. * m The modulus (prime).
  33741. * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
  33742. */
  33743. static int sp_521_mod_mul_norm_21(sp_digit* r, const sp_digit* a, const sp_digit* m)
  33744. {
  33745. (void)m;
  33746. if (r != a) {
  33747. XMEMCPY(r, a, 21 * sizeof(sp_digit));
  33748. }
  33749. return MP_OKAY;
  33750. }
  33751. #ifdef WOLFSSL_SP_SMALL
  33752. /* Multiply the point by the scalar and return the result.
  33753. * If map is true then convert result to affine coordinates.
  33754. *
  33755. * Small implementation using add and double that is cache attack resistant but
  33756. * allocates memory rather than use large stacks.
  33757. * 521 adds and doubles.
  33758. *
  33759. * r Resulting point.
  33760. * g Point to multiply.
  33761. * k Scalar to multiply by.
  33762. * map Indicates whether to convert result to affine.
  33763. * ct Constant time required.
  33764. * heap Heap to use for allocation.
  33765. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  33766. */
  33767. #ifdef WOLFSSL_SP_NONBLOCK
  33768. typedef struct sp_521_ecc_mulmod_21_ctx {
  33769. int state;
  33770. union {
  33771. sp_521_proj_point_dbl_21_ctx dbl_ctx;
  33772. sp_521_proj_point_add_21_ctx add_ctx;
  33773. };
  33774. sp_point_521 t[3];
  33775. sp_digit tmp[2 * 21 * 6];
  33776. sp_digit n;
  33777. int i;
  33778. int c;
  33779. int y;
  33780. } sp_521_ecc_mulmod_21_ctx;
  33781. static int sp_521_ecc_mulmod_21_nb(sp_ecc_ctx_t* sp_ctx, sp_point_521* r,
  33782. const sp_point_521* g, const sp_digit* k, int map, int ct, void* heap)
  33783. {
  33784. int err = FP_WOULDBLOCK;
  33785. sp_521_ecc_mulmod_21_ctx* ctx = (sp_521_ecc_mulmod_21_ctx*)sp_ctx->data;
  33786. typedef char ctx_size_test[sizeof(sp_521_ecc_mulmod_21_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  33787. (void)sizeof(ctx_size_test);
  33788. /* Implementation is constant time. */
  33789. (void)ct;
  33790. switch (ctx->state) {
  33791. case 0: /* INIT */
  33792. XMEMSET(ctx->t, 0, sizeof(sp_point_521) * 3);
  33793. ctx->i = 20;
  33794. ctx->c = 21;
  33795. ctx->n = k[ctx->i--] << (25 - ctx->c);
  33796. /* t[0] = {0, 0, 1} * norm */
  33797. ctx->t[0].infinity = 1;
  33798. ctx->state = 1;
  33799. break;
  33800. case 1: /* T1X */
  33801. /* t[1] = {g->x, g->y, g->z} * norm */
  33802. err = sp_521_mod_mul_norm_21(ctx->t[1].x, g->x, p521_mod);
  33803. ctx->state = 2;
  33804. break;
  33805. case 2: /* T1Y */
  33806. err = sp_521_mod_mul_norm_21(ctx->t[1].y, g->y, p521_mod);
  33807. ctx->state = 3;
  33808. break;
  33809. case 3: /* T1Z */
  33810. err = sp_521_mod_mul_norm_21(ctx->t[1].z, g->z, p521_mod);
  33811. ctx->state = 4;
  33812. break;
  33813. case 4: /* ADDPREP */
  33814. if (ctx->c == 0) {
  33815. if (ctx->i == -1) {
  33816. ctx->state = 7;
  33817. break;
  33818. }
  33819. ctx->n = k[ctx->i--];
  33820. ctx->c = 25;
  33821. }
  33822. ctx->y = (ctx->n >> 24) & 1;
  33823. ctx->n <<= 1;
  33824. XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx));
  33825. ctx->state = 5;
  33826. break;
  33827. case 5: /* ADD */
  33828. err = sp_521_proj_point_add_21_nb((sp_ecc_ctx_t*)&ctx->add_ctx,
  33829. &ctx->t[ctx->y^1], &ctx->t[0], &ctx->t[1], ctx->tmp);
  33830. if (err == MP_OKAY) {
  33831. XMEMCPY(&ctx->t[2], (void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) +
  33832. ((size_t)&ctx->t[1] & addr_mask[ctx->y])),
  33833. sizeof(sp_point_521));
  33834. XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
  33835. ctx->state = 6;
  33836. }
  33837. break;
  33838. case 6: /* DBL */
  33839. err = sp_521_proj_point_dbl_21_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->t[2],
  33840. &ctx->t[2], ctx->tmp);
  33841. if (err == MP_OKAY) {
  33842. XMEMCPY((void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) +
  33843. ((size_t)&ctx->t[1] & addr_mask[ctx->y])), &ctx->t[2],
  33844. sizeof(sp_point_521));
  33845. ctx->state = 4;
  33846. ctx->c--;
  33847. }
  33848. break;
  33849. case 7: /* MAP */
  33850. if (map != 0) {
  33851. sp_521_map_21(r, &ctx->t[0], ctx->tmp);
  33852. }
  33853. else {
  33854. XMEMCPY(r, &ctx->t[0], sizeof(sp_point_521));
  33855. }
  33856. err = MP_OKAY;
  33857. break;
  33858. }
  33859. if (err == MP_OKAY && ctx->state != 7) {
  33860. err = FP_WOULDBLOCK;
  33861. }
  33862. if (err != FP_WOULDBLOCK) {
  33863. ForceZero(ctx->tmp, sizeof(ctx->tmp));
  33864. ForceZero(ctx->t, sizeof(ctx->t));
  33865. }
  33866. (void)heap;
  33867. return err;
  33868. }
  33869. #endif /* WOLFSSL_SP_NONBLOCK */
  33870. static int sp_521_ecc_mulmod_21(sp_point_521* r, const sp_point_521* g,
  33871. const sp_digit* k, int map, int ct, void* heap)
  33872. {
  33873. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  33874. sp_point_521* t = NULL;
  33875. sp_digit* tmp = NULL;
  33876. #else
  33877. sp_point_521 t[3];
  33878. sp_digit tmp[2 * 21 * 6];
  33879. #endif
  33880. sp_digit n;
  33881. int i;
  33882. int c;
  33883. int y;
  33884. int err = MP_OKAY;
  33885. /* Implementation is constant time. */
  33886. (void)ct;
  33887. (void)heap;
  33888. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  33889. t = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 3, heap,
  33890. DYNAMIC_TYPE_ECC);
  33891. if (t == NULL)
  33892. err = MEMORY_E;
  33893. if (err == MP_OKAY) {
  33894. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 21 * 6, heap,
  33895. DYNAMIC_TYPE_ECC);
  33896. if (tmp == NULL)
  33897. err = MEMORY_E;
  33898. }
  33899. #endif
  33900. if (err == MP_OKAY) {
  33901. XMEMSET(t, 0, sizeof(sp_point_521) * 3);
  33902. /* t[0] = {0, 0, 1} * norm */
  33903. t[0].infinity = 1;
  33904. /* t[1] = {g->x, g->y, g->z} * norm */
  33905. err = sp_521_mod_mul_norm_21(t[1].x, g->x, p521_mod);
  33906. }
  33907. if (err == MP_OKAY)
  33908. err = sp_521_mod_mul_norm_21(t[1].y, g->y, p521_mod);
  33909. if (err == MP_OKAY)
  33910. err = sp_521_mod_mul_norm_21(t[1].z, g->z, p521_mod);
  33911. if (err == MP_OKAY) {
  33912. i = 20;
  33913. c = 21;
  33914. n = k[i--] << (25 - c);
  33915. for (; ; c--) {
  33916. if (c == 0) {
  33917. if (i == -1)
  33918. break;
  33919. n = k[i--];
  33920. c = 25;
  33921. }
  33922. y = (n >> 24) & 1;
  33923. n <<= 1;
  33924. sp_521_proj_point_add_21(&t[y^1], &t[0], &t[1], tmp);
  33925. XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) +
  33926. ((size_t)&t[1] & addr_mask[y])),
  33927. sizeof(sp_point_521));
  33928. sp_521_proj_point_dbl_21(&t[2], &t[2], tmp);
  33929. XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) +
  33930. ((size_t)&t[1] & addr_mask[y])), &t[2],
  33931. sizeof(sp_point_521));
  33932. }
  33933. if (map != 0) {
  33934. sp_521_map_21(r, &t[0], tmp);
  33935. }
  33936. else {
  33937. XMEMCPY(r, &t[0], sizeof(sp_point_521));
  33938. }
  33939. }
  33940. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  33941. if (tmp != NULL)
  33942. #endif
  33943. {
  33944. ForceZero(tmp, sizeof(sp_digit) * 2 * 21 * 6);
  33945. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  33946. XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
  33947. #endif
  33948. }
  33949. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  33950. if (t != NULL)
  33951. #endif
  33952. {
  33953. ForceZero(t, sizeof(sp_point_521) * 3);
  33954. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  33955. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  33956. #endif
  33957. }
  33958. return err;
  33959. }
  33960. #else
  33961. /* A table entry for pre-computed points. */
  33962. typedef struct sp_table_entry_521 {
  33963. sp_digit x[21];
  33964. sp_digit y[21];
  33965. } sp_table_entry_521;
  33966. /* Conditionally copy a into r using the mask m.
  33967. * m is -1 to copy and 0 when not.
  33968. *
  33969. * r A single precision number to copy over.
  33970. * a A single precision number to copy.
  33971. * m Mask value to apply.
  33972. */
  33973. static void sp_521_cond_copy_21(sp_digit* r, const sp_digit* a, const sp_digit m)
  33974. {
  33975. sp_digit t[21];
  33976. #ifdef WOLFSSL_SP_SMALL
  33977. int i;
  33978. for (i = 0; i < 21; i++) {
  33979. t[i] = r[i] ^ a[i];
  33980. }
  33981. for (i = 0; i < 21; i++) {
  33982. r[i] ^= t[i] & m;
  33983. }
  33984. #else
  33985. t[ 0] = r[ 0] ^ a[ 0];
  33986. t[ 1] = r[ 1] ^ a[ 1];
  33987. t[ 2] = r[ 2] ^ a[ 2];
  33988. t[ 3] = r[ 3] ^ a[ 3];
  33989. t[ 4] = r[ 4] ^ a[ 4];
  33990. t[ 5] = r[ 5] ^ a[ 5];
  33991. t[ 6] = r[ 6] ^ a[ 6];
  33992. t[ 7] = r[ 7] ^ a[ 7];
  33993. t[ 8] = r[ 8] ^ a[ 8];
  33994. t[ 9] = r[ 9] ^ a[ 9];
  33995. t[10] = r[10] ^ a[10];
  33996. t[11] = r[11] ^ a[11];
  33997. t[12] = r[12] ^ a[12];
  33998. t[13] = r[13] ^ a[13];
  33999. t[14] = r[14] ^ a[14];
  34000. t[15] = r[15] ^ a[15];
  34001. t[16] = r[16] ^ a[16];
  34002. t[17] = r[17] ^ a[17];
  34003. t[18] = r[18] ^ a[18];
  34004. t[19] = r[19] ^ a[19];
  34005. t[20] = r[20] ^ a[20];
  34006. r[ 0] ^= t[ 0] & m;
  34007. r[ 1] ^= t[ 1] & m;
  34008. r[ 2] ^= t[ 2] & m;
  34009. r[ 3] ^= t[ 3] & m;
  34010. r[ 4] ^= t[ 4] & m;
  34011. r[ 5] ^= t[ 5] & m;
  34012. r[ 6] ^= t[ 6] & m;
  34013. r[ 7] ^= t[ 7] & m;
  34014. r[ 8] ^= t[ 8] & m;
  34015. r[ 9] ^= t[ 9] & m;
  34016. r[10] ^= t[10] & m;
  34017. r[11] ^= t[11] & m;
  34018. r[12] ^= t[12] & m;
  34019. r[13] ^= t[13] & m;
  34020. r[14] ^= t[14] & m;
  34021. r[15] ^= t[15] & m;
  34022. r[16] ^= t[16] & m;
  34023. r[17] ^= t[17] & m;
  34024. r[18] ^= t[18] & m;
  34025. r[19] ^= t[19] & m;
  34026. r[20] ^= t[20] & m;
  34027. #endif /* WOLFSSL_SP_SMALL */
  34028. }
  34029. #define sp_521_mont_dbl_lower_21 sp_521_mont_dbl_21
  34030. #define sp_521_mont_tpl_lower_21 sp_521_mont_tpl_21
  34031. /* Double the Montgomery form projective point p a number of times.
  34032. *
  34033. * r Result of repeated doubling of point.
  34034. * p Point to double.
  34035. * n Number of times to double
  34036. * t Temporary ordinate data.
  34037. */
  34038. static void sp_521_proj_point_dbl_n_21(sp_point_521* p, int i,
  34039. sp_digit* t)
  34040. {
  34041. sp_digit* w = t;
  34042. sp_digit* a = t + 2*21;
  34043. sp_digit* b = t + 4*21;
  34044. sp_digit* t1 = t + 6*21;
  34045. sp_digit* t2 = t + 8*21;
  34046. sp_digit* x;
  34047. sp_digit* y;
  34048. sp_digit* z;
  34049. volatile int n = i;
  34050. x = p->x;
  34051. y = p->y;
  34052. z = p->z;
  34053. /* Y = 2*Y */
  34054. sp_521_mont_dbl_21(y, y, p521_mod);
  34055. /* W = Z^4 */
  34056. sp_521_mont_sqr_21(w, z, p521_mod, p521_mp_mod);
  34057. sp_521_mont_sqr_21(w, w, p521_mod, p521_mp_mod);
  34058. #ifndef WOLFSSL_SP_SMALL
  34059. while (--n > 0)
  34060. #else
  34061. while (--n >= 0)
  34062. #endif
  34063. {
  34064. /* A = 3*(X^2 - W) */
  34065. sp_521_mont_sqr_21(t1, x, p521_mod, p521_mp_mod);
  34066. sp_521_mont_sub_21(t1, t1, w, p521_mod);
  34067. sp_521_mont_tpl_lower_21(a, t1, p521_mod);
  34068. /* B = X*Y^2 */
  34069. sp_521_mont_sqr_21(t1, y, p521_mod, p521_mp_mod);
  34070. sp_521_mont_mul_21(b, t1, x, p521_mod, p521_mp_mod);
  34071. /* X = A^2 - 2B */
  34072. sp_521_mont_sqr_21(x, a, p521_mod, p521_mp_mod);
  34073. sp_521_mont_dbl_21(t2, b, p521_mod);
  34074. sp_521_mont_sub_21(x, x, t2, p521_mod);
  34075. /* b = 2.(B - X) */
  34076. sp_521_mont_sub_lower_21(t2, b, x, p521_mod);
  34077. sp_521_mont_dbl_lower_21(b, t2, p521_mod);
  34078. /* Z = Z*Y */
  34079. sp_521_mont_mul_21(z, z, y, p521_mod, p521_mp_mod);
  34080. /* t1 = Y^4 */
  34081. sp_521_mont_sqr_21(t1, t1, p521_mod, p521_mp_mod);
  34082. #ifdef WOLFSSL_SP_SMALL
  34083. if (n != 0)
  34084. #endif
  34085. {
  34086. /* W = W*Y^4 */
  34087. sp_521_mont_mul_21(w, w, t1, p521_mod, p521_mp_mod);
  34088. }
  34089. /* y = 2*A*(B - X) - Y^4 */
  34090. sp_521_mont_mul_21(y, b, a, p521_mod, p521_mp_mod);
  34091. sp_521_mont_sub_21(y, y, t1, p521_mod);
  34092. }
  34093. #ifndef WOLFSSL_SP_SMALL
  34094. /* A = 3*(X^2 - W) */
  34095. sp_521_mont_sqr_21(t1, x, p521_mod, p521_mp_mod);
  34096. sp_521_mont_sub_21(t1, t1, w, p521_mod);
  34097. sp_521_mont_tpl_lower_21(a, t1, p521_mod);
  34098. /* B = X*Y^2 */
  34099. sp_521_mont_sqr_21(t1, y, p521_mod, p521_mp_mod);
  34100. sp_521_mont_mul_21(b, t1, x, p521_mod, p521_mp_mod);
  34101. /* X = A^2 - 2B */
  34102. sp_521_mont_sqr_21(x, a, p521_mod, p521_mp_mod);
  34103. sp_521_mont_dbl_21(t2, b, p521_mod);
  34104. sp_521_mont_sub_21(x, x, t2, p521_mod);
  34105. /* b = 2.(B - X) */
  34106. sp_521_mont_sub_lower_21(t2, b, x, p521_mod);
  34107. sp_521_mont_dbl_lower_21(b, t2, p521_mod);
  34108. /* Z = Z*Y */
  34109. sp_521_mont_mul_21(z, z, y, p521_mod, p521_mp_mod);
  34110. /* t1 = Y^4 */
  34111. sp_521_mont_sqr_21(t1, t1, p521_mod, p521_mp_mod);
  34112. /* y = 2*A*(B - X) - Y^4 */
  34113. sp_521_mont_mul_21(y, b, a, p521_mod, p521_mp_mod);
  34114. sp_521_mont_sub_21(y, y, t1, p521_mod);
  34115. #endif
  34116. /* Y = Y/2 */
  34117. sp_521_div2_21(y, y, p521_mod);
  34118. }
  34119. /* Double the Montgomery form projective point p a number of times.
  34120. *
  34121. * r Result of repeated doubling of point.
  34122. * p Point to double.
  34123. * n Number of times to double
  34124. * t Temporary ordinate data.
  34125. */
  34126. static void sp_521_proj_point_dbl_n_store_21(sp_point_521* r,
  34127. const sp_point_521* p, int n, int m, sp_digit* t)
  34128. {
  34129. sp_digit* w = t;
  34130. sp_digit* a = t + 2*21;
  34131. sp_digit* b = t + 4*21;
  34132. sp_digit* t1 = t + 6*21;
  34133. sp_digit* t2 = t + 8*21;
  34134. sp_digit* x = r[2*m].x;
  34135. sp_digit* y = r[(1<<n)*m].y;
  34136. sp_digit* z = r[2*m].z;
  34137. int i;
  34138. int j;
  34139. for (i=0; i<21; i++) {
  34140. x[i] = p->x[i];
  34141. }
  34142. for (i=0; i<21; i++) {
  34143. y[i] = p->y[i];
  34144. }
  34145. for (i=0; i<21; i++) {
  34146. z[i] = p->z[i];
  34147. }
  34148. /* Y = 2*Y */
  34149. sp_521_mont_dbl_21(y, y, p521_mod);
  34150. /* W = Z^4 */
  34151. sp_521_mont_sqr_21(w, z, p521_mod, p521_mp_mod);
  34152. sp_521_mont_sqr_21(w, w, p521_mod, p521_mp_mod);
  34153. j = m;
  34154. for (i=1; i<=n; i++) {
  34155. j *= 2;
  34156. /* A = 3*(X^2 - W) */
  34157. sp_521_mont_sqr_21(t1, x, p521_mod, p521_mp_mod);
  34158. sp_521_mont_sub_21(t1, t1, w, p521_mod);
  34159. sp_521_mont_tpl_lower_21(a, t1, p521_mod);
  34160. /* B = X*Y^2 */
  34161. sp_521_mont_sqr_21(t1, y, p521_mod, p521_mp_mod);
  34162. sp_521_mont_mul_21(b, t1, x, p521_mod, p521_mp_mod);
  34163. x = r[j].x;
  34164. /* X = A^2 - 2B */
  34165. sp_521_mont_sqr_21(x, a, p521_mod, p521_mp_mod);
  34166. sp_521_mont_dbl_21(t2, b, p521_mod);
  34167. sp_521_mont_sub_21(x, x, t2, p521_mod);
  34168. /* b = 2.(B - X) */
  34169. sp_521_mont_sub_lower_21(t2, b, x, p521_mod);
  34170. sp_521_mont_dbl_lower_21(b, t2, p521_mod);
  34171. /* Z = Z*Y */
  34172. sp_521_mont_mul_21(r[j].z, z, y, p521_mod, p521_mp_mod);
  34173. z = r[j].z;
  34174. /* t1 = Y^4 */
  34175. sp_521_mont_sqr_21(t1, t1, p521_mod, p521_mp_mod);
  34176. if (i != n) {
  34177. /* W = W*Y^4 */
  34178. sp_521_mont_mul_21(w, w, t1, p521_mod, p521_mp_mod);
  34179. }
  34180. /* y = 2*A*(B - X) - Y^4 */
  34181. sp_521_mont_mul_21(y, b, a, p521_mod, p521_mp_mod);
  34182. sp_521_mont_sub_21(y, y, t1, p521_mod);
  34183. /* Y = Y/2 */
  34184. sp_521_div2_21(r[j].y, y, p521_mod);
  34185. r[j].infinity = 0;
  34186. }
  34187. }
  34188. /* Add two Montgomery form projective points.
  34189. *
  34190. * ra Result of addition.
  34191. * rs Result of subtraction.
  34192. * p First point to add.
  34193. * q Second point to add.
  34194. * t Temporary ordinate data.
  34195. */
  34196. static void sp_521_proj_point_add_sub_21(sp_point_521* ra,
  34197. sp_point_521* rs, const sp_point_521* p, const sp_point_521* q,
  34198. sp_digit* t)
  34199. {
  34200. sp_digit* t1 = t;
  34201. sp_digit* t2 = t + 2*21;
  34202. sp_digit* t3 = t + 4*21;
  34203. sp_digit* t4 = t + 6*21;
  34204. sp_digit* t5 = t + 8*21;
  34205. sp_digit* t6 = t + 10*21;
  34206. sp_digit* xa = ra->x;
  34207. sp_digit* ya = ra->y;
  34208. sp_digit* za = ra->z;
  34209. sp_digit* xs = rs->x;
  34210. sp_digit* ys = rs->y;
  34211. sp_digit* zs = rs->z;
  34212. XMEMCPY(xa, p->x, sizeof(p->x) / 2);
  34213. XMEMCPY(ya, p->y, sizeof(p->y) / 2);
  34214. XMEMCPY(za, p->z, sizeof(p->z) / 2);
  34215. ra->infinity = 0;
  34216. rs->infinity = 0;
  34217. /* U1 = X1*Z2^2 */
  34218. sp_521_mont_sqr_21(t1, q->z, p521_mod, p521_mp_mod);
  34219. sp_521_mont_mul_21(t3, t1, q->z, p521_mod, p521_mp_mod);
  34220. sp_521_mont_mul_21(t1, t1, xa, p521_mod, p521_mp_mod);
  34221. /* U2 = X2*Z1^2 */
  34222. sp_521_mont_sqr_21(t2, za, p521_mod, p521_mp_mod);
  34223. sp_521_mont_mul_21(t4, t2, za, p521_mod, p521_mp_mod);
  34224. sp_521_mont_mul_21(t2, t2, q->x, p521_mod, p521_mp_mod);
  34225. /* S1 = Y1*Z2^3 */
  34226. sp_521_mont_mul_21(t3, t3, ya, p521_mod, p521_mp_mod);
  34227. /* S2 = Y2*Z1^3 */
  34228. sp_521_mont_mul_21(t4, t4, q->y, p521_mod, p521_mp_mod);
  34229. /* H = U2 - U1 */
  34230. sp_521_mont_sub_21(t2, t2, t1, p521_mod);
  34231. /* RS = S2 + S1 */
  34232. sp_521_mont_add_21(t6, t4, t3, p521_mod);
  34233. /* R = S2 - S1 */
  34234. sp_521_mont_sub_21(t4, t4, t3, p521_mod);
  34235. /* Z3 = H*Z1*Z2 */
  34236. /* ZS = H*Z1*Z2 */
  34237. sp_521_mont_mul_21(za, za, q->z, p521_mod, p521_mp_mod);
  34238. sp_521_mont_mul_21(za, za, t2, p521_mod, p521_mp_mod);
  34239. XMEMCPY(zs, za, sizeof(p->z)/2);
  34240. /* X3 = R^2 - H^3 - 2*U1*H^2 */
  34241. /* XS = RS^2 - H^3 - 2*U1*H^2 */
  34242. sp_521_mont_sqr_21(xa, t4, p521_mod, p521_mp_mod);
  34243. sp_521_mont_sqr_21(xs, t6, p521_mod, p521_mp_mod);
  34244. sp_521_mont_sqr_21(t5, t2, p521_mod, p521_mp_mod);
  34245. sp_521_mont_mul_21(ya, t1, t5, p521_mod, p521_mp_mod);
  34246. sp_521_mont_mul_21(t5, t5, t2, p521_mod, p521_mp_mod);
  34247. sp_521_mont_sub_21(xa, xa, t5, p521_mod);
  34248. sp_521_mont_sub_21(xs, xs, t5, p521_mod);
  34249. sp_521_mont_dbl_21(t1, ya, p521_mod);
  34250. sp_521_mont_sub_21(xa, xa, t1, p521_mod);
  34251. sp_521_mont_sub_21(xs, xs, t1, p521_mod);
  34252. /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
  34253. /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */
  34254. sp_521_mont_sub_lower_21(ys, ya, xs, p521_mod);
  34255. sp_521_mont_sub_lower_21(ya, ya, xa, p521_mod);
  34256. sp_521_mont_mul_21(ya, ya, t4, p521_mod, p521_mp_mod);
  34257. sp_521_sub_21(t6, p521_mod, t6);
  34258. sp_521_mont_mul_21(ys, ys, t6, p521_mod, p521_mp_mod);
  34259. sp_521_mont_mul_21(t5, t5, t3, p521_mod, p521_mp_mod);
  34260. sp_521_mont_sub_21(ya, ya, t5, p521_mod);
  34261. sp_521_mont_sub_21(ys, ys, t5, p521_mod);
  34262. }
  34263. /* Structure used to describe recoding of scalar multiplication. */
  34264. typedef struct ecc_recode_521 {
  34265. /* Index into pre-computation table. */
  34266. uint8_t i;
  34267. /* Use the negative of the point. */
  34268. uint8_t neg;
  34269. } ecc_recode_521;
  34270. /* The index into pre-computation table to use. */
  34271. static const uint8_t recode_index_21_6[66] = {
  34272. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
  34273. 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
  34274. 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
  34275. 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
  34276. 0, 1,
  34277. };
  34278. /* Whether to negate y-ordinate. */
  34279. static const uint8_t recode_neg_21_6[66] = {
  34280. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  34281. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  34282. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  34283. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  34284. 0, 0,
  34285. };
  34286. /* Recode the scalar for multiplication using pre-computed values and
  34287. * subtraction.
  34288. *
  34289. * k Scalar to multiply by.
  34290. * v Vector of operations to perform.
  34291. */
  34292. static void sp_521_ecc_recode_6_21(const sp_digit* k, ecc_recode_521* v)
  34293. {
  34294. int i;
  34295. int j;
  34296. uint8_t y;
  34297. int carry = 0;
  34298. int o;
  34299. sp_digit n;
  34300. j = 0;
  34301. n = k[j];
  34302. o = 0;
  34303. for (i=0; i<87; i++) {
  34304. y = (int8_t)n;
  34305. if (o + 6 < 25) {
  34306. y &= 0x3f;
  34307. n >>= 6;
  34308. o += 6;
  34309. }
  34310. else if (o + 6 == 25) {
  34311. n >>= 6;
  34312. if (++j < 21)
  34313. n = k[j];
  34314. o = 0;
  34315. }
  34316. else if (++j < 21) {
  34317. n = k[j];
  34318. y |= (uint8_t)((n << (25 - o)) & 0x3f);
  34319. o -= 19;
  34320. n >>= o;
  34321. }
  34322. y += (uint8_t)carry;
  34323. v[i].i = recode_index_21_6[y];
  34324. v[i].neg = recode_neg_21_6[y];
  34325. carry = (y >> 6) + v[i].neg;
  34326. }
  34327. }
  34328. #ifndef WC_NO_CACHE_RESISTANT
  34329. /* Touch each possible point that could be being copied.
  34330. *
  34331. * r Point to copy into.
  34332. * table Table - start of the entires to access
  34333. * idx Index of entry to retrieve.
  34334. */
  34335. static void sp_521_get_point_33_21(sp_point_521* r, const sp_point_521* table,
  34336. int idx)
  34337. {
  34338. int i;
  34339. sp_digit mask;
  34340. r->x[0] = 0;
  34341. r->x[1] = 0;
  34342. r->x[2] = 0;
  34343. r->x[3] = 0;
  34344. r->x[4] = 0;
  34345. r->x[5] = 0;
  34346. r->x[6] = 0;
  34347. r->x[7] = 0;
  34348. r->x[8] = 0;
  34349. r->x[9] = 0;
  34350. r->x[10] = 0;
  34351. r->x[11] = 0;
  34352. r->x[12] = 0;
  34353. r->x[13] = 0;
  34354. r->x[14] = 0;
  34355. r->x[15] = 0;
  34356. r->x[16] = 0;
  34357. r->x[17] = 0;
  34358. r->x[18] = 0;
  34359. r->x[19] = 0;
  34360. r->x[20] = 0;
  34361. r->y[0] = 0;
  34362. r->y[1] = 0;
  34363. r->y[2] = 0;
  34364. r->y[3] = 0;
  34365. r->y[4] = 0;
  34366. r->y[5] = 0;
  34367. r->y[6] = 0;
  34368. r->y[7] = 0;
  34369. r->y[8] = 0;
  34370. r->y[9] = 0;
  34371. r->y[10] = 0;
  34372. r->y[11] = 0;
  34373. r->y[12] = 0;
  34374. r->y[13] = 0;
  34375. r->y[14] = 0;
  34376. r->y[15] = 0;
  34377. r->y[16] = 0;
  34378. r->y[17] = 0;
  34379. r->y[18] = 0;
  34380. r->y[19] = 0;
  34381. r->y[20] = 0;
  34382. r->z[0] = 0;
  34383. r->z[1] = 0;
  34384. r->z[2] = 0;
  34385. r->z[3] = 0;
  34386. r->z[4] = 0;
  34387. r->z[5] = 0;
  34388. r->z[6] = 0;
  34389. r->z[7] = 0;
  34390. r->z[8] = 0;
  34391. r->z[9] = 0;
  34392. r->z[10] = 0;
  34393. r->z[11] = 0;
  34394. r->z[12] = 0;
  34395. r->z[13] = 0;
  34396. r->z[14] = 0;
  34397. r->z[15] = 0;
  34398. r->z[16] = 0;
  34399. r->z[17] = 0;
  34400. r->z[18] = 0;
  34401. r->z[19] = 0;
  34402. r->z[20] = 0;
  34403. for (i = 1; i < 33; i++) {
  34404. mask = 0 - (i == idx);
  34405. r->x[0] |= mask & table[i].x[0];
  34406. r->x[1] |= mask & table[i].x[1];
  34407. r->x[2] |= mask & table[i].x[2];
  34408. r->x[3] |= mask & table[i].x[3];
  34409. r->x[4] |= mask & table[i].x[4];
  34410. r->x[5] |= mask & table[i].x[5];
  34411. r->x[6] |= mask & table[i].x[6];
  34412. r->x[7] |= mask & table[i].x[7];
  34413. r->x[8] |= mask & table[i].x[8];
  34414. r->x[9] |= mask & table[i].x[9];
  34415. r->x[10] |= mask & table[i].x[10];
  34416. r->x[11] |= mask & table[i].x[11];
  34417. r->x[12] |= mask & table[i].x[12];
  34418. r->x[13] |= mask & table[i].x[13];
  34419. r->x[14] |= mask & table[i].x[14];
  34420. r->x[15] |= mask & table[i].x[15];
  34421. r->x[16] |= mask & table[i].x[16];
  34422. r->x[17] |= mask & table[i].x[17];
  34423. r->x[18] |= mask & table[i].x[18];
  34424. r->x[19] |= mask & table[i].x[19];
  34425. r->x[20] |= mask & table[i].x[20];
  34426. r->y[0] |= mask & table[i].y[0];
  34427. r->y[1] |= mask & table[i].y[1];
  34428. r->y[2] |= mask & table[i].y[2];
  34429. r->y[3] |= mask & table[i].y[3];
  34430. r->y[4] |= mask & table[i].y[4];
  34431. r->y[5] |= mask & table[i].y[5];
  34432. r->y[6] |= mask & table[i].y[6];
  34433. r->y[7] |= mask & table[i].y[7];
  34434. r->y[8] |= mask & table[i].y[8];
  34435. r->y[9] |= mask & table[i].y[9];
  34436. r->y[10] |= mask & table[i].y[10];
  34437. r->y[11] |= mask & table[i].y[11];
  34438. r->y[12] |= mask & table[i].y[12];
  34439. r->y[13] |= mask & table[i].y[13];
  34440. r->y[14] |= mask & table[i].y[14];
  34441. r->y[15] |= mask & table[i].y[15];
  34442. r->y[16] |= mask & table[i].y[16];
  34443. r->y[17] |= mask & table[i].y[17];
  34444. r->y[18] |= mask & table[i].y[18];
  34445. r->y[19] |= mask & table[i].y[19];
  34446. r->y[20] |= mask & table[i].y[20];
  34447. r->z[0] |= mask & table[i].z[0];
  34448. r->z[1] |= mask & table[i].z[1];
  34449. r->z[2] |= mask & table[i].z[2];
  34450. r->z[3] |= mask & table[i].z[3];
  34451. r->z[4] |= mask & table[i].z[4];
  34452. r->z[5] |= mask & table[i].z[5];
  34453. r->z[6] |= mask & table[i].z[6];
  34454. r->z[7] |= mask & table[i].z[7];
  34455. r->z[8] |= mask & table[i].z[8];
  34456. r->z[9] |= mask & table[i].z[9];
  34457. r->z[10] |= mask & table[i].z[10];
  34458. r->z[11] |= mask & table[i].z[11];
  34459. r->z[12] |= mask & table[i].z[12];
  34460. r->z[13] |= mask & table[i].z[13];
  34461. r->z[14] |= mask & table[i].z[14];
  34462. r->z[15] |= mask & table[i].z[15];
  34463. r->z[16] |= mask & table[i].z[16];
  34464. r->z[17] |= mask & table[i].z[17];
  34465. r->z[18] |= mask & table[i].z[18];
  34466. r->z[19] |= mask & table[i].z[19];
  34467. r->z[20] |= mask & table[i].z[20];
  34468. }
  34469. }
  34470. #endif /* !WC_NO_CACHE_RESISTANT */
  34471. /* Multiply the point by the scalar and return the result.
  34472. * If map is true then convert result to affine coordinates.
  34473. *
  34474. * Window technique of 6 bits. (Add-Sub variation.)
  34475. * Calculate 0..32 times the point. Use function that adds and
  34476. * subtracts the same two points.
  34477. * Recode to add or subtract one of the computed points.
  34478. * Double to push up.
  34479. * NOT a sliding window.
  34480. *
  34481. * r Resulting point.
  34482. * g Point to multiply.
  34483. * k Scalar to multiply by.
  34484. * map Indicates whether to convert result to affine.
  34485. * ct Constant time required.
  34486. * heap Heap to use for allocation.
  34487. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  34488. */
  34489. static int sp_521_ecc_mulmod_win_add_sub_21(sp_point_521* r, const sp_point_521* g,
  34490. const sp_digit* k, int map, int ct, void* heap)
  34491. {
  34492. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  34493. sp_point_521* t = NULL;
  34494. sp_digit* tmp = NULL;
  34495. #else
  34496. sp_point_521 t[33+2];
  34497. sp_digit tmp[2 * 21 * 6];
  34498. #endif
  34499. sp_point_521* rt = NULL;
  34500. sp_point_521* p = NULL;
  34501. sp_digit* negy;
  34502. int i;
  34503. ecc_recode_521 v[87];
  34504. int err = MP_OKAY;
  34505. /* Constant time used for cache attack resistance implementation. */
  34506. (void)ct;
  34507. (void)heap;
  34508. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  34509. t = (sp_point_521*)XMALLOC(sizeof(sp_point_521) *
  34510. (33+2), heap, DYNAMIC_TYPE_ECC);
  34511. if (t == NULL)
  34512. err = MEMORY_E;
  34513. if (err == MP_OKAY) {
  34514. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 21 * 6,
  34515. heap, DYNAMIC_TYPE_ECC);
  34516. if (tmp == NULL)
  34517. err = MEMORY_E;
  34518. }
  34519. #endif
  34520. if (err == MP_OKAY) {
  34521. rt = t + 33;
  34522. p = t + 33+1;
  34523. /* t[0] = {0, 0, 1} * norm */
  34524. XMEMSET(&t[0], 0, sizeof(t[0]));
  34525. t[0].infinity = 1;
  34526. /* t[1] = {g->x, g->y, g->z} * norm */
  34527. err = sp_521_mod_mul_norm_21(t[1].x, g->x, p521_mod);
  34528. }
  34529. if (err == MP_OKAY) {
  34530. err = sp_521_mod_mul_norm_21(t[1].y, g->y, p521_mod);
  34531. }
  34532. if (err == MP_OKAY) {
  34533. err = sp_521_mod_mul_norm_21(t[1].z, g->z, p521_mod);
  34534. }
  34535. if (err == MP_OKAY) {
  34536. t[1].infinity = 0;
  34537. /* t[2] ... t[32] */
  34538. sp_521_proj_point_dbl_n_store_21(t, &t[ 1], 5, 1, tmp);
  34539. sp_521_proj_point_add_21(&t[ 3], &t[ 2], &t[ 1], tmp);
  34540. sp_521_proj_point_dbl_21(&t[ 6], &t[ 3], tmp);
  34541. sp_521_proj_point_add_sub_21(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp);
  34542. sp_521_proj_point_dbl_21(&t[10], &t[ 5], tmp);
  34543. sp_521_proj_point_add_sub_21(&t[11], &t[ 9], &t[10], &t[ 1], tmp);
  34544. sp_521_proj_point_dbl_21(&t[12], &t[ 6], tmp);
  34545. sp_521_proj_point_dbl_21(&t[14], &t[ 7], tmp);
  34546. sp_521_proj_point_add_sub_21(&t[15], &t[13], &t[14], &t[ 1], tmp);
  34547. sp_521_proj_point_dbl_21(&t[18], &t[ 9], tmp);
  34548. sp_521_proj_point_add_sub_21(&t[19], &t[17], &t[18], &t[ 1], tmp);
  34549. sp_521_proj_point_dbl_21(&t[20], &t[10], tmp);
  34550. sp_521_proj_point_dbl_21(&t[22], &t[11], tmp);
  34551. sp_521_proj_point_add_sub_21(&t[23], &t[21], &t[22], &t[ 1], tmp);
  34552. sp_521_proj_point_dbl_21(&t[24], &t[12], tmp);
  34553. sp_521_proj_point_dbl_21(&t[26], &t[13], tmp);
  34554. sp_521_proj_point_add_sub_21(&t[27], &t[25], &t[26], &t[ 1], tmp);
  34555. sp_521_proj_point_dbl_21(&t[28], &t[14], tmp);
  34556. sp_521_proj_point_dbl_21(&t[30], &t[15], tmp);
  34557. sp_521_proj_point_add_sub_21(&t[31], &t[29], &t[30], &t[ 1], tmp);
  34558. negy = t[0].y;
  34559. sp_521_ecc_recode_6_21(k, v);
  34560. i = 86;
  34561. #ifndef WC_NO_CACHE_RESISTANT
  34562. if (ct) {
  34563. sp_521_get_point_33_21(rt, t, v[i].i);
  34564. rt->infinity = !v[i].i;
  34565. }
  34566. else
  34567. #endif
  34568. {
  34569. XMEMCPY(rt, &t[v[i].i], sizeof(sp_point_521));
  34570. }
  34571. for (--i; i>=0; i--) {
  34572. sp_521_proj_point_dbl_n_21(rt, 6, tmp);
  34573. #ifndef WC_NO_CACHE_RESISTANT
  34574. if (ct) {
  34575. sp_521_get_point_33_21(p, t, v[i].i);
  34576. p->infinity = !v[i].i;
  34577. }
  34578. else
  34579. #endif
  34580. {
  34581. XMEMCPY(p, &t[v[i].i], sizeof(sp_point_521));
  34582. }
  34583. sp_521_sub_21(negy, p521_mod, p->y);
  34584. sp_521_norm_21(negy);
  34585. sp_521_cond_copy_21(p->y, negy, (sp_digit)0 - v[i].neg);
  34586. sp_521_proj_point_add_21(rt, rt, p, tmp);
  34587. }
  34588. if (map != 0) {
  34589. sp_521_map_21(r, rt, tmp);
  34590. }
  34591. else {
  34592. XMEMCPY(r, rt, sizeof(sp_point_521));
  34593. }
  34594. }
  34595. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  34596. if (t != NULL)
  34597. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  34598. if (tmp != NULL)
  34599. XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
  34600. #endif
  34601. return err;
  34602. }
  34603. #ifdef FP_ECC
  34604. #endif /* FP_ECC */
  34605. /* Add two Montgomery form projective points. The second point has a q value of
  34606. * one.
  34607. * Only the first point can be the same pointer as the result point.
  34608. *
  34609. * r Result of addition.
  34610. * p First point to add.
  34611. * q Second point to add.
  34612. * t Temporary ordinate data.
  34613. */
  34614. static void sp_521_proj_point_add_qz1_21(sp_point_521* r, const sp_point_521* p,
  34615. const sp_point_521* q, sp_digit* t)
  34616. {
  34617. sp_digit* t1 = t;
  34618. sp_digit* t2 = t + 2*21;
  34619. sp_digit* t3 = t + 4*21;
  34620. sp_digit* t4 = t + 6*21;
  34621. sp_digit* t5 = t + 8*21;
  34622. sp_digit* t6 = t + 10*21;
  34623. /* Check double */
  34624. (void)sp_521_sub_21(t1, p521_mod, q->y);
  34625. sp_521_norm_21(t1);
  34626. if ((~p->infinity & ~q->infinity &
  34627. sp_521_cmp_equal_21(p->x, q->x) & sp_521_cmp_equal_21(p->z, q->z) &
  34628. (sp_521_cmp_equal_21(p->y, q->y) | sp_521_cmp_equal_21(p->y, t1))) != 0) {
  34629. sp_521_proj_point_dbl_21(r, p, t);
  34630. }
  34631. else {
  34632. sp_digit maskp;
  34633. sp_digit maskq;
  34634. sp_digit maskt;
  34635. sp_digit* x = t2;
  34636. sp_digit* y = t5;
  34637. sp_digit* z = t6;
  34638. int i;
  34639. /* U2 = X2*Z1^2 */
  34640. sp_521_mont_sqr_21(t2, p->z, p521_mod, p521_mp_mod);
  34641. sp_521_mont_mul_21(t4, t2, p->z, p521_mod, p521_mp_mod);
  34642. sp_521_mont_mul_21(t2, t2, q->x, p521_mod, p521_mp_mod);
  34643. /* S2 = Y2*Z1^3 */
  34644. sp_521_mont_mul_21(t4, t4, q->y, p521_mod, p521_mp_mod);
  34645. /* H = U2 - X1 */
  34646. sp_521_mont_sub_21(t2, t2, p->x, p521_mod);
  34647. /* R = S2 - Y1 */
  34648. sp_521_mont_sub_21(t4, t4, p->y, p521_mod);
  34649. /* Z3 = H*Z1 */
  34650. sp_521_mont_mul_21(z, p->z, t2, p521_mod, p521_mp_mod);
  34651. /* X3 = R^2 - H^3 - 2*X1*H^2 */
  34652. sp_521_mont_sqr_21(t1, t4, p521_mod, p521_mp_mod);
  34653. sp_521_mont_sqr_21(t5, t2, p521_mod, p521_mp_mod);
  34654. sp_521_mont_mul_21(t3, p->x, t5, p521_mod, p521_mp_mod);
  34655. sp_521_mont_mul_21(t5, t5, t2, p521_mod, p521_mp_mod);
  34656. sp_521_mont_sub_21(x, t1, t5, p521_mod);
  34657. sp_521_mont_dbl_21(t1, t3, p521_mod);
  34658. sp_521_mont_sub_21(x, x, t1, p521_mod);
  34659. /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */
  34660. sp_521_mont_sub_lower_21(t3, t3, x, p521_mod);
  34661. sp_521_mont_mul_21(t3, t3, t4, p521_mod, p521_mp_mod);
  34662. sp_521_mont_mul_21(t5, t5, p->y, p521_mod, p521_mp_mod);
  34663. sp_521_mont_sub_21(y, t3, t5, p521_mod);
  34664. maskp = 0 - (q->infinity & (!p->infinity));
  34665. maskq = 0 - (p->infinity & (!q->infinity));
  34666. maskt = ~(maskp | maskq);
  34667. for (i = 0; i < 21; i++) {
  34668. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | (x[i] & maskt);
  34669. }
  34670. for (i = 0; i < 21; i++) {
  34671. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | (y[i] & maskt);
  34672. }
  34673. for (i = 0; i < 21; i++) {
  34674. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | (z[i] & maskt);
  34675. }
  34676. r->z[0] |= p->infinity & q->infinity;
  34677. r->infinity = p->infinity & q->infinity;
  34678. }
  34679. }
  34680. #ifdef FP_ECC
  34681. /* Convert the projective point to affine.
  34682. * Ordinates are in Montgomery form.
  34683. *
  34684. * a Point to convert.
  34685. * t Temporary data.
  34686. */
  34687. static void sp_521_proj_to_affine_21(sp_point_521* a, sp_digit* t)
  34688. {
  34689. sp_digit* t1 = t;
  34690. sp_digit* t2 = t + 2 * 21;
  34691. sp_digit* tmp = t + 4 * 21;
  34692. sp_521_mont_inv_21(t1, a->z, tmp);
  34693. sp_521_mont_sqr_21(t2, t1, p521_mod, p521_mp_mod);
  34694. sp_521_mont_mul_21(t1, t2, t1, p521_mod, p521_mp_mod);
  34695. sp_521_mont_mul_21(a->x, a->x, t2, p521_mod, p521_mp_mod);
  34696. sp_521_mont_mul_21(a->y, a->y, t1, p521_mod, p521_mp_mod);
  34697. XMEMCPY(a->z, p521_norm_mod, sizeof(p521_norm_mod));
  34698. }
  34699. /* Generate the pre-computed table of points for the base point.
  34700. *
  34701. * width = 8
  34702. * 256 entries
  34703. * 65 bits between
  34704. *
  34705. * a The base point.
  34706. * table Place to store generated point data.
  34707. * tmp Temporary data.
  34708. * heap Heap to use for allocation.
  34709. */
  34710. static int sp_521_gen_stripe_table_21(const sp_point_521* a,
  34711. sp_table_entry_521* table, sp_digit* tmp, void* heap)
  34712. {
  34713. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  34714. sp_point_521* t = NULL;
  34715. #else
  34716. sp_point_521 t[3];
  34717. #endif
  34718. sp_point_521* s1 = NULL;
  34719. sp_point_521* s2 = NULL;
  34720. int i;
  34721. int j;
  34722. int err = MP_OKAY;
  34723. (void)heap;
  34724. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  34725. t = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 3, heap,
  34726. DYNAMIC_TYPE_ECC);
  34727. if (t == NULL)
  34728. err = MEMORY_E;
  34729. #endif
  34730. if (err == MP_OKAY) {
  34731. s1 = t + 1;
  34732. s2 = t + 2;
  34733. err = sp_521_mod_mul_norm_21(t->x, a->x, p521_mod);
  34734. }
  34735. if (err == MP_OKAY) {
  34736. err = sp_521_mod_mul_norm_21(t->y, a->y, p521_mod);
  34737. }
  34738. if (err == MP_OKAY) {
  34739. err = sp_521_mod_mul_norm_21(t->z, a->z, p521_mod);
  34740. }
  34741. if (err == MP_OKAY) {
  34742. t->infinity = 0;
  34743. sp_521_proj_to_affine_21(t, tmp);
  34744. XMEMCPY(s1->z, p521_norm_mod, sizeof(p521_norm_mod));
  34745. s1->infinity = 0;
  34746. XMEMCPY(s2->z, p521_norm_mod, sizeof(p521_norm_mod));
  34747. s2->infinity = 0;
  34748. /* table[0] = {0, 0, infinity} */
  34749. XMEMSET(&table[0], 0, sizeof(sp_table_entry_521));
  34750. /* table[1] = Affine version of 'a' in Montgomery form */
  34751. XMEMCPY(table[1].x, t->x, sizeof(table->x));
  34752. XMEMCPY(table[1].y, t->y, sizeof(table->y));
  34753. for (i=1; i<8; i++) {
  34754. sp_521_proj_point_dbl_n_21(t, 66, tmp);
  34755. sp_521_proj_to_affine_21(t, tmp);
  34756. XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
  34757. XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
  34758. }
  34759. for (i=1; i<8; i++) {
  34760. XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
  34761. XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
  34762. for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
  34763. XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
  34764. XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
  34765. sp_521_proj_point_add_qz1_21(t, s1, s2, tmp);
  34766. sp_521_proj_to_affine_21(t, tmp);
  34767. XMEMCPY(table[j].x, t->x, sizeof(table->x));
  34768. XMEMCPY(table[j].y, t->y, sizeof(table->y));
  34769. }
  34770. }
  34771. }
  34772. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  34773. if (t != NULL)
  34774. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  34775. #endif
  34776. return err;
  34777. }
  34778. #endif /* FP_ECC */
  34779. #ifndef WC_NO_CACHE_RESISTANT
  34780. /* Touch each possible entry that could be being copied.
  34781. *
  34782. * r Point to copy into.
  34783. * table Table - start of the entires to access
  34784. * idx Index of entry to retrieve.
  34785. */
  34786. static void sp_521_get_entry_256_21(sp_point_521* r,
  34787. const sp_table_entry_521* table, int idx)
  34788. {
  34789. int i;
  34790. sp_digit mask;
  34791. r->x[0] = 0;
  34792. r->x[1] = 0;
  34793. r->x[2] = 0;
  34794. r->x[3] = 0;
  34795. r->x[4] = 0;
  34796. r->x[5] = 0;
  34797. r->x[6] = 0;
  34798. r->x[7] = 0;
  34799. r->x[8] = 0;
  34800. r->x[9] = 0;
  34801. r->x[10] = 0;
  34802. r->x[11] = 0;
  34803. r->x[12] = 0;
  34804. r->x[13] = 0;
  34805. r->x[14] = 0;
  34806. r->x[15] = 0;
  34807. r->x[16] = 0;
  34808. r->x[17] = 0;
  34809. r->x[18] = 0;
  34810. r->x[19] = 0;
  34811. r->x[20] = 0;
  34812. r->y[0] = 0;
  34813. r->y[1] = 0;
  34814. r->y[2] = 0;
  34815. r->y[3] = 0;
  34816. r->y[4] = 0;
  34817. r->y[5] = 0;
  34818. r->y[6] = 0;
  34819. r->y[7] = 0;
  34820. r->y[8] = 0;
  34821. r->y[9] = 0;
  34822. r->y[10] = 0;
  34823. r->y[11] = 0;
  34824. r->y[12] = 0;
  34825. r->y[13] = 0;
  34826. r->y[14] = 0;
  34827. r->y[15] = 0;
  34828. r->y[16] = 0;
  34829. r->y[17] = 0;
  34830. r->y[18] = 0;
  34831. r->y[19] = 0;
  34832. r->y[20] = 0;
  34833. for (i = 1; i < 256; i++) {
  34834. mask = 0 - (i == idx);
  34835. r->x[0] |= mask & table[i].x[0];
  34836. r->x[1] |= mask & table[i].x[1];
  34837. r->x[2] |= mask & table[i].x[2];
  34838. r->x[3] |= mask & table[i].x[3];
  34839. r->x[4] |= mask & table[i].x[4];
  34840. r->x[5] |= mask & table[i].x[5];
  34841. r->x[6] |= mask & table[i].x[6];
  34842. r->x[7] |= mask & table[i].x[7];
  34843. r->x[8] |= mask & table[i].x[8];
  34844. r->x[9] |= mask & table[i].x[9];
  34845. r->x[10] |= mask & table[i].x[10];
  34846. r->x[11] |= mask & table[i].x[11];
  34847. r->x[12] |= mask & table[i].x[12];
  34848. r->x[13] |= mask & table[i].x[13];
  34849. r->x[14] |= mask & table[i].x[14];
  34850. r->x[15] |= mask & table[i].x[15];
  34851. r->x[16] |= mask & table[i].x[16];
  34852. r->x[17] |= mask & table[i].x[17];
  34853. r->x[18] |= mask & table[i].x[18];
  34854. r->x[19] |= mask & table[i].x[19];
  34855. r->x[20] |= mask & table[i].x[20];
  34856. r->y[0] |= mask & table[i].y[0];
  34857. r->y[1] |= mask & table[i].y[1];
  34858. r->y[2] |= mask & table[i].y[2];
  34859. r->y[3] |= mask & table[i].y[3];
  34860. r->y[4] |= mask & table[i].y[4];
  34861. r->y[5] |= mask & table[i].y[5];
  34862. r->y[6] |= mask & table[i].y[6];
  34863. r->y[7] |= mask & table[i].y[7];
  34864. r->y[8] |= mask & table[i].y[8];
  34865. r->y[9] |= mask & table[i].y[9];
  34866. r->y[10] |= mask & table[i].y[10];
  34867. r->y[11] |= mask & table[i].y[11];
  34868. r->y[12] |= mask & table[i].y[12];
  34869. r->y[13] |= mask & table[i].y[13];
  34870. r->y[14] |= mask & table[i].y[14];
  34871. r->y[15] |= mask & table[i].y[15];
  34872. r->y[16] |= mask & table[i].y[16];
  34873. r->y[17] |= mask & table[i].y[17];
  34874. r->y[18] |= mask & table[i].y[18];
  34875. r->y[19] |= mask & table[i].y[19];
  34876. r->y[20] |= mask & table[i].y[20];
  34877. }
  34878. }
  34879. #endif /* !WC_NO_CACHE_RESISTANT */
  34880. /* Multiply the point by the scalar and return the result.
  34881. * If map is true then convert result to affine coordinates.
  34882. *
  34883. * Stripe implementation.
  34884. * Pre-generated: 2^0, 2^65, ...
  34885. * Pre-generated: products of all combinations of above.
  34886. * 8 doubles and adds (with qz=1)
  34887. *
  34888. * r Resulting point.
  34889. * k Scalar to multiply by.
  34890. * table Pre-computed table.
  34891. * map Indicates whether to convert result to affine.
  34892. * ct Constant time required.
  34893. * heap Heap to use for allocation.
  34894. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  34895. */
  34896. static int sp_521_ecc_mulmod_stripe_21(sp_point_521* r, const sp_point_521* g,
  34897. const sp_table_entry_521* table, const sp_digit* k, int map,
  34898. int ct, void* heap)
  34899. {
  34900. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  34901. sp_point_521* rt = NULL;
  34902. sp_digit* t = NULL;
  34903. #else
  34904. sp_point_521 rt[2];
  34905. sp_digit t[2 * 21 * 6];
  34906. #endif
  34907. sp_point_521* p = NULL;
  34908. int i;
  34909. int j;
  34910. int y;
  34911. int x;
  34912. int err = MP_OKAY;
  34913. (void)g;
  34914. /* Constant time used for cache attack resistance implementation. */
  34915. (void)ct;
  34916. (void)heap;
  34917. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  34918. rt = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap,
  34919. DYNAMIC_TYPE_ECC);
  34920. if (rt == NULL)
  34921. err = MEMORY_E;
  34922. if (err == MP_OKAY) {
  34923. t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 21 * 6, heap,
  34924. DYNAMIC_TYPE_ECC);
  34925. if (t == NULL)
  34926. err = MEMORY_E;
  34927. }
  34928. #endif
  34929. if (err == MP_OKAY) {
  34930. p = rt + 1;
  34931. XMEMCPY(p->z, p521_norm_mod, sizeof(p521_norm_mod));
  34932. XMEMCPY(rt->z, p521_norm_mod, sizeof(p521_norm_mod));
  34933. y = 0;
  34934. x = 65;
  34935. for (j=0; j<8 && x<521; j++) {
  34936. y |= (int)(((k[x / 25] >> (x % 25)) & 1) << j);
  34937. x += 66;
  34938. }
  34939. #ifndef WC_NO_CACHE_RESISTANT
  34940. if (ct) {
  34941. sp_521_get_entry_256_21(rt, table, y);
  34942. } else
  34943. #endif
  34944. {
  34945. XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
  34946. XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
  34947. }
  34948. rt->infinity = !y;
  34949. for (i=64; i>=0; i--) {
  34950. y = 0;
  34951. x = i;
  34952. for (j=0; j<8 && x<521; j++) {
  34953. y |= (int)(((k[x / 25] >> (x % 25)) & 1) << j);
  34954. x += 66;
  34955. }
  34956. sp_521_proj_point_dbl_21(rt, rt, t);
  34957. #ifndef WC_NO_CACHE_RESISTANT
  34958. if (ct) {
  34959. sp_521_get_entry_256_21(p, table, y);
  34960. }
  34961. else
  34962. #endif
  34963. {
  34964. XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
  34965. XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
  34966. }
  34967. p->infinity = !y;
  34968. sp_521_proj_point_add_qz1_21(rt, rt, p, t);
  34969. }
  34970. if (map != 0) {
  34971. sp_521_map_21(r, rt, t);
  34972. }
  34973. else {
  34974. XMEMCPY(r, rt, sizeof(sp_point_521));
  34975. }
  34976. }
  34977. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  34978. if (t != NULL)
  34979. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  34980. if (rt != NULL)
  34981. XFREE(rt, heap, DYNAMIC_TYPE_ECC);
  34982. #endif
  34983. return err;
  34984. }
  34985. #ifdef FP_ECC
  34986. #ifndef FP_ENTRIES
  34987. #define FP_ENTRIES 16
  34988. #endif
  34989. /* Cache entry - holds precomputation tables for a point. */
  34990. typedef struct sp_cache_521_t {
  34991. /* X ordinate of point that table was generated from. */
  34992. sp_digit x[21];
  34993. /* Y ordinate of point that table was generated from. */
  34994. sp_digit y[21];
  34995. /* Precomputation table for point. */
  34996. sp_table_entry_521 table[256];
  34997. /* Count of entries in table. */
  34998. uint32_t cnt;
  34999. /* Point and table set in entry. */
  35000. int set;
  35001. } sp_cache_521_t;
  35002. /* Cache of tables. */
  35003. static THREAD_LS_T sp_cache_521_t sp_cache_521[FP_ENTRIES];
  35004. /* Index of last entry in cache. */
  35005. static THREAD_LS_T int sp_cache_521_last = -1;
  35006. /* Cache has been initialized. */
  35007. static THREAD_LS_T int sp_cache_521_inited = 0;
  35008. #ifndef HAVE_THREAD_LS
  35009. static volatile int initCacheMutex_521 = 0;
  35010. static wolfSSL_Mutex sp_cache_521_lock;
  35011. #endif
  35012. /* Get the cache entry for the point.
  35013. *
  35014. * g [in] Point scalar multipling.
  35015. * cache [out] Cache table to use.
  35016. */
  35017. static void sp_ecc_get_cache_521(const sp_point_521* g, sp_cache_521_t** cache)
  35018. {
  35019. int i;
  35020. int j;
  35021. uint32_t least;
  35022. if (sp_cache_521_inited == 0) {
  35023. for (i=0; i<FP_ENTRIES; i++) {
  35024. sp_cache_521[i].set = 0;
  35025. }
  35026. sp_cache_521_inited = 1;
  35027. }
  35028. /* Compare point with those in cache. */
  35029. for (i=0; i<FP_ENTRIES; i++) {
  35030. if (!sp_cache_521[i].set)
  35031. continue;
  35032. if (sp_521_cmp_equal_21(g->x, sp_cache_521[i].x) &
  35033. sp_521_cmp_equal_21(g->y, sp_cache_521[i].y)) {
  35034. sp_cache_521[i].cnt++;
  35035. break;
  35036. }
  35037. }
  35038. /* No match. */
  35039. if (i == FP_ENTRIES) {
  35040. /* Find empty entry. */
  35041. i = (sp_cache_521_last + 1) % FP_ENTRIES;
  35042. for (; i != sp_cache_521_last; i=(i+1)%FP_ENTRIES) {
  35043. if (!sp_cache_521[i].set) {
  35044. break;
  35045. }
  35046. }
  35047. /* Evict least used. */
  35048. if (i == sp_cache_521_last) {
  35049. least = sp_cache_521[0].cnt;
  35050. for (j=1; j<FP_ENTRIES; j++) {
  35051. if (sp_cache_521[j].cnt < least) {
  35052. i = j;
  35053. least = sp_cache_521[i].cnt;
  35054. }
  35055. }
  35056. }
  35057. XMEMCPY(sp_cache_521[i].x, g->x, sizeof(sp_cache_521[i].x));
  35058. XMEMCPY(sp_cache_521[i].y, g->y, sizeof(sp_cache_521[i].y));
  35059. sp_cache_521[i].set = 1;
  35060. sp_cache_521[i].cnt = 1;
  35061. }
  35062. *cache = &sp_cache_521[i];
  35063. sp_cache_521_last = i;
  35064. }
  35065. #endif /* FP_ECC */
  35066. /* Multiply the base point of P521 by the scalar and return the result.
  35067. * If map is true then convert result to affine coordinates.
  35068. *
  35069. * r Resulting point.
  35070. * g Point to multiply.
  35071. * k Scalar to multiply by.
  35072. * map Indicates whether to convert result to affine.
  35073. * ct Constant time required.
  35074. * heap Heap to use for allocation.
  35075. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  35076. */
  35077. static int sp_521_ecc_mulmod_21(sp_point_521* r, const sp_point_521* g, const sp_digit* k,
  35078. int map, int ct, void* heap)
  35079. {
  35080. #ifndef FP_ECC
  35081. return sp_521_ecc_mulmod_win_add_sub_21(r, g, k, map, ct, heap);
  35082. #else
  35083. sp_digit tmp[2 * 21 * 6];
  35084. sp_cache_521_t* cache;
  35085. int err = MP_OKAY;
  35086. #ifndef HAVE_THREAD_LS
  35087. if (initCacheMutex_521 == 0) {
  35088. wc_InitMutex(&sp_cache_521_lock);
  35089. initCacheMutex_521 = 1;
  35090. }
  35091. if (wc_LockMutex(&sp_cache_521_lock) != 0)
  35092. err = BAD_MUTEX_E;
  35093. #endif /* HAVE_THREAD_LS */
  35094. if (err == MP_OKAY) {
  35095. sp_ecc_get_cache_521(g, &cache);
  35096. if (cache->cnt == 2)
  35097. sp_521_gen_stripe_table_21(g, cache->table, tmp, heap);
  35098. #ifndef HAVE_THREAD_LS
  35099. wc_UnLockMutex(&sp_cache_521_lock);
  35100. #endif /* HAVE_THREAD_LS */
  35101. if (cache->cnt < 2) {
  35102. err = sp_521_ecc_mulmod_win_add_sub_21(r, g, k, map, ct, heap);
  35103. }
  35104. else {
  35105. err = sp_521_ecc_mulmod_stripe_21(r, g, cache->table, k,
  35106. map, ct, heap);
  35107. }
  35108. }
  35109. return err;
  35110. #endif
  35111. }
  35112. #endif
  35113. /* Multiply the point by the scalar and return the result.
  35114. * If map is true then convert result to affine coordinates.
  35115. *
  35116. * km Scalar to multiply by.
  35117. * p Point to multiply.
  35118. * r Resulting point.
  35119. * map Indicates whether to convert result to affine.
  35120. * heap Heap to use for allocation.
  35121. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  35122. */
  35123. int sp_ecc_mulmod_521(const mp_int* km, const ecc_point* gm, ecc_point* r,
  35124. int map, void* heap)
  35125. {
  35126. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  35127. sp_point_521* point = NULL;
  35128. sp_digit* k = NULL;
  35129. #else
  35130. sp_point_521 point[1];
  35131. sp_digit k[21];
  35132. #endif
  35133. int err = MP_OKAY;
  35134. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  35135. point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap,
  35136. DYNAMIC_TYPE_ECC);
  35137. if (point == NULL)
  35138. err = MEMORY_E;
  35139. if (err == MP_OKAY) {
  35140. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 21, heap,
  35141. DYNAMIC_TYPE_ECC);
  35142. if (k == NULL)
  35143. err = MEMORY_E;
  35144. }
  35145. #endif
  35146. if (err == MP_OKAY) {
  35147. sp_521_from_mp(k, 21, km);
  35148. sp_521_point_from_ecc_point_21(point, gm);
  35149. err = sp_521_ecc_mulmod_21(point, point, k, map, 1, heap);
  35150. }
  35151. if (err == MP_OKAY) {
  35152. err = sp_521_point_to_ecc_point_21(point, r);
  35153. }
  35154. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  35155. if (k != NULL)
  35156. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  35157. if (point != NULL)
  35158. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  35159. #endif
  35160. return err;
  35161. }
  35162. /* Multiply the point by the scalar, add point a and return the result.
  35163. * If map is true then convert result to affine coordinates.
  35164. *
  35165. * km Scalar to multiply by.
  35166. * p Point to multiply.
  35167. * am Point to add to scalar mulitply result.
  35168. * inMont Point to add is in montgomery form.
  35169. * r Resulting point.
  35170. * map Indicates whether to convert result to affine.
  35171. * heap Heap to use for allocation.
  35172. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  35173. */
  35174. int sp_ecc_mulmod_add_521(const mp_int* km, const ecc_point* gm,
  35175. const ecc_point* am, int inMont, ecc_point* r, int map, void* heap)
  35176. {
  35177. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  35178. sp_point_521* point = NULL;
  35179. sp_digit* k = NULL;
  35180. #else
  35181. sp_point_521 point[2];
  35182. sp_digit k[21 + 21 * 2 * 6];
  35183. #endif
  35184. sp_point_521* addP = NULL;
  35185. sp_digit* tmp = NULL;
  35186. int err = MP_OKAY;
  35187. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  35188. point = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap,
  35189. DYNAMIC_TYPE_ECC);
  35190. if (point == NULL)
  35191. err = MEMORY_E;
  35192. if (err == MP_OKAY) {
  35193. k = (sp_digit*)XMALLOC(
  35194. sizeof(sp_digit) * (21 + 21 * 2 * 6), heap,
  35195. DYNAMIC_TYPE_ECC);
  35196. if (k == NULL)
  35197. err = MEMORY_E;
  35198. }
  35199. #endif
  35200. if (err == MP_OKAY) {
  35201. addP = point + 1;
  35202. tmp = k + 21;
  35203. sp_521_from_mp(k, 21, km);
  35204. sp_521_point_from_ecc_point_21(point, gm);
  35205. sp_521_point_from_ecc_point_21(addP, am);
  35206. }
  35207. if ((err == MP_OKAY) && (!inMont)) {
  35208. err = sp_521_mod_mul_norm_21(addP->x, addP->x, p521_mod);
  35209. }
  35210. if ((err == MP_OKAY) && (!inMont)) {
  35211. err = sp_521_mod_mul_norm_21(addP->y, addP->y, p521_mod);
  35212. }
  35213. if ((err == MP_OKAY) && (!inMont)) {
  35214. err = sp_521_mod_mul_norm_21(addP->z, addP->z, p521_mod);
  35215. }
  35216. if (err == MP_OKAY) {
  35217. err = sp_521_ecc_mulmod_21(point, point, k, 0, 0, heap);
  35218. }
  35219. if (err == MP_OKAY) {
  35220. sp_521_proj_point_add_21(point, point, addP, tmp);
  35221. if (map) {
  35222. sp_521_map_21(point, point, tmp);
  35223. }
  35224. err = sp_521_point_to_ecc_point_21(point, r);
  35225. }
  35226. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  35227. if (k != NULL)
  35228. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  35229. if (point != NULL)
  35230. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  35231. #endif
  35232. return err;
  35233. }
  35234. #ifdef WOLFSSL_SP_SMALL
  35235. /* Multiply the base point of P521 by the scalar and return the result.
  35236. * If map is true then convert result to affine coordinates.
  35237. *
  35238. * r Resulting point.
  35239. * k Scalar to multiply by.
  35240. * map Indicates whether to convert result to affine.
  35241. * heap Heap to use for allocation.
  35242. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  35243. */
  35244. static int sp_521_ecc_mulmod_base_21(sp_point_521* r, const sp_digit* k,
  35245. int map, int ct, void* heap)
  35246. {
  35247. /* No pre-computed values. */
  35248. return sp_521_ecc_mulmod_21(r, &p521_base, k, map, ct, heap);
  35249. }
  35250. #else
  35251. /* Striping precomputation table.
  35252. * 8 points combined into a table of 256 points.
  35253. * Distance of 66 between points.
  35254. */
  35255. static const sp_table_entry_521 p521_table[256] = {
  35256. /* 0 */
  35257. { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  35258. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
  35259. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  35260. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
  35261. /* 1 */
  35262. { { 0x0e5bd66,0x13f18e1,0x0a6fe5f,0x030ad48,0x1348b3c,0x1fd46f1,
  35263. 0x1049e8b,0x051fc3b,0x1efe759,0x0a5af3b,0x14f6ea8,0x1ec0d69,
  35264. 0x01f828a,0x029fda9,0x19204e4,0x1688538,0x1662395,0x0cf1f65,
  35265. 0x1013a73,0x1c0d6e0,0x00c6858 },
  35266. { 0x1d16650,0x14a3b4f,0x090222f,0x0d44e58,0x153c708,0x1683b09,
  35267. 0x0e404fe,0x0818aa1,0x15ef426,0x1f7394c,0x1998b25,0x1a2e4e7,
  35268. 0x0817afb,0x0bcda23,0x1d51125,0x037b331,0x1b42c7d,0x02e452f,
  35269. 0x08ef001,0x12d4f13,0x0118392 } },
  35270. /* 2 */
  35271. { { 0x10ccb51,0x0c33387,0x1d2a00e,0x026ca92,0x187e1d0,0x194f6cd,
  35272. 0x13c86ca,0x06efeb1,0x0a3add3,0x16074d5,0x023fec1,0x0ba1d3a,
  35273. 0x07f13b3,0x0b3b0b1,0x02fd132,0x07de9bb,0x014758a,0x1d250c6,
  35274. 0x0010eb6,0x0aedbb4,0x013e96a },
  35275. { 0x12d95a3,0x1127c31,0x00a4af7,0x0298a49,0x19f15ef,0x0d5d0cb,
  35276. 0x018fa6f,0x00f55bb,0x0a962b7,0x0f029fa,0x1636637,0x05bc284,
  35277. 0x1cc598a,0x030e11a,0x0968674,0x1a6593f,0x110e8ff,0x0076a32,
  35278. 0x1de33ab,0x153ba3d,0x01852ae } },
  35279. /* 3 */
  35280. { { 0x0af1fe3,0x08eec75,0x14af42a,0x0488016,0x0db3866,0x15f8690,
  35281. 0x01aa486,0x081fed4,0x0a768c9,0x00943cd,0x1bb0de5,0x1579343,
  35282. 0x1cf3791,0x139c1a1,0x04fef98,0x1578392,0x0abe222,0x1b945a1,
  35283. 0x0e7bcc4,0x18150c5,0x0157874 },
  35284. { 0x0f03d49,0x078c273,0x180c2b2,0x083c917,0x09c357e,0x0e5ef7d,
  35285. 0x17bce05,0x078059c,0x15fd8dc,0x120e3d5,0x0c4275e,0x0f93f5d,
  35286. 0x184bef6,0x1427a69,0x0633286,0x0155c5f,0x07d672f,0x1bf01ea,
  35287. 0x15625a2,0x0356b03,0x000724b } },
  35288. /* 4 */
  35289. { { 0x19314e0,0x196a5ef,0x0ab2413,0x1bcf401,0x1aae850,0x177d81e,
  35290. 0x0420d60,0x1a4f246,0x1ec7fe6,0x078e141,0x15d2a20,0x132c333,
  35291. 0x072d5b3,0x1ca803f,0x0482e6c,0x1e07cbe,0x1734773,0x118691b,
  35292. 0x0de2da1,0x0324e67,0x0121f4c },
  35293. { 0x08b51f0,0x1ffb6fd,0x17c3c40,0x0281c57,0x0e7afb5,0x12a0b8d,
  35294. 0x0e03a0c,0x12a2260,0x0cda10d,0x01a80dc,0x0a3007a,0x0e3c9e7,
  35295. 0x0910577,0x1640383,0x14865aa,0x070431e,0x0aaa562,0x09b04d8,
  35296. 0x12829fc,0x0af20d2,0x01db8c2 } },
  35297. /* 5 */
  35298. { { 0x0c0958d,0x1b86659,0x0e1cc00,0x0cd34f6,0x09aef16,0x064d9c4,
  35299. 0x1cf3d20,0x0924f25,0x0fab3e1,0x194c279,0x12259c2,0x086ca0e,
  35300. 0x0a9751e,0x1699ed9,0x0ae6756,0x09b5539,0x132b44a,0x0a6ca2e,
  35301. 0x1b1dcc9,0x1994a42,0x000aa26 },
  35302. { 0x1e66d18,0x10ea0fc,0x19eb36f,0x0d5422f,0x00aeef9,0x186925c,
  35303. 0x0528b76,0x17e0a64,0x15c98b7,0x0e7d913,0x0f2121b,0x086dbfa,
  35304. 0x0c613e7,0x1e526a9,0x1c0fe84,0x03cc8dc,0x1771855,0x0864714,
  35305. 0x1ea149f,0x121d597,0x01c6f5e } },
  35306. /* 6 */
  35307. { { 0x0b2d58f,0x178f3a5,0x000a8b0,0x185412f,0x01bbf82,0x05dbb56,
  35308. 0x1ac91dc,0x17acb07,0x15667f7,0x1276cf6,0x1a25fa3,0x1b0dfb2,
  35309. 0x15d8c01,0x1fdf078,0x0e5684c,0x1b962cc,0x19dd99c,0x0a8f279,
  35310. 0x0837ac9,0x108494e,0x0082de0 },
  35311. { 0x0ea91af,0x129d930,0x1f765ea,0x0ef463b,0x04384af,0x084ddf5,
  35312. 0x1c8e573,0x1c39b05,0x0f30058,0x0be0ced,0x1e3a5e6,0x018dcb8,
  35313. 0x05443b6,0x0bad8c2,0x0ba6d7d,0x19c2df5,0x13308c2,0x12e7437,
  35314. 0x1d8fea1,0x19cb1e9,0x0073983 } },
  35315. /* 7 */
  35316. { { 0x017609d,0x09898c1,0x1002bba,0x084825f,0x1f8a9dd,0x163194b,
  35317. 0x19930a1,0x0bdc22f,0x07bf1c6,0x01bc16b,0x0fbb973,0x09b71a0,
  35318. 0x19e8c14,0x0d5c9bc,0x0b2b2ca,0x1098e03,0x1b5b077,0x190af58,
  35319. 0x0bff361,0x013f503,0x00f82c4 },
  35320. { 0x18139a4,0x09bb31b,0x0a4c01f,0x176ab7d,0x06d969e,0x045e4ee,
  35321. 0x035bda3,0x0858f8c,0x15f93f2,0x0274230,0x1c5f661,0x1454e82,
  35322. 0x0e8461c,0x185f890,0x04c39e7,0x133af1d,0x0026b56,0x170aaa5,
  35323. 0x093edb7,0x18ee04d,0x007de69 } },
  35324. /* 8 */
  35325. { { 0x1ee80d7,0x08dd825,0x19a586d,0x1eed25b,0x0e1f6a1,0x15e1de8,
  35326. 0x191b283,0x1e106f3,0x1930644,0x005ffd3,0x16c1dc7,0x170e721,
  35327. 0x0997c67,0x1d6d0e7,0x170cf87,0x16a2412,0x0ddac54,0x11e2805,
  35328. 0x0c46195,0x03a6c1a,0x00b0c23 },
  35329. { 0x1bcab2f,0x0494c1c,0x082818a,0x00c9ba4,0x00c0678,0x1ee1506,
  35330. 0x18211d8,0x1c60c5e,0x11938c3,0x074ed39,0x11bae62,0x1e5aa5c,
  35331. 0x1d69be8,0x152ef07,0x17234b5,0x01c4dca,0x163db2c,0x1f9d1fe,
  35332. 0x192ffd5,0x18db3e3,0x014a899 } },
  35333. /* 9 */
  35334. { { 0x005ce88,0x171d0f6,0x080a7fd,0x0d6d5fa,0x18fc249,0x1f5803f,
  35335. 0x081ddbe,0x080173a,0x1eebded,0x087605e,0x1c03ded,0x0e84d26,
  35336. 0x0eaef97,0x1fbd818,0x1b8de84,0x03eef00,0x1171b90,0x1ae78be,
  35337. 0x0a56b83,0x0dcbbf9,0x0159903 },
  35338. { 0x00e8e0c,0x1b25a80,0x17e402b,0x080df69,0x13f2ae0,0x0f91dd6,
  35339. 0x1699d12,0x152bec3,0x0255b25,0x0548c21,0x0f19403,0x07cd1c6,
  35340. 0x01fa6af,0x016013e,0x0dcf003,0x0814a28,0x1a19728,0x04cf9e6,
  35341. 0x03a1090,0x0c56f3a,0x00e798c } },
  35342. /* 10 */
  35343. { { 0x04d0f28,0x1e25457,0x01bba31,0x1eacda0,0x1a8a55e,0x1720119,
  35344. 0x17d9419,0x0ec6f30,0x15d321b,0x0f6655a,0x146c1e3,0x0dad706,
  35345. 0x0b38b96,0x0beaa45,0x022794d,0x156165d,0x02fe631,0x1bd4f47,
  35346. 0x1d714de,0x0c1f2bc,0x005945c },
  35347. { 0x067d79c,0x13e9a3c,0x0602f28,0x0b03903,0x1f460b1,0x15c628b,
  35348. 0x166ae5d,0x1b2fd85,0x061b91e,0x0682243,0x07457ff,0x144bb38,
  35349. 0x19730a7,0x1ca64ed,0x0b3c967,0x0b47714,0x1875dec,0x1473c25,
  35350. 0x1944c7b,0x0a4c0e7,0x0004062 } },
  35351. /* 11 */
  35352. { { 0x1631bba,0x0272e78,0x14937b8,0x1e2ade8,0x00e6c1d,0x0184c82,
  35353. 0x0fcc393,0x18e0cc0,0x16b6abe,0x1b24d21,0x053dbb6,0x0139ed7,
  35354. 0x15354f5,0x1b5bf05,0x1b3d1a4,0x0dba4ff,0x07eba1e,0x153d388,
  35355. 0x0251432,0x1db58ad,0x0022889 },
  35356. { 0x05596f2,0x148b768,0x0e2e404,0x1960479,0x03901da,0x0a55f0f,
  35357. 0x14fb39f,0x0264a03,0x0a9c903,0x140a820,0x051b42c,0x07e38da,
  35358. 0x169dbcd,0x1a770c4,0x08756c5,0x04df6df,0x161a912,0x024d750,
  35359. 0x02a0261,0x19ddbf7,0x0154754 } },
  35360. /* 12 */
  35361. { { 0x070b2f0,0x113d821,0x135ed93,0x117e9ae,0x04b34e4,0x13915d4,
  35362. 0x0fa2c30,0x039630d,0x19ff9b7,0x0a52c4e,0x15af13d,0x09be69f,
  35363. 0x1d9887e,0x1a097a4,0x119a7f5,0x13a2d6f,0x1bb77f8,0x020046c,
  35364. 0x040b81d,0x1284d79,0x01cfafb },
  35365. { 0x02935ca,0x07968b3,0x111b329,0x0732fb9,0x0847c70,0x1e3cfc1,
  35366. 0x1a794d4,0x1e98113,0x15215f0,0x16c6cc4,0x046e767,0x1179012,
  35367. 0x0359cf0,0x16f13d5,0x00d5039,0x0641a96,0x03ef69e,0x1a97a6b,
  35368. 0x13bc64e,0x02ffad2,0x00e6a02 } },
  35369. /* 13 */
  35370. { { 0x0214780,0x0f313ba,0x07aaddf,0x0e40e8b,0x0a06681,0x03fd80e,
  35371. 0x1e6dfa7,0x18fef0a,0x1d6d4b7,0x0aaa460,0x12a8e79,0x03214cd,
  35372. 0x0f45756,0x0c282d2,0x0506c0e,0x0c9d7f0,0x17c4c88,0x1d2e506,
  35373. 0x184a74f,0x15f2a13,0x0053bf8 },
  35374. { 0x1285092,0x194ec42,0x197ef26,0x151ddab,0x02f31da,0x0c555cc,
  35375. 0x1a43bd8,0x1a33866,0x0d2626e,0x1770a7a,0x1638243,0x0e160fd,
  35376. 0x0042295,0x039b682,0x1de483a,0x1a03a32,0x1ffede7,0x1a3f712,
  35377. 0x11eadce,0x0438757,0x01b93c9 } },
  35378. /* 14 */
  35379. { { 0x08b2b14,0x103e650,0x11fc2da,0x177e2e9,0x0a978de,0x0659525,
  35380. 0x0e0a310,0x0705239,0x090adc8,0x0e3c139,0x1b779a5,0x1655183,
  35381. 0x0008da8,0x087de91,0x073acbe,0x1729ce8,0x1e5322d,0x12fc4e4,
  35382. 0x1cf1523,0x0cc10b6,0x007d182 },
  35383. { 0x1efd012,0x1fc1516,0x1fbda7a,0x08b42a6,0x01ecb09,0x18408e8,
  35384. 0x1d4d4fb,0x1d478aa,0x1b2bd4d,0x0e44153,0x05a7216,0x12e4f7f,
  35385. 0x1b00a1f,0x0592d68,0x0eb7d78,0x0c00a0c,0x106f253,0x0260ff9,
  35386. 0x044bf86,0x02b7d88,0x01178e5 } },
  35387. /* 15 */
  35388. { { 0x1e3d3d5,0x03c3ff7,0x089e4c5,0x0b3b12e,0x09e76f6,0x1b567a9,
  35389. 0x1fb4782,0x1b22b8e,0x01c5e8d,0x015bd90,0x199ebe7,0x11e2bea,
  35390. 0x1478803,0x19abb77,0x031d9bf,0x02a95e7,0x1c80040,0x1cf8311,
  35391. 0x1a20ed4,0x078897b,0x009647d },
  35392. { 0x01b21a4,0x1ab1c6f,0x0704c81,0x02ae210,0x1b6399c,0x001accd,
  35393. 0x1819dd7,0x1ea645c,0x1ade60c,0x03fef3f,0x0641657,0x0881df8,
  35394. 0x001b195,0x0ebd9cb,0x1c2b233,0x14e7cfc,0x03d6a6f,0x02552d4,
  35395. 0x0c201d9,0x119f58c,0x004234f } },
  35396. /* 16 */
  35397. { { 0x06492ad,0x0f38d14,0x0b13b8c,0x08cbf0d,0x08f3de4,0x189e5a0,
  35398. 0x0035369,0x009d12e,0x1a86b71,0x1687af4,0x0b0585e,0x1c9e4ae,
  35399. 0x19d9a62,0x12e60e4,0x1488fbc,0x05c18ef,0x1613b96,0x0f6ffb4,
  35400. 0x0762c81,0x1a51e70,0x008e818 },
  35401. { 0x0df1f60,0x118e7c6,0x183dc84,0x16ce2ee,0x0b640f2,0x02d201c,
  35402. 0x1be3381,0x13f7ce4,0x0037068,0x11142ee,0x08372d0,0x1f1ee5d,
  35403. 0x037196b,0x0404331,0x1bde157,0x1fc9142,0x1c7c326,0x06a70cf,
  35404. 0x1da2fd1,0x190add1,0x013efdb } },
  35405. /* 17 */
  35406. { { 0x0a3ace5,0x06827f3,0x070778d,0x1d12c32,0x0dbb603,0x0f687a0,
  35407. 0x0001fdd,0x16b69b8,0x095b259,0x0f0735e,0x17c0805,0x14cc4c2,
  35408. 0x18dfbcb,0x098f51f,0x1b150cf,0x1f04965,0x0e4103f,0x1215858,
  35409. 0x1200ccb,0x02a0c18,0x0111193 },
  35410. { 0x05452f1,0x1f51402,0x1cee665,0x1ee3e7e,0x00b678c,0x1499474,
  35411. 0x0f77107,0x04694a5,0x0e6af1c,0x1f932b7,0x08579ed,0x0b73688,
  35412. 0x0bc4380,0x1852014,0x09cd3cb,0x0edc475,0x0794224,0x1f1e392,
  35413. 0x031833d,0x05d160d,0x01f16dc } },
  35414. /* 18 */
  35415. { { 0x1fc0de5,0x1d737ff,0x1c92f37,0x1f5694b,0x0801814,0x15546ed,
  35416. 0x0d963a8,0x0823202,0x1da4f04,0x1d8e57a,0x001847c,0x19b6682,
  35417. 0x08f24b9,0x0b7067c,0x10c93b6,0x0b90491,0x1342305,0x0a5bf51,
  35418. 0x0424b8a,0x06b6c91,0x01d36e8 },
  35419. { 0x1372f27,0x1bd7383,0x0669fad,0x150775c,0x0779b4f,0x014f5da,
  35420. 0x16b8595,0x07f42eb,0x0fc03ef,0x0176133,0x071f125,0x0d52d32,
  35421. 0x1c0e5fc,0x0b129e9,0x1d8793d,0x1ce7141,0x158de74,0x0bd08ff,
  35422. 0x0937a46,0x0499a8c,0x0002605 } },
  35423. /* 19 */
  35424. { { 0x1342e08,0x0e86500,0x02bd16d,0x016e93e,0x109ed4f,0x14ec022,
  35425. 0x00b6594,0x139d6aa,0x16d8035,0x15843ed,0x0120017,0x150e987,
  35426. 0x04eaa66,0x03ad43c,0x1cb1e83,0x062fdd2,0x0216874,0x0460b4f,
  35427. 0x1727efd,0x0aadc1c,0x014f81c },
  35428. { 0x120674d,0x05895f0,0x02b09ac,0x12433e0,0x06bf09b,0x0c65536,
  35429. 0x1ccb759,0x13c3c3c,0x18292d9,0x1b8e2d7,0x16fe031,0x0a524bf,
  35430. 0x1d5d813,0x1b3361b,0x06f5e60,0x1ed01cc,0x06a1d0d,0x1c6d64a,
  35431. 0x0e7c260,0x19ed098,0x009f58d } },
  35432. /* 20 */
  35433. { { 0x17dc837,0x148813d,0x0710505,0x096a1d6,0x0d71975,0x133a0d9,
  35434. 0x024ab5f,0x07009e8,0x1bc824a,0x0853f8e,0x082f3c7,0x00ad91c,
  35435. 0x10570b2,0x0d0c0ed,0x0cb8ee7,0x0a114ce,0x16e0a7b,0x13c4031,
  35436. 0x07dc124,0x1ea0599,0x004511a },
  35437. { 0x16f4ffa,0x106ca62,0x03e82e0,0x0589e18,0x1c6205a,0x1030350,
  35438. 0x0f53a86,0x1f733e6,0x079b316,0x1d5b233,0x0903f06,0x10a5c9e,
  35439. 0x0305aa0,0x096bee2,0x14e6de2,0x180e644,0x11206e3,0x181b2bf,
  35440. 0x1b6d98c,0x00a5019,0x0059284 } },
  35441. /* 21 */
  35442. { { 0x197760c,0x04388a1,0x141a434,0x0c393f9,0x19020b7,0x1f127bd,
  35443. 0x11fea61,0x1418ffd,0x0522335,0x119dc50,0x0728403,0x15fb5c4,
  35444. 0x0073dbe,0x1d81911,0x0301828,0x0bb4c8b,0x1b8ee14,0x1cdce39,
  35445. 0x1ffd8bb,0x0cc3ca4,0x00aa31c },
  35446. { 0x1430b5e,0x0c75840,0x15a6bd4,0x14a1dc1,0x132f9ce,0x175f45d,
  35447. 0x0c2d6a9,0x1121d9b,0x09fe1d6,0x18afbf9,0x0732687,0x11e634b,
  35448. 0x03ce5d6,0x0455953,0x159e650,0x19ca9e9,0x0ef4347,0x1742d8e,
  35449. 0x01b41dd,0x0847805,0x01768ff } },
  35450. /* 22 */
  35451. { { 0x1dcec23,0x0082619,0x1466159,0x179ba0e,0x1af0d61,0x07984d5,
  35452. 0x0bd4531,0x02a90db,0x1de4887,0x00de47a,0x0e6e8fc,0x15e3a6a,
  35453. 0x0cddd6b,0x1d1df47,0x1f99974,0x10cbf76,0x0c3cb5d,0x07c8ced,
  35454. 0x0485268,0x007b47e,0x0173fe2 },
  35455. { 0x0d4a3d1,0x174d0bc,0x1b6010e,0x110ca62,0x04d5cf5,0x0bb231d,
  35456. 0x09b0104,0x089d5e0,0x1f84afa,0x0b631c7,0x0908b4c,0x072fffd,
  35457. 0x13512f2,0x13115b0,0x07aa811,0x00d1ad2,0x0a397e7,0x02442b7,
  35458. 0x1286ccf,0x0365c7e,0x01b542d } },
  35459. /* 23 */
  35460. { { 0x1487402,0x196af0f,0x1757d46,0x0cf55e3,0x036016e,0x14e1057,
  35461. 0x1c7d5b6,0x1fa3d67,0x1ece45b,0x0dbe9b0,0x0a78609,0x0c6604f,
  35462. 0x0942db0,0x14208b2,0x08a1ddf,0x0e7a17e,0x0c44587,0x07afe70,
  35463. 0x175e97c,0x062a3a5,0x001fb2b },
  35464. { 0x1aa096a,0x1b9f47d,0x01e0409,0x17c1275,0x152726e,0x1f8bc08,
  35465. 0x1341cb1,0x0ecb8a7,0x0ab5dca,0x069efe8,0x1cb528e,0x1b0b0fd,
  35466. 0x02bb4a7,0x1bf588e,0x070804e,0x1445eb9,0x0340b6d,0x0af1a9e,
  35467. 0x0c97b2b,0x1aa14b4,0x0039846 } },
  35468. /* 24 */
  35469. { { 0x077df58,0x13b9b0b,0x15b1db6,0x0e396a1,0x164bd56,0x0407f91,
  35470. 0x11f5c28,0x0600887,0x1865324,0x0542a14,0x04079e8,0x1ba586a,
  35471. 0x1682002,0x0462e6b,0x0f1850d,0x1e27f7d,0x1aeca6c,0x07f8ac8,
  35472. 0x02fe370,0x0f85cd3,0x00fb91c },
  35473. { 0x0de14d5,0x02e5689,0x0089a9f,0x1ecac39,0x1c448c5,0x0dd9ed5,
  35474. 0x190c1f3,0x1af3f1b,0x1c76811,0x02c7808,0x1881267,0x00dcea8,
  35475. 0x091e898,0x04d3a72,0x0ab428b,0x06f87ca,0x05cb2be,0x0901a34,
  35476. 0x082f1cb,0x0c648a1,0x00ec7a8 } },
  35477. /* 25 */
  35478. { { 0x086786e,0x0c610c5,0x0b20ce0,0x08426fc,0x0d537f7,0x1375907,
  35479. 0x043469f,0x006bb2d,0x05cdc48,0x1c87638,0x1ef5d65,0x059049e,
  35480. 0x1446916,0x070f878,0x19fbe75,0x02b9413,0x08bce99,0x1e98609,
  35481. 0x11c489b,0x028becd,0x002d810 },
  35482. { 0x11d87e5,0x1a4fadb,0x1b68c49,0x02f6059,0x05f3b14,0x1d7f8b1,
  35483. 0x1b4bb82,0x04e048a,0x1fcae66,0x1fbd9d4,0x16617e5,0x1f1e6f7,
  35484. 0x010d6eb,0x1fd3686,0x0aa06e5,0x1e26e41,0x00121f2,0x0d94f8d,
  35485. 0x130376c,0x0d45f0b,0x003de32 } },
  35486. /* 26 */
  35487. { { 0x0c2ee78,0x19cc59c,0x0fb89bc,0x034eb41,0x00c3d10,0x0d3fc72,
  35488. 0x05c1959,0x0ba6b46,0x104019e,0x094c2f1,0x1d2dbb4,0x0c85702,
  35489. 0x0a21e2a,0x17c0529,0x0857ba2,0x1b01c4b,0x1e68518,0x12e8f07,
  35490. 0x13dbaa6,0x1782700,0x00848cb },
  35491. { 0x1d45169,0x143486f,0x0341da0,0x10b3a7d,0x18d7e09,0x1c5fe11,
  35492. 0x0204736,0x09046eb,0x0162cf6,0x04caa3d,0x056e321,0x167769a,
  35493. 0x06494ba,0x03024cd,0x0b2f15f,0x19fdb04,0x04ea8a1,0x1d62191,
  35494. 0x1f19662,0x0c68d2a,0x00d9435 } },
  35495. /* 27 */
  35496. { { 0x0271323,0x14929b4,0x135cac1,0x10939a0,0x04d9e0a,0x18e63e9,
  35497. 0x17efcac,0x0c355c6,0x157a3e3,0x07b25a7,0x13a1591,0x0d0c052,
  35498. 0x0e14904,0x01e76a5,0x120bb9d,0x1b48fbb,0x0a57e2c,0x065c953,
  35499. 0x1f07e5a,0x1885df7,0x013f989 },
  35500. { 0x0651600,0x0c5efdc,0x0bbafb6,0x08f479f,0x0c36343,0x18d1134,
  35501. 0x0950cd6,0x00f2742,0x1d58255,0x0c6d3ee,0x1ac7a55,0x16470a5,
  35502. 0x05a5173,0x114afaa,0x16b9614,0x1a203be,0x0ef6646,0x172a371,
  35503. 0x1627e18,0x02d458b,0x01faf7e } },
  35504. /* 28 */
  35505. { { 0x1ec136d,0x0364763,0x146c35d,0x0f9a226,0x18e1d82,0x03d08b7,
  35506. 0x0eb4fc6,0x0caec94,0x1136e84,0x18dcb47,0x060f08b,0x05290a1,
  35507. 0x19d41aa,0x1f38b92,0x08fb312,0x0293842,0x152763c,0x0ee6e55,
  35508. 0x008ae0b,0x0a16302,0x016da7f },
  35509. { 0x0a5e258,0x1299686,0x09efe67,0x0f2f6c5,0x0148ad1,0x1feef7d,
  35510. 0x090bb1d,0x1891a14,0x174f9b6,0x028c5e6,0x048b516,0x0170ffa,
  35511. 0x17c53b3,0x1da8596,0x033464f,0x155d377,0x0eebc01,0x08d0b4d,
  35512. 0x1789b82,0x1362143,0x01c57e4 } },
  35513. /* 29 */
  35514. { { 0x1210716,0x1f33a90,0x1000b2a,0x060fc04,0x01a296a,0x01bcadc,
  35515. 0x1047632,0x0d5295f,0x0dd9efa,0x079019a,0x15a1bda,0x13d6cef,
  35516. 0x155be2f,0x1fae713,0x04fc9de,0x0f8b8d4,0x041b975,0x07bec91,
  35517. 0x1d3d2e3,0x07a5e98,0x013270c },
  35518. { 0x1209aa4,0x0304e46,0x10dbe72,0x05b656a,0x06f413a,0x091a2ea,
  35519. 0x0b468a6,0x09f2d6e,0x19487c3,0x0379575,0x028dd46,0x02ed688,
  35520. 0x0e4fa72,0x1ed29ac,0x10824d9,0x1662074,0x1e3ff25,0x0788f56,
  35521. 0x017582e,0x0e02a6a,0x01a99a5 } },
  35522. /* 30 */
  35523. { { 0x07495bb,0x089c9b7,0x0746b85,0x109210f,0x0bd2fd2,0x1ebb7e7,
  35524. 0x0ac2ca7,0x0393846,0x1c60e72,0x0d06a4d,0x08278a8,0x1706a2f,
  35525. 0x189f582,0x0ec5d6f,0x0de027a,0x1176958,0x09e0ad4,0x1a5526f,
  35526. 0x0db3121,0x0826259,0x0027fd0 },
  35527. { 0x0d4fb6d,0x0817775,0x12fb015,0x1a14c05,0x160c25e,0x1fa503b,
  35528. 0x1a106f5,0x028b174,0x054edce,0x145b019,0x1d85330,0x1c72072,
  35529. 0x13b9d41,0x0c0f76c,0x086dc74,0x0961684,0x1c2332d,0x0e80871,
  35530. 0x0ac3906,0x0b144fb,0x0096dfe } },
  35531. /* 31 */
  35532. { { 0x1ebd24e,0x17e6b3e,0x01d5335,0x0135c56,0x1e3fca6,0x0be1365,
  35533. 0x108bbc8,0x07f4fb1,0x0b9620e,0x01681f0,0x07e1f75,0x042d8ff,
  35534. 0x0e634bf,0x04b97ff,0x0c7b14e,0x07cee45,0x1c1d60d,0x141d4ab,
  35535. 0x1da94df,0x1cbf0c1,0x0162edf },
  35536. { 0x0ea20b8,0x02a0078,0x0401028,0x1c3af2d,0x0872ac7,0x0d86561,
  35537. 0x097243b,0x14eeecb,0x0b62939,0x0fadc98,0x12dc227,0x0edd5e5,
  35538. 0x12f78a6,0x097f5e0,0x01ccafd,0x015a606,0x0deba19,0x09d3320,
  35539. 0x0f9f8d0,0x15c2bf2,0x00d536e } },
  35540. /* 32 */
  35541. { { 0x1c88f3c,0x08cfb50,0x1129b18,0x185d8d2,0x124e5fe,0x017f954,
  35542. 0x0b1815d,0x0f89915,0x0ddb22c,0x056ef0f,0x1496ed8,0x0719f4b,
  35543. 0x0097289,0x1608bef,0x16b13df,0x05383f4,0x0b74829,0x0a0f9ad,
  35544. 0x0bf657d,0x09d1f21,0x0180d1c },
  35545. { 0x1cd8358,0x0739ed3,0x0480bf1,0x0fe5439,0x19361a5,0x0a69441,
  35546. 0x1c4c2b6,0x1c5ede5,0x02b6a78,0x1bf1233,0x098b378,0x1f16f38,
  35547. 0x190babf,0x10dacbd,0x0b807bd,0x09cc8d9,0x1f0a60d,0x0ce0f19,
  35548. 0x1407e11,0x084501b,0x000e52a } },
  35549. /* 33 */
  35550. { { 0x1013755,0x1205207,0x03a5cb5,0x0ff7070,0x0b6dce7,0x1b25988,
  35551. 0x139e5fa,0x06c4f13,0x193ca5a,0x1382585,0x17ff263,0x01feb17,
  35552. 0x1218c36,0x191861b,0x0c7cc8e,0x10ba2a7,0x0885a73,0x1eb59c8,
  35553. 0x1ae4efd,0x0261eaa,0x004a071 },
  35554. { 0x0ef3f88,0x104b5ff,0x0514a68,0x1370567,0x02eba86,0x1332539,
  35555. 0x0612a1c,0x084ffc4,0x1858ff9,0x06e05d0,0x03276a8,0x1d6ae92,
  35556. 0x0833799,0x00ac467,0x0d5bd8a,0x19dc43a,0x07fa7b2,0x0beecde,
  35557. 0x0f3ebba,0x0349d14,0x00d21e6 } },
  35558. /* 34 */
  35559. { { 0x1068656,0x0db14f4,0x137fb17,0x193fdbc,0x023bd70,0x0a2aa33,
  35560. 0x156f7f3,0x0838f15,0x06291a7,0x1cc0ee9,0x19a23bd,0x1b24ec3,
  35561. 0x0f3ac53,0x0adc939,0x05a24a9,0x0dfd8d5,0x1b80654,0x1210bf3,
  35562. 0x0e78bd5,0x1807975,0x015e793 },
  35563. { 0x0ff39be,0x0caa1b7,0x1da023f,0x1db7fe9,0x1a1af07,0x120b0b2,
  35564. 0x1eaf6c0,0x05307a8,0x1d47980,0x1e2e97e,0x0b9becd,0x12f0c16,
  35565. 0x189d86d,0x0746dcc,0x18ca13b,0x17377c7,0x0b5d868,0x1cf824f,
  35566. 0x16b462c,0x1d14f13,0x018e3b3 } },
  35567. /* 35 */
  35568. { { 0x11e61f0,0x1362b72,0x1d5d5c0,0x0660fe4,0x1ddbcaa,0x1757a0e,
  35569. 0x09baec6,0x1752540,0x0e2d7f5,0x19f49be,0x1ab6468,0x003d78b,
  35570. 0x1d1f7cc,0x1723403,0x0ad9974,0x12a3321,0x1555341,0x0e15227,
  35571. 0x0599012,0x18394cf,0x00aa099 },
  35572. { 0x197e387,0x0d484c7,0x15a6d58,0x108bc3b,0x1605177,0x18eb55f,
  35573. 0x144adff,0x1123ff4,0x0d09a9c,0x16d2ad2,0x00b8ad0,0x18e3a45,
  35574. 0x0d5e5a7,0x13a0c2d,0x096880f,0x15dffbf,0x09dea0b,0x10cd89b,
  35575. 0x1b30285,0x1df2283,0x01a3a5e } },
  35576. /* 36 */
  35577. { { 0x0573b81,0x106853d,0x13bcabc,0x10cc329,0x1eac1ca,0x188e1a3,
  35578. 0x0b6342d,0x085de1a,0x0ba099d,0x17500b6,0x1ea329a,0x1a50a0c,
  35579. 0x0fa6609,0x1d09a8f,0x14b1801,0x04c68d4,0x018b11c,0x06d5c2c,
  35580. 0x0c700cf,0x1f48bb7,0x0121f17 },
  35581. { 0x03279d6,0x05c3d7e,0x07867ee,0x178403e,0x030e76a,0x1610eef,
  35582. 0x1aa0e01,0x09e055e,0x1c63f82,0x17ebf15,0x14694fa,0x1c4c8d7,
  35583. 0x047b074,0x1109c8b,0x1bd24c6,0x1b37f9a,0x139c172,0x0d5967e,
  35584. 0x16d673c,0x07d6969,0x010a62f } },
  35585. /* 37 */
  35586. { { 0x0689a1b,0x16f1b70,0x19cb900,0x1afb95f,0x1dccc9f,0x0e85fdc,
  35587. 0x0b5f895,0x1b3c9bd,0x04ada04,0x1f743f7,0x0b9dd35,0x073d7fa,
  35588. 0x1b5a850,0x1b8595c,0x0b1995d,0x0777450,0x026ba10,0x0d3d654,
  35589. 0x1f3541c,0x0051758,0x011aac7 },
  35590. { 0x00c8f04,0x0e9ce34,0x0d78b98,0x1969167,0x0f09c4c,0x1a279e1,
  35591. 0x026f655,0x126262c,0x0aaccb5,0x0b9725a,0x1ec825b,0x0194b5b,
  35592. 0x0fdb706,0x0fe9f66,0x1f6790c,0x054e78c,0x06fe175,0x00a43d1,
  35593. 0x134215f,0x0a6cc6c,0x01e33d9 } },
  35594. /* 38 */
  35595. { { 0x0ec9e7f,0x02835a6,0x063f999,0x0861557,0x044564b,0x1fd1425,
  35596. 0x1407c5c,0x0e4bc36,0x015c974,0x1dbdebf,0x1b00cf9,0x0f5105b,
  35597. 0x02d6cc6,0x0531dbb,0x18ba4d0,0x05f9a3f,0x01b3f8e,0x11d0427,
  35598. 0x0b9b9d4,0x1c9b513,0x00fdccc },
  35599. { 0x12fd820,0x1fc7760,0x1ccc1e5,0x152db48,0x125f892,0x0cbdfa1,
  35600. 0x0907556,0x19eb2fa,0x002b753,0x1779ad6,0x1f3ae8e,0x12bbece,
  35601. 0x0c8a73f,0x08ddd63,0x0a24adf,0x0f160b6,0x183cc52,0x1483a8a,
  35602. 0x11fd17d,0x1daa7f4,0x001c2f5 } },
  35603. /* 39 */
  35604. { { 0x140b79c,0x00b2f55,0x06a0e45,0x104b691,0x1fb6eed,0x16083fd,
  35605. 0x1adf629,0x117b426,0x18e01f2,0x018edc5,0x1e641f5,0x01bb49a,
  35606. 0x0584e5d,0x1238f34,0x0a451ca,0x0dff0d3,0x1699837,0x0ac6834,
  35607. 0x118c47f,0x0d36e98,0x0006ce3 },
  35608. { 0x0dd1452,0x1b9e88d,0x08a9b01,0x0bdb1d3,0x0e4e9c9,0x0ad2061,
  35609. 0x038cb28,0x11fd1ff,0x0af62f1,0x1e5be9b,0x05212cf,0x0ddddd9,
  35610. 0x1b2ca33,0x1d90202,0x15b9ea4,0x106a549,0x031956d,0x1b6c868,
  35611. 0x07280f9,0x0eac07b,0x00e5dd3 } },
  35612. /* 40 */
  35613. { { 0x1481bf7,0x194bec5,0x00f3317,0x0854267,0x06a2a3e,0x005cb60,
  35614. 0x14a3371,0x0793c28,0x11189da,0x115f9af,0x15fe9e6,0x1312d9a,
  35615. 0x0bb8adb,0x09abe99,0x0924d72,0x0df5b83,0x180c2d7,0x0a8fd92,
  35616. 0x13c8f78,0x043d684,0x01ba987 },
  35617. { 0x0a4b397,0x16d57a9,0x1952300,0x181a169,0x03c5f4c,0x1f3ce6e,
  35618. 0x136cded,0x16c537c,0x0b33970,0x1a19b76,0x0231ffc,0x16f9250,
  35619. 0x11ed3dc,0x011446d,0x0a43bfc,0x1ab35d8,0x151e96e,0x19523ce,
  35620. 0x1b63e97,0x1db0e0e,0x00929d7 } },
  35621. /* 41 */
  35622. { { 0x060043c,0x0d785f3,0x1d3763b,0x1602dc0,0x04aa2cc,0x061d9ec,
  35623. 0x1a39f8b,0x1893a46,0x05c269f,0x1da8098,0x0cf8d91,0x1dc27bc,
  35624. 0x04d0194,0x1c4e528,0x0cd86e5,0x1623bb6,0x033984d,0x0466a8c,
  35625. 0x03b24bc,0x1003d99,0x00c6d5b },
  35626. { 0x1ab9887,0x08e0aa3,0x0044cfe,0x14d6b56,0x0f285e2,0x1fe40c1,
  35627. 0x139684c,0x05936e6,0x038d869,0x021ad3a,0x00ba057,0x08f8865,
  35628. 0x0a3c92b,0x0e3de6d,0x048c7d6,0x1190c32,0x1c34d15,0x11d7212,
  35629. 0x1688f32,0x0d1fd78,0x00117f5 } },
  35630. /* 42 */
  35631. { { 0x15caa87,0x1eceadf,0x1276332,0x1ed1bb1,0x17bfc60,0x0a6f6f0,
  35632. 0x136ef1f,0x17ec7d6,0x18270b5,0x1b72ca2,0x063f9ef,0x0f4b981,
  35633. 0x1588713,0x02ebdc7,0x17ada1c,0x14a6794,0x0ee4b25,0x025bef7,
  35634. 0x09c029b,0x08b8649,0x00ef8e0 },
  35635. { 0x0cf52bc,0x00e4938,0x0a60583,0x152198c,0x0bf3f63,0x18147da,
  35636. 0x10872fc,0x1e2bffe,0x1523bef,0x140816b,0x1384142,0x1347173,
  35637. 0x1eff330,0x03310d8,0x0769340,0x0f00f1d,0x09fcc0a,0x14bbafc,
  35638. 0x005e184,0x0890ca0,0x00eb590 } },
  35639. /* 43 */
  35640. { { 0x1bd33ec,0x1327ef5,0x15e6299,0x019cb5a,0x0cf9a66,0x1dab768,
  35641. 0x1b01543,0x0ddd9a0,0x11d5aaa,0x0652fd6,0x09fc1ed,0x1cb7291,
  35642. 0x1a36dae,0x17f0e08,0x18de21f,0x0a897a5,0x0c491d2,0x120fb0d,
  35643. 0x0fff63a,0x1ee0e25,0x00be49d },
  35644. { 0x1acdb56,0x178fab2,0x0f79838,0x08bcbcb,0x12f13c8,0x1d02097,
  35645. 0x14d5385,0x1df72ff,0x1d9c93b,0x11433e7,0x055f922,0x02d64b5,
  35646. 0x1f9ca9d,0x050c31a,0x157066d,0x15ce23e,0x0f58d26,0x0cd9c34,
  35647. 0x1251507,0x0900829,0x0000ac4 } },
  35648. /* 44 */
  35649. { { 0x0ad38db,0x1e7c4ea,0x1445b06,0x027ae28,0x1180f38,0x18121d0,
  35650. 0x09d672d,0x0d8b698,0x1163a71,0x0eb26b1,0x122f6d7,0x1fd426c,
  35651. 0x09bbd2e,0x126f4cb,0x1c61fe7,0x1188b48,0x112e2de,0x1b2ef34,
  35652. 0x0f6b429,0x0be5389,0x0048e07 },
  35653. { 0x04dd88d,0x1aa3a2f,0x0bf000c,0x1100aef,0x1828363,0x19447b8,
  35654. 0x1700489,0x1bdc966,0x1e68989,0x0047ec8,0x1dc6eb4,0x062b9a7,
  35655. 0x0242142,0x1f26d0f,0x0c08ffc,0x05762b9,0x035b566,0x0bf35ce,
  35656. 0x1ec13f9,0x1e82caf,0x0072143 } },
  35657. /* 45 */
  35658. { { 0x0f40f2c,0x1823613,0x0c76c1a,0x18d9af8,0x1d5d246,0x09d4dbd,
  35659. 0x189c065,0x0df554a,0x08f0043,0x16494dc,0x0198356,0x125843a,
  35660. 0x0619373,0x0deb6df,0x1e7b456,0x087f3a4,0x15ad17c,0x09bbe26,
  35661. 0x03f3409,0x1db4a17,0x0179800 },
  35662. { 0x0132f31,0x0ee059b,0x0e8ee23,0x0255bce,0x0f8f4f0,0x1ef15cb,
  35663. 0x07b0c80,0x066710b,0x0231b65,0x0d81c0a,0x024f2bb,0x1a41428,
  35664. 0x19ad08c,0x0e15f17,0x1e1b511,0x1813f73,0x132f6eb,0x0fe9eca,
  35665. 0x0bbd1e3,0x16b1323,0x013d757 } },
  35666. /* 46 */
  35667. { { 0x00f894b,0x168802c,0x11bdf66,0x15b24bc,0x1612488,0x0d3432d,
  35668. 0x1f850b9,0x0268a92,0x117f9a8,0x0370829,0x0cd5072,0x0415f14,
  35669. 0x18d8aa8,0x1d336ab,0x1e41981,0x11c474c,0x0ae5f75,0x023efb0,
  35670. 0x1fe2ad7,0x1a99214,0x0107cad },
  35671. { 0x164ad0e,0x18227b3,0x06ccd5a,0x024a031,0x169fe0e,0x0a6db57,
  35672. 0x129897c,0x0a85bd5,0x11bd77d,0x0f93bcf,0x0a2573a,0x03e4b9f,
  35673. 0x0397991,0x1b78cd6,0x1a533b6,0x08963a9,0x01701af,0x0e1a99a,
  35674. 0x031c9fd,0x087ffea,0x003bcac } },
  35675. /* 47 */
  35676. { { 0x1c1d4cf,0x14a8e41,0x0d3c5d0,0x01648b8,0x003791d,0x16e638f,
  35677. 0x03bda70,0x0cfd51f,0x12a3107,0x152bd14,0x0522f4b,0x0d77625,
  35678. 0x03255b4,0x07f575c,0x1707824,0x17eb255,0x18c449a,0x0d06968,
  35679. 0x12a29a2,0x193feb8,0x00199e8 },
  35680. { 0x128171a,0x1dce6f5,0x01ef27d,0x07aaed3,0x0fd7840,0x1fc1267,
  35681. 0x1cefc8b,0x18ab169,0x1bf333c,0x104d9c9,0x13adcbb,0x0745603,
  35682. 0x0debff8,0x11014ce,0x0cd3114,0x1eea2b7,0x0a066eb,0x1d1e1f4,
  35683. 0x074173c,0x1c0f769,0x01a65de } },
  35684. /* 48 */
  35685. { { 0x114257b,0x0ac6b58,0x18c026a,0x03a92eb,0x129afd4,0x173d88b,
  35686. 0x1e6d4ea,0x1060e50,0x1edd1ac,0x1c8d849,0x19e5d41,0x0fa23d6,
  35687. 0x0acfefc,0x1133ada,0x152f4df,0x0a2fe1c,0x17e8d69,0x1c4d316,
  35688. 0x0084268,0x100bb04,0x006b96f },
  35689. { 0x1b5f9f4,0x0ea8bab,0x1345205,0x0c80b68,0x05c9e43,0x0380b07,
  35690. 0x1778392,0x1f06885,0x11ef6b3,0x09ff7ca,0x05febe5,0x19ebee9,
  35691. 0x17919e4,0x00b7785,0x18f3134,0x1ddda49,0x0872512,0x1fe2e55,
  35692. 0x0ef45c0,0x1480534,0x01b6f1b } },
  35693. /* 49 */
  35694. { { 0x09252ac,0x1421aa9,0x0360a99,0x00e9cf6,0x1da626c,0x1f43559,
  35695. 0x0330782,0x0a6aa10,0x14ed5dc,0x1a529fb,0x107f414,0x028019a,
  35696. 0x1ca9eff,0x0b3a448,0x1f25171,0x16b5a1c,0x095ec53,0x06f525c,
  35697. 0x1454262,0x0cf7de2,0x01ffefc },
  35698. { 0x06033fd,0x0e08498,0x1766623,0x13e6d0e,0x1b28797,0x019ae28,
  35699. 0x0bc9b8f,0x1ac9a73,0x1124e29,0x0392cfe,0x16f7f29,0x0ae1883,
  35700. 0x155d60c,0x06606c4,0x0892d84,0x1ff0c0c,0x0e5eea8,0x1d020ea,
  35701. 0x19361c1,0x01c2b95,0x01fd292 } },
  35702. /* 50 */
  35703. { { 0x167da85,0x0af8666,0x08559b4,0x08b58a9,0x0e98b6f,0x1638e1d,
  35704. 0x18087c6,0x0485e0b,0x0475592,0x1f59113,0x015b707,0x0ac2cdd,
  35705. 0x072a2f1,0x17da5d2,0x1ac5159,0x12416cb,0x1d2a29d,0x19a3445,
  35706. 0x07532e6,0x19d0ddf,0x0061943 },
  35707. { 0x0c91174,0x0b10c55,0x08d2d1a,0x1883bb2,0x05b519e,0x03b1d24,
  35708. 0x0b7ca7c,0x0676fdf,0x1712c8b,0x028bf93,0x0e18c26,0x1d8760a,
  35709. 0x04a02e7,0x0ff9f1f,0x0f116ec,0x0c90c8d,0x16f2949,0x1a35744,
  35710. 0x0f4ae4f,0x162c93d,0x01462ae } },
  35711. /* 51 */
  35712. { { 0x0e4d3c3,0x07a0ff4,0x076c7cd,0x1eb76fd,0x080d87f,0x085abce,
  35713. 0x1b02b64,0x15de042,0x1b87349,0x1125bb0,0x09b300a,0x0a50561,
  35714. 0x17054bc,0x17968ca,0x131c0a6,0x0d9ba76,0x0e2adbe,0x00725c8,
  35715. 0x181828d,0x0e9f024,0x00cf8e7 },
  35716. { 0x0229950,0x1cede17,0x0dc0f1f,0x0db3f05,0x0b11f84,0x0602f9d,
  35717. 0x1668fc4,0x19456f5,0x10f1820,0x01f56a7,0x1eccc88,0x1791997,
  35718. 0x1151dbc,0x0333837,0x1672bc0,0x13abc77,0x0250605,0x12d1cdf,
  35719. 0x12bf993,0x070f91b,0x014c984 } },
  35720. /* 52 */
  35721. { { 0x0011531,0x13abfc7,0x15f1c22,0x0587b9a,0x1f45b17,0x0ccf14b,
  35722. 0x127f70b,0x02b51d5,0x1b93b64,0x0a7740f,0x023a1a7,0x16a94a9,
  35723. 0x10a5833,0x05dbd5b,0x155870c,0x1e753bb,0x184b3bd,0x1daded1,
  35724. 0x177ccca,0x13f1c03,0x0124f90 },
  35725. { 0x141e782,0x0554255,0x0e1f16e,0x0d0a3bb,0x1de2012,0x0415e90,
  35726. 0x0a9f665,0x077e937,0x1f4b641,0x0cb1ef5,0x0788901,0x1f76f9a,
  35727. 0x0eed369,0x0dd6b07,0x1d25774,0x061dbb9,0x093892e,0x0f5a3ab,
  35728. 0x1c2884b,0x0237b15,0x010baaf } },
  35729. /* 53 */
  35730. { { 0x0ec64e2,0x100ba0b,0x1af9c51,0x1efaf8d,0x1fd14ac,0x05b8bb5,
  35731. 0x0128d9a,0x0383c6a,0x1741b04,0x171f9f9,0x0d9ec1c,0x0a945a7,
  35732. 0x0d651fa,0x12bec94,0x0fb728f,0x1e832c4,0x08b72c8,0x194dba7,
  35733. 0x09eaebb,0x13968e6,0x00383d9 },
  35734. { 0x0342a3f,0x0e859ed,0x0552023,0x05bde95,0x1200246,0x1ad4300,
  35735. 0x190bbaa,0x0da3638,0x106e54b,0x10f1502,0x1b3c697,0x021e218,
  35736. 0x109ba17,0x07c81e6,0x13f0d98,0x0cdea66,0x0011341,0x1cb4f00,
  35737. 0x15710d4,0x04c0e82,0x00fafaa } },
  35738. /* 54 */
  35739. { { 0x12de285,0x0687338,0x1717217,0x010d3eb,0x0d2ff8b,0x0769c4e,
  35740. 0x0ae4b7d,0x1086e54,0x055b99c,0x1a92698,0x0800cd8,0x0b45c0f,
  35741. 0x1346fef,0x0b704a4,0x0b20b6b,0x12a5614,0x02172a8,0x159b133,
  35742. 0x1c85fad,0x1963115,0x002c9af },
  35743. { 0x064c5b5,0x0ea3b4d,0x1f874ee,0x1c89899,0x00d8d5d,0x036dffd,
  35744. 0x163bc47,0x1daac10,0x141c14a,0x10ecbc7,0x1fa1533,0x1ce46bd,
  35745. 0x1d251f9,0x023a2ba,0x1430530,0x13807f3,0x18ebda8,0x0069641,
  35746. 0x1b32770,0x1e08166,0x016fa25 } },
  35747. /* 55 */
  35748. { { 0x0ad682d,0x0cef54e,0x0e46c8f,0x068c6d2,0x07acb1b,0x07926bc,
  35749. 0x0662170,0x19d3eb8,0x1d41883,0x1fb17e3,0x15791b7,0x13bea6a,
  35750. 0x05d1ab2,0x048e6d0,0x06c72ca,0x067daad,0x1c452c6,0x06d8a6d,
  35751. 0x08d150a,0x1770d85,0x01941ac },
  35752. { 0x0db8127,0x1386412,0x1d6f61a,0x1e836f9,0x04a6563,0x046cda4,
  35753. 0x16afae4,0x0151b09,0x1899c26,0x1755731,0x0da55ea,0x1656888,
  35754. 0x0d13ed6,0x0854964,0x1253e67,0x1972e77,0x02bd04b,0x1cbc797,
  35755. 0x05a9597,0x0711dee,0x007456a } },
  35756. /* 56 */
  35757. { { 0x0fc1f77,0x16ff24b,0x15a9820,0x1e268f5,0x104c435,0x15f22bd,
  35758. 0x0537097,0x155e84d,0x1b6f764,0x050b834,0x00f6859,0x07aa09b,
  35759. 0x10e0387,0x1064119,0x0e76d4b,0x1367d61,0x14ed423,0x14c4359,
  35760. 0x0620536,0x10fe54b,0x016a765 },
  35761. { 0x1c71a5d,0x07c7475,0x08cda46,0x050a80a,0x09141a4,0x0165e62,
  35762. 0x0273306,0x14fac7e,0x1e09057,0x17f2ce9,0x0763ad2,0x161bc47,
  35763. 0x12e633d,0x1eca4a5,0x12160b7,0x1fac375,0x0414704,0x0c5c8ad,
  35764. 0x13abbf6,0x0cd53bf,0x010ee08 } },
  35765. /* 57 */
  35766. { { 0x0e07a4d,0x0623829,0x1740ad4,0x11cbae8,0x1f6d38b,0x1789133,
  35767. 0x111f386,0x1ef6829,0x139c505,0x1f25a25,0x1ce6f80,0x0f2b0de,
  35768. 0x1c59f3d,0x13e178d,0x066f29f,0x1f5a994,0x01ec063,0x18e28e0,
  35769. 0x1d0a2be,0x126f4af,0x0080da3 },
  35770. { 0x02369fa,0x0654e88,0x18d7a76,0x16e0d81,0x0009bff,0x1aaec07,
  35771. 0x0669e5a,0x0985c14,0x0ac0d09,0x107216f,0x1061eb6,0x058af0f,
  35772. 0x166c1be,0x0e7d025,0x12b8b32,0x0e680da,0x0607657,0x0ad8675,
  35773. 0x1f258a1,0x04a48b8,0x00d82d5 } },
  35774. /* 58 */
  35775. { { 0x093de69,0x191c657,0x1a6db72,0x0677fb5,0x0963c83,0x1bcc1b2,
  35776. 0x07d37a2,0x15c6790,0x0ae8bf8,0x09d1122,0x1aeb338,0x0f0c987,
  35777. 0x160bc6e,0x0aad2d6,0x0de94f1,0x128b350,0x135bc7e,0x0c3aec6,
  35778. 0x07d1bf3,0x00aa69f,0x001fb37 },
  35779. { 0x1b974a1,0x093863f,0x1205e3a,0x01d3da4,0x03448fa,0x1ffdea1,
  35780. 0x1b0f592,0x078282c,0x1d79f4b,0x02d5221,0x1cca828,0x09e2773,
  35781. 0x1ed855a,0x164811a,0x1af3e36,0x0569097,0x1878db5,0x0b2c24c,
  35782. 0x1234274,0x1ab3e3c,0x0183aa4 } },
  35783. /* 59 */
  35784. { { 0x1ffad9f,0x02ebaed,0x03f3b96,0x09e833b,0x04df617,0x0349a2b,
  35785. 0x0fd679b,0x018dee7,0x183d59b,0x003c9e8,0x122542e,0x1f87253,
  35786. 0x0b6baf4,0x14cb15d,0x1116a54,0x024e77a,0x145eaa9,0x1a95b0c,
  35787. 0x1471e16,0x19bffe7,0x01be4fc },
  35788. { 0x0b2857f,0x1c26cbe,0x0fd0170,0x100d6f5,0x0cf8305,0x1673592,
  35789. 0x1745d0e,0x16dea51,0x0bc43d6,0x03dc7d1,0x1592e4b,0x117e29c,
  35790. 0x1a8f0e2,0x095cf80,0x1a6f1cf,0x107cc36,0x1403dd3,0x1d5c5f5,
  35791. 0x1e4651a,0x1d418b2,0x00aeacc } },
  35792. /* 60 */
  35793. { { 0x163c2de,0x05d7700,0x029269a,0x17d64ed,0x042d0b2,0x0d73b3e,
  35794. 0x1c493ff,0x086ad0d,0x10aaca9,0x136d2ea,0x02473e4,0x099dc02,
  35795. 0x0d699c3,0x09925f6,0x0951501,0x141527a,0x0f14193,0x08db5ac,
  35796. 0x1847327,0x0924bda,0x014ff14 },
  35797. { 0x1ed9259,0x0d30660,0x09fdfd8,0x065e3ab,0x1be37aa,0x177a188,
  35798. 0x1c4f41e,0x1740708,0x14e6fa7,0x0f99ea4,0x0dcc326,0x182d17a,
  35799. 0x1c43928,0x0dcaabe,0x13e333d,0x17dcae7,0x060d1a2,0x005e36a,
  35800. 0x0ec5584,0x1a32870,0x014527c } },
  35801. /* 61 */
  35802. { { 0x027af4e,0x1289a9a,0x0df52f9,0x02621b2,0x0e6c0bb,0x1338e19,
  35803. 0x09dab2a,0x0ed7b1d,0x0d3a9c3,0x0bd9fea,0x1c26aa7,0x10c68e2,
  35804. 0x00124ce,0x00c028e,0x1739074,0x1dc3844,0x04ff9e8,0x02a4494,
  35805. 0x0d713b2,0x105392a,0x013d22d },
  35806. { 0x1b15e02,0x0f6ced0,0x01a1ac0,0x18603cb,0x1d092ba,0x1209ad8,
  35807. 0x0860d5d,0x1497f4f,0x16f7159,0x0772cdb,0x0434370,0x00a2301,
  35808. 0x169171a,0x1c0290c,0x054c6ee,0x0f208b8,0x0fc2092,0x0ba0498,
  35809. 0x18cdda1,0x169198e,0x0008963 } },
  35810. /* 62 */
  35811. { { 0x0aaaed5,0x05b107a,0x1ba03fa,0x1bfd0e3,0x1068de7,0x1fe5a58,
  35812. 0x00c3ffa,0x0b65644,0x1c3a215,0x06fdf73,0x06e0175,0x15184ed,
  35813. 0x10a7a26,0x169cf57,0x1f79dc1,0x1e0646e,0x047f615,0x0f8d492,
  35814. 0x0b66dcc,0x1035088,0x012aa1b },
  35815. { 0x1152e8f,0x133e858,0x0530a67,0x0f256bc,0x0e773d9,0x05abd11,
  35816. 0x041cfc7,0x145c1b0,0x0bf1da4,0x1d7854e,0x0d12680,0x0c1d845,
  35817. 0x1d169b1,0x0e96be8,0x0b06b23,0x11dc970,0x0a6bfc9,0x0ba8456,
  35818. 0x0f2fa85,0x124881c,0x0150549 } },
  35819. /* 63 */
  35820. { { 0x13a4602,0x0250550,0x1839c00,0x07a1a58,0x105c71a,0x0bcde2a,
  35821. 0x0918e9b,0x1e949fc,0x0d54d9d,0x03c759d,0x0f1ee3a,0x120ee7a,
  35822. 0x057ecca,0x122767d,0x0eec9e0,0x1a2f2b6,0x01fb124,0x045187b,
  35823. 0x1d8cabc,0x1ca0029,0x01155b7 },
  35824. { 0x0f0021a,0x017664f,0x07518b1,0x0ff0ad9,0x18017fd,0x123c5e2,
  35825. 0x10ee0b9,0x1b621c4,0x11505a4,0x183a334,0x1fba96b,0x143899a,
  35826. 0x0ad9bb0,0x0a95768,0x0e8e68b,0x1e13bd1,0x09ab549,0x003a3a2,
  35827. 0x195fe99,0x11ef7b3,0x013fd5c } },
  35828. /* 64 */
  35829. { { 0x053c22b,0x0673dad,0x11a86f6,0x1af9568,0x18733fc,0x1659ca3,
  35830. 0x0938922,0x01f8899,0x0a38c79,0x0c4458f,0x0d08dea,0x0dd62b8,
  35831. 0x0336afb,0x1db8103,0x04ee2a3,0x011f572,0x0c59175,0x19a5bbe,
  35832. 0x0791cca,0x03af4ff,0x0050a93 },
  35833. { 0x0d21d18,0x121482b,0x0286a42,0x0eab682,0x0266630,0x053582c,
  35834. 0x12a2e25,0x0b968d0,0x1828cf7,0x10d6f31,0x1c0a8e2,0x10b424e,
  35835. 0x094fb2f,0x16fbdb8,0x1fdf416,0x03b6d07,0x092a68d,0x00e9fad,
  35836. 0x024f357,0x19c3b78,0x00f5243 } },
  35837. /* 65 */
  35838. { { 0x17d7891,0x0c1e1e9,0x1b2a3f0,0x13fb0cb,0x17b5014,0x10c2208,
  35839. 0x10f5a3c,0x0b01edc,0x15a07f6,0x1a8f612,0x00c80ab,0x0d975a6,
  35840. 0x158fe5a,0x0833b77,0x179a3cc,0x000192b,0x11fca4e,0x03a8471,
  35841. 0x1dcd495,0x1cb52ae,0x0159783 },
  35842. { 0x0537ad9,0x0dab897,0x13def07,0x1a6b7d3,0x1e87112,0x1fcde5a,
  35843. 0x0ad2355,0x18f76a4,0x0a8b3cb,0x17fbc48,0x136d707,0x1c23cbd,
  35844. 0x0d4f306,0x19c3f3f,0x16a0e48,0x03c7a61,0x0f47232,0x026c8fe,
  35845. 0x104a99f,0x0f76c5c,0x009f848 } },
  35846. /* 66 */
  35847. { { 0x0b8e08e,0x0fc07c6,0x1b5a1bd,0x02492df,0x1cfd2c4,0x1bee6fb,
  35848. 0x0dd0d82,0x0be00c3,0x157f4d0,0x0dd7fef,0x0187c93,0x18548b0,
  35849. 0x04b1993,0x0ef4ca6,0x1b2a342,0x1c0c4d8,0x04d2747,0x077b869,
  35850. 0x066572f,0x0ba9c77,0x00ffd4e },
  35851. { 0x0f40077,0x0f122e3,0x1418c5c,0x0a0e47c,0x1592e04,0x15fec40,
  35852. 0x1bdf9a9,0x1c06b90,0x16d9d9c,0x104ace8,0x15dc32e,0x1fd07d6,
  35853. 0x1d2e7f8,0x0206b1e,0x1ac2207,0x08832b1,0x1daeb9e,0x0ab199d,
  35854. 0x0bf47d3,0x072fbe7,0x0034fb0 } },
  35855. /* 67 */
  35856. { { 0x158815c,0x0702f59,0x1f65ee1,0x09c8210,0x1abcb2d,0x182ebd1,
  35857. 0x162241f,0x0390f4e,0x17a9d48,0x083bc6a,0x1932f4d,0x1ff085a,
  35858. 0x1e9d34c,0x067944f,0x167356b,0x058dc10,0x191dd2b,0x141b96a,
  35859. 0x02d02d8,0x1a905c3,0x006bc06 },
  35860. { 0x04ed375,0x14ad06d,0x0bab441,0x10531b5,0x11baf58,0x1b84962,
  35861. 0x086d3d2,0x06b6051,0x07a335b,0x15c3ed7,0x1fbf622,0x06c40ac,
  35862. 0x14a7359,0x199061b,0x127f040,0x11660f4,0x0c4a355,0x1b9bd65,
  35863. 0x103f3a6,0x0d2d469,0x001ed30 } },
  35864. /* 68 */
  35865. { { 0x13902fe,0x085585e,0x0ecf655,0x170d53a,0x1bba4b4,0x0e561bc,
  35866. 0x182a65d,0x1b874b3,0x1333605,0x02f4398,0x10b1601,0x118435f,
  35867. 0x11f2c59,0x177ce5f,0x1fe35bf,0x0788503,0x1d09bf8,0x0c15f6a,
  35868. 0x0a04c75,0x1b3ab6a,0x01579d1 },
  35869. { 0x119258e,0x0d182aa,0x0aa1a1f,0x1204fbc,0x13f539f,0x11186b3,
  35870. 0x05d1f5a,0x108d3f5,0x15f5d16,0x18d7591,0x1907d6a,0x128ebef,
  35871. 0x135bbfe,0x0b53ff5,0x151aaec,0x0a30f7a,0x0e8e16d,0x0957dea,
  35872. 0x13254f7,0x0f7c277,0x0160743 } },
  35873. /* 69 */
  35874. { { 0x09755a3,0x0b2d4f7,0x0ac557c,0x1570593,0x0c8d5a1,0x15cbf30,
  35875. 0x1916aad,0x0e2cb43,0x0ab05e2,0x00266d8,0x020c3cc,0x16a4db6,
  35876. 0x0b9e0c3,0x1ad65ef,0x187b069,0x1093155,0x084761e,0x1209ea2,
  35877. 0x06e718b,0x1c13776,0x01e9589 },
  35878. { 0x072258d,0x09040ce,0x0f519d4,0x08b82b2,0x01dcd73,0x008fedb,
  35879. 0x1e9ee47,0x11cd8c4,0x1885790,0x0e9f4df,0x0f1a3b4,0x0dfca61,
  35880. 0x1f9aac0,0x15ada27,0x1705aed,0x1dbaa24,0x1b6db90,0x01c4305,
  35881. 0x0efb6d7,0x1d1611f,0x01aa96f } },
  35882. /* 70 */
  35883. { { 0x057c0f8,0x12eec79,0x0364c8e,0x05ba742,0x0884dc9,0x1c6701a,
  35884. 0x1e73aee,0x15207e6,0x1a47262,0x10bd6a9,0x01b1b58,0x002ea5c,
  35885. 0x0da1df2,0x0192146,0x0dc8f83,0x18c59eb,0x0892c30,0x00f2e9c,
  35886. 0x1dfe0b3,0x121e3e8,0x01fdd9a },
  35887. { 0x163ab59,0x093dd0b,0x0fa60c3,0x1ce46f0,0x0f27d93,0x0cb4556,
  35888. 0x0099251,0x1ab02ab,0x01700d5,0x1928d19,0x11b67d8,0x1ce6062,
  35889. 0x12cf6bb,0x132df87,0x173d157,0x047f6d9,0x0ce6323,0x0405500,
  35890. 0x05a91d1,0x13cc59b,0x01496e4 } },
  35891. /* 71 */
  35892. { { 0x0574c09,0x185bf20,0x1a5afbf,0x067fd01,0x176f264,0x11bec8d,
  35893. 0x14d4bac,0x0041677,0x17edc31,0x006315b,0x08db70f,0x1296849,
  35894. 0x1ef9893,0x1e3621a,0x1a99309,0x1a0edd3,0x1c4e388,0x196fe10,
  35895. 0x139a792,0x10a5ed4,0x0139cc3 },
  35896. { 0x1096b91,0x051ffdd,0x10f948e,0x0ae7b1a,0x0e72c9e,0x0bbaac7,
  35897. 0x16c4631,0x169822d,0x0dc47d4,0x07644e9,0x06557d5,0x1a6a85c,
  35898. 0x1c2006d,0x1a1ba3a,0x12bb5a9,0x1208200,0x12a2bee,0x0e0eee1,
  35899. 0x164ccb2,0x082f45d,0x01fb597 } },
  35900. /* 72 */
  35901. { { 0x19bae66,0x18cc0c2,0x106cf03,0x0308baf,0x0b48e9b,0x151e0f5,
  35902. 0x0700d14,0x0738d9d,0x0ff8103,0x1c25006,0x035bf88,0x1c22bf3,
  35903. 0x1bcd7ed,0x1c506ea,0x08038f4,0x0380def,0x08a3c7e,0x1ab6eca,
  35904. 0x194e987,0x034fa31,0x00d09d2 },
  35905. { 0x00eb3fb,0x1edd7c4,0x1f27e73,0x0ebd07e,0x04cfd29,0x053a5a3,
  35906. 0x1f5be8a,0x006c374,0x1dfb13e,0x01006af,0x0984a2e,0x1e96465,
  35907. 0x0e03bc8,0x00d46c3,0x1ee4b0a,0x0dd4fa3,0x1ae706d,0x13433af,
  35908. 0x1eac630,0x10c115d,0x011d9b0 } },
  35909. /* 73 */
  35910. { { 0x1d2f539,0x1b0a35d,0x0e885f3,0x00edc4d,0x16052fc,0x1f2533c,
  35911. 0x0746352,0x1506d04,0x09f3f39,0x1c11a11,0x1e1cea3,0x0d72867,
  35912. 0x0868b84,0x18b7a2b,0x074fcd9,0x0eea0f4,0x0282fd4,0x16fb01f,
  35913. 0x05d7889,0x16058ad,0x000377c },
  35914. { 0x001dd59,0x0d6e9c6,0x0debc9d,0x1d73834,0x1c213a9,0x1e2a01c,
  35915. 0x1441137,0x10cd215,0x007ee0d,0x0177103,0x1f10388,0x1d2acc3,
  35916. 0x16896ed,0x085817a,0x135ce63,0x03448d6,0x191e5af,0x0e65cb4,
  35917. 0x04fdc49,0x05035f8,0x009fd5c } },
  35918. /* 74 */
  35919. { { 0x1073a5a,0x062a5eb,0x11f7216,0x190c3d5,0x07c81a5,0x10100d4,
  35920. 0x128e79c,0x19ca3f0,0x040e003,0x0954fc7,0x06677a5,0x0956b1e,
  35921. 0x0b76bdc,0x0ab6601,0x1c48c8b,0x0c5e639,0x06383f1,0x0db31a7,
  35922. 0x1e5a784,0x002fdd1,0x016984c },
  35923. { 0x089f1fa,0x019b12e,0x01e3c7d,0x016d2f6,0x0a02a63,0x02dbfa2,
  35924. 0x079712c,0x1986662,0x14fede4,0x1e65728,0x096a929,0x10e8960,
  35925. 0x0d0d26e,0x1c26dbd,0x16ddeef,0x183fcfa,0x0a8f571,0x01cf78d,
  35926. 0x0633348,0x1752508,0x018d65e } },
  35927. /* 75 */
  35928. { { 0x0bb2537,0x03355c5,0x05be8de,0x16cb661,0x14ac4cb,0x0145698,
  35929. 0x09fb4a9,0x12d04ff,0x010e9e1,0x0e8cfb1,0x006d3a5,0x0f41130,
  35930. 0x0331eb9,0x15745c1,0x19de98a,0x12c8555,0x02a5f5c,0x04b49eb,
  35931. 0x18da2e1,0x17fd2e7,0x00adff5 },
  35932. { 0x12b0dee,0x1d710a4,0x0b3a8fb,0x1d2c058,0x0143e9e,0x1dccf29,
  35933. 0x1f265bc,0x0b2426c,0x0e93b8f,0x0bc5958,0x1304fb7,0x187020c,
  35934. 0x1a8d541,0x1ab9c73,0x0e5c36b,0x16349cd,0x0168373,0x1d7b766,
  35935. 0x12b8823,0x147e9ee,0x0180dbf } },
  35936. /* 76 */
  35937. { { 0x07a6aa0,0x0310d48,0x07dac09,0x1080f0f,0x0f56cb6,0x14549a7,
  35938. 0x02da205,0x0908987,0x19b9a90,0x06b1c69,0x107c81c,0x154104a,
  35939. 0x106968c,0x0fe445a,0x165c14c,0x0af0818,0x0d5af63,0x1aab26f,
  35940. 0x1352533,0x11318f8,0x0097e7e },
  35941. { 0x16ebb2f,0x04c6cb5,0x049b877,0x18f553c,0x092a17f,0x1516341,
  35942. 0x03f6fe8,0x0376c1e,0x0b2e185,0x0319386,0x0933fa7,0x04cb039,
  35943. 0x15898db,0x188cace,0x02098e2,0x11a3328,0x08ea54b,0x0722798,
  35944. 0x1398c25,0x133d708,0x00d6963 } },
  35945. /* 77 */
  35946. { { 0x03769ee,0x079b15c,0x12cfe80,0x187df89,0x12d040a,0x15eb43b,
  35947. 0x0e2255e,0x0518726,0x1940a71,0x1132212,0x10a8c58,0x191fd84,
  35948. 0x11909c4,0x12d0d2a,0x1923c79,0x042e5a3,0x0f1049c,0x0345eb8,
  35949. 0x026dff5,0x125a56e,0x0041c86 },
  35950. { 0x1816784,0x04550ef,0x173938e,0x0a037ce,0x0a58c8a,0x133c092,
  35951. 0x17fec0a,0x1c13693,0x0eda721,0x1994cf0,0x0997b29,0x03ebccf,
  35952. 0x168a0bd,0x02b638d,0x07a47a2,0x15461b0,0x0f4c005,0x11bd771,
  35953. 0x1656efc,0x000ea00,0x0073d94 } },
  35954. /* 78 */
  35955. { { 0x10c0ef3,0x1562500,0x0682a44,0x109d036,0x0e654bd,0x1a9a848,
  35956. 0x18f713c,0x1351e0a,0x1b47d18,0x06e20f9,0x0302704,0x1a0de47,
  35957. 0x07122ed,0x020d67b,0x1305abf,0x10a4044,0x1348375,0x18e65c9,
  35958. 0x09d6b9b,0x16be524,0x01271a4 },
  35959. { 0x0e688b5,0x1ea399e,0x1a2de4b,0x0fb9538,0x14566d3,0x0b88e80,
  35960. 0x0c9b950,0x151f9d2,0x03cc341,0x1dd0a77,0x0b047f8,0x0998424,
  35961. 0x156b8ab,0x1ae9bcd,0x1e9d8ef,0x05f2381,0x0aef152,0x0caf169,
  35962. 0x073e569,0x04367a6,0x00acd4e } },
  35963. /* 79 */
  35964. { { 0x18e061a,0x1d3bc8e,0x08c1004,0x0159909,0x02707e7,0x17b1b53,
  35965. 0x0099bac,0x13ad581,0x177b25c,0x08bf510,0x1cd73fa,0x177ae1f,
  35966. 0x1eddb78,0x020c4c5,0x0236cac,0x1c88aa0,0x0fcce0a,0x187ac52,
  35967. 0x095f439,0x12472e4,0x0043ed0 },
  35968. { 0x0e129e6,0x0bbd9f1,0x135cb2b,0x0e1e37c,0x1b8c4a8,0x02b199f,
  35969. 0x037fc80,0x0875dca,0x12a6915,0x0132c60,0x189902f,0x199571f,
  35970. 0x0f95dc0,0x0cb2d05,0x13ad610,0x1b33cd2,0x053edd1,0x1be9dd5,
  35971. 0x087b721,0x0276411,0x00832df } },
  35972. /* 80 */
  35973. { { 0x181c3f2,0x09123e8,0x08fffab,0x1de66f6,0x115d35b,0x0483394,
  35974. 0x1f2e9d2,0x143b699,0x1fda7a3,0x07b86c7,0x1d5a1b9,0x0832f24,
  35975. 0x1e226b6,0x17f8fbc,0x010218d,0x149d1d0,0x139cf5f,0x04c7425,
  35976. 0x02827d8,0x1417d3b,0x00da57a },
  35977. { 0x0fcea66,0x0767aa7,0x1ebb503,0x195f8ed,0x18df2ae,0x0ac2d44,
  35978. 0x0692324,0x14ac7e3,0x113f00a,0x088ded3,0x172e7ec,0x1f56896,
  35979. 0x116687a,0x1293106,0x157ec49,0x06b578d,0x11bbacb,0x157ca9f,
  35980. 0x1e53134,0x0126e1f,0x00ed997 } },
  35981. /* 81 */
  35982. { { 0x0b54c89,0x1ab7034,0x108ab27,0x1b9ce6f,0x08ecc17,0x044da98,
  35983. 0x1a0feac,0x036411d,0x1543fbd,0x079d094,0x175c1ac,0x19f1089,
  35984. 0x0d1b204,0x0f61720,0x05d7227,0x1229501,0x1ae9399,0x1845808,
  35985. 0x119d37d,0x1742e0e,0x00176b4 },
  35986. { 0x1dfc175,0x0b754c7,0x0c31c48,0x06fc1eb,0x17b7fc6,0x199d1a3,
  35987. 0x0a17f3a,0x16f11a0,0x10223ea,0x13cc0a7,0x1b648ad,0x0416a38,
  35988. 0x1d90787,0x0e09fa8,0x1675692,0x0c16ab0,0x10bfaed,0x1734fc2,
  35989. 0x14332ac,0x135088d,0x005c249 } },
  35990. /* 82 */
  35991. { { 0x1e7bcf1,0x0c0fdb9,0x1ef9075,0x19ba782,0x16dde61,0x0ccfec8,
  35992. 0x05fb3e8,0x12f8c53,0x1c159db,0x13ac439,0x0ca0c06,0x112cc82,
  35993. 0x184ed77,0x14a1548,0x1cb3a24,0x149772c,0x187816b,0x1f9f722,
  35994. 0x195375f,0x0f42919,0x01234fb },
  35995. { 0x009be8c,0x0c057f8,0x0e87c17,0x0ef1be3,0x02e938d,0x16f3103,
  35996. 0x0ba10c4,0x1734fc4,0x16070c4,0x0694f3f,0x1768dd2,0x07d7436,
  35997. 0x135cd9c,0x1238ba2,0x146f4be,0x13cce3c,0x0b056ab,0x0ca04c5,
  35998. 0x07df1a8,0x1095789,0x0049bb5 } },
  35999. /* 83 */
  36000. { { 0x0a470f7,0x12a980f,0x18c2a7c,0x11d24a9,0x001bf80,0x1001c6d,
  36001. 0x1a7a9c6,0x10e130a,0x15913ca,0x0959770,0x007f6c3,0x0097705,
  36002. 0x0aae170,0x08c72e1,0x171bac0,0x08757b6,0x04c1fa9,0x0d2b563,
  36003. 0x0a4b540,0x1ec8ee3,0x00531aa },
  36004. { 0x0345730,0x0f7a483,0x1f0a59e,0x1d08de6,0x146aaa4,0x1e1d55c,
  36005. 0x09ac069,0x09df02e,0x08166df,0x1c046d1,0x1370fb2,0x1f849c0,
  36006. 0x14e9fb3,0x1b760cd,0x02d876d,0x1a27d3c,0x05eeed6,0x0373fb3,
  36007. 0x1a9d4e1,0x1b180f0,0x00e570e } },
  36008. /* 84 */
  36009. { { 0x08ce13f,0x0b72c08,0x004d991,0x1a1c72f,0x15bfc58,0x1ca4f4d,
  36010. 0x0a12fa8,0x0fa096d,0x075af66,0x14db35e,0x0559afa,0x0db9512,
  36011. 0x1a7cb4d,0x1fb0aca,0x0f3b3c2,0x04a4036,0x13d002e,0x1218963,
  36012. 0x04d697e,0x0ed130c,0x014b81d },
  36013. { 0x01078ec,0x1de12c2,0x1535011,0x0c2f388,0x15aa9c9,0x08fc7e3,
  36014. 0x0182521,0x03ed42c,0x0ce3409,0x0c6a71f,0x15040a6,0x0e0911c,
  36015. 0x1e9a9f6,0x0ed4562,0x0a03e21,0x046197e,0x0a08fec,0x0e32656,
  36016. 0x0252ddd,0x10c960a,0x002b0ac } },
  36017. /* 85 */
  36018. { { 0x15daf7f,0x0371cc7,0x1419ad8,0x122124e,0x0838548,0x02c5392,
  36019. 0x1717023,0x1c7444a,0x0c90f3e,0x19b17e8,0x057c08b,0x15e810f,
  36020. 0x0ac9633,0x0212fad,0x1c42f44,0x1b7f6e2,0x005ec06,0x0e100bf,
  36021. 0x06e2ef3,0x0fb9058,0x01c8d9c },
  36022. { 0x0b8bed9,0x00fef8c,0x0495f6d,0x11c7446,0x0948330,0x08e25df,
  36023. 0x0779dca,0x15f79f2,0x141448a,0x185cb95,0x16918a6,0x0c67889,
  36024. 0x0295dfc,0x00dfa85,0x0e7118c,0x0626321,0x177869e,0x08c5b37,
  36025. 0x086eab6,0x09c5f42,0x00f5a8a } },
  36026. /* 86 */
  36027. { { 0x00251ea,0x0a884e5,0x06c2329,0x164f4d9,0x12aeed8,0x107a947,
  36028. 0x02fad58,0x0ad2035,0x0ae13fc,0x14210f4,0x04f01e6,0x03890b3,
  36029. 0x171349f,0x068d586,0x1820d64,0x1b21253,0x09baeb5,0x1cb7149,
  36030. 0x166699b,0x05e3f1e,0x00ce96c },
  36031. { 0x0be8bd7,0x025a889,0x066f92f,0x1e78cfd,0x14846a0,0x1d1c327,
  36032. 0x11f4d34,0x103b139,0x073f439,0x1b23889,0x13959c7,0x06484db,
  36033. 0x0bc32bc,0x181584b,0x04d3aff,0x1056fee,0x00b0d06,0x0ab0278,
  36034. 0x0f3a2d6,0x07afd5c,0x011cfd2 } },
  36035. /* 87 */
  36036. { { 0x07689a6,0x1236651,0x1cafe25,0x06aac82,0x16a7dc4,0x1e5fe66,
  36037. 0x0923ad5,0x1ca617b,0x15b1adf,0x188fffd,0x162fd26,0x01b6e23,
  36038. 0x1b9f2d8,0x1b872d2,0x1e7f7c2,0x1143bd0,0x1836bd1,0x04ba9a0,
  36039. 0x12ff541,0x0a4d7b1,0x0114c8c },
  36040. { 0x17388bd,0x1392df7,0x1a9f57f,0x1fcfff5,0x11c3dbd,0x16f1567,
  36041. 0x16e25f9,0x1f6f072,0x09ebf1b,0x0d3964d,0x01451a0,0x0e0ed2f,
  36042. 0x0f65265,0x1a93385,0x097b367,0x0fa9072,0x1d283d5,0x121bde6,
  36043. 0x003b2c0,0x0e654f9,0x01ceb5d } },
  36044. /* 88 */
  36045. { { 0x1d376d7,0x0fe6767,0x01369fe,0x1d4cd61,0x0b4eab3,0x1c8dec3,
  36046. 0x0342356,0x1b0d592,0x08aa304,0x11eadbf,0x19a93ea,0x0856ff0,
  36047. 0x0127f3d,0x1dc09d7,0x1467ea2,0x1240d2b,0x0d7e34a,0x0e9c3cc,
  36048. 0x0cb0737,0x1814d34,0x0073df7 },
  36049. { 0x0315b16,0x000dd9c,0x03e6f8b,0x133c319,0x1daa7c8,0x1b5c298,
  36050. 0x0fed022,0x10347a8,0x068092a,0x0acf246,0x1eab52c,0x1b3d06d,
  36051. 0x1077e93,0x1234cb9,0x1b58d86,0x1c8eda9,0x1f66297,0x12b4e59,
  36052. 0x1e047e9,0x1b0307c,0x0185b69 } },
  36053. /* 89 */
  36054. { { 0x19cb764,0x13f59d5,0x15b463c,0x031d783,0x1bbefc2,0x1cd53cd,
  36055. 0x0376c11,0x1ea8eec,0x009e542,0x068b692,0x066e5ad,0x11a378d,
  36056. 0x0ae35c3,0x0646c64,0x0cab896,0x148ba27,0x15267a3,0x042bce0,
  36057. 0x1155301,0x16e6aed,0x00d9773 },
  36058. { 0x018c299,0x0523981,0x08ce588,0x0733ef1,0x09be29b,0x07a0a7b,
  36059. 0x0802521,0x1a88d09,0x19a2ca4,0x163a49b,0x0deacec,0x0e7cd1b,
  36060. 0x1f09c07,0x09ae1ab,0x007c166,0x1c7e4c3,0x03d8b7d,0x0049898,
  36061. 0x03edb82,0x1ff9a1c,0x0060f3e } },
  36062. /* 90 */
  36063. { { 0x05d6530,0x00a5f59,0x103dc8f,0x13352fa,0x1e015b3,0x1bfb112,
  36064. 0x0f12fef,0x1e24138,0x014b4f0,0x1ec62ce,0x1a3b3e0,0x1fbc7ef,
  36065. 0x0fcf002,0x0f58f78,0x14d4f24,0x018c06b,0x0a5201f,0x01ca621,
  36066. 0x0fa3b8d,0x025156f,0x01b5787 },
  36067. { 0x10110cd,0x1be9d5b,0x06d6824,0x188ef22,0x00fa4ef,0x1d260cf,
  36068. 0x0bd6f14,0x1e58d59,0x138d509,0x0980879,0x0b071af,0x1057ca9,
  36069. 0x1f3ee2a,0x127951d,0x1a99f0f,0x18f7263,0x06ef089,0x1bd2653,
  36070. 0x1288d8b,0x14589e6,0x00b05bd } },
  36071. /* 91 */
  36072. { { 0x1f575cd,0x05038e8,0x060ad09,0x034a46e,0x15693b0,0x164ea00,
  36073. 0x0d80a68,0x0c02826,0x19c914a,0x0621a45,0x0cc7054,0x0e7a12b,
  36074. 0x0290245,0x117ea4b,0x05d7f48,0x164eedf,0x086e210,0x1d0b824,
  36075. 0x16ea4de,0x137026d,0x01f6ac2 },
  36076. { 0x15da491,0x0f7aabb,0x160827b,0x1c56d55,0x05953f9,0x1a06ad9,
  36077. 0x084186e,0x1b0cd2d,0x14d5127,0x1e22988,0x0b418b3,0x195303d,
  36078. 0x032f21d,0x179db89,0x0f93c1e,0x1e41a7e,0x0b89646,0x1896683,
  36079. 0x0443d6e,0x06c6d2d,0x015e241 } },
  36080. /* 92 */
  36081. { { 0x0cfc44e,0x027e81f,0x0f54321,0x10a0876,0x0095f2c,0x1e82cd2,
  36082. 0x19f6f26,0x1bf34bf,0x0f65bec,0x1c9947d,0x0587348,0x08e34cf,
  36083. 0x1de3102,0x1ddaefe,0x078e6fe,0x18b75d5,0x0d0133d,0x0c0115b,
  36084. 0x1c4b0de,0x0f5536b,0x0141bed },
  36085. { 0x194d941,0x1802cfe,0x006025b,0x00fa9fe,0x1c6e9f0,0x0f82f1f,
  36086. 0x1d661de,0x133cc75,0x100483c,0x0207859,0x0661c13,0x1ddee54,
  36087. 0x1104d2f,0x0325253,0x1dced6d,0x0fe3db6,0x10f4936,0x1005b3b,
  36088. 0x0a7ef4a,0x1c06025,0x01694f7 } },
  36089. /* 93 */
  36090. { { 0x09095fd,0x0eeb9c5,0x15e837d,0x03a79d0,0x04b7a02,0x16e3b3e,
  36091. 0x1e5af97,0x0112154,0x1180a08,0x124bf7f,0x042aad5,0x1c3ecde,
  36092. 0x06b9856,0x1cc3cbb,0x0a62090,0x00c0262,0x0f73ba8,0x0b0ba46,
  36093. 0x1576a4a,0x120ed8a,0x001207d },
  36094. { 0x044394d,0x04d008e,0x19142c1,0x0e19c93,0x15f25ef,0x14a132f,
  36095. 0x027c2c5,0x1f03c74,0x0109b33,0x02decff,0x04cb90b,0x087f461,
  36096. 0x1207f2a,0x0367c57,0x1aaff2b,0x0ce44e6,0x004f336,0x056fbfd,
  36097. 0x0a749ac,0x1d25f7f,0x00e02f1 } },
  36098. /* 94 */
  36099. { { 0x1be4d4a,0x0725331,0x1246549,0x1acde79,0x1fa57be,0x1d3e668,
  36100. 0x04fe9f9,0x1a7baf9,0x088c5d1,0x07467b5,0x147c79c,0x12f47e4,
  36101. 0x15b2579,0x11aaa67,0x17b163b,0x0e21214,0x0d7065a,0x1346934,
  36102. 0x014227a,0x07a9a41,0x004c7c2 },
  36103. { 0x152d132,0x12badde,0x13158eb,0x0e71903,0x0fb8daa,0x131dcc8,
  36104. 0x1b94793,0x10e12d4,0x0b239d3,0x0eb59b3,0x127fb54,0x10e94ba,
  36105. 0x1aed5f8,0x01d4603,0x1424765,0x0d5c404,0x05ae468,0x10807c2,
  36106. 0x1ad3bd6,0x0b3ae8f,0x01c21af } },
  36107. /* 95 */
  36108. { { 0x1441308,0x1e00f6e,0x02417de,0x090c611,0x0dc3494,0x0b08e68,
  36109. 0x029d1d6,0x0cc55e7,0x14c23ce,0x0d38930,0x0bfb484,0x0f6bf17,
  36110. 0x1937f31,0x0649f03,0x1eee7fd,0x0a59e9d,0x0dd8ecc,0x1440787,
  36111. 0x172760a,0x19ba59b,0x0028480 },
  36112. { 0x1f807ac,0x0e506e1,0x1527a3c,0x057a0e0,0x0a3e4fc,0x1c5db63,
  36113. 0x0285247,0x19b5a7a,0x13d6dfa,0x1f70e7e,0x11bfef8,0x0372bf6,
  36114. 0x1cee46b,0x1eeae7d,0x01eceb1,0x1d16ea4,0x0d9b1b8,0x16ac060,
  36115. 0x1ef7446,0x0cd3e98,0x008452c } },
  36116. /* 96 */
  36117. { { 0x0ace6d5,0x1a3a3e0,0x1eb690a,0x177ce50,0x15acb64,0x1e130a6,
  36118. 0x1226626,0x03de660,0x0ff05c7,0x0bff41b,0x0b11420,0x048da6b,
  36119. 0x1c772eb,0x1bad4e1,0x17f0858,0x1adfafe,0x01acbc0,0x1fdb7cf,
  36120. 0x083a5cc,0x07862ae,0x009a764 },
  36121. { 0x1845ccf,0x10b5a79,0x16f52c8,0x0121780,0x1c174e8,0x02481bc,
  36122. 0x031d358,0x00cf4aa,0x16358c8,0x0b91050,0x1dedb6f,0x188354c,
  36123. 0x0e838f9,0x1371704,0x0ccb065,0x0db4a6e,0x15e496f,0x0d81943,
  36124. 0x10c18c3,0x04e99f3,0x000c52b } },
  36125. /* 97 */
  36126. { { 0x0a58beb,0x173c147,0x0921bb0,0x1a6ccbf,0x0b404c1,0x1a07f81,
  36127. 0x17eb482,0x14aa8da,0x029d3e6,0x1aefbdb,0x006647e,0x08dacd9,
  36128. 0x1ef1868,0x17167f1,0x1a42f79,0x1a2d77c,0x1a01410,0x14bd75c,
  36129. 0x0b323a4,0x102a917,0x00cb59d },
  36130. { 0x0f66a23,0x0e9d6dd,0x0207641,0x0e81bf6,0x0333738,0x007a196,
  36131. 0x0d7792c,0x07cdaaa,0x007d3a0,0x0bff474,0x0f2a038,0x1fee0cd,
  36132. 0x1529544,0x1d6ffd2,0x10ae5b2,0x0dd48c1,0x19445a2,0x04f80c6,
  36133. 0x128d3ff,0x0702ce4,0x011ed54 } },
  36134. /* 98 */
  36135. { { 0x17f8a61,0x039fdde,0x02ed8aa,0x0377cb0,0x1e18cd7,0x1fb4c02,
  36136. 0x07acd99,0x181fab9,0x1571d3d,0x1c6a7b0,0x1e6f22a,0x042af07,
  36137. 0x14e2e45,0x121cc58,0x10ddd2c,0x0236a6d,0x16374d8,0x196da51,
  36138. 0x17af8f0,0x1e252e5,0x01389f7 },
  36139. { 0x18fefb2,0x1f90e3c,0x09caee5,0x0a20f75,0x1c76fcb,0x0ddab44,
  36140. 0x1dd83eb,0x18a25f7,0x1d33ea6,0x13245f3,0x04d2946,0x132646c,
  36141. 0x1b412a2,0x04c2c49,0x0f605a6,0x15b4894,0x18f3e66,0x1b0a24a,
  36142. 0x1a1ed15,0x1f8f36e,0x0140b4d } },
  36143. /* 99 */
  36144. { { 0x0be5bb9,0x0a2b83d,0x06fa0ec,0x11ca3b0,0x0e0cbfd,0x013d7fd,
  36145. 0x17d2726,0x0a841b5,0x0a687b5,0x1d392a4,0x105ccf0,0x07f7dd6,
  36146. 0x0308026,0x09c13e3,0x053f70f,0x16e1ce0,0x184b5e3,0x03e80c7,
  36147. 0x0f3dc5a,0x107c01f,0x00151d4 },
  36148. { 0x1578aa3,0x11e3e35,0x16b8553,0x0ba6087,0x111ce9b,0x004080a,
  36149. 0x07a6ed8,0x0deabf1,0x0f405ac,0x1618889,0x02b1ed3,0x09b0401,
  36150. 0x067e66a,0x12e297d,0x10034e4,0x185d6e7,0x1988aca,0x1f70dcc,
  36151. 0x02d5d14,0x063b2ac,0x008fdfa } },
  36152. /* 100 */
  36153. { { 0x11cf8d8,0x0507012,0x0f4b31d,0x1a083e5,0x14d8949,0x15e7296,
  36154. 0x12924cf,0x15c16e6,0x15c5bcd,0x0d62fa8,0x002e4f8,0x1f982c4,
  36155. 0x0ed3ecd,0x13c9b9b,0x01a899a,0x0d2804a,0x08bea6e,0x0ac2d0e,
  36156. 0x0643e4d,0x19baa72,0x000e081 },
  36157. { 0x1e28412,0x1ccab29,0x192c157,0x05b64e2,0x0d1526f,0x19d6e38,
  36158. 0x097ac77,0x1bb9aac,0x0dd35de,0x16229e5,0x03ff8b4,0x1093507,
  36159. 0x09ed442,0x0e0672c,0x08304dd,0x16c135a,0x081bd99,0x196afdd,
  36160. 0x08bbec1,0x083b98c,0x01ad5be } },
  36161. /* 101 */
  36162. { { 0x1850756,0x17b33c7,0x165d58e,0x1ca5e76,0x06d37aa,0x14217ac,
  36163. 0x0294de5,0x12e21a7,0x1f743f9,0x0d57ccf,0x06a2eb3,0x0bcb27e,
  36164. 0x192fa75,0x004fbe6,0x1c13855,0x0ca1635,0x00ad6d0,0x131dfcd,
  36165. 0x16aff66,0x039d5aa,0x000e67b },
  36166. { 0x1f43178,0x054705a,0x0cccd98,0x1b3986b,0x16bd412,0x07b4042,
  36167. 0x1e98e20,0x0e27af7,0x02e622c,0x19b96b3,0x009115f,0x17cedff,
  36168. 0x11ad7b7,0x06d8272,0x0af7a02,0x0b91a1e,0x1fe4bd1,0x170f3c0,
  36169. 0x03940bc,0x0eb7f77,0x01941f4 } },
  36170. /* 102 */
  36171. { { 0x03543ec,0x015fceb,0x1cf9e52,0x19422fd,0x185cb67,0x066631c,
  36172. 0x018e058,0x03d158a,0x1729bdc,0x0b65f6a,0x1a1b7d5,0x12fb444,
  36173. 0x1cd62ed,0x040f5bb,0x0932d7f,0x05db362,0x16672fa,0x126bda7,
  36174. 0x00cd6e5,0x05354ef,0x017260b },
  36175. { 0x03df7c6,0x1e3db52,0x01b086f,0x077840e,0x05acac2,0x0ecac04,
  36176. 0x0def0d1,0x179d6de,0x0a32a08,0x0c79069,0x14f17a7,0x09eda32,
  36177. 0x10f0892,0x027b406,0x0975f1b,0x12258fa,0x0372de9,0x0327351,
  36178. 0x0b39913,0x180d88a,0x00ebda1 } },
  36179. /* 103 */
  36180. { { 0x11dd110,0x1be2e20,0x1128999,0x1459323,0x0d6787a,0x0b336b0,
  36181. 0x1a90691,0x02aa77c,0x0c15f9f,0x1f38b55,0x131ec9c,0x0c7e1c1,
  36182. 0x10a93b8,0x1531255,0x015c45c,0x184c148,0x16e1a39,0x072f3b2,
  36183. 0x1bdbc4c,0x1af16a5,0x0046af8 },
  36184. { 0x0f38dff,0x10a58b8,0x0415e58,0x1024742,0x1e35d82,0x1f6c091,
  36185. 0x1135255,0x0c208d4,0x00da601,0x0c7d4dd,0x01104d8,0x054aa9f,
  36186. 0x0be7cdd,0x0cf54ad,0x10958f8,0x06169e3,0x014cb2a,0x0e222cf,
  36187. 0x07fe6aa,0x115bacc,0x0183c74 } },
  36188. /* 104 */
  36189. { { 0x1e58caf,0x00f9cce,0x0990ca6,0x1b0ea7d,0x05bb80f,0x08ca430,
  36190. 0x07c90b4,0x015907f,0x003eeb0,0x0486783,0x0f5e73d,0x04a2f8e,
  36191. 0x1b4037f,0x1926a30,0x10827f5,0x0419f08,0x0d22724,0x13581fb,
  36192. 0x0d0e3e8,0x17a53d6,0x01526f4 },
  36193. { 0x189e51c,0x081a561,0x063a593,0x12db6fb,0x0cda55e,0x09e2c1d,
  36194. 0x05f7ba4,0x081655d,0x1feb034,0x1c983bd,0x1878a41,0x06f13a8,
  36195. 0x1eaa16e,0x021dfc5,0x099d4cc,0x1187f61,0x042ba7d,0x04eba4d,
  36196. 0x0ee4977,0x03cdacd,0x00ec7c4 } },
  36197. /* 105 */
  36198. { { 0x1da8398,0x19a2ee2,0x10c0ba6,0x1f76718,0x1c66841,0x1dda3d5,
  36199. 0x11589f0,0x1bb9c75,0x1738d2c,0x1df5895,0x0c46163,0x15aed0e,
  36200. 0x14d4bc2,0x1dea7a7,0x0876c72,0x0361d2a,0x0aefe4e,0x1153486,
  36201. 0x0ffaf8f,0x042bd6f,0x0194375 },
  36202. { 0x0dfd661,0x11a7897,0x07d132c,0x1ddaa58,0x0149984,0x1c7cc60,
  36203. 0x1c98363,0x12065a4,0x07be385,0x13b7272,0x02d9cbf,0x0e7b2bd,
  36204. 0x0254358,0x1958074,0x1b0e5ff,0x03d7122,0x105bad6,0x11dcdfb,
  36205. 0x184c6ef,0x1203055,0x00007ee } },
  36206. /* 106 */
  36207. { { 0x1fbcb5c,0x1f54f49,0x0a6f4db,0x073f50a,0x182be58,0x108dd01,
  36208. 0x0c497f5,0x06e1648,0x1cd8a26,0x0cd71bf,0x151c129,0x0c1c7b1,
  36209. 0x19ab78c,0x02620db,0x0b090f5,0x1398a37,0x1eaeda4,0x1e2000f,
  36210. 0x0f71fa7,0x1d48950,0x00f6988 },
  36211. { 0x077f79e,0x0655278,0x0435364,0x03b3c4b,0x14d1760,0x0da5bbf,
  36212. 0x0eecf48,0x16c23bd,0x09037e1,0x18d9fb0,0x0fb3c00,0x1b0426b,
  36213. 0x1af113e,0x19481ee,0x1004de7,0x1252ded,0x1caa6f1,0x09b5ef3,
  36214. 0x16eeb61,0x076d093,0x006c57d } },
  36215. /* 107 */
  36216. { { 0x0bfccb0,0x1f71c4d,0x198e58f,0x0972ced,0x0c6e2a2,0x1d3693b,
  36217. 0x03c0a12,0x1a3f0ed,0x0465853,0x1c5d1dd,0x0ae6db0,0x06da371,
  36218. 0x116e3ab,0x03d0399,0x1f25d09,0x07e6403,0x1182523,0x17eea0b,
  36219. 0x118779e,0x19f5035,0x00214da },
  36220. { 0x0a3198c,0x14f9bf5,0x0754d96,0x0bf9173,0x0be8a34,0x1af65e6,
  36221. 0x1c4ab53,0x029484f,0x00c2375,0x020ffb0,0x09ec17a,0x18b4514,
  36222. 0x135d9e8,0x1142cff,0x0ddd111,0x1bc6e5a,0x0ffea8b,0x00e0230,
  36223. 0x073d6fe,0x1c93425,0x01810a0 } },
  36224. /* 108 */
  36225. { { 0x1843c3e,0x101d7a2,0x0b9da20,0x07557d7,0x0601e30,0x06fb15a,
  36226. 0x023cd89,0x15072f6,0x0d21e5a,0x1439a45,0x10ac395,0x18e7344,
  36227. 0x0d2cf12,0x1953b63,0x123b404,0x0a34590,0x1c2f527,0x0db9550,
  36228. 0x0b00b41,0x052d872,0x00f3b63 },
  36229. { 0x0f3d1f0,0x1a156e3,0x0e53392,0x065ea65,0x0f0dcc5,0x021ece1,
  36230. 0x0ccd60d,0x196af02,0x0dc8dd9,0x0808c77,0x1c64bed,0x034bdd0,
  36231. 0x023039e,0x0aba0ce,0x1dc99f5,0x0d61932,0x04c30f9,0x123177d,
  36232. 0x134f0d6,0x1f6f2c7,0x01f7454 } },
  36233. /* 109 */
  36234. { { 0x1153926,0x140ca4e,0x152043c,0x03056ae,0x02e28c9,0x0f4a64a,
  36235. 0x0ecc142,0x0ae9684,0x0de9d6b,0x0d66295,0x128c531,0x1873167,
  36236. 0x05aa746,0x031eade,0x13a8c1f,0x193121e,0x1a2e1cc,0x0212aa9,
  36237. 0x1db6465,0x03317fe,0x008e271 },
  36238. { 0x08e672b,0x007231e,0x109f1e4,0x1a7e5bf,0x103675c,0x10b1e4b,
  36239. 0x147debc,0x160e092,0x07aceaa,0x06b4c84,0x148da5d,0x0352fd1,
  36240. 0x15482f2,0x009ee08,0x1ef0772,0x19a27b9,0x08004f6,0x106715e,
  36241. 0x0afebfc,0x08cc590,0x003f2a5 } },
  36242. /* 110 */
  36243. { { 0x188a8bc,0x1a0f30a,0x0b2c373,0x1c4218a,0x0f48cd0,0x073d22b,
  36244. 0x18af5d6,0x0ae670a,0x148b9b9,0x1006aa5,0x026e785,0x10174d7,
  36245. 0x0f461df,0x04c6641,0x1f53c5c,0x0e28fef,0x1cd1497,0x08b3f80,
  36246. 0x045b17e,0x070a22c,0x0048b13 },
  36247. { 0x12617f0,0x1b199ae,0x181b7ad,0x04dd970,0x1f9a577,0x08fe749,
  36248. 0x00cb46e,0x12f5278,0x16c84b9,0x1d21c45,0x1296fbd,0x044b047,
  36249. 0x0bbfe80,0x1ad197b,0x06700a0,0x0b8b0de,0x1ade3cb,0x0f9366a,
  36250. 0x1430776,0x1bb8eed,0x01e77f5 } },
  36251. /* 111 */
  36252. { { 0x0e764c9,0x1f76437,0x0b30f27,0x0d60f90,0x11bec83,0x02d8a16,
  36253. 0x0cb9a80,0x1d4d7e3,0x129e8a5,0x077a8d1,0x189071c,0x131c7ff,
  36254. 0x08517d2,0x194b361,0x0e278a1,0x198ed76,0x0a92c7a,0x09d16d4,
  36255. 0x0ca886d,0x19224ce,0x004a902 },
  36256. { 0x17ce110,0x08dce47,0x1bc65b1,0x0f5d606,0x1cc33a8,0x152cf16,
  36257. 0x1426029,0x00104d2,0x1e78db5,0x1579353,0x0ec0c33,0x070992b,
  36258. 0x0282f3c,0x126217a,0x15ba7dc,0x09414db,0x02970ac,0x03b46ef,
  36259. 0x0f48bbf,0x1b9c960,0x016f4ae } },
  36260. /* 112 */
  36261. { { 0x1ed03c0,0x1819576,0x15341df,0x04b11bb,0x0684a05,0x02df079,
  36262. 0x0f13e6a,0x176da13,0x1e0b9b6,0x0ed063f,0x0d621ef,0x18fde5f,
  36263. 0x1e19689,0x161e673,0x0a5a583,0x055cbf1,0x1d5768d,0x15821ec,
  36264. 0x0c84866,0x101037b,0x006829c },
  36265. { 0x059f006,0x0397d6f,0x1d69afe,0x0d972fd,0x02b9ffc,0x173f7c6,
  36266. 0x0576d62,0x03e6e32,0x1f4ccaa,0x1711e50,0x09f3130,0x0c1d138,
  36267. 0x061af8c,0x0435ee6,0x1975f9f,0x1bc87dd,0x07f9bd8,0x1c912da,
  36268. 0x0c93c22,0x0fe8c69,0x00b453e } },
  36269. /* 113 */
  36270. { { 0x1048bda,0x04b6871,0x1939531,0x128787b,0x02b6749,0x16a84f7,
  36271. 0x127dd30,0x1135840,0x0543c50,0x00fb48f,0x08d96ec,0x014620b,
  36272. 0x09cd996,0x1c58b82,0x164fff9,0x128ce69,0x1b3f82c,0x0814fcc,
  36273. 0x05869d5,0x18bd440,0x0091785 },
  36274. { 0x13dbdb6,0x0fcbc4a,0x067ed15,0x132fd94,0x0a9e84d,0x0a6bad7,
  36275. 0x140a4db,0x1f48e77,0x0c15276,0x0e0be54,0x1d8d5aa,0x02668f8,
  36276. 0x129cf66,0x01cb9c6,0x1a0d82c,0x06c1294,0x0a86973,0x0e9f218,
  36277. 0x0ac9fc8,0x0a65bdc,0x01b40ae } },
  36278. /* 114 */
  36279. { { 0x164cb8b,0x0874128,0x19f5a04,0x1e4aa54,0x0979af4,0x0c2a93b,
  36280. 0x1b43a34,0x189c21a,0x1fb64ea,0x1b62bc3,0x09164b3,0x0c77588,
  36281. 0x1084081,0x1e706c0,0x03ffcdf,0x182b8bb,0x049da84,0x0c59427,
  36282. 0x0998fb2,0x00aace6,0x0010ed8 },
  36283. { 0x1f3ee9e,0x1a01828,0x1c7841b,0x136715b,0x0e8e3ee,0x1eb2249,
  36284. 0x1e9ba84,0x163a790,0x180e1ab,0x1da4fa2,0x15ca609,0x02f217f,
  36285. 0x1fc283d,0x17e3d1a,0x1943e96,0x15a9f1f,0x145ade3,0x13b9ed2,
  36286. 0x068877c,0x1f55c9b,0x01f878b } },
  36287. /* 115 */
  36288. { { 0x1ad5678,0x06c7455,0x096eb98,0x1dcc018,0x0afa72c,0x1447108,
  36289. 0x182d130,0x13f73a9,0x0d254cf,0x0223fbb,0x18ae959,0x17892b3,
  36290. 0x0c1fb36,0x14b0899,0x0f1135c,0x01e3272,0x01ffc14,0x06bd444,
  36291. 0x1425992,0x10c2511,0x009127a },
  36292. { 0x09e690c,0x16010c5,0x0856d4d,0x03d569f,0x05dcc52,0x0772a64,
  36293. 0x1108ec0,0x090135e,0x1af3a8e,0x1bc9a92,0x0c7616c,0x06116ee,
  36294. 0x15e1f36,0x0a0e7da,0x0d875e0,0x08a536a,0x09eeffc,0x07520f9,
  36295. 0x1df498d,0x0eab633,0x00e8cf5 } },
  36296. /* 116 */
  36297. { { 0x012b398,0x0dc06e9,0x0dcc07b,0x03aa7ba,0x1039618,0x097d4ae,
  36298. 0x1811e29,0x0da1c10,0x0a7825e,0x08f3219,0x1b393eb,0x178a661,
  36299. 0x0fe0185,0x183c49b,0x03dcc4e,0x0dd46a1,0x0fd9e7f,0x00ee4c1,
  36300. 0x1555ad8,0x074c05a,0x00e8dbf },
  36301. { 0x19e05bc,0x1191a13,0x0f4f0dd,0x19e888a,0x1f5f40e,0x1183c9b,
  36302. 0x17d35fe,0x0446218,0x0108d7e,0x07fd69b,0x062ef17,0x1de7855,
  36303. 0x00f2f01,0x0bea3fc,0x0ac5c67,0x05c3861,0x118a9b2,0x03de4fc,
  36304. 0x00d37e5,0x1b8a55d,0x01f9f53 } },
  36305. /* 117 */
  36306. { { 0x183f89b,0x15a4f60,0x1b53c99,0x04beb00,0x13fb5f0,0x1618406,
  36307. 0x10ad653,0x02fa614,0x0371cd9,0x1b58ca0,0x1f89b52,0x15576fe,
  36308. 0x04f7541,0x16adbdb,0x149a7ac,0x06d8bca,0x1c17f80,0x0870d42,
  36309. 0x097c99d,0x1e1e45b,0x01cea0f },
  36310. { 0x08e11f8,0x1eab51d,0x0d5180a,0x03ebf35,0x0986402,0x06496b9,
  36311. 0x0b16833,0x0178ce8,0x0523f65,0x122b4f3,0x0afed35,0x1037eff,
  36312. 0x0bc8e46,0x01e4f36,0x09d651f,0x1fe4168,0x0d538f5,0x1159ca9,
  36313. 0x1c12ba8,0x1f1c703,0x01b0818 } },
  36314. /* 118 */
  36315. { { 0x10d90f0,0x0dffd72,0x1370ef9,0x17ea023,0x0cb3b11,0x08efd62,
  36316. 0x09c469a,0x0e7c219,0x14ea1a7,0x176108e,0x1bbad98,0x1d77cb0,
  36317. 0x1d5a979,0x106178f,0x1c5aac6,0x17fd49b,0x17ec57b,0x17f4f1f,
  36318. 0x0b949bd,0x0b2c1cb,0x015e1b0 },
  36319. { 0x030e62e,0x10252c3,0x06dc723,0x1cc88fc,0x1d00310,0x1a223d1,
  36320. 0x1ad850e,0x1479e3c,0x17462e7,0x155dc28,0x09c9364,0x1410000,
  36321. 0x1f8309e,0x12294b6,0x00175c3,0x1b0243b,0x1b33d4e,0x1079c24,
  36322. 0x00d3513,0x17ff78d,0x00962d6 } },
  36323. /* 119 */
  36324. { { 0x0e07711,0x1f2c6a4,0x0ecb44f,0x11a4e14,0x10f8364,0x0ff8263,
  36325. 0x024b633,0x0282a2f,0x051411f,0x0ddb2bc,0x1e29545,0x1b207c9,
  36326. 0x0f6c31c,0x02099b1,0x1e1c548,0x0da9ae7,0x1eeeca0,0x197f012,
  36327. 0x1538c5f,0x0dc82f2,0x00ad32a },
  36328. { 0x1d147df,0x0631fb4,0x0dedf8e,0x1ce217e,0x169bb06,0x0a8a6f5,
  36329. 0x1afbca3,0x1b3729b,0x18d11c3,0x19183fd,0x1718112,0x1bf2070,
  36330. 0x033b369,0x13c0074,0x1a8bd27,0x03838d1,0x0587d50,0x0781459,
  36331. 0x13bde06,0x0f0442b,0x0055970 } },
  36332. /* 120 */
  36333. { { 0x0c1d751,0x1a8edaa,0x1448430,0x03741f2,0x0144530,0x0e45f6c,
  36334. 0x0cd3eff,0x0154efd,0x0cf2368,0x0c6c09c,0x1ca1812,0x0949c09,
  36335. 0x1a928c1,0x0b52db6,0x064b6e8,0x122072c,0x15b5f9a,0x124ef54,
  36336. 0x05c9040,0x1a8af00,0x008580d },
  36337. { 0x009221c,0x1928007,0x015ba41,0x03e43bc,0x02e05b2,0x1304a83,
  36338. 0x0be8783,0x0528919,0x16f7751,0x0bfdcbd,0x0d2b299,0x037be3e,
  36339. 0x165d299,0x04ff8ae,0x1b356b1,0x1d8f34c,0x097d049,0x06e0eb4,
  36340. 0x1caebaa,0x1f9509c,0x0067388 } },
  36341. /* 121 */
  36342. { { 0x0ef1dd3,0x05a4ed3,0x15d9948,0x1c774d9,0x191a045,0x1eafa41,
  36343. 0x0602bcc,0x0953909,0x0ef0747,0x09e7ad9,0x1ec7ab9,0x1d34f17,
  36344. 0x1aa35b2,0x16d4837,0x0a5ff5b,0x059e9d9,0x1891b9f,0x0f8d49b,
  36345. 0x0aca162,0x0a66d27,0x010d667 },
  36346. { 0x1691faf,0x0824b39,0x18616d4,0x13aafd8,0x1c73d3a,0x054292e,
  36347. 0x086ee4c,0x0d2fc52,0x040b05b,0x0a7ab8f,0x0fb7282,0x002e827,
  36348. 0x185e96a,0x068d35c,0x1f53dca,0x1d16f3c,0x1da3ead,0x0aa8a1f,
  36349. 0x05b9153,0x170889a,0x00fb859 } },
  36350. /* 122 */
  36351. { { 0x0667aaf,0x1041f3e,0x12e9f08,0x1295239,0x13545cb,0x1074a51,
  36352. 0x064c632,0x18f943d,0x1e4eaa0,0x1d7ff91,0x15a1130,0x086c85e,
  36353. 0x0ba21ac,0x106a968,0x11a2a2d,0x003a9f9,0x05b6a93,0x0a00d2c,
  36354. 0x01eaf38,0x1eec592,0x00a3547 },
  36355. { 0x1e260ce,0x09f69fd,0x07e98f7,0x1b01b80,0x0717752,0x0ed1f21,
  36356. 0x0dd75bc,0x01dabf5,0x05261f1,0x18b4325,0x135aed7,0x1ec7a41,
  36357. 0x16be7b1,0x110d632,0x18e3040,0x1231d3a,0x0f6673b,0x0189bdc,
  36358. 0x0b68bee,0x1688709,0x017423e } },
  36359. /* 123 */
  36360. { { 0x01fbcf4,0x113e215,0x17b8653,0x16bf59a,0x0c0d285,0x0f3303a,
  36361. 0x1af7645,0x134eb85,0x0ef0a6a,0x134b288,0x13d1607,0x1f420cf,
  36362. 0x1a13c5a,0x1df70fd,0x1804f05,0x0f3ce57,0x0d6dad2,0x0c2d203,
  36363. 0x050b3d6,0x052a3aa,0x0031004 },
  36364. { 0x02bbc45,0x1af60d1,0x1361a9c,0x14feade,0x0ee5391,0x1000ef2,
  36365. 0x1e7408d,0x04a60b5,0x1aa2f8d,0x0590c28,0x16de2aa,0x0db030f,
  36366. 0x030e2c3,0x10d4446,0x13020fe,0x0fab79f,0x17fbd3e,0x1dc8ed5,
  36367. 0x13f7408,0x10a8c1e,0x00f462d } },
  36368. /* 124 */
  36369. { { 0x172d703,0x05d0124,0x080fd5a,0x1a72131,0x1c44ca1,0x14642af,
  36370. 0x1950ab8,0x06dd371,0x05b1b45,0x1ea79b0,0x1df9213,0x00f698f,
  36371. 0x1d2e08b,0x1118411,0x0bcee60,0x1fa2608,0x1131889,0x0e4ffe9,
  36372. 0x1b1a0d6,0x1e0ca58,0x01bb56a },
  36373. { 0x0e0f16a,0x182f103,0x1297b6f,0x15ae8c8,0x1c1ac2f,0x09638d7,
  36374. 0x02a603e,0x143cb34,0x136c800,0x1d71beb,0x05e3704,0x1f8c46c,
  36375. 0x105f20e,0x15a3778,0x0e962e0,0x013c888,0x1cf4425,0x064a8be,
  36376. 0x103b66c,0x17682ac,0x01667d0 } },
  36377. /* 125 */
  36378. { { 0x122842d,0x185309e,0x1380ea8,0x0b6789d,0x0c6e00f,0x1c15bcc,
  36379. 0x13e1db7,0x18b0ec9,0x178d208,0x1496c36,0x02152b6,0x0723cf1,
  36380. 0x140a52d,0x12cd84c,0x06c9bee,0x1f93493,0x1ad04c5,0x02ee099,
  36381. 0x138fc4d,0x0124d26,0x01dda5c },
  36382. { 0x0d6d673,0x0e5617d,0x0ff9bc3,0x0a01e76,0x0d8fdf0,0x0bab74b,
  36383. 0x065058c,0x1c7d9ce,0x10a4d80,0x0c87a49,0x04c004e,0x126c63a,
  36384. 0x18f2aca,0x1aac0b1,0x04659b1,0x0acf3dd,0x174e6dd,0x136f87a,
  36385. 0x135c736,0x0490d19,0x0111be1 } },
  36386. /* 126 */
  36387. { { 0x15cc1b4,0x0639323,0x1e33d91,0x1256e72,0x115fc2f,0x1ebf5bc,
  36388. 0x19b4438,0x1c0cb4f,0x0f40c38,0x1a2710d,0x1493f2e,0x0573c35,
  36389. 0x0598866,0x01ab037,0x02e9377,0x127ee4e,0x02c1a4f,0x1e1c1a5,
  36390. 0x0d8a935,0x0193446,0x002193d },
  36391. { 0x169fd7f,0x1bdc67b,0x0ee78b2,0x0f13442,0x1815da9,0x0887f78,
  36392. 0x03159ae,0x070f69f,0x1269314,0x0445984,0x0cdf008,0x037b24b,
  36393. 0x05477b7,0x1353207,0x126a484,0x18ddf40,0x1bdfd21,0x169eef8,
  36394. 0x0ca95ac,0x1f3afa4,0x00649b5 } },
  36395. /* 127 */
  36396. { { 0x19a9c35,0x056fc33,0x1e5b590,0x0796e9a,0x0dad98e,0x074ed7e,
  36397. 0x03aed7e,0x0788c97,0x0ad4a07,0x19c30a7,0x17955d1,0x01dc5db,
  36398. 0x19bd86c,0x0bb6705,0x0cc5ce1,0x1f72cee,0x1274095,0x0cdae99,
  36399. 0x1826bab,0x015d67d,0x013672f },
  36400. { 0x0e54ba5,0x063b6b2,0x14868e2,0x03b88e9,0x03fe7af,0x13b840b,
  36401. 0x1a746ca,0x15aff47,0x0de1240,0x023da4f,0x00c0e81,0x16cd8e4,
  36402. 0x13d9f64,0x135e810,0x11e00a7,0x07d4b63,0x0700aa0,0x18e578e,
  36403. 0x0ee174a,0x0301d67,0x0103179 } },
  36404. /* 128 */
  36405. { { 0x12ed12f,0x1a7cfd7,0x162ab6f,0x09e701f,0x0e1d19e,0x0f40d76,
  36406. 0x0f6d68e,0x17812af,0x1626ef6,0x0c19990,0x16ca37e,0x0bd419e,
  36407. 0x14110ae,0x101c966,0x0565140,0x0f0ab56,0x0876bc6,0x133e24c,
  36408. 0x0ff5871,0x1cb2714,0x004ace7 },
  36409. { 0x0c7dea9,0x0dcf794,0x0611671,0x1414d4e,0x102f95b,0x013b4e6,
  36410. 0x1095e08,0x12c069b,0x094dd68,0x09d8584,0x1aa5688,0x16ff6bb,
  36411. 0x0903730,0x10be544,0x090fb41,0x140a5fc,0x117fb1b,0x10b67a6,
  36412. 0x09be5b6,0x123ad64,0x01c0d86 } },
  36413. /* 129 */
  36414. { { 0x18015c2,0x16f9fdf,0x0b62a8b,0x1b892a0,0x07f8236,0x1218abf,
  36415. 0x1db829a,0x019d121,0x1a2d04b,0x0c77992,0x076eacc,0x0d1b501,
  36416. 0x019cc06,0x0d33e51,0x09a4deb,0x17893ba,0x12c83fe,0x04793e0,
  36417. 0x126e611,0x07b65e7,0x002987b },
  36418. { 0x12e3dc7,0x1d7687e,0x1554df9,0x16e82bf,0x098e8bd,0x122f92a,
  36419. 0x1b26962,0x1a1f81a,0x0209c85,0x1eadd5d,0x0787ba0,0x1b8daaf,
  36420. 0x0d31ec8,0x12815ff,0x132b42e,0x17de23e,0x0ce1f41,0x0e21973,
  36421. 0x0fff299,0x015f557,0x01913b1 } },
  36422. /* 130 */
  36423. { { 0x1053af7,0x1bef829,0x13d2f67,0x0b65143,0x0030476,0x14821c3,
  36424. 0x1e3f1f3,0x1ba882e,0x0ac8c5d,0x1df69b7,0x07b1863,0x0277f6b,
  36425. 0x0f27b13,0x10d8df6,0x0995bfe,0x0e7533a,0x1459459,0x099a709,
  36426. 0x0d8ad65,0x0311198,0x018c326 },
  36427. { 0x07f6ff8,0x1d20a55,0x11ebd04,0x107f56f,0x092aeb8,0x0183dd0,
  36428. 0x021adf3,0x01df43b,0x1234610,0x040e092,0x10324f7,0x04e6042,
  36429. 0x1593d4d,0x1308241,0x1b5f8f3,0x12be743,0x0cfdf17,0x1715c8f,
  36430. 0x1a7b505,0x1b82346,0x0191160 } },
  36431. /* 131 */
  36432. { { 0x157d7cc,0x17a3745,0x0e1a69c,0x0a97e04,0x1140b0e,0x19d48e9,
  36433. 0x0e5b816,0x1c110d8,0x1a4ec26,0x1cd59d4,0x1d63a46,0x15d78a1,
  36434. 0x10742fe,0x0af1357,0x04b1821,0x1b3ee2b,0x076bb1c,0x0ca1e6a,
  36435. 0x1fc0b22,0x12ffa98,0x017c3ed },
  36436. { 0x0d54964,0x01281f3,0x03014ec,0x058d463,0x19bd116,0x0146116,
  36437. 0x1b3d273,0x08031fe,0x0035346,0x02e3c20,0x1019a29,0x06bd699,
  36438. 0x038ea33,0x1a16df0,0x15c9fe3,0x1879af5,0x111fdf6,0x158abf4,
  36439. 0x1264b5d,0x112993d,0x01b3a7f } },
  36440. /* 132 */
  36441. { { 0x109ea77,0x171cbd7,0x1716479,0x12ebb84,0x06a760b,0x050cbd9,
  36442. 0x03022e5,0x0331808,0x0b68ce6,0x00dd654,0x08d5901,0x1a2ab7a,
  36443. 0x1fa19a0,0x0cbbd99,0x1296e53,0x1a0530d,0x1f8e5fb,0x0f98fc3,
  36444. 0x06407e6,0x18ab4d6,0x00b8f76 },
  36445. { 0x046ec9f,0x1fc619c,0x09185d6,0x193bd59,0x1462205,0x0846f87,
  36446. 0x17b028c,0x0512596,0x1cfaed9,0x1ced941,0x127eca1,0x0008ca0,
  36447. 0x11477dc,0x0b77281,0x1492eb2,0x19c8a91,0x11656ad,0x1d3edb5,
  36448. 0x0c71a13,0x019b575,0x00fc011 } },
  36449. /* 133 */
  36450. { { 0x1308bf2,0x1b36c26,0x0010546,0x1facc70,0x19013c9,0x1c1dfcc,
  36451. 0x17e4bf4,0x1f8d125,0x03ffc8e,0x0877ec2,0x1a8a1e8,0x02d8627,
  36452. 0x00527e3,0x1d06fba,0x1db8f34,0x1a5431d,0x030f6eb,0x165cb72,
  36453. 0x1c3b933,0x17d9e54,0x018cc1e },
  36454. { 0x070404c,0x0a56b8d,0x08c2034,0x01f39c5,0x0ad21dd,0x11f0393,
  36455. 0x0f378ea,0x1217299,0x16363a6,0x15acb08,0x078ad02,0x1e8b8d6,
  36456. 0x1be70bf,0x1367762,0x05b742d,0x0af8025,0x0747477,0x06a6595,
  36457. 0x15f647a,0x11194c7,0x00aa089 } },
  36458. /* 134 */
  36459. { { 0x0db0396,0x0e7e57c,0x09daa8b,0x0f6845b,0x08ae8f3,0x042b927,
  36460. 0x00d2659,0x07eca5f,0x07bf149,0x123e1e2,0x11e93bd,0x168d604,
  36461. 0x0e8b600,0x1d75ed4,0x1cf90e5,0x11be157,0x11fa795,0x1170e91,
  36462. 0x0206eac,0x0d2563f,0x00ef38e },
  36463. { 0x0cf3047,0x00b4493,0x01607cf,0x08b2a73,0x1ad14f9,0x1f905b6,
  36464. 0x17470a4,0x02ffbd0,0x0f57abb,0x152a1b7,0x1378e0b,0x1ff82f2,
  36465. 0x0f0d1a8,0x15ff669,0x0942388,0x0c08537,0x07fdb78,0x0088785,
  36466. 0x1378c7e,0x1cdec8f,0x01962ad } },
  36467. /* 135 */
  36468. { { 0x0c78898,0x1529bff,0x1dff265,0x05bc1f4,0x0b39de7,0x0658478,
  36469. 0x1dab34d,0x0a7eda0,0x0da78d3,0x06c5dc1,0x04b306b,0x09a7407,
  36470. 0x1d5fe80,0x12c0aa4,0x1eb7b7b,0x18db356,0x1a0c067,0x1c41c80,
  36471. 0x1b64fcd,0x0bff449,0x0191585 },
  36472. { 0x19ebef3,0x1871b5f,0x05dca55,0x0bbe966,0x021046a,0x00b5ae7,
  36473. 0x06a569a,0x023f371,0x1288d0e,0x0f9c940,0x04566ab,0x17ca72f,
  36474. 0x12d6baa,0x0e47d5d,0x06bfb81,0x15e2082,0x1afe5c7,0x1f8c961,
  36475. 0x1f738de,0x05d039a,0x00f7aa7 } },
  36476. /* 136 */
  36477. { { 0x0c386ee,0x11e078b,0x00e483e,0x13a9813,0x133b046,0x15189b5,
  36478. 0x15c8a1d,0x00cf3c1,0x03c406c,0x01e0549,0x0f89f4d,0x1c7c9bd,
  36479. 0x0aef220,0x0cb7807,0x15ec784,0x1b9fe13,0x1d824a9,0x0a507ae,
  36480. 0x0707421,0x105d8b3,0x01e2535 },
  36481. { 0x138c7ed,0x1793128,0x0237323,0x08ca8ff,0x1ec4319,0x054a446,
  36482. 0x14eb774,0x1b856dc,0x08257eb,0x1cf8f7d,0x032627a,0x0dd63e1,
  36483. 0x08c583c,0x000b1bb,0x1cda445,0x01c7be2,0x18bdbc2,0x131417f,
  36484. 0x12f5453,0x10200b3,0x00d526b } },
  36485. /* 137 */
  36486. { { 0x0025949,0x0a917d0,0x0514912,0x1e177b1,0x126d888,0x1b90b7d,
  36487. 0x0bd7f98,0x1ec6688,0x0472827,0x0761db2,0x109a076,0x034733f,
  36488. 0x0d91d8a,0x1463b88,0x08cbab5,0x04ec4da,0x02fe51b,0x1c72dff,
  36489. 0x14427e9,0x1e9fdbf,0x00040f9 },
  36490. { 0x14a05e0,0x17528b5,0x03ac654,0x1de438f,0x0b0d48e,0x0befede,
  36491. 0x1986466,0x1fac9a6,0x08b4c21,0x088d902,0x08c0e83,0x136d7d2,
  36492. 0x09a6f56,0x1c62f40,0x03d8259,0x0bb1c57,0x1ab3680,0x139135a,
  36493. 0x0cd2728,0x1fe301b,0x01bdd6c } },
  36494. /* 138 */
  36495. { { 0x03cc612,0x1c2bb4a,0x071e927,0x1d06566,0x0914319,0x056f5ee,
  36496. 0x18a5f33,0x043244b,0x0b06198,0x08c7da1,0x0731f12,0x01084b6,
  36497. 0x10accb3,0x132372f,0x074cd1e,0x07c44ea,0x0ae590e,0x0757da5,
  36498. 0x1128002,0x08c0705,0x0151821 },
  36499. { 0x196a461,0x040eddf,0x0e90f09,0x136a547,0x11c122e,0x06d845a,
  36500. 0x0163919,0x03a4385,0x06d6a08,0x080a5bc,0x0f3bdec,0x1da9ea6,
  36501. 0x1c167d3,0x00aa2fb,0x1ecca52,0x0f73ed9,0x11c449b,0x0f52369,
  36502. 0x18870a6,0x1aec272,0x0081cfa } },
  36503. /* 139 */
  36504. { { 0x18a7f0e,0x0b193a3,0x0177bde,0x05bc2ee,0x114183e,0x108bf44,
  36505. 0x09b7d5c,0x19fa494,0x1b7cd52,0x06d8d84,0x0f0580f,0x13f75b0,
  36506. 0x099e42b,0x184f7c6,0x1c74ba9,0x0999ad2,0x05b8ee5,0x00c4a7e,
  36507. 0x129483f,0x0f69ca6,0x00fcf75 },
  36508. { 0x0b62347,0x08c6643,0x04a1695,0x04f7855,0x0c51c9d,0x13393ff,
  36509. 0x0ac14a5,0x0de5dd4,0x00ae43e,0x045471d,0x0819aef,0x16bc0b9,
  36510. 0x0d80535,0x0419cc3,0x1ff36c6,0x099bb23,0x1ba3237,0x197a52d,
  36511. 0x1480890,0x0c74921,0x0124087 } },
  36512. /* 140 */
  36513. { { 0x0fac14d,0x05cb927,0x14f3926,0x1b4f353,0x16f4bf8,0x103e14d,
  36514. 0x036f75b,0x0701e3d,0x1717715,0x161867e,0x00c98fe,0x1a44e36,
  36515. 0x154c91e,0x0cda2af,0x04e0cd4,0x1257f7f,0x1891270,0x0bb52f3,
  36516. 0x1204ef6,0x0ce9c36,0x0128a97 },
  36517. { 0x03e5924,0x11e20ac,0x1418a6d,0x031e2e3,0x01f9aff,0x113d143,
  36518. 0x0cf36ac,0x0e0568b,0x08a11ab,0x1ceaeed,0x0da5c64,0x0f61d1b,
  36519. 0x052bfb4,0x0760840,0x08de77c,0x03002ac,0x08124ce,0x157ad32,
  36520. 0x13e52ae,0x1188686,0x01508d9 } },
  36521. /* 141 */
  36522. { { 0x1ffc80f,0x0ff39e7,0x0fdb7aa,0x17a868e,0x023e2e9,0x09bdd3f,
  36523. 0x0fb4f27,0x0ae4ff6,0x07a3fc3,0x19bb369,0x1280f5c,0x19e71c0,
  36524. 0x03d0db4,0x15df07a,0x1805d48,0x0de9f19,0x119da98,0x1ec3f5b,
  36525. 0x1f9ac0d,0x16a15c5,0x01536d1 },
  36526. { 0x040bab1,0x1aef7ed,0x098cdc7,0x1f3657b,0x07d6a8a,0x0565438,
  36527. 0x1722435,0x156bd14,0x1643ff8,0x0b9787f,0x03b0bd3,0x01b297f,
  36528. 0x029c4c1,0x075c9f1,0x0c3aae8,0x1fa026d,0x08f1d2d,0x15e2587,
  36529. 0x14d2820,0x0a5cb53,0x01429f2 } },
  36530. /* 142 */
  36531. { { 0x10e7020,0x1ea60be,0x05a12bf,0x156a904,0x1b169aa,0x079a47c,
  36532. 0x05c2162,0x177b7c0,0x1885986,0x175fb7f,0x070e076,0x0fea2bf,
  36533. 0x1bb3398,0x0254a53,0x1157cb0,0x0d092fc,0x042a0ed,0x01cd20a,
  36534. 0x1bdde63,0x15a94c3,0x01541c1 },
  36535. { 0x12709c4,0x1db1403,0x17f9d91,0x171021c,0x1330d68,0x1707b1d,
  36536. 0x021d3a4,0x175a37b,0x1f8bea9,0x02727dc,0x0260685,0x1831063,
  36537. 0x07c15af,0x1b46350,0x071720a,0x016cdc3,0x1a236e0,0x042c62b,
  36538. 0x1f2debb,0x0aa2200,0x00119b2 } },
  36539. /* 143 */
  36540. { { 0x087027d,0x07693e4,0x0a18487,0x0a57f56,0x0050f33,0x0a88f13,
  36541. 0x0f07067,0x1eadc6e,0x17f4c69,0x16a61d4,0x09aed00,0x0d5e4a4,
  36542. 0x10e6f35,0x01f3d61,0x040470e,0x1fbf677,0x03d33d8,0x1a1d861,
  36543. 0x1cba8d8,0x0721ef5,0x000ba8c },
  36544. { 0x0851bac,0x061eb3f,0x13f310c,0x134bea8,0x0991c38,0x1dd030c,
  36545. 0x0f1919f,0x1e800d7,0x097cbdb,0x04e8127,0x12b6b75,0x0fbaee6,
  36546. 0x0a4539b,0x1465b69,0x0ea3e7c,0x1675b21,0x0304de4,0x03d490c,
  36547. 0x1ee5a4a,0x0e65df4,0x006ab28 } },
  36548. /* 144 */
  36549. { { 0x0ed5986,0x15a9691,0x1819c76,0x14b0a67,0x1eee627,0x0aaff1e,
  36550. 0x18deb3c,0x065d1fd,0x17ae8b1,0x0b0a486,0x022e533,0x030a694,
  36551. 0x102706e,0x1ce0ae1,0x17ff54b,0x15a8d50,0x0f351a5,0x1ead112,
  36552. 0x135c02e,0x036daaa,0x01e644d },
  36553. { 0x02e4e9c,0x1834343,0x1f925a0,0x1890ec7,0x1e5cd76,0x01ce557,
  36554. 0x059e702,0x05ac061,0x18d83d6,0x07265f5,0x112b8b0,0x0a9c237,
  36555. 0x02911e2,0x127e503,0x0835f21,0x0e08b2d,0x1d5e9a2,0x07abc2e,
  36556. 0x0f8104b,0x0cefa1e,0x01be2f4 } },
  36557. /* 145 */
  36558. { { 0x101a6dc,0x0096ed5,0x0da5300,0x035c35b,0x191bd6c,0x18283c9,
  36559. 0x16bb2e6,0x03e75cf,0x062a106,0x138a7cf,0x14dadf0,0x1dcf52c,
  36560. 0x0b71978,0x0f0bb2a,0x1046f41,0x07ba9dd,0x0e0efab,0x0e388b3,
  36561. 0x1fb6fd8,0x154ae50,0x01d70f7 },
  36562. { 0x1eb5932,0x137bea8,0x12909ba,0x14bf105,0x154ea0a,0x1cfbee1,
  36563. 0x1825ddc,0x0682eb6,0x09be579,0x19a8c95,0x117b334,0x0846f0a,
  36564. 0x1d9801f,0x1db21e4,0x0e38959,0x157d865,0x1d723e3,0x0dca08e,
  36565. 0x1c71942,0x1bd4d19,0x00ee656 } },
  36566. /* 146 */
  36567. { { 0x0890deb,0x070a050,0x12f534e,0x1b79d70,0x1f7bd87,0x020ef65,
  36568. 0x1fdcae8,0x1d2a3e1,0x0a6820b,0x1f76385,0x018a62b,0x0147189,
  36569. 0x0475519,0x1380876,0x16e9563,0x0f363d9,0x1b88c78,0x0676c8e,
  36570. 0x1d78857,0x1c7c99d,0x014c08d },
  36571. { 0x0266da2,0x09a768b,0x0026705,0x16f6992,0x1ce322e,0x093b444,
  36572. 0x12bbda6,0x09a6fbd,0x105c284,0x09284bf,0x1466ad9,0x1c26358,
  36573. 0x06d23b7,0x12d1e64,0x0baedc9,0x08aead0,0x1b9628c,0x186298e,
  36574. 0x0e014dc,0x01d170e,0x00be2e0 } },
  36575. /* 147 */
  36576. { { 0x1ed32e9,0x1e4002b,0x065ce01,0x1ef8049,0x027e40c,0x1aa4182,
  36577. 0x1aaeeae,0x1e8b0a0,0x1ce820b,0x124bbb7,0x10fa055,0x0527658,
  36578. 0x08b5353,0x07f7b32,0x07a0d4f,0x1b94ace,0x13f903b,0x09390be,
  36579. 0x004ff5e,0x1382135,0x01dc40a },
  36580. { 0x1b21a38,0x153619e,0x1f91afa,0x03ae7de,0x0ae222e,0x0ea83fe,
  36581. 0x0139ef4,0x1563fed,0x0587a77,0x0dd6332,0x12935bd,0x1ec418c,
  36582. 0x0a58c74,0x153e1bc,0x0a0df65,0x1c81299,0x1313e42,0x1fa1efa,
  36583. 0x0d27853,0x14868ff,0x013f8a9 } },
  36584. /* 148 */
  36585. { { 0x12f8923,0x1a76fcc,0x07ce16a,0x00dfa41,0x024aa5e,0x09a0777,
  36586. 0x06e1c6c,0x0804f7d,0x191e0bb,0x0abe88f,0x1318b0a,0x15a5e7a,
  36587. 0x0f425af,0x03ffbd5,0x08c4a1b,0x197d25a,0x12b0114,0x0cb2095,
  36588. 0x0f88d4a,0x0d44638,0x019f670 },
  36589. { 0x05c02af,0x1dde911,0x06341ac,0x0c7f47d,0x13ebc16,0x07a4172,
  36590. 0x0add6e1,0x1bf4dbe,0x12bfc55,0x095a290,0x09cf6a4,0x1a80a25,
  36591. 0x0430bdb,0x1ea9f55,0x03d0f64,0x1faa758,0x1e40c27,0x07e1ac7,
  36592. 0x065092d,0x03077d2,0x00a32cb } },
  36593. /* 149 */
  36594. { { 0x1a6a746,0x186169f,0x12a38e6,0x043ab44,0x084a792,0x06f95af,
  36595. 0x02451e3,0x166e14b,0x130666c,0x144033e,0x1c741a2,0x013deda,
  36596. 0x04b09a7,0x0032e8c,0x001e8f8,0x12890a0,0x14bb8dc,0x0382357,
  36597. 0x19524eb,0x1462538,0x01fd2b6 },
  36598. { 0x05f2771,0x0eadef2,0x16574f5,0x15e865d,0x0542b08,0x19535dc,
  36599. 0x103efc8,0x1645d9a,0x1e8becc,0x1e5b0a1,0x1891fc3,0x02757f1,
  36600. 0x1bcecc5,0x06d181c,0x1755bde,0x141bf2a,0x01956c2,0x148abe3,
  36601. 0x00c7f8a,0x06b97e6,0x018ca6d } },
  36602. /* 150 */
  36603. { { 0x00c4923,0x0058ddf,0x01ef760,0x00d2052,0x046ae74,0x1de8638,
  36604. 0x0cdfe55,0x1704731,0x19655f8,0x1470d4e,0x1d0542a,0x0ff4a01,
  36605. 0x0ecd292,0x10173d7,0x1aa71b4,0x0d25d04,0x0b39f29,0x05a67ac,
  36606. 0x1d055df,0x070d197,0x011f309 },
  36607. { 0x13ed442,0x1af3d19,0x1deeb72,0x1f20dfd,0x0e5c8e2,0x0c79145,
  36608. 0x0048cf6,0x0b85b36,0x07ffe12,0x119796d,0x0c60d51,0x0e63744,
  36609. 0x1259487,0x0969628,0x12ab96c,0x1b38941,0x0589857,0x15f8073,
  36610. 0x13c803d,0x02010ca,0x0172c5d } },
  36611. /* 151 */
  36612. { { 0x1c283e0,0x0a02317,0x0039625,0x08fdc11,0x1763398,0x1e8b117,
  36613. 0x0d03adf,0x1dbf5e3,0x0f598c5,0x07a8a8f,0x0366efb,0x05eefc0,
  36614. 0x146b4d9,0x14621fe,0x10f8ece,0x1a3a4ea,0x12c6511,0x19cca70,
  36615. 0x1c16db4,0x08343b5,0x00c6dd8 },
  36616. { 0x1b991ad,0x10bf011,0x14508f6,0x06e3f74,0x0ab2b21,0x0e0c3cd,
  36617. 0x1b16837,0x1b9682f,0x15f63ac,0x19de456,0x09f5405,0x04203c5,
  36618. 0x082fcf5,0x1083680,0x0dcff41,0x0259ec6,0x1de7db0,0x18f4108,
  36619. 0x1d9517b,0x0ecdb2a,0x018ca07 } },
  36620. /* 152 */
  36621. { { 0x180dfaf,0x1a3dcd7,0x1fce390,0x1f388cc,0x080b631,0x0de11c5,
  36622. 0x16c99b7,0x140dfe3,0x1aa8718,0x0b0f1b2,0x070d7d8,0x19215e6,
  36623. 0x08e7f7a,0x1e34237,0x0e0c747,0x0eb6980,0x1106841,0x10f334e,
  36624. 0x0d2dcc6,0x13ac412,0x00c76da },
  36625. { 0x1e4e78b,0x1acbdd1,0x1e6a607,0x18aa133,0x0c14ded,0x0446309,
  36626. 0x0e6564c,0x0b17e6e,0x19b2074,0x02b4183,0x1da401f,0x188f444,
  36627. 0x13c4440,0x1bf36d7,0x17c8f23,0x122076d,0x0254292,0x1a7b316,
  36628. 0x0cede58,0x14db631,0x00f9f4e } },
  36629. /* 153 */
  36630. { { 0x0d36049,0x0f5c467,0x07e319a,0x03e8373,0x07a4ffe,0x1970844,
  36631. 0x1d58da9,0x114d216,0x065a0bb,0x1eeb546,0x10a5559,0x18b12dc,
  36632. 0x0d42cf8,0x0d55ffd,0x01ad7cc,0x04d48a5,0x0f28f6f,0x18fbefd,
  36633. 0x186b940,0x13c1581,0x0120c5d },
  36634. { 0x0c10da7,0x171ffd6,0x1b96bef,0x1328928,0x07e2d5f,0x01107fb,
  36635. 0x1fa18f1,0x05d1d82,0x0bd6f63,0x137ba0a,0x127bd3f,0x181f87f,
  36636. 0x104a9e3,0x01dfdc3,0x1fcf2e8,0x0685a4b,0x000bb03,0x10c7e9b,
  36637. 0x014334b,0x07cea60,0x01ac1e6 } },
  36638. /* 154 */
  36639. { { 0x13d6a02,0x1e83e47,0x0347760,0x18fde9a,0x11fc143,0x03d7b0b,
  36640. 0x12fc353,0x1e19532,0x0827c5c,0x0549f4c,0x05e20b2,0x18f656d,
  36641. 0x1a4a102,0x052af45,0x0f21f56,0x0c9e0c6,0x02fcc2d,0x00d7441,
  36642. 0x01b407f,0x136a7f3,0x01c12ce },
  36643. { 0x1dc1b79,0x11cfeca,0x05aa165,0x087e9cc,0x0728f75,0x117dcf9,
  36644. 0x0f133b7,0x13cdce0,0x0d50fae,0x017bb40,0x14c3b41,0x187785a,
  36645. 0x0c0546b,0x06eacc5,0x09001af,0x0922001,0x0c9e129,0x09f9943,
  36646. 0x1afe58a,0x1044ab6,0x0146777 } },
  36647. /* 155 */
  36648. { { 0x10c98fe,0x0a10f71,0x1c16be0,0x01f859a,0x1eb0feb,0x0fb5696,
  36649. 0x1329853,0x1d13658,0x09ba314,0x1c09a6f,0x12c5b74,0x1d709e0,
  36650. 0x08a443d,0x183fc65,0x155bb83,0x0722ff8,0x1bb3a4f,0x09e0e41,
  36651. 0x06b7350,0x0fba496,0x0199839 },
  36652. { 0x14781e6,0x0f0bf6f,0x0407280,0x128de3f,0x12d7c31,0x18486d1,
  36653. 0x0984ed4,0x00f444f,0x0a7c8c6,0x04ad8ee,0x1a5c249,0x17ddbb8,
  36654. 0x181cf2f,0x02b0404,0x0f60aed,0x069ae3a,0x1a30851,0x0e7e6ee,
  36655. 0x19e6310,0x02e36b2,0x00d23dd } },
  36656. /* 156 */
  36657. { { 0x0dd7e96,0x007c26a,0x10325e9,0x150813f,0x1114c8e,0x0889c9b,
  36658. 0x0a79aa7,0x1ad8ade,0x18fd8c6,0x1b03310,0x1a79f0e,0x150c004,
  36659. 0x1fad3ba,0x02c94ea,0x04f1ac0,0x06cb628,0x040222e,0x060d6bf,
  36660. 0x1e62abb,0x04c4348,0x01d36a8 },
  36661. { 0x1003c81,0x022e260,0x180abab,0x15e87b0,0x1ef9ef5,0x1bba34c,
  36662. 0x17d7983,0x0b06d4c,0x1bf5d28,0x18973d5,0x0b3bc7c,0x1903909,
  36663. 0x122f53e,0x0e9245a,0x18cb28a,0x0b8c0c7,0x1c581e6,0x1ff4d53,
  36664. 0x0a1065c,0x10d934a,0x0017e36 } },
  36665. /* 157 */
  36666. { { 0x090de99,0x17f32cf,0x0d8c2cb,0x195a0b5,0x1e4485b,0x0724495,
  36667. 0x1a94b85,0x10f8914,0x0226286,0x16c2a18,0x0f6d50a,0x1d2abd6,
  36668. 0x01261f0,0x0a2f2c2,0x1a0618f,0x0ae7291,0x00f8ed7,0x067f0e7,
  36669. 0x1612b79,0x1e3feaf,0x003fbd6 },
  36670. { 0x1bf968c,0x188eee8,0x11cb50d,0x1a91bf4,0x1558d7c,0x12d2b36,
  36671. 0x0488f90,0x08293e1,0x05c26d0,0x07c199c,0x105d0c3,0x03e2f85,
  36672. 0x19be7b8,0x08a1ece,0x0f70cf9,0x07f5dc7,0x03594fd,0x179c2d6,
  36673. 0x1f46046,0x039e853,0x0113755 } },
  36674. /* 158 */
  36675. { { 0x0193bb2,0x07aad90,0x01c924a,0x00e6217,0x16e579d,0x02e93b4,
  36676. 0x18c274d,0x114bdc0,0x0a87186,0x121f219,0x0e1a0e6,0x07c2220,
  36677. 0x0828c11,0x1199788,0x01bb3ce,0x1976905,0x0370385,0x199a455,
  36678. 0x1c5636b,0x1ff955d,0x00c6698 },
  36679. { 0x0908745,0x062a57b,0x0fee811,0x08d466a,0x06b336e,0x10f410d,
  36680. 0x0a14b55,0x0fed298,0x0363491,0x194bcb8,0x184c546,0x077303e,
  36681. 0x0f6e102,0x17a352f,0x05f70af,0x09efed0,0x0af8e11,0x1c9ef50,
  36682. 0x15cb16f,0x1e79abd,0x0136c3c } },
  36683. /* 159 */
  36684. { { 0x1080de4,0x1ccd5bd,0x0e5aee1,0x1bad3b0,0x1b8f781,0x17c7b19,
  36685. 0x0aaaa61,0x194ed68,0x0a54bc5,0x0ba601c,0x0beee57,0x0c0b538,
  36686. 0x1076fcb,0x000bc49,0x146d102,0x0de1b08,0x0389d28,0x1a07806,
  36687. 0x1150c98,0x11d2a41,0x014c303 },
  36688. { 0x177aad9,0x1e1c0b4,0x0f8f252,0x05ae10f,0x0dbfd08,0x0ff6845,
  36689. 0x008321d,0x1f80da1,0x0345656,0x0e7426a,0x1b753b8,0x11c01fa,
  36690. 0x0071c4d,0x152fd5a,0x0ce2c89,0x1d6de46,0x0c10bae,0x06a3bf5,
  36691. 0x1e0309b,0x161176b,0x0078e4d } },
  36692. /* 160 */
  36693. { { 0x078342a,0x0e89508,0x0190044,0x1cab342,0x0534725,0x09ffee8,
  36694. 0x075643f,0x03fd48b,0x106f0ac,0x1b4a54f,0x06f1a73,0x15b67c3,
  36695. 0x00f6d24,0x1ceee68,0x18e3d7a,0x1ba9c79,0x166b632,0x09c2007,
  36696. 0x0578715,0x11fbf7c,0x0085cab },
  36697. { 0x109422f,0x01fb5c6,0x10ec2a5,0x0c1f311,0x17d2975,0x19726c8,
  36698. 0x107e8bb,0x07eab48,0x135f7c1,0x1a1a91d,0x0b4ffd9,0x080fdb5,
  36699. 0x0d274d3,0x09a3921,0x10450d6,0x0c2bab2,0x1013bb8,0x08e5939,
  36700. 0x15de533,0x06e0097,0x007da04 } },
  36701. /* 161 */
  36702. { { 0x1712c44,0x1ccd316,0x15de092,0x114d2c4,0x148368f,0x0f11438,
  36703. 0x010cb59,0x1f11dad,0x06f5bc5,0x0014183,0x0d1e745,0x02429d8,
  36704. 0x10e6cf3,0x09936db,0x16dbd12,0x126d72d,0x098ca32,0x1e52d60,
  36705. 0x1fa886b,0x04918e5,0x004d69e },
  36706. { 0x11269fb,0x0484953,0x0d802aa,0x1030ca1,0x0f6bdba,0x1aaed91,
  36707. 0x10a8e7e,0x1a03b39,0x16311e9,0x1e7586f,0x10b0743,0x0f39215,
  36708. 0x0a6faeb,0x058f9b9,0x04ec88b,0x0832647,0x1dfbc8c,0x0315379,
  36709. 0x1fa399d,0x1461645,0x00019de } },
  36710. /* 162 */
  36711. { { 0x0b3118b,0x144d609,0x0959f7d,0x1ad96dd,0x106ee39,0x1e6cbc6,
  36712. 0x08b0861,0x10f9f98,0x18d537d,0x0c2db40,0x15b6cae,0x02a5d3e,
  36713. 0x1575845,0x0f04c60,0x00e61c5,0x059a41f,0x1c83b21,0x1df4b52,
  36714. 0x06b0711,0x140671b,0x01fb3dd },
  36715. { 0x1a0a9b8,0x1bff067,0x1dd7c1a,0x0fc45b9,0x1478bac,0x1443e44,
  36716. 0x178104d,0x179e702,0x0914c54,0x0c08eef,0x07a993b,0x02c01ea,
  36717. 0x17c8c24,0x064382b,0x045360d,0x17968c7,0x152a8ab,0x1769272,
  36718. 0x1913d4b,0x1d73d04,0x00019e5 } },
  36719. /* 163 */
  36720. { { 0x0d52313,0x0d02733,0x0af47d9,0x0a9a7ee,0x1d69454,0x1bd708f,
  36721. 0x176be9a,0x08e5781,0x0571ab2,0x10fbcec,0x0a35a24,0x12cd5cb,
  36722. 0x13d4c5f,0x1762e70,0x185dc5a,0x17a73fb,0x1a4b764,0x1b87376,
  36723. 0x04359e0,0x12810b3,0x01efffe },
  36724. { 0x08f92e8,0x10713ec,0x08f3cfe,0x1b38ee2,0x021ef0f,0x13a6dd5,
  36725. 0x05d3224,0x0c4c4b3,0x1b9ba27,0x067d252,0x0f2bdb5,0x13a48dd,
  36726. 0x1010c90,0x07c7143,0x05e8436,0x1dd4406,0x1e1453a,0x1d83b8e,
  36727. 0x031ac28,0x188f22d,0x00eadf0 } },
  36728. /* 164 */
  36729. { { 0x0854477,0x00f2426,0x11f046f,0x090c71c,0x0bec25b,0x0e2a6c9,
  36730. 0x180ae1a,0x1a487a9,0x0be1e7e,0x18c6f19,0x18312b8,0x1d60d68,
  36731. 0x1ef5471,0x1521357,0x0b9efce,0x05b8271,0x0ddd845,0x091d713,
  36732. 0x1e0b7a7,0x1f83aaa,0x01649d3 },
  36733. { 0x0de1979,0x0571885,0x1ca361f,0x1a76978,0x0847041,0x01e4df5,
  36734. 0x0f1015b,0x0ce7124,0x0d74ae4,0x17f0c15,0x1926b8d,0x0de9d97,
  36735. 0x1592bff,0x0e20fcf,0x0036e03,0x00e2acd,0x06fe463,0x19add60,
  36736. 0x1b41cc1,0x11698fa,0x00c06d6 } },
  36737. /* 165 */
  36738. { { 0x14dfcf2,0x115f3c2,0x0f436f8,0x1f4d5c7,0x0e21a7d,0x10f6237,
  36739. 0x0eb4694,0x099e8c6,0x041a948,0x14a293d,0x048fcfb,0x1736554,
  36740. 0x121145e,0x0571e54,0x0d2a0ab,0x1b24aac,0x0a0fc85,0x070bb56,
  36741. 0x0420b63,0x19eff83,0x0078504 },
  36742. { 0x199793c,0x073e21b,0x1ed75d3,0x116aa33,0x14ddd61,0x1fcc043,
  36743. 0x17e4e57,0x1cc59ed,0x1b8bf61,0x07522e8,0x13d53c0,0x0c27b9f,
  36744. 0x1026863,0x01801ad,0x108edd8,0x15396ce,0x1344028,0x14fde3a,
  36745. 0x14681df,0x059c6e0,0x00f47b5 } },
  36746. /* 166 */
  36747. { { 0x0bec962,0x1ec56cb,0x01ebafd,0x0c2fc02,0x11cc81f,0x07082c6,
  36748. 0x1142485,0x13ec988,0x142394c,0x014c621,0x18144db,0x0a5a34c,
  36749. 0x03d9100,0x086fc12,0x190dd52,0x1bd4986,0x01efe5c,0x09189df,
  36750. 0x09fedec,0x14c1efa,0x0076249 },
  36751. { 0x0f593a0,0x1ac1c0e,0x1679d25,0x1706c98,0x0c9ceef,0x0e4cc88,
  36752. 0x04ccf81,0x1c65eb4,0x1421808,0x0752f0f,0x1a3d3cc,0x149e9eb,
  36753. 0x0756fb3,0x1b6065a,0x0b9b8ba,0x198d459,0x1fd08bd,0x1b05983,
  36754. 0x1fe3045,0x0f20381,0x001aee1 } },
  36755. /* 167 */
  36756. { { 0x1aa9e14,0x019b5c4,0x003f012,0x03ecece,0x0663427,0x15b4c03,
  36757. 0x010ce41,0x0469b54,0x1ebb7ab,0x0123f70,0x06814cc,0x154fd6b,
  36758. 0x15969b4,0x00007a6,0x03be096,0x0d6b7af,0x0eb4602,0x072ed9c,
  36759. 0x15a15b1,0x087cbaf,0x003b06a },
  36760. { 0x12a0ee7,0x1741c76,0x004ea82,0x11e2dd1,0x04bbe52,0x13209b8,
  36761. 0x17d713a,0x0cf156d,0x006e298,0x1f4065b,0x07b4ad6,0x16e5e8b,
  36762. 0x1af19b1,0x0bb0a90,0x0733934,0x0de76f5,0x194aa51,0x09cd7fc,
  36763. 0x0d05a49,0x125d0d6,0x000797d } },
  36764. /* 168 */
  36765. { { 0x0f3a8ca,0x176f0ad,0x07b096b,0x054b86a,0x1392478,0x1f60401,
  36766. 0x08fefe4,0x16883cf,0x0e6f425,0x027c9e2,0x1d8026c,0x05d903c,
  36767. 0x06e4ec1,0x08c07fe,0x1cd9b51,0x1de74f2,0x1b50e0a,0x0e949e5,
  36768. 0x035c764,0x12d288d,0x0061a14 },
  36769. { 0x15a67a1,0x02a0e33,0x041bd4b,0x011ebfd,0x07d38d3,0x1f4c473,
  36770. 0x0f333da,0x10c54e1,0x0185898,0x101f65f,0x1c116eb,0x0c2ce0c,
  36771. 0x16ecd02,0x086546c,0x0b37664,0x0e6ba3f,0x08230c0,0x03d5085,
  36772. 0x0ca3c87,0x0fcaa86,0x00152a2 } },
  36773. /* 169 */
  36774. { { 0x0057e27,0x104f073,0x1368f75,0x0f8f48a,0x07e8b6a,0x196eadc,
  36775. 0x045147c,0x1c5feb3,0x0d0ef51,0x11cbd44,0x19d51ba,0x0d424aa,
  36776. 0x00c4986,0x19145a4,0x11722c4,0x132f5d4,0x077dd01,0x11edf07,
  36777. 0x14619f4,0x1d451f8,0x01f80e2 },
  36778. { 0x1d0820b,0x0a096b4,0x08618a5,0x0e3d4cb,0x0317312,0x031c068,
  36779. 0x00887ac,0x00d84f9,0x075fe97,0x1fea77e,0x074941f,0x14aeb4e,
  36780. 0x037b396,0x03e5baa,0x1200147,0x17dc6c3,0x0d7ad4d,0x0f03eda,
  36781. 0x0c64b51,0x0903e93,0x01431c7 } },
  36782. /* 170 */
  36783. { { 0x0e1cc4d,0x1968204,0x07b97aa,0x075a5b8,0x093758d,0x0e39c9f,
  36784. 0x1f7f972,0x10619d6,0x1d33796,0x186c354,0x1e1b5d4,0x0795c49,
  36785. 0x0bef528,0x1858dd8,0x1746993,0x09c7956,0x01f54db,0x0cb555e,
  36786. 0x0f00316,0x1b0f987,0x01443e3 },
  36787. { 0x160e7b0,0x141098e,0x0063942,0x16ba67a,0x1c9b629,0x0299c6f,
  36788. 0x1b90bf4,0x1d58a95,0x0e821c6,0x13c7960,0x10272c1,0x0ebe0d5,
  36789. 0x16e5c9d,0x0980c6f,0x0d5d44d,0x18ccf06,0x1ac0bf8,0x0c0e537,
  36790. 0x142b8b7,0x10041d3,0x00e17fc } },
  36791. /* 171 */
  36792. { { 0x1aaa5eb,0x0a3a08d,0x00da2b7,0x12f37b0,0x02cbb75,0x1ff6910,
  36793. 0x0310337,0x083b0d0,0x04e0911,0x011d478,0x122e1c7,0x03da40e,
  36794. 0x0965d14,0x12cf494,0x1a855d5,0x1b7fcb0,0x1cd5006,0x03e346b,
  36795. 0x095a69d,0x15a1be4,0x0148da0 },
  36796. { 0x19069d7,0x062edbf,0x069323f,0x0ab80a6,0x0487d24,0x116d9d1,
  36797. 0x12267a6,0x0418b56,0x0b4fe97,0x15fea9c,0x1cd7914,0x1949a4f,
  36798. 0x1373a04,0x1716d64,0x0ef1527,0x1cfc4f9,0x09dff3e,0x0014391,
  36799. 0x036a4d8,0x130f1a5,0x00d0317 } },
  36800. /* 172 */
  36801. { { 0x166c047,0x1f4dd9d,0x187626d,0x12c0547,0x02e6586,0x0dce001,
  36802. 0x08a5f23,0x14689f0,0x1d08a74,0x13b5651,0x0e63783,0x0e3bf9a,
  36803. 0x0afbf1a,0x0190733,0x0edbaaa,0x13f8a5f,0x0bc179c,0x0541687,
  36804. 0x19eacad,0x019ede9,0x000f4e0 },
  36805. { 0x090c439,0x0074d24,0x1ac9093,0x17786b4,0x17564a2,0x1ba4be9,
  36806. 0x11e7766,0x0852b48,0x1612de9,0x0ff9f86,0x1400ce8,0x0ff9cc1,
  36807. 0x1a35862,0x09120be,0x176a301,0x1070b02,0x0d4ef6b,0x1283082,
  36808. 0x05ba5aa,0x0e51a5e,0x0120800 } },
  36809. /* 173 */
  36810. { { 0x1039042,0x191b955,0x13b65db,0x193f410,0x10e6978,0x1f60a18,
  36811. 0x174bd62,0x187a07f,0x1fe2045,0x1006080,0x16a4a0c,0x1ef5614,
  36812. 0x18e6868,0x130fd7f,0x1257477,0x044ca4d,0x127b7b1,0x1d0f100,
  36813. 0x0a97b45,0x07baf18,0x00898e6 },
  36814. { 0x0bba4ee,0x099ed11,0x15d2ed9,0x0fe92d4,0x1eff639,0x19535c9,
  36815. 0x0a7dc53,0x07e8126,0x11dfdd7,0x041245e,0x1286c68,0x1e5cd37,
  36816. 0x0762f33,0x1d17019,0x05df992,0x1ee8334,0x19375dd,0x05e2874,
  36817. 0x095af47,0x152f3e9,0x0095b87 } },
  36818. /* 174 */
  36819. { { 0x1c1f177,0x19b54b3,0x0f27a0d,0x10c0026,0x1b6d350,0x164d2d8,
  36820. 0x0ee49ba,0x0392849,0x0c27ef3,0x14e00d3,0x0d21c1e,0x174a245,
  36821. 0x05ad93b,0x0e8d64c,0x0e538aa,0x02eb73d,0x006d53f,0x0288e01,
  36822. 0x040b645,0x1d64a4a,0x00b1d13 },
  36823. { 0x15a1171,0x1edf5b3,0x0ac73f9,0x182d81a,0x1228295,0x1e44655,
  36824. 0x16d6815,0x19f1b64,0x0d300e9,0x1f54f4b,0x154badc,0x06fe4d2,
  36825. 0x1fb0e00,0x0f07cc6,0x0740d72,0x0901fd5,0x1b8d290,0x0c30724,
  36826. 0x00dacc6,0x1d2a258,0x0037a35 } },
  36827. /* 175 */
  36828. { { 0x100df48,0x194f747,0x0c13159,0x0c23590,0x189ca7b,0x1d4091d,
  36829. 0x15fe62c,0x1d492f4,0x1c21ca3,0x0218d8c,0x0cf39f8,0x1bd7c57,
  36830. 0x1945a73,0x16e3bc0,0x01b30ae,0x07be25f,0x1e4e5eb,0x02ff802,
  36831. 0x149f73c,0x0bbaf5b,0x005ef95 },
  36832. { 0x0ee402f,0x117fd00,0x0d33830,0x1476617,0x1b335e2,0x1e5880a,
  36833. 0x1474190,0x110a84a,0x13cd196,0x10c1fa2,0x1952d31,0x1e45e17,
  36834. 0x04c6664,0x061066f,0x1d33fb9,0x188eb4b,0x12f80a4,0x0ee554b,
  36835. 0x04447b6,0x15e400b,0x019cde4 } },
  36836. /* 176 */
  36837. { { 0x171f428,0x085e46b,0x0e0a7a7,0x13c8794,0x1ac1ecd,0x09d6781,
  36838. 0x19203ae,0x07f1abd,0x1065a2a,0x11197c0,0x0e29cc5,0x1f545e1,
  36839. 0x021fc04,0x012a3a5,0x037df9c,0x0bede95,0x1f23bb1,0x128d627,
  36840. 0x0254394,0x0436e7c,0x006b66e },
  36841. { 0x1a41dee,0x0c24033,0x0cfd672,0x1cf67c5,0x0cfa95a,0x0a2a709,
  36842. 0x00e1a24,0x148a9b3,0x1eefca6,0x06eedef,0x072dd7c,0x164823d,
  36843. 0x035f691,0x1f79046,0x0e79d9b,0x079ed53,0x00018b3,0x0f46f88,
  36844. 0x0705d2a,0x0ab593a,0x01c4b8a } },
  36845. /* 177 */
  36846. { { 0x04cccb8,0x1ac312e,0x0fbea67,0x125de9a,0x10bf520,0x17e43c3,
  36847. 0x195da27,0x0dc51e9,0x0da1420,0x11b37cb,0x0841f68,0x1400f8a,
  36848. 0x1090331,0x0a50787,0x03533ab,0x08f608f,0x0e2472a,0x0d944cf,
  36849. 0x1081d52,0x0ca69cc,0x0110ae9 },
  36850. { 0x0ed05b0,0x0eb2ae6,0x150cb30,0x1202eb2,0x0bac3f0,0x0bbe6bd,
  36851. 0x1c29239,0x0db75d6,0x140e98d,0x0580449,0x1493c61,0x0ca6c07,
  36852. 0x1d26983,0x12b90b9,0x051620c,0x083bcdc,0x1266111,0x00e9a45,
  36853. 0x1e89fcd,0x04afb9d,0x006be52 } },
  36854. /* 178 */
  36855. { { 0x147e655,0x1c799e4,0x1e56499,0x1411246,0x1f0fb76,0x011ce8f,
  36856. 0x19d15e4,0x19d65bf,0x03cdbb7,0x1043a49,0x1b5073a,0x1b720be,
  36857. 0x0821326,0x1cee2ac,0x06ba6b9,0x02e04b6,0x00ce9c3,0x070a29a,
  36858. 0x0b0e2a7,0x0058534,0x00c3075 },
  36859. { 0x156ace2,0x12788e0,0x14a4304,0x0ef3fe4,0x0c170fe,0x08b8d91,
  36860. 0x06a05b8,0x12ec1bf,0x155de27,0x0cde541,0x131e768,0x0fd4f8d,
  36861. 0x101ad92,0x0eb0fbb,0x1640448,0x00d7650,0x026261c,0x1ff4064,
  36862. 0x08990ae,0x01a6715,0x015e405 } },
  36863. /* 179 */
  36864. { { 0x0ad87bc,0x0bc14f5,0x12f724e,0x0f03d09,0x00ac936,0x0f27ef7,
  36865. 0x10935ab,0x0ad6af3,0x1690d7f,0x05cd5d2,0x1ec2e54,0x13a7a29,
  36866. 0x16f09b2,0x12d073d,0x1a13c8c,0x09fe7a0,0x1d3606f,0x1828a74,
  36867. 0x02b5cce,0x17ba4dd,0x0077e63 },
  36868. { 0x0d25c6d,0x0837670,0x173c2bf,0x1401745,0x1d90021,0x0dd9cc6,
  36869. 0x15dc231,0x1f83604,0x0198ff8,0x1bf836c,0x0b35a01,0x1fe36fc,
  36870. 0x1287d50,0x131d1ab,0x1d7815c,0x0b535de,0x092fa92,0x0df92bc,
  36871. 0x0e743a5,0x1a7be0e,0x0111847 } },
  36872. /* 180 */
  36873. { { 0x0c82924,0x1ce63ff,0x15a54aa,0x134e441,0x1c76dd6,0x1778710,
  36874. 0x09f7a81,0x0094c6a,0x0271839,0x19f28e1,0x001f22a,0x0bd4e2d,
  36875. 0x06f4db3,0x1a47892,0x0fb7829,0x0c12b1e,0x0444115,0x178a49b,
  36876. 0x1d2ce37,0x0b07a30,0x00f75f6 },
  36877. { 0x1927eb7,0x0c4f085,0x049e8e4,0x1385c5e,0x087c635,0x14b37a5,
  36878. 0x108cdff,0x10a16e5,0x0105e55,0x015c1c1,0x10e7e44,0x000dcb1,
  36879. 0x0963fee,0x0c8da99,0x014bb8e,0x1f2f67e,0x14ccbaf,0x03fadc2,
  36880. 0x1e01418,0x1cbed8b,0x016a935 } },
  36881. /* 181 */
  36882. { { 0x1d88d38,0x101aaef,0x1d03c66,0x078a93b,0x155cd8e,0x080370a,
  36883. 0x0a78c13,0x1cc644e,0x0fd0b0c,0x0b5b836,0x0ab4c7c,0x18126be,
  36884. 0x1ff156d,0x1bd1efc,0x031484f,0x0bf6b66,0x092a55e,0x14f94e6,
  36885. 0x0e16368,0x19fba85,0x0144a0e },
  36886. { 0x0658a92,0x08aefa9,0x185ad70,0x0f88502,0x1ce3ed1,0x0c9548d,
  36887. 0x17dc1ff,0x12d4ab2,0x19cd5d8,0x11e45fe,0x11cac59,0x087eb52,
  36888. 0x1d07763,0x1819f0d,0x19132a2,0x005f629,0x1861e5c,0x113d0e4,
  36889. 0x113fecc,0x01e5899,0x01b5ece } },
  36890. /* 182 */
  36891. { { 0x1211943,0x13dd598,0x09705c4,0x0cad086,0x04a8cac,0x0afe1f2,
  36892. 0x02e2361,0x14ba5fc,0x0ce91ee,0x1d5d586,0x11f4491,0x1b88f1d,
  36893. 0x1a5d23d,0x066cff7,0x061b79c,0x0aecd47,0x0678265,0x11963dc,
  36894. 0x1abb1fe,0x080317d,0x00873e5 },
  36895. { 0x18d17c1,0x1437959,0x103725b,0x18e3f40,0x1cbfbd0,0x024ce5c,
  36896. 0x0ade7e2,0x017c223,0x0f71ec8,0x0a3e2e7,0x025a487,0x17828d9,
  36897. 0x11acaa3,0x1e98b19,0x0487038,0x0ecb6bf,0x01ee768,0x018fd04,
  36898. 0x07bfc9c,0x15fabe8,0x00fed5d } },
  36899. /* 183 */
  36900. { { 0x0da1348,0x085cea6,0x04ea2bc,0x044b860,0x10769fd,0x0be115d,
  36901. 0x096c625,0x1888a15,0x1f5acf1,0x057eb63,0x1e00a57,0x02813fd,
  36902. 0x1dcf71a,0x17044fa,0x080a7d7,0x05751c2,0x0fb0fbd,0x04ba954,
  36903. 0x1dc32d6,0x044ebed,0x009061e },
  36904. { 0x1bda16a,0x125628f,0x0a8adc2,0x13e3bf4,0x19910e7,0x0a2fb7b,
  36905. 0x184cb66,0x1df7459,0x0eb4ba4,0x086acd7,0x0b54f51,0x136697e,
  36906. 0x086a8e0,0x131063d,0x0040813,0x18de8ec,0x03d0a53,0x131fc4a,
  36907. 0x1fabd5a,0x123a330,0x013214c } },
  36908. /* 184 */
  36909. { { 0x10d66c3,0x1d89024,0x0813953,0x1141b90,0x0aed732,0x1a14a6f,
  36910. 0x130e012,0x0cf7402,0x131ddc4,0x197d155,0x0bb444f,0x0bd5068,
  36911. 0x0e70ff5,0x1181a70,0x0369cbc,0x1c78363,0x1bebd8a,0x156e186,
  36912. 0x1a51680,0x17bede7,0x009c179 },
  36913. { 0x084c26f,0x09477ba,0x0ec51b2,0x03de55b,0x006b7db,0x0c6ed39,
  36914. 0x1d520fd,0x16c110f,0x04bc7ed,0x0f27106,0x12bf73f,0x043b2eb,
  36915. 0x00484d1,0x035f761,0x0d659c2,0x1b6cf8b,0x088a6d6,0x05abcd5,
  36916. 0x0461d22,0x0db0fc8,0x001522c } },
  36917. /* 185 */
  36918. { { 0x071d4ae,0x083abe2,0x09d82a2,0x0a8743b,0x1ef4b1a,0x1380d0f,
  36919. 0x0c609aa,0x1277125,0x059c65f,0x1a6a729,0x077cd6f,0x1253af1,
  36920. 0x12923af,0x05bce1f,0x12d1b18,0x1e26079,0x0e7cf4c,0x04aac16,
  36921. 0x15fc3b1,0x0103684,0x011c7da },
  36922. { 0x0eef274,0x03572cd,0x020fe4b,0x1e286f8,0x06c5bf4,0x1e4357f,
  36923. 0x0c08f84,0x0c154e9,0x02a2253,0x10ed673,0x027e974,0x057044b,
  36924. 0x0fb3d57,0x0fd3a58,0x128e45b,0x123527a,0x0dcb128,0x0f3b66c,
  36925. 0x07d33ef,0x12347eb,0x019aa03 } },
  36926. /* 186 */
  36927. { { 0x03fc3f1,0x1d34f10,0x08a4152,0x16c420d,0x09168cc,0x0afd4f8,
  36928. 0x01502ab,0x0df6103,0x0bff7ed,0x05c7907,0x052bf7b,0x0c317df,
  36929. 0x1b2c80a,0x1855e8e,0x1763282,0x014f9c4,0x041028e,0x13af33d,
  36930. 0x1ba56e6,0x0cc5bba,0x01b2dd7 },
  36931. { 0x089d7ee,0x1f93cf9,0x01721f7,0x13dd444,0x0d755d5,0x056d632,
  36932. 0x1f55306,0x0335d61,0x17ec010,0x1462367,0x15c290e,0x1cfd691,
  36933. 0x186fc90,0x0859cf7,0x1714f04,0x0b4412c,0x1cc3854,0x122abbb,
  36934. 0x1f7408f,0x0861eea,0x016ea33 } },
  36935. /* 187 */
  36936. { { 0x1f53d2c,0x19ca487,0x06e7ea7,0x0d60069,0x0dc9159,0x0cbcb3c,
  36937. 0x1405356,0x115e214,0x1a8a6b7,0x0eb96d5,0x05ec413,0x0a8116a,
  36938. 0x00ef5de,0x1369cdf,0x0ae42f2,0x0fee028,0x1e9eda1,0x0657551,
  36939. 0x1acc446,0x0d13ac0,0x016da01 },
  36940. { 0x06afff7,0x052b1fa,0x17cfa9b,0x14694bc,0x1945c7b,0x0cc7ec1,
  36941. 0x19322aa,0x0bd83ff,0x0b63f53,0x15300a3,0x1427950,0x1111a3e,
  36942. 0x1b50816,0x0fc6686,0x04636aa,0x0cee5a3,0x0bb78a3,0x13282f3,
  36943. 0x131b719,0x0075033,0x01ef4ab } },
  36944. /* 188 */
  36945. { { 0x176d986,0x04e8a69,0x16c0182,0x0f45b86,0x10f4e07,0x1f96436,
  36946. 0x1c2694f,0x1903822,0x1123c3f,0x17a5d22,0x15bf0bf,0x0b4e36c,
  36947. 0x1b852cd,0x0ff7d45,0x1f1d224,0x016ef6a,0x03e4811,0x0c7829c,
  36948. 0x0b1684a,0x0ba75aa,0x004c4b5 },
  36949. { 0x1827633,0x067f9f9,0x1a59444,0x0bc015f,0x086784d,0x16997d0,
  36950. 0x1e208fa,0x10d9670,0x02b91cd,0x0e7a68b,0x0d8e28f,0x14b1cde,
  36951. 0x02078b6,0x145bfea,0x1e4844b,0x107ce66,0x04dee56,0x1b4b202,
  36952. 0x038a10c,0x08421e5,0x01223b8 } },
  36953. /* 189 */
  36954. { { 0x1ebeb27,0x054d4e1,0x03e1b0a,0x0a7deb2,0x17bcdcb,0x173f9be,
  36955. 0x0b84536,0x193d114,0x0726ea7,0x19a9172,0x104e200,0x070d182,
  36956. 0x1599d50,0x10b10ab,0x0c6bb29,0x0c9b0b3,0x1ebfcc5,0x138cfe7,
  36957. 0x0bae38d,0x0ef5e23,0x00433a5 },
  36958. { 0x1eba922,0x1367037,0x1a4f0fc,0x1c8eb4a,0x1f6c83e,0x1f9bc72,
  36959. 0x19d00a2,0x1e2fef2,0x0bdc3f6,0x152f1b4,0x1642bb4,0x14154dd,
  36960. 0x153d034,0x0523e5e,0x070e931,0x0579076,0x06e4dce,0x1d27855,
  36961. 0x132803a,0x0f5e86e,0x01c097c } },
  36962. /* 190 */
  36963. { { 0x1c28de7,0x1b8bc3c,0x0c3000d,0x1557386,0x017aa2a,0x1e30f5b,
  36964. 0x060999a,0x0088610,0x14d78b5,0x05adae7,0x03f1cb8,0x0a5b30e,
  36965. 0x05d76a7,0x0a05bde,0x11a27d7,0x1a07476,0x06787f2,0x0d4bfec,
  36966. 0x158182a,0x0f6bddf,0x01c06ab },
  36967. { 0x1b71704,0x156d8ff,0x0ec7a67,0x16721fc,0x036e58b,0x078cd52,
  36968. 0x0e0b2ad,0x1b9dd95,0x0e0f3d9,0x12496fd,0x02b44b6,0x097adc4,
  36969. 0x022a0f5,0x1edde93,0x027e83d,0x1d6a95f,0x01ae8d2,0x06e6285,
  36970. 0x1df41d6,0x13f02dd,0x00b7979 } },
  36971. /* 191 */
  36972. { { 0x04f98cc,0x0323108,0x1aba7b1,0x04e55db,0x0511592,0x110c37a,
  36973. 0x0f741f9,0x16cf5d2,0x08d6d69,0x0be7013,0x0ea3cf4,0x0c11fa8,
  36974. 0x17b5347,0x1e055bc,0x1fc704d,0x1323bd0,0x1a8139f,0x11dfacb,
  36975. 0x151f835,0x0750b7c,0x008de29 },
  36976. { 0x0f668b1,0x156e9c7,0x1d90260,0x1ac2392,0x054e6b2,0x0ea131e,
  36977. 0x1ac4870,0x0e679ce,0x0eff64e,0x09a5947,0x0584a8c,0x135850e,
  36978. 0x14af71a,0x1d049ac,0x1222bca,0x011d063,0x112ba91,0x105b248,
  36979. 0x13d0df6,0x178b8ab,0x01138fe } },
  36980. /* 192 */
  36981. { { 0x0a2daa2,0x052c4e2,0x0231fa7,0x18801ec,0x18ea703,0x0ba8818,
  36982. 0x1416354,0x052df19,0x04abb6f,0x1249a39,0x05aad09,0x07c3285,
  36983. 0x1d0be55,0x1628b2b,0x1e4e63e,0x01d5135,0x0ec4f88,0x0f1196f,
  36984. 0x1ec786c,0x02ec3cc,0x01372f8 },
  36985. { 0x020f662,0x0a5e39d,0x1409440,0x1893db2,0x1fb7e77,0x15cb290,
  36986. 0x025bed8,0x0fd13ea,0x1a2e8d3,0x132ce33,0x105c38e,0x144cb00,
  36987. 0x140f2b2,0x0f6a851,0x1d3f39a,0x1801e2c,0x17efdc3,0x1d55229,
  36988. 0x13a6764,0x077fb49,0x0198f3c } },
  36989. /* 193 */
  36990. { { 0x1614189,0x0fae6c0,0x07deeac,0x0a4964b,0x07d56c4,0x1da0af6,
  36991. 0x092c917,0x1f38f75,0x07af6be,0x015e46e,0x123a08c,0x01c0e96,
  36992. 0x1f91b77,0x0db68d8,0x04cdb82,0x0192e94,0x157e668,0x0942e09,
  36993. 0x1f32d89,0x1970278,0x012d59b },
  36994. { 0x0019927,0x0c1da3e,0x156f76b,0x0ec61bf,0x010f266,0x102e91f,
  36995. 0x1b168c7,0x0c02bb7,0x0456ac4,0x15372fd,0x12b208a,0x0a52487,
  36996. 0x0946956,0x06e464f,0x07271fd,0x080cb8d,0x009e24a,0x1d6d93f,
  36997. 0x1904c06,0x0f469d5,0x01ccdfa } },
  36998. /* 194 */
  36999. { { 0x1cb1a7d,0x14326ac,0x03b85da,0x06d5df7,0x0d864ca,0x11586c2,
  37000. 0x0eb2c70,0x03a1dd0,0x1d980df,0x1405375,0x133b65f,0x1988ff2,
  37001. 0x15f582a,0x1d39608,0x073448c,0x0f76f45,0x0a8c710,0x0670951,
  37002. 0x1b6028c,0x1394ac9,0x0150022 },
  37003. { 0x11c180b,0x05d6a97,0x08425dd,0x11ae935,0x108be99,0x0de8dd6,
  37004. 0x122ad5b,0x1352f18,0x00afbea,0x169f1f2,0x1717f1b,0x12f62a7,
  37005. 0x108a8be,0x0df49f6,0x11fc256,0x0477b5b,0x1082cee,0x1469214,
  37006. 0x109ca77,0x0a478db,0x0016417 } },
  37007. /* 195 */
  37008. { { 0x014a31e,0x16678b6,0x10b5d3b,0x0965bc7,0x088e253,0x1621e1a,
  37009. 0x0d665f3,0x06df376,0x1916ac9,0x10822ce,0x1910010,0x18053ef,
  37010. 0x0371d15,0x022a9ac,0x071f049,0x148cf19,0x08dec94,0x0e64baa,
  37011. 0x059eeb6,0x0cf0306,0x014e4ca },
  37012. { 0x10312bf,0x1782ac6,0x19980ce,0x0aa82c3,0x1d1bf4f,0x00bc0ed,
  37013. 0x1169fe9,0x1aa4b32,0x000eef1,0x1a4a6d4,0x0ee340c,0x1d80f38,
  37014. 0x096c505,0x0e4fb73,0x0b86b78,0x01554e1,0x0c17683,0x0014478,
  37015. 0x18a8183,0x19fc774,0x000c7f4 } },
  37016. /* 196 */
  37017. { { 0x17d6006,0x1a23e82,0x02c0362,0x0dfae39,0x18b976e,0x07a07a9,
  37018. 0x180a6af,0x106bcef,0x0f103a7,0x1df71c3,0x1cb12c4,0x1840bc8,
  37019. 0x1420a6a,0x18fe58c,0x0c117d8,0x17e9287,0x19fc00a,0x0f2ee0e,
  37020. 0x1555ade,0x0178e14,0x01b528c },
  37021. { 0x08640b8,0x083f745,0x004aea7,0x07a1c68,0x0561102,0x1257449,
  37022. 0x1956ef8,0x19b8f9c,0x0fa579d,0x1ac7292,0x0eff978,0x0e2a6ef,
  37023. 0x0457ce2,0x1e04a3f,0x19471b0,0x0f04cc8,0x150f4a9,0x12fdec6,
  37024. 0x0b87056,0x1ba51fc,0x008d6fc } },
  37025. /* 197 */
  37026. { { 0x07202c8,0x0517b2e,0x0362d59,0x04b4a96,0x1d63405,0x1a7dfab,
  37027. 0x159c850,0x1470829,0x01d9830,0x08a10af,0x03ef860,0x11aabde,
  37028. 0x1fc7a75,0x137abfc,0x01773e3,0x0d3a6ae,0x056d922,0x1aeea4d,
  37029. 0x16d27e5,0x02baf57,0x00f18f0 },
  37030. { 0x0799ce6,0x188885a,0x1f6c1c4,0x1259796,0x15bbfb9,0x1d10f11,
  37031. 0x0327fde,0x1fd83e0,0x1b18f49,0x04eb489,0x1e566c0,0x12a3579,
  37032. 0x0e8da61,0x06a10a3,0x1a1c84c,0x047e21c,0x017ae5f,0x1aac194,
  37033. 0x0b9ce1a,0x0b76d13,0x0143c9b } },
  37034. /* 198 */
  37035. { { 0x0c74424,0x1946da4,0x0bad08c,0x03a3396,0x12616e1,0x0b710b9,
  37036. 0x064a903,0x0a5ca68,0x00cbdc7,0x0c1d4a6,0x0eec077,0x00a1ae6,
  37037. 0x005c623,0x0dbd229,0x0358c69,0x023919a,0x0259a40,0x0e66e05,
  37038. 0x11b9f35,0x022598c,0x01e622f },
  37039. { 0x01e4c4b,0x1714d1f,0x12291f5,0x113f62a,0x15f8253,0x09f18ce,
  37040. 0x016d53f,0x0ccfc6e,0x00a08b9,0x02672cd,0x0fa36e3,0x13cfb19,
  37041. 0x15bca74,0x17761eb,0x1125baa,0x0627b98,0x03a8a1a,0x00bee39,
  37042. 0x13ae4d8,0x1feef51,0x01a5250 } },
  37043. /* 199 */
  37044. { { 0x029bd79,0x103937f,0x0cd2956,0x009f321,0x0574a81,0x0ab4c1b,
  37045. 0x051b6ab,0x1ded20d,0x150d41f,0x12c055c,0x1dfd143,0x0a28dcd,
  37046. 0x0abc75b,0x1879b8c,0x03325ef,0x0810ea1,0x0a4a563,0x028dd16,
  37047. 0x1936244,0x0720efc,0x017275c },
  37048. { 0x17ca6bd,0x06657fb,0x17d7cdf,0x037b631,0x00a0df4,0x0f00fbf,
  37049. 0x13fe006,0x0573e8d,0x0aa65d7,0x1279ea2,0x198fa6f,0x1158dc6,
  37050. 0x0d7822d,0x1f7cedb,0x0dfe488,0x15354be,0x19dabe4,0x13f8569,
  37051. 0x1a7322e,0x0af8e1e,0x0098a0a } },
  37052. /* 200 */
  37053. { { 0x0fd5286,0x0867a00,0x00f3671,0x0ae5496,0x1ea5b9d,0x0d739f0,
  37054. 0x03e7814,0x049ebcc,0x0951b38,0x14da8a1,0x13599ff,0x05a13f6,
  37055. 0x16b034b,0x16e2842,0x14dea03,0x0045c96,0x0128cb0,0x134f708,
  37056. 0x09522bb,0x173cb8d,0x00ed7c8 },
  37057. { 0x133619b,0x003de6c,0x1865d18,0x1c573bf,0x0ce7668,0x1715170,
  37058. 0x1574f31,0x05f53dd,0x17eebf3,0x0d0a7af,0x113d90d,0x131acf9,
  37059. 0x0c75cb8,0x1c2860b,0x08617f1,0x1392d96,0x07645f7,0x004c3a5,
  37060. 0x1f6d1d1,0x11f15c4,0x0139746 } },
  37061. /* 201 */
  37062. { { 0x08684f6,0x13456e4,0x16ff177,0x16c334f,0x1c1edaa,0x1d0c7ab,
  37063. 0x05cd6c9,0x1d64b1a,0x18ecd89,0x13f3db2,0x07dfaac,0x138db0f,
  37064. 0x1b3d888,0x13eadf7,0x1f725b5,0x1ae7951,0x0ae37ba,0x1e426c3,
  37065. 0x1a395b5,0x1232ed9,0x01a4c7e },
  37066. { 0x119ffa6,0x0d2a031,0x0131400,0x18269d8,0x0cae64e,0x0092160,
  37067. 0x0a5b355,0x1dc3ed3,0x0bf2cae,0x0d12cf7,0x1ba0167,0x0f18517,
  37068. 0x0488e79,0x1c74487,0x1212fae,0x0ffb3d2,0x0d0fb22,0x0072923,
  37069. 0x09758c6,0x054a94c,0x01b78be } },
  37070. /* 202 */
  37071. { { 0x072f13a,0x1aaa57a,0x0472888,0x0eae67d,0x1ac993b,0x00b4517,
  37072. 0x1a7c25b,0x06a4d5f,0x14b1275,0x07f3b0e,0x01c329f,0x10e7cee,
  37073. 0x1684301,0x03f3e6f,0x0daaab7,0x05da8cd,0x1eaa156,0x06d16ea,
  37074. 0x07ebe36,0x145c007,0x0016a81 },
  37075. { 0x03de3bf,0x03ace27,0x022aa20,0x02a5e61,0x0c1e2e1,0x1f5d2d8,
  37076. 0x1b66aa9,0x195965b,0x19f9c11,0x032eaa9,0x1170653,0x1b0f61b,
  37077. 0x010ab9b,0x051fa5b,0x0be325b,0x0bf3fa6,0x1cc28cb,0x1a4c217,
  37078. 0x0438877,0x1c4f997,0x00f431a } },
  37079. /* 203 */
  37080. { { 0x00ccd0a,0x10506b5,0x1554eca,0x04b3276,0x03eeec8,0x1339535,
  37081. 0x01bf677,0x19f6269,0x00da05d,0x0ce28a4,0x061d363,0x089ace7,
  37082. 0x09c4aa4,0x114d1ae,0x13cd6cb,0x0fd5bb3,0x15f8917,0x0eb5ecd,
  37083. 0x0811c28,0x01eb3a5,0x01d69af },
  37084. { 0x07535fd,0x02263dd,0x1ce6cbe,0x1b5085f,0x05bd4c3,0x08cba5a,
  37085. 0x127b7a5,0x1d8bfc2,0x1fd4453,0x0c174cb,0x0df039a,0x00bbcd8,
  37086. 0x0aa63f7,0x0961f7b,0x0c3daa7,0x151ac13,0x1861776,0x05f6e9a,
  37087. 0x17846de,0x1148d5d,0x0176404 } },
  37088. /* 204 */
  37089. { { 0x1a251d1,0x03772a8,0x17f691f,0x041a4f3,0x1ef4bf1,0x08c5145,
  37090. 0x14e33b1,0x0dc985a,0x13880be,0x195bc43,0x06c82c6,0x1f1c37d,
  37091. 0x1ec69cc,0x1bcb50c,0x077fab8,0x17bd5c8,0x1c9fb50,0x012b3b7,
  37092. 0x0f86030,0x02b40a0,0x016a8b8 },
  37093. { 0x1f5ef65,0x042fb29,0x0414b28,0x12ef64a,0x01dfbbf,0x1a37f33,
  37094. 0x01f8e8c,0x1df11d5,0x01b95f7,0x0eefef7,0x17abb09,0x1cd2b6c,
  37095. 0x1b22074,0x0617011,0x01a6855,0x0776a23,0x17742e8,0x0c300da,
  37096. 0x0a1df9f,0x08ca59f,0x0015146 } },
  37097. /* 205 */
  37098. { { 0x1fa58f1,0x029e42b,0x19c0942,0x1099498,0x158a4e6,0x00fa06d,
  37099. 0x1b4286e,0x17a0f72,0x0558e8c,0x0328f08,0x0e233e9,0x08dc85c,
  37100. 0x081a640,0x0221b04,0x0c354e5,0x11fa0a3,0x1b3e26b,0x1615f9a,
  37101. 0x1c0b3f3,0x0f0e12a,0x00fd4ae },
  37102. { 0x153d498,0x0de14ef,0x1890f1e,0x1c226fe,0x0cf31c4,0x11e76fa,
  37103. 0x015b05e,0x0bb276d,0x06cd911,0x030898e,0x03376c9,0x08a7245,
  37104. 0x11ab30a,0x069015f,0x1dd5eda,0x10c25d2,0x07ce610,0x053336f,
  37105. 0x1d809ad,0x01fcca9,0x0051c20 } },
  37106. /* 206 */
  37107. { { 0x1a2b4b5,0x1081e58,0x05a3aa5,0x1d08781,0x18dccbf,0x17fdadc,
  37108. 0x01cb661,0x184d46e,0x0169d3a,0x1d03d79,0x0dc7c4b,0x1734ee2,
  37109. 0x0f8bb85,0x13e14cf,0x18434d3,0x05df9d5,0x069e237,0x09ea5ee,
  37110. 0x17615bc,0x1beebb1,0x0039378 },
  37111. { 0x07ff5d9,0x0817fef,0x0728c7a,0x0464b41,0x0e9a85d,0x0c97e68,
  37112. 0x04e9bd0,0x167ae37,0x115b076,0x0952b9b,0x047473d,0x150cdce,
  37113. 0x19d726a,0x1614940,0x186c77c,0x0bbcc16,0x15cc801,0x191272b,
  37114. 0x02de791,0x1127c23,0x01dc68e } },
  37115. /* 207 */
  37116. { { 0x1feda73,0x127fcb7,0x0062de4,0x0d41b44,0x0709f40,0x0ac26ff,
  37117. 0x083abe2,0x0806d1c,0x08355a0,0x04a8897,0x1df5f00,0x0a51fae,
  37118. 0x08259d4,0x15fc796,0x1125594,0x0623761,0x12844c5,0x0bfb18c,
  37119. 0x119b675,0x1a1c9f0,0x00d5698 },
  37120. { 0x15d204d,0x0b27d00,0x114f843,0x14dba21,0x1b626bf,0x14c64a3,
  37121. 0x0398e9d,0x0ac10ff,0x105337a,0x12d32a3,0x11e0bd4,0x0489beb,
  37122. 0x1f558e2,0x02afdd7,0x0a87906,0x0706091,0x18e47ee,0x1a47910,
  37123. 0x0e118f4,0x0472b22,0x004df25 } },
  37124. /* 208 */
  37125. { { 0x0695310,0x07eb4ec,0x03a9dbd,0x1efd0ed,0x028eb09,0x0a99547,
  37126. 0x0604b83,0x0f20738,0x0c572ac,0x0d33ba2,0x158a4f7,0x01c0f0b,
  37127. 0x121f980,0x1ed3b5d,0x1f8a968,0x0e42e57,0x190a2bc,0x13768ad,
  37128. 0x05e22a3,0x1cc37fa,0x004cd80 },
  37129. { 0x0730056,0x001b80b,0x150ee7d,0x1fb9da7,0x06f45fe,0x1283a12,
  37130. 0x1d8f06a,0x0e615fa,0x0ff92ae,0x0f2e329,0x0818fc8,0x061a376,
  37131. 0x006ef08,0x096912a,0x0c1bb30,0x0003830,0x13a1f15,0x0276ecd,
  37132. 0x0331509,0x164b718,0x01f4e4e } },
  37133. /* 209 */
  37134. { { 0x1db5c18,0x0d38a50,0x1d33b58,0x1cecee0,0x1454e61,0x1b42ef4,
  37135. 0x1ef95ef,0x1cbd2e1,0x1d2145b,0x10d8629,0x0697c88,0x1037dc9,
  37136. 0x03b9318,0x0a588e8,0x0e46be8,0x0426e01,0x0493ec2,0x1e3577f,
  37137. 0x098802b,0x0a9d28a,0x013c505 },
  37138. { 0x164c92e,0x022f3b9,0x03a350b,0x0ae6a43,0x0050026,0x09f9e2f,
  37139. 0x1680a13,0x0d7a503,0x0dbf764,0x097c212,0x1cc13cc,0x1e5490b,
  37140. 0x13e1a88,0x0893d28,0x0fd58c4,0x1c178b0,0x0c71a60,0x076bca8,
  37141. 0x0dedc29,0x0abc209,0x00c6928 } },
  37142. /* 210 */
  37143. { { 0x04614e7,0x10c2e32,0x1092341,0x1c8e934,0x0e906ca,0x03f2941,
  37144. 0x04ba896,0x19ab0a8,0x0d12857,0x1b1cc85,0x164ed4d,0x1ee174a,
  37145. 0x06770c7,0x0eae952,0x13db713,0x1437585,0x0563b69,0x12b26d2,
  37146. 0x01e2576,0x1efc283,0x01c8639 },
  37147. { 0x0589620,0x0b5817c,0x0150172,0x0683c88,0x0fe468a,0x15684e1,
  37148. 0x1684425,0x1dd7e45,0x09c652a,0x039e14c,0x186e3ef,0x1f16a8f,
  37149. 0x13cdef9,0x0bbedfb,0x1cde16a,0x0aa5ae0,0x1aa7e13,0x1854950,
  37150. 0x08e4f4f,0x0c22807,0x015b227 } },
  37151. /* 211 */
  37152. { { 0x1bfaf32,0x0d3d80f,0x1486269,0x017ccc3,0x1c5a62d,0x11da26a,
  37153. 0x03d7bd7,0x0c48f2e,0x1f43bbf,0x15000f6,0x0b9680f,0x050a4c1,
  37154. 0x0ca8e74,0x134be31,0x0267af4,0x0ec87d7,0x1e6751a,0x11b5001,
  37155. 0x081c969,0x0f18a37,0x00eaef1 },
  37156. { 0x1d51f28,0x1c74fcd,0x0112ab3,0x1750e24,0x19febbd,0x1e41b29,
  37157. 0x0b4e96f,0x11f0f01,0x110e6f0,0x0451a66,0x06ac390,0x1421048,
  37158. 0x018104c,0x0c53315,0x0f9c73a,0x091ad08,0x1142320,0x1cee742,
  37159. 0x13cf461,0x14477c3,0x01fa5cb } },
  37160. /* 212 */
  37161. { { 0x173a15c,0x064e914,0x07ccbfa,0x1ba852f,0x06fec8d,0x157d9f3,
  37162. 0x128e42d,0x044735e,0x0ab65ef,0x1d8f21b,0x17f36c2,0x003ccd8,
  37163. 0x0b8f262,0x0d7a438,0x1ffa28d,0x09c4879,0x06f2bb4,0x132d714,
  37164. 0x07745c8,0x1c5074a,0x0114da2 },
  37165. { 0x1e3d708,0x04d2b60,0x1e992a7,0x1e3961d,0x0fe62d3,0x143aa02,
  37166. 0x0a6125f,0x1f5e0e0,0x13cea46,0x1c5beb5,0x01898c4,0x069d071,
  37167. 0x0907806,0x18e1848,0x1a10a01,0x10c8e4f,0x1d7e583,0x1f857bc,
  37168. 0x08da899,0x10cb056,0x0104c1b } },
  37169. /* 213 */
  37170. { { 0x126c894,0x184f6d2,0x148ccbf,0x002958f,0x15abf12,0x0c949a4,
  37171. 0x13734f3,0x0ad6df2,0x092e6b5,0x1d57589,0x1b0c6ff,0x0dd4206,
  37172. 0x0e19379,0x183ff99,0x148df9d,0x0cf7153,0x10d829d,0x1eb2d2d,
  37173. 0x0ca4922,0x1b6aadb,0x01b348e },
  37174. { 0x0d46575,0x0fcd96f,0x0b3dbba,0x15ff4d3,0x096ca08,0x169be8a,
  37175. 0x0ce87c5,0x003ab5d,0x1789e5d,0x1283ed8,0x1f31152,0x1c53904,
  37176. 0x1705e2c,0x14b2733,0x0db9294,0x08de453,0x0ba4c0e,0x082b1d8,
  37177. 0x0f11921,0x1848909,0x00a3e75 } },
  37178. /* 214 */
  37179. { { 0x0f6615d,0x1a3b7e9,0x06a43f2,0x11b31b5,0x0b7f9b7,0x1ef883a,
  37180. 0x17c734a,0x063c5fb,0x09b956f,0x1ed1843,0x1bab7ca,0x05ef6b2,
  37181. 0x18f3cca,0x1aad929,0x1027e2c,0x08db723,0x0f3c6c8,0x12379fb,
  37182. 0x085190b,0x12731c5,0x01ff9bb },
  37183. { 0x17bd645,0x06a7ad0,0x1549446,0x17b7ada,0x17033ea,0x0684aba,
  37184. 0x01bf1cd,0x06a00fd,0x15f53c4,0x065032f,0x1f74666,0x137ffa4,
  37185. 0x0a9949d,0x14a968e,0x1138c11,0x02039bb,0x0fb81ac,0x1c2655a,
  37186. 0x095ac01,0x00f3f29,0x000346d } },
  37187. /* 215 */
  37188. { { 0x0bfdedd,0x1c727d3,0x1be657a,0x1cf4e98,0x193a285,0x04d1294,
  37189. 0x15344f4,0x0cf17ab,0x019a5f7,0x15085f3,0x0ecd03a,0x107c19d,
  37190. 0x03d3db0,0x0edfbd4,0x0ce9e2c,0x047c38c,0x03ec30f,0x093325e,
  37191. 0x1e820de,0x01f1e20,0x01c9663 },
  37192. { 0x0f86a80,0x065a5ef,0x06aeefd,0x107f04b,0x1fa4ec7,0x0a99640,
  37193. 0x1d81182,0x125497e,0x08b909e,0x0ddbd66,0x010581c,0x062e2f1,
  37194. 0x08ca1d7,0x050d5c9,0x1fc52fb,0x0ab4afe,0x16e5f84,0x0dff500,
  37195. 0x1c87a26,0x18ed737,0x002d7b8 } },
  37196. /* 216 */
  37197. { { 0x19f8e7d,0x102b1a5,0x02a11a1,0x0ec7f8b,0x001176b,0x176b451,
  37198. 0x169f8bf,0x121cf4b,0x0651831,0x033bb1f,0x1deb5b3,0x0205d26,
  37199. 0x017d7d0,0x1b81919,0x1f11c81,0x16a0b99,0x031534b,0x0ab9f70,
  37200. 0x1c689da,0x03df181,0x00f31bf },
  37201. { 0x0935667,0x1ae2586,0x0e2d8d7,0x120c1a5,0x14152c3,0x01d2ba3,
  37202. 0x0b0b8df,0x19bdff5,0x00b72e0,0x0afe626,0x18091ff,0x1373e9e,
  37203. 0x13b743f,0x1cf0b79,0x10b8d51,0x1df380b,0x0473074,0x1d111a6,
  37204. 0x056ab38,0x05e4f29,0x0124409 } },
  37205. /* 217 */
  37206. { { 0x10f9170,0x0bc28d9,0x16c56ff,0x126ff9c,0x115aa1e,0x021bdcb,
  37207. 0x157824a,0x0e79ffa,0x1c32f12,0x056692c,0x1878d22,0x19e4917,
  37208. 0x0b5a145,0x1d2de31,0x0d02181,0x0de8c74,0x1151815,0x1b14b75,
  37209. 0x1dd3870,0x1f5a324,0x01e7397 },
  37210. { 0x08225b5,0x1ccfa4e,0x1134d8b,0x128d6ef,0x13efce4,0x00f48d9,
  37211. 0x1d4c215,0x1268a3b,0x038f3d6,0x1e96c9a,0x1ed5382,0x05adce4,
  37212. 0x000b5de,0x1b116ca,0x164a709,0x1529685,0x12356f6,0x09b5673,
  37213. 0x132bc81,0x0319abf,0x004464a } },
  37214. /* 218 */
  37215. { { 0x1a95d63,0x10555d5,0x11b636f,0x02f6966,0x12780c6,0x06c0a14,
  37216. 0x1e18c38,0x098c861,0x0b56ef0,0x1adf015,0x18d8ce1,0x172af0b,
  37217. 0x04c28fe,0x009649f,0x1005e57,0x10547aa,0x1c1e36f,0x144ffa8,
  37218. 0x03babf5,0x11912a2,0x016b3c4 },
  37219. { 0x0f064be,0x03f5d6a,0x0a65e4a,0x0aa9d7b,0x1a77d55,0x1b93f50,
  37220. 0x17bc988,0x18c8ce8,0x189f366,0x088fac8,0x15baf6a,0x0b9b8b3,
  37221. 0x137e543,0x1a92690,0x0136ba9,0x1671a75,0x11c4395,0x0e3d8ee,
  37222. 0x0a08f12,0x07ce083,0x001cca1 } },
  37223. /* 219 */
  37224. { { 0x14d64b0,0x0c30643,0x18318e6,0x042ca79,0x1375b09,0x108cc31,
  37225. 0x00003aa,0x0ba2ce0,0x1621cd1,0x1633c84,0x1c37358,0x1bacefa,
  37226. 0x0dbe1d7,0x182dea6,0x1c3c9c0,0x11e61df,0x021362f,0x003b763,
  37227. 0x19116de,0x00902cf,0x01d8812 },
  37228. { 0x01f9758,0x04d070b,0x138a05d,0x1d4789f,0x060915f,0x0eec57f,
  37229. 0x1390644,0x013ea6f,0x079a51a,0x11b5456,0x173e3bf,0x0968594,
  37230. 0x1567fb5,0x12482bf,0x172b81f,0x096c837,0x0c5a424,0x1db8ff8,
  37231. 0x0d81960,0x0b4a6c9,0x0106481 } },
  37232. /* 220 */
  37233. { { 0x139cc39,0x14e1f77,0x1b45e31,0x09f4c6a,0x1830456,0x17dcc84,
  37234. 0x0d50904,0x14b7a78,0x179dbb2,0x0ea98e9,0x1d78f68,0x0311cfc,
  37235. 0x114865f,0x0580a3d,0x0b13888,0x135605b,0x1ca33d2,0x1facf28,
  37236. 0x1ec1d3b,0x09effc6,0x00f1c96 },
  37237. { 0x0301262,0x0605307,0x08b5c20,0x00a7214,0x1a45806,0x054814c,
  37238. 0x1fe6b32,0x185b4ce,0x114c0f1,0x1d7482b,0x1b67df7,0x1e2cdcc,
  37239. 0x043665f,0x03c2349,0x19b7631,0x060f990,0x18fc4cc,0x062d7f4,
  37240. 0x02fd439,0x0774c7c,0x003960e } },
  37241. /* 221 */
  37242. { { 0x19ecdb3,0x0289b4a,0x06f869e,0x0ff3d2b,0x089af61,0x106e441,
  37243. 0x0cae337,0x02aa28b,0x07c079e,0x1483858,0x089057f,0x09a6a1c,
  37244. 0x02f77f0,0x1ac6b6a,0x0adcdc8,0x0c53567,0x1b9ba7b,0x08a7ea0,
  37245. 0x1003f49,0x05b01ce,0x01937b3 },
  37246. { 0x147886f,0x006a6b8,0x072b976,0x02aed90,0x008ced6,0x138bddf,
  37247. 0x01a4990,0x043c29d,0x0abb4bd,0x0e6f8cc,0x00c22e7,0x0c8cca6,
  37248. 0x07658be,0x0cce8ce,0x1c64b6b,0x1624df7,0x1b3304a,0x0aad1e8,
  37249. 0x089378c,0x1e97cbf,0x000e943 } },
  37250. /* 222 */
  37251. { { 0x1e9ea48,0x1202c3f,0x121b150,0x0ac36ae,0x0f24f82,0x18cba05,
  37252. 0x104f1e1,0x09b3a58,0x170eb87,0x1d4df3c,0x0e8ea89,0x11c16c5,
  37253. 0x0c43fef,0x160df85,0x08fca18,0x061c214,0x0f34af1,0x1a8e13b,
  37254. 0x19573af,0x1a3d355,0x0185f6c },
  37255. { 0x0369093,0x17d3fa0,0x1828937,0x0cb0b03,0x11f1d9d,0x0976cf0,
  37256. 0x0fccf94,0x12d3201,0x1ed1208,0x1c5422c,0x0f0e66f,0x0abd16e,
  37257. 0x1e83245,0x07b7aa7,0x08c15a6,0x046aaa9,0x1a53c25,0x0954eb6,
  37258. 0x0824ecc,0x0df2085,0x016ae6a } },
  37259. /* 223 */
  37260. { { 0x12cdd35,0x091e48a,0x1bc6cb8,0x110c805,0x0e6e43a,0x072dead,
  37261. 0x1c37ee7,0x0291257,0x0758049,0x0565c25,0x0bbb0ad,0x0bffea0,
  37262. 0x0e8c7f5,0x1519f7a,0x029ee4e,0x0400339,0x157fd9d,0x1835881,
  37263. 0x0e8ef3a,0x033fe01,0x00273e3 },
  37264. { 0x1e360a3,0x017bbd5,0x129860b,0x095bfdf,0x17ef5c8,0x05b7e62,
  37265. 0x0329994,0x005349e,0x0aaf0b2,0x1a7c72b,0x1bc558f,0x1141449,
  37266. 0x135c850,0x0f522f8,0x1d8bf64,0x0db7db1,0x1a02803,0x1f96491,
  37267. 0x093440e,0x1949803,0x018a4a9 } },
  37268. /* 224 */
  37269. { { 0x048e339,0x1dbcc2a,0x05d8a8f,0x1e31473,0x1e8770c,0x148b866,
  37270. 0x15d35e9,0x15822c0,0x12b6067,0x1d82e2c,0x04e2ad2,0x1b61090,
  37271. 0x14de0d2,0x0484f3c,0x076ae49,0x02bee29,0x0b67903,0x041d19b,
  37272. 0x0cd6896,0x00e9b34,0x013ccd9 },
  37273. { 0x01b784d,0x0e2f056,0x0b87a0e,0x0ddca4f,0x0b65c8c,0x0447605,
  37274. 0x1851a87,0x0b1a790,0x046c1bf,0x100fbc8,0x0940a88,0x0c4e7fb,
  37275. 0x0571cec,0x112dc83,0x0fe23ac,0x1bf9bfe,0x098c556,0x0360f86,
  37276. 0x013e973,0x0445549,0x00acaa3 } },
  37277. /* 225 */
  37278. { { 0x1b4dfd6,0x1a5e1e4,0x0a4c5f9,0x07f1cec,0x05ba805,0x061a901,
  37279. 0x1701676,0x168060f,0x0b85a20,0x0481b66,0x1c4d647,0x1e14470,
  37280. 0x0ef2c63,0x054afda,0x0676763,0x18d8c35,0x1399850,0x01ebe27,
  37281. 0x00a659a,0x12d392d,0x0169162 },
  37282. { 0x163ee53,0x1e133e5,0x0d4df44,0x02ebd58,0x07b12e6,0x0d5fe53,
  37283. 0x0684464,0x13f666d,0x1ee1af6,0x168324e,0x10479d6,0x1e0023b,
  37284. 0x054d7a6,0x0dcfcbb,0x1c0c2e3,0x0266501,0x1a3f0ab,0x1510000,
  37285. 0x0763318,0x1931a47,0x0194e17 } },
  37286. /* 226 */
  37287. { { 0x18fe898,0x0c05a0e,0x14d1c83,0x0e64308,0x0d7a28b,0x190ba04,
  37288. 0x10e1413,0x15fe3e7,0x1166aa6,0x09c0e6a,0x1838d57,0x010998a,
  37289. 0x0d9cde6,0x0f30f16,0x0107c29,0x12a3596,0x0f5d9b4,0x031088b,
  37290. 0x1b8ab0b,0x1c2da6f,0x00c4509 },
  37291. { 0x06fd79e,0x1106216,0x0c3ae0a,0x1c75ef1,0x15b7ee4,0x0c0ce54,
  37292. 0x18f06eb,0x0d27b36,0x0985525,0x06b3a6f,0x06743c4,0x0965f38,
  37293. 0x0917de6,0x03e2f35,0x0feaebd,0x1b6df40,0x0ad2ce2,0x142c5e2,
  37294. 0x1f27463,0x0470143,0x00c976c } },
  37295. /* 227 */
  37296. { { 0x064f114,0x18f7c58,0x1d32445,0x0a9e5e1,0x03cb156,0x19315bc,
  37297. 0x161515e,0x0d860a4,0x10f3493,0x1463380,0x107fb51,0x05fd334,
  37298. 0x09ef26d,0x13fbfb5,0x168899e,0x1f837ed,0x0dba01b,0x012b1dc,
  37299. 0x0d03b50,0x06d90b8,0x000e14b },
  37300. { 0x1db67e6,0x1f13212,0x017d795,0x12fe5d2,0x05df4e8,0x1621344,
  37301. 0x1945009,0x126f065,0x03e8750,0x095f131,0x0e1a44c,0x17b078a,
  37302. 0x1d856b5,0x0ab9a7c,0x072b956,0x090c2b6,0x1e2d5aa,0x02d03df,
  37303. 0x1a2aed6,0x192de19,0x01d07a4 } },
  37304. /* 228 */
  37305. { { 0x03aa2e9,0x0a682a9,0x0181efd,0x19da7a1,0x08841e0,0x0dfdb4e,
  37306. 0x1db89fe,0x10aad07,0x0162bdf,0x0583fa2,0x0373277,0x10720f6,
  37307. 0x0e62d17,0x12bd29b,0x12ee2ad,0x0fa7945,0x0d27cf4,0x04c5cd0,
  37308. 0x1ba98dc,0x0a9ad0b,0x01f2ff1 },
  37309. { 0x0b232ac,0x1bb452b,0x0aad5a2,0x0c7e54a,0x0e8d6e3,0x1bfe302,
  37310. 0x1e85a20,0x12375d0,0x1d10a76,0x1e2c541,0x157efba,0x15e1f28,
  37311. 0x0ead5e4,0x1eb2a71,0x0835b0d,0x104aa34,0x0b9da7c,0x0c6207e,
  37312. 0x0366e4c,0x1679aec,0x00b26d7 } },
  37313. /* 229 */
  37314. { { 0x12eaf45,0x0861f5d,0x04bdec2,0x18c5ff7,0x0d24d91,0x1b791ef,
  37315. 0x0fa929c,0x1c77e54,0x16ff0fd,0x0dccf5e,0x040bd6d,0x0abb942,
  37316. 0x08bca2b,0x03f0195,0x080f360,0x02f51ec,0x048a8bf,0x0aa085a,
  37317. 0x077156c,0x0cc14fc,0x0109b86 },
  37318. { 0x0a2fbd8,0x058ed01,0x0296c52,0x167645d,0x1ed85e8,0x095a84f,
  37319. 0x083921c,0x02c26f1,0x0c6a3e5,0x02b00a4,0x0ed40da,0x04382c6,
  37320. 0x1171009,0x12a8938,0x049450c,0x0208f27,0x1d207d3,0x1bda498,
  37321. 0x150b82e,0x1ce4570,0x00ea623 } },
  37322. /* 230 */
  37323. { { 0x0972688,0x011e992,0x1d88212,0x04007ea,0x18b83c1,0x06a2942,
  37324. 0x19a41b4,0x0fc329a,0x02c6f74,0x010cac2,0x1b626a1,0x05d2028,
  37325. 0x02c8f8a,0x1a28dde,0x1b0779d,0x109f453,0x0b8f7f2,0x1fb115b,
  37326. 0x0dc7913,0x03b7d2f,0x006083f },
  37327. { 0x19dd56b,0x04999cc,0x17a6659,0x152f48f,0x0cfac0b,0x147d901,
  37328. 0x162baef,0x194ccc1,0x0f61d7b,0x1e14eec,0x1705351,0x0a3b0b5,
  37329. 0x1c6f5fb,0x07cfea0,0x16b1e21,0x07cd9cc,0x1d4ff51,0x10e734e,
  37330. 0x1f9674f,0x1cb23df,0x00231ac } },
  37331. /* 231 */
  37332. { { 0x1fda771,0x1d21c54,0x0038b99,0x190cc62,0x026f652,0x19f91db,
  37333. 0x0792384,0x03fbf63,0x0035d2d,0x0cfc479,0x0fa1e16,0x02251a2,
  37334. 0x071723a,0x1da8e70,0x02a8a4b,0x1750512,0x10ebbd9,0x072f9d3,
  37335. 0x1d1452d,0x104ce66,0x0155dde },
  37336. { 0x0f59a95,0x15bbf6b,0x108022c,0x0604040,0x13f853e,0x163bcbc,
  37337. 0x0ab07ae,0x0eca44a,0x1b56b66,0x166e5cc,0x0a9401b,0x13f32e4,
  37338. 0x104abdb,0x02715d6,0x0843cfc,0x1ba9a4c,0x0ff3034,0x08652d0,
  37339. 0x0b02e03,0x1b0101b,0x0041333 } },
  37340. /* 232 */
  37341. { { 0x1a85a06,0x083849a,0x0d13a14,0x0c85de3,0x0e166e7,0x1d9d36a,
  37342. 0x02dc681,0x0d50952,0x030329e,0x16eb600,0x1549675,0x14ca7aa,
  37343. 0x1e20c4b,0x17c5682,0x0ec9abd,0x1999bdc,0x1412ab4,0x01071ea,
  37344. 0x0501909,0x1312695,0x01bd797 },
  37345. { 0x00c7ff0,0x0e8c247,0x0d03ca8,0x192a876,0x1ae85ef,0x0e98c5d,
  37346. 0x0c6bbd4,0x14dd2c8,0x075878f,0x0e9f6a7,0x057d4b9,0x13b7851,
  37347. 0x1c4d2a2,0x0f88833,0x1c9e1dc,0x09dca75,0x1649e7f,0x13666f4,
  37348. 0x15b5d36,0x111b434,0x0192351 } },
  37349. /* 233 */
  37350. { { 0x1d310ed,0x1909001,0x0c46c20,0x1930f60,0x120ee8c,0x02ac546,
  37351. 0x0749a13,0x1913ca9,0x0b7167e,0x112f9e7,0x156ed57,0x09e897e,
  37352. 0x17acf11,0x030e480,0x07b71dc,0x0878103,0x0e6deb3,0x0bacd22,
  37353. 0x1326d7b,0x1f3efc0,0x007858d },
  37354. { 0x1f13222,0x03f5d9d,0x08453e9,0x1bd40fb,0x1e451dc,0x0c12178,
  37355. 0x1eb0f03,0x03c37d3,0x136eb87,0x192bea6,0x0c64364,0x0eb57d4,
  37356. 0x13f49e7,0x075f159,0x1b4647d,0x0012c80,0x13c0c11,0x033d562,
  37357. 0x0e06b1e,0x0b9f17a,0x01f4521 } },
  37358. /* 234 */
  37359. { { 0x0493b79,0x145477d,0x0ab0e1f,0x169d638,0x120e270,0x1911905,
  37360. 0x0fe827f,0x07b3e72,0x0a91c39,0x170dd57,0x0a36597,0x0c34271,
  37361. 0x04deda9,0x0bdea87,0x0ac8e32,0x191c0d3,0x08a2363,0x17fb46a,
  37362. 0x1931305,0x1c01cb9,0x0158af8 },
  37363. { 0x1c509a1,0x0e78367,0x01d5b33,0x1f84d98,0x00f411e,0x0e2bf83,
  37364. 0x17f5936,0x158da19,0x132e99c,0x0a8a429,0x1a5442a,0x167b171,
  37365. 0x1d58f9a,0x1886e1f,0x1a61c26,0x06a134f,0x03d75ef,0x1c1c842,
  37366. 0x0a4c4b1,0x1993a0b,0x01b628c } },
  37367. /* 235 */
  37368. { { 0x141463f,0x1a78071,0x1e80764,0x1c2a1b4,0x14c8a6c,0x04aa9f8,
  37369. 0x183f104,0x123b690,0x0a93f4a,0x11def2d,0x16019f0,0x0f0e59a,
  37370. 0x009f47c,0x0219ee4,0x0cc0152,0x054fa3a,0x1f975a3,0x08605f3,
  37371. 0x031d76a,0x0eefab1,0x012e08b },
  37372. { 0x1a10d37,0x0940bb0,0x16977f0,0x02b8a1e,0x0d7b618,0x03be307,
  37373. 0x0576de5,0x016515f,0x133c531,0x05515bb,0x06099e8,0x1570a62,
  37374. 0x1f905fa,0x15a0cac,0x03a6059,0x0ef09e8,0x05216b3,0x04e65a1,
  37375. 0x0619ab3,0x0baef8d,0x00c5683 } },
  37376. /* 236 */
  37377. { { 0x1450a66,0x18a6595,0x1053a75,0x18fb7fb,0x1318885,0x1350600,
  37378. 0x03616d1,0x14ccab5,0x15bdfc1,0x1510f4c,0x1e4b440,0x1931cce,
  37379. 0x177a0d7,0x1aa853c,0x006ed5e,0x1a66e54,0x0335d74,0x0a16231,
  37380. 0x036b525,0x09c3811,0x008b7be },
  37381. { 0x1812273,0x1d81fca,0x15fc61c,0x05dc7ee,0x0e26ed3,0x1310bd1,
  37382. 0x03ab9b6,0x09e58e2,0x0261d9f,0x1a85aba,0x0768b66,0x1f536f8,
  37383. 0x0743971,0x02542ef,0x113ee1f,0x026f645,0x051ec22,0x17b961a,
  37384. 0x1ee8649,0x0acd18e,0x0173134 } },
  37385. /* 237 */
  37386. { { 0x03ba183,0x1463d45,0x1e9cf8f,0x17fc713,0x0e8cebb,0x0dd307a,
  37387. 0x11a1c3e,0x1071d48,0x1cb601a,0x08bb71a,0x14b6d15,0x184c25c,
  37388. 0x11f90bd,0x07b895f,0x1e79166,0x0a99b2b,0x00fbea0,0x1cde990,
  37389. 0x157f502,0x0337edb,0x017a2cf },
  37390. { 0x0736feb,0x1b65133,0x18bdc73,0x13bcf9f,0x1de86f4,0x1482b1d,
  37391. 0x0f3a3f0,0x09f8c15,0x0726b6e,0x17451e7,0x048d6ea,0x088a7e5,
  37392. 0x1ed2382,0x1287fd2,0x0d55fd5,0x1ee8949,0x054113e,0x150a29f,
  37393. 0x1909b74,0x0ed4a67,0x01b07c6 } },
  37394. /* 238 */
  37395. { { 0x1d96872,0x101f91a,0x032bd79,0x187f4b7,0x0b1a23c,0x046e2fd,
  37396. 0x01c6fa6,0x17aa8b3,0x1d430c0,0x1974244,0x16730f8,0x13c0ec9,
  37397. 0x0d7ec26,0x1960620,0x08e084b,0x10769ee,0x183887b,0x096ca30,
  37398. 0x1c62904,0x1f4ce25,0x0010281 },
  37399. { 0x0858b37,0x00247b2,0x176600a,0x1e6afbc,0x00e149a,0x0f5d8c7,
  37400. 0x01e4586,0x1416443,0x19f2b0b,0x0810059,0x072eb88,0x15cc207,
  37401. 0x1d5a87e,0x1cabce8,0x1f7376c,0x0a2bc9d,0x0aa2788,0x10d9c47,
  37402. 0x0061e2a,0x0a58799,0x002c1a5 } },
  37403. /* 239 */
  37404. { { 0x0a723dc,0x1fa8007,0x08c5eb1,0x088562a,0x0a5f04f,0x042e430,
  37405. 0x05116fa,0x004c7a9,0x1ff1197,0x0fccc9f,0x1633a98,0x08b9898,
  37406. 0x16c3fba,0x1ce6b01,0x145479a,0x04777cd,0x11557b9,0x13ad1d5,
  37407. 0x1acbf51,0x00f8a59,0x01474ec },
  37408. { 0x188239d,0x11e9976,0x1a5311a,0x0d06b5c,0x0d1b8ae,0x1759738,
  37409. 0x18c967f,0x16be9fb,0x043bc0b,0x11dfb8e,0x0a9c148,0x016f1ec,
  37410. 0x053cd22,0x0ff3ccd,0x092183a,0x0ff2644,0x10324ab,0x1ec2ac3,
  37411. 0x1652562,0x1ee6616,0x010f8e0 } },
  37412. /* 240 */
  37413. { { 0x067d520,0x0e3dd9e,0x07b2bcd,0x1647f95,0x18f4958,0x1d54046,
  37414. 0x1c6522e,0x15c0ef1,0x02135e8,0x0c61867,0x03bfdd0,0x1353911,
  37415. 0x0bcdd8d,0x1b98a25,0x01d77c3,0x14a68e4,0x0954506,0x0daa4e4,
  37416. 0x1eedff1,0x0712f2b,0x011c4ef },
  37417. { 0x1f5e698,0x164d621,0x18e8ff8,0x19c714b,0x0e77fcb,0x04e170e,
  37418. 0x12438c2,0x002da0b,0x1ac1d58,0x13a79ff,0x0e74a96,0x0440703,
  37419. 0x0baeeda,0x1af9cb0,0x162c50f,0x1577db2,0x0510db7,0x032ffe8,
  37420. 0x0816dc6,0x0fcd00f,0x00ce8e9 } },
  37421. /* 241 */
  37422. { { 0x0e86a83,0x0f30dc6,0x0580894,0x1f7efce,0x0604159,0x1819bbc,
  37423. 0x1f75d23,0x085f824,0x1450522,0x1e5961b,0x1a826e1,0x01e9269,
  37424. 0x01bd495,0x0233ca2,0x11b100f,0x082d4a2,0x11023ba,0x0f456a3,
  37425. 0x1d8e3ac,0x1034c15,0x01b389b },
  37426. { 0x0150c69,0x0c9a774,0x12f39a6,0x11c4f82,0x14f7590,0x00ca7fb,
  37427. 0x0a245a8,0x0ecbb81,0x01bd51b,0x07a4e99,0x1e58c0e,0x00bc30e,
  37428. 0x086bc33,0x1e9da53,0x0bcfeff,0x1e313fc,0x177d7ca,0x18a04d9,
  37429. 0x0e3c426,0x1d42773,0x01b3029 } },
  37430. /* 242 */
  37431. { { 0x1a2fd88,0x09c6912,0x180fbde,0x199d740,0x090f2f7,0x136ffa4,
  37432. 0x072035e,0x10c987c,0x02883f9,0x063c79b,0x194c140,0x0b25331,
  37433. 0x13ed92b,0x192eee3,0x02a3c6c,0x0e11403,0x187d5d3,0x1b6ffec,
  37434. 0x147ca2e,0x06aa9e1,0x0059dcd },
  37435. { 0x1a74e7d,0x1720e91,0x17d85f1,0x1cbb665,0x14b61eb,0x1ffd05c,
  37436. 0x1fe9e79,0x01a785f,0x12ebb7a,0x19b315b,0x17e70d1,0x0bdc035,
  37437. 0x04a8641,0x0a33c93,0x00b0c99,0x138ae2a,0x1492fa0,0x10b4889,
  37438. 0x11d2421,0x1e69544,0x0195897 } },
  37439. /* 243 */
  37440. { { 0x1adc253,0x0e9acd5,0x0579211,0x198f2f9,0x0054b92,0x10c1097,
  37441. 0x0d6f668,0x04e4553,0x0a52b88,0x1dc052f,0x0719da6,0x0f1c5cc,
  37442. 0x13ea38e,0x04587c5,0x09d2c68,0x10a99f6,0x0e3db9d,0x1db5521,
  37443. 0x1804b5c,0x044a46a,0x01638ba },
  37444. { 0x1c8c576,0x00737ba,0x1749f3b,0x19c978f,0x0bb20e7,0x0c03935,
  37445. 0x08321a7,0x16e12b1,0x08a023e,0x0846335,0x042c56a,0x01d4ec2,
  37446. 0x06ca9f5,0x0c37b0d,0x0326650,0x0d3b0cd,0x0ed2a0a,0x1ceef91,
  37447. 0x0fe2843,0x1c312f7,0x01e0bfe } },
  37448. /* 244 */
  37449. { { 0x0319e4f,0x0340c24,0x1e809b6,0x0ab4b0d,0x0be6f6b,0x189932b,
  37450. 0x1621899,0x1f57deb,0x198529c,0x0129562,0x0a73eeb,0x0be2c56,
  37451. 0x0de7cc4,0x11531ac,0x0141826,0x158e1dc,0x0a42940,0x07be5ce,
  37452. 0x0216c7c,0x0955d95,0x01adfb4 },
  37453. { 0x198678e,0x1d49b73,0x10e19ad,0x0732a80,0x0a01e10,0x14305be,
  37454. 0x078de05,0x0afe492,0x1b745d8,0x17fea41,0x017b5bb,0x0c5148e,
  37455. 0x175dbb3,0x1952e87,0x15a3526,0x1fdc6af,0x09a2389,0x168d429,
  37456. 0x09ff5a1,0x184a923,0x01addbb } },
  37457. /* 245 */
  37458. { { 0x09686a3,0x05d104b,0x0fd7843,0x0bc780a,0x108b1c5,0x1a38811,
  37459. 0x0c4d09b,0x0702e25,0x1490330,0x1c8b2d8,0x0549ec7,0x002e5a0,
  37460. 0x0245b72,0x154d1a7,0x13d991e,0x06b90df,0x194b0be,0x128faa5,
  37461. 0x08578e0,0x16454ab,0x00e3fcc },
  37462. { 0x14dc0be,0x0f2762d,0x1712a9c,0x11b639a,0x1b13624,0x170803d,
  37463. 0x1fd0c11,0x147e6d7,0x1da9c99,0x134036b,0x06f1416,0x0ddd069,
  37464. 0x109cbfc,0x109f042,0x01c79cf,0x091824d,0x02767f4,0x0af3551,
  37465. 0x169eebe,0x0ef0f85,0x01b9ba7 } },
  37466. /* 246 */
  37467. { { 0x1a73375,0x12c7762,0x10e06af,0x1af5158,0x175df69,0x0541ad0,
  37468. 0x0542b3b,0x01e59e6,0x1f507d3,0x03d8304,0x0c1092e,0x14578c1,
  37469. 0x0c9ae53,0x0087c87,0x0c78609,0x1137692,0x10fadd6,0x122963e,
  37470. 0x1d8c6a3,0x0a69228,0x0013ab4 },
  37471. { 0x084f3af,0x0ec2b46,0x0cfabcb,0x043755c,0x029dc09,0x0b58384,
  37472. 0x0aa162e,0x02c8ca8,0x0e8a825,0x11306a0,0x14c8ad0,0x1b58b86,
  37473. 0x12b9e5e,0x1cf6d06,0x09e5580,0x1721579,0x1c6b962,0x1435e83,
  37474. 0x07b14c0,0x05b58f6,0x010a2e2 } },
  37475. /* 247 */
  37476. { { 0x19d8f0a,0x1e04e91,0x0085997,0x1957142,0x12b2e03,0x19a3bdc,
  37477. 0x05da005,0x009c86d,0x18e3616,0x19c76cf,0x0186faa,0x123b3d6,
  37478. 0x1079b00,0x1f422b3,0x1089950,0x145c19a,0x0c72fe1,0x1d07bbf,
  37479. 0x18280c3,0x0842c4e,0x00931d2 },
  37480. { 0x0646bc3,0x1c1a67c,0x1be7ea7,0x04815d2,0x1df94a5,0x08bbe8b,
  37481. 0x0e240de,0x19b2038,0x0ffeb66,0x0fe8322,0x0491967,0x05d8ef7,
  37482. 0x0f81aec,0x06cc0ea,0x1cedfcb,0x161265b,0x169f377,0x1e4de1f,
  37483. 0x1616762,0x1e69e7b,0x0125dae } },
  37484. /* 248 */
  37485. { { 0x0c123bc,0x0228dd1,0x0952b02,0x101031f,0x11e83a6,0x0abdc56,
  37486. 0x15c0a62,0x02cadba,0x0f0f12f,0x03f971a,0x1e85373,0x1866153,
  37487. 0x0c1f6a9,0x197f3c1,0x1268aee,0x0a9bbdf,0x097709f,0x1e98ce3,
  37488. 0x1918294,0x047197a,0x01dc0b8 },
  37489. { 0x0dfb6f6,0x09480a2,0x149bd92,0x08dc803,0x070d7cb,0x09bd6c1,
  37490. 0x0903921,0x1b234e1,0x170d8db,0x06b30da,0x03562e1,0x0475e2e,
  37491. 0x12ca272,0x11a270e,0x0d33c51,0x1c3f5dd,0x095ab9d,0x1912afe,
  37492. 0x0f717a9,0x1c2215b,0x01f8cd6 } },
  37493. /* 249 */
  37494. { { 0x0b8a0a7,0x1e35cbc,0x17a8a95,0x0dd067d,0x04b4aeb,0x089ff39,
  37495. 0x05f052f,0x1c93c8c,0x0fc2e8e,0x00c3444,0x11fbbf1,0x1493f62,
  37496. 0x1b8d398,0x1733167,0x1c647c4,0x145d9d3,0x089958b,0x0b0c391,
  37497. 0x02e3543,0x1a1e360,0x002dbd6 },
  37498. { 0x0c93cc9,0x07eff12,0x039e257,0x0173ce3,0x09ed778,0x1d7bf59,
  37499. 0x0e960e2,0x0d20391,0x04ddcbf,0x1129c3f,0x035aec0,0x017f430,
  37500. 0x0264b25,0x04a3e3e,0x1a39523,0x1e79ada,0x0329923,0x14153db,
  37501. 0x1440f34,0x006c265,0x000fb8f } },
  37502. /* 250 */
  37503. { { 0x0d9d494,0x059f846,0x07ce066,0x1329e9f,0x1b2065b,0x19c7d4c,
  37504. 0x08880f1,0x196ecc9,0x0d8d229,0x0cfa60a,0x1152cc6,0x0b898a3,
  37505. 0x12ddad7,0x0909d19,0x0cb382f,0x0f65f34,0x085888c,0x179d108,
  37506. 0x0c7fc82,0x1f46c4b,0x00d16de },
  37507. { 0x1a296eb,0x002a40c,0x0c4d138,0x0ba3522,0x1d94ff1,0x1522a78,
  37508. 0x0b4affa,0x0ffafbd,0x14d40bd,0x132d401,0x0692beb,0x08fc300,
  37509. 0x17604f1,0x12f06f3,0x0c123e6,0x0594130,0x0a5ff57,0x1d1d8ce,
  37510. 0x0087445,0x0fb74e3,0x00e0a23 } },
  37511. /* 251 */
  37512. { { 0x1630ee8,0x15fc248,0x0c07b6e,0x040bd6a,0x1e6589c,0x08fa3de,
  37513. 0x0acb681,0x1033efa,0x0212bbe,0x1554fcb,0x048492b,0x1abd285,
  37514. 0x1bdced3,0x1a21af2,0x07d6e27,0x1ecded2,0x0339411,0x10cb026,
  37515. 0x0d5bc36,0x1813948,0x00e6b7f },
  37516. { 0x14f811c,0x07209fb,0x176c4a5,0x03bf1b1,0x1a42d83,0x1a0c648,
  37517. 0x1c85e58,0x1d84fea,0x088ebcd,0x1ef290c,0x016f257,0x00ddd46,
  37518. 0x01fdd5e,0x163345b,0x0798222,0x030c3da,0x016eb81,0x0199d78,
  37519. 0x17773af,0x16325a2,0x01c95ec } },
  37520. /* 252 */
  37521. { { 0x0bde442,0x19bd1f0,0x1cfa49e,0x10cdef4,0x00543fe,0x0886177,
  37522. 0x074823b,0x065a61b,0x1a6617a,0x1bce1a0,0x173e2eb,0x10e1a3a,
  37523. 0x0be7367,0x11d5e7c,0x14373a7,0x0bcf605,0x0dd772b,0x0ff11e9,
  37524. 0x1ff1c31,0x19dd403,0x010b29f },
  37525. { 0x0d803ff,0x05726b1,0x1aa4c6f,0x1fb7860,0x13ee913,0x0083314,
  37526. 0x19eaf63,0x0b15e3b,0x0e7a6d6,0x042bc15,0x1d381b5,0x125c205,
  37527. 0x0691265,0x09b7d7f,0x08c49fc,0x0242723,0x0408837,0x0235c9a,
  37528. 0x0c7858d,0x1687014,0x00ba53b } },
  37529. /* 253 */
  37530. { { 0x05636b0,0x08bfe65,0x171d8b9,0x02d5742,0x0296e02,0x173d96a,
  37531. 0x1f5f084,0x108b551,0x15717ad,0x08be736,0x0bcd5e5,0x10b7316,
  37532. 0x1ce762b,0x0facd83,0x1e65ad7,0x1ede085,0x0bbf37e,0x0f9b995,
  37533. 0x150ad22,0x028bd48,0x015da5d },
  37534. { 0x07f6e3f,0x1e2af55,0x16f079d,0x0f54940,0x1f4d99a,0x0141139,
  37535. 0x1f5dd16,0x1f74ada,0x177b748,0x1844afd,0x07d7476,0x199c0c5,
  37536. 0x1b1c484,0x1acc01f,0x0c72428,0x171a1eb,0x1291720,0x121d627,
  37537. 0x0ab04fc,0x017fd0e,0x00e98c1 } },
  37538. /* 254 */
  37539. { { 0x06c4fd6,0x023c2e0,0x0e76747,0x0ba4b85,0x1f4b902,0x0c17925,
  37540. 0x17ac752,0x0560826,0x0ba4fef,0x159f6e1,0x181eace,0x073f31b,
  37541. 0x1d55a52,0x04b7a5b,0x1f126ac,0x1902bab,0x1603844,0x1e28514,
  37542. 0x159daca,0x0291a02,0x0047db1 },
  37543. { 0x0f3bad9,0x1ce6288,0x0753127,0x1804520,0x090888f,0x1da26fa,
  37544. 0x157af11,0x0d122f4,0x0f39f2b,0x05975e3,0x0658a88,0x075e09d,
  37545. 0x170c58e,0x0b9eead,0x0adf06d,0x1eed8a5,0x1d6a329,0x195aa56,
  37546. 0x0bd328e,0x15a3d70,0x010859d } },
  37547. /* 255 */
  37548. { { 0x182d1ad,0x0209450,0x111598b,0x1c4122d,0x1751796,0x140b23b,
  37549. 0x109cae9,0x1834ee0,0x0b92c85,0x164587d,0x0cb81fe,0x05bf5df,
  37550. 0x0d207ab,0x1c30d99,0x0d4c281,0x1a28b8e,0x16588ae,0x0b1edf6,
  37551. 0x094e927,0x179b941,0x00bd547 },
  37552. { 0x1056b51,0x09c17c3,0x044a9f0,0x16261f3,0x03d91ed,0x002da16,
  37553. 0x1791b4e,0x12bef8f,0x1fd31a9,0x0b080f5,0x1ee2a91,0x05699a7,
  37554. 0x0e1efd2,0x0f58bde,0x0e477de,0x01865fc,0x0c6616c,0x05a6a60,
  37555. 0x046fbbd,0x00477ce,0x011219f } },
  37556. };
  37557. /* Multiply the base point of P521 by the scalar and return the result.
  37558. * If map is true then convert result to affine coordinates.
  37559. *
  37560. * Stripe implementation.
  37561. * Pre-generated: 2^0, 2^65, ...
  37562. * Pre-generated: products of all combinations of above.
  37563. * 8 doubles and adds (with qz=1)
  37564. *
  37565. * r Resulting point.
  37566. * k Scalar to multiply by.
  37567. * map Indicates whether to convert result to affine.
  37568. * ct Constant time required.
  37569. * heap Heap to use for allocation.
  37570. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  37571. */
  37572. static int sp_521_ecc_mulmod_base_21(sp_point_521* r, const sp_digit* k,
  37573. int map, int ct, void* heap)
  37574. {
  37575. return sp_521_ecc_mulmod_stripe_21(r, &p521_base, p521_table,
  37576. k, map, ct, heap);
  37577. }
  37578. #endif
  37579. /* Multiply the base point of P521 by the scalar and return the result.
  37580. * If map is true then convert result to affine coordinates.
  37581. *
  37582. * km Scalar to multiply by.
  37583. * r Resulting point.
  37584. * map Indicates whether to convert result to affine.
  37585. * heap Heap to use for allocation.
  37586. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  37587. */
  37588. int sp_ecc_mulmod_base_521(const mp_int* km, ecc_point* r, int map, void* heap)
  37589. {
  37590. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  37591. sp_point_521* point = NULL;
  37592. sp_digit* k = NULL;
  37593. #else
  37594. sp_point_521 point[1];
  37595. sp_digit k[21];
  37596. #endif
  37597. int err = MP_OKAY;
  37598. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  37599. point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap,
  37600. DYNAMIC_TYPE_ECC);
  37601. if (point == NULL)
  37602. err = MEMORY_E;
  37603. if (err == MP_OKAY) {
  37604. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 21, heap,
  37605. DYNAMIC_TYPE_ECC);
  37606. if (k == NULL)
  37607. err = MEMORY_E;
  37608. }
  37609. #endif
  37610. if (err == MP_OKAY) {
  37611. sp_521_from_mp(k, 21, km);
  37612. err = sp_521_ecc_mulmod_base_21(point, k, map, 1, heap);
  37613. }
  37614. if (err == MP_OKAY) {
  37615. err = sp_521_point_to_ecc_point_21(point, r);
  37616. }
  37617. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  37618. if (k != NULL)
  37619. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  37620. if (point != NULL)
  37621. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  37622. #endif
  37623. return err;
  37624. }
  37625. /* Multiply the base point of P521 by the scalar, add point a and return
  37626. * the result. If map is true then convert result to affine coordinates.
  37627. *
  37628. * km Scalar to multiply by.
  37629. * am Point to add to scalar mulitply result.
  37630. * inMont Point to add is in montgomery form.
  37631. * r Resulting point.
  37632. * map Indicates whether to convert result to affine.
  37633. * heap Heap to use for allocation.
  37634. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  37635. */
  37636. int sp_ecc_mulmod_base_add_521(const mp_int* km, const ecc_point* am,
  37637. int inMont, ecc_point* r, int map, void* heap)
  37638. {
  37639. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  37640. sp_point_521* point = NULL;
  37641. sp_digit* k = NULL;
  37642. #else
  37643. sp_point_521 point[2];
  37644. sp_digit k[21 + 21 * 2 * 6];
  37645. #endif
  37646. sp_point_521* addP = NULL;
  37647. sp_digit* tmp = NULL;
  37648. int err = MP_OKAY;
  37649. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  37650. point = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap,
  37651. DYNAMIC_TYPE_ECC);
  37652. if (point == NULL)
  37653. err = MEMORY_E;
  37654. if (err == MP_OKAY) {
  37655. k = (sp_digit*)XMALLOC(
  37656. sizeof(sp_digit) * (21 + 21 * 2 * 6),
  37657. heap, DYNAMIC_TYPE_ECC);
  37658. if (k == NULL)
  37659. err = MEMORY_E;
  37660. }
  37661. #endif
  37662. if (err == MP_OKAY) {
  37663. addP = point + 1;
  37664. tmp = k + 21;
  37665. sp_521_from_mp(k, 21, km);
  37666. sp_521_point_from_ecc_point_21(addP, am);
  37667. }
  37668. if ((err == MP_OKAY) && (!inMont)) {
  37669. err = sp_521_mod_mul_norm_21(addP->x, addP->x, p521_mod);
  37670. }
  37671. if ((err == MP_OKAY) && (!inMont)) {
  37672. err = sp_521_mod_mul_norm_21(addP->y, addP->y, p521_mod);
  37673. }
  37674. if ((err == MP_OKAY) && (!inMont)) {
  37675. err = sp_521_mod_mul_norm_21(addP->z, addP->z, p521_mod);
  37676. }
  37677. if (err == MP_OKAY) {
  37678. err = sp_521_ecc_mulmod_base_21(point, k, 0, 0, heap);
  37679. }
  37680. if (err == MP_OKAY) {
  37681. sp_521_proj_point_add_21(point, point, addP, tmp);
  37682. if (map) {
  37683. sp_521_map_21(point, point, tmp);
  37684. }
  37685. err = sp_521_point_to_ecc_point_21(point, r);
  37686. }
  37687. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  37688. if (k != NULL)
  37689. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  37690. if (point)
  37691. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  37692. #endif
  37693. return err;
  37694. }
  37695. #if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
  37696. defined(HAVE_ECC_VERIFY)
  37697. #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
  37698. /* Add 1 to a. (a = a + 1)
  37699. *
  37700. * r A single precision integer.
  37701. * a A single precision integer.
  37702. */
  37703. SP_NOINLINE static void sp_521_add_one_21(sp_digit* a)
  37704. {
  37705. a[0]++;
  37706. sp_521_norm_21(a);
  37707. }
  37708. /* Read big endian unsigned byte array into r.
  37709. *
  37710. * r A single precision integer.
  37711. * size Maximum number of bytes to convert
  37712. * a Byte array.
  37713. * n Number of bytes in array to read.
  37714. */
  37715. static void sp_521_from_bin(sp_digit* r, int size, const byte* a, int n)
  37716. {
  37717. int i;
  37718. int j = 0;
  37719. word32 s = 0;
  37720. r[0] = 0;
  37721. for (i = n-1; i >= 0; i--) {
  37722. r[j] |= (((sp_digit)a[i]) << s);
  37723. if (s >= 17U) {
  37724. r[j] &= 0x1ffffff;
  37725. s = 25U - s;
  37726. if (j + 1 >= size) {
  37727. break;
  37728. }
  37729. r[++j] = (sp_digit)a[i] >> s;
  37730. s = 8U - s;
  37731. }
  37732. else {
  37733. s += 8U;
  37734. }
  37735. }
  37736. for (j++; j < size; j++) {
  37737. r[j] = 0;
  37738. }
  37739. }
  37740. /* Generates a scalar that is in the range 1..order-1.
  37741. *
  37742. * rng Random number generator.
  37743. * k Scalar value.
  37744. * returns RNG failures, MEMORY_E when memory allocation fails and
  37745. * MP_OKAY on success.
  37746. */
  37747. static int sp_521_ecc_gen_k_21(WC_RNG* rng, sp_digit* k)
  37748. {
  37749. int err;
  37750. byte buf[66];
  37751. do {
  37752. err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf));
  37753. if (err == 0) {
  37754. buf[0] &= 0x1;
  37755. sp_521_from_bin(k, 21, buf, (int)sizeof(buf));
  37756. if (sp_521_cmp_21(k, p521_order2) <= 0) {
  37757. sp_521_add_one_21(k);
  37758. break;
  37759. }
  37760. }
  37761. }
  37762. while (err == 0);
  37763. return err;
  37764. }
  37765. /* Makes a random EC key pair.
  37766. *
  37767. * rng Random number generator.
  37768. * priv Generated private value.
  37769. * pub Generated public point.
  37770. * heap Heap to use for allocation.
  37771. * returns ECC_INF_E when the point does not have the correct order, RNG
  37772. * failures, MEMORY_E when memory allocation fails and MP_OKAY on success.
  37773. */
  37774. int sp_ecc_make_key_521(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap)
  37775. {
  37776. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  37777. sp_point_521* point = NULL;
  37778. sp_digit* k = NULL;
  37779. #else
  37780. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  37781. sp_point_521 point[2];
  37782. #else
  37783. sp_point_521 point[1];
  37784. #endif
  37785. sp_digit k[21];
  37786. #endif
  37787. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  37788. sp_point_521* infinity = NULL;
  37789. #endif
  37790. int err = MP_OKAY;
  37791. (void)heap;
  37792. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  37793. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  37794. point = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap, DYNAMIC_TYPE_ECC);
  37795. #else
  37796. point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap, DYNAMIC_TYPE_ECC);
  37797. #endif
  37798. if (point == NULL)
  37799. err = MEMORY_E;
  37800. if (err == MP_OKAY) {
  37801. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 21, heap,
  37802. DYNAMIC_TYPE_ECC);
  37803. if (k == NULL)
  37804. err = MEMORY_E;
  37805. }
  37806. #endif
  37807. if (err == MP_OKAY) {
  37808. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  37809. infinity = point + 1;
  37810. #endif
  37811. err = sp_521_ecc_gen_k_21(rng, k);
  37812. }
  37813. if (err == MP_OKAY) {
  37814. err = sp_521_ecc_mulmod_base_21(point, k, 1, 1, NULL);
  37815. }
  37816. #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
  37817. if (err == MP_OKAY) {
  37818. err = sp_521_ecc_mulmod_21(infinity, point, p521_order, 1, 1, NULL);
  37819. }
  37820. if (err == MP_OKAY) {
  37821. if (sp_521_iszero_21(point->x) || sp_521_iszero_21(point->y)) {
  37822. err = ECC_INF_E;
  37823. }
  37824. }
  37825. #endif
  37826. if (err == MP_OKAY) {
  37827. err = sp_521_to_mp(k, priv);
  37828. }
  37829. if (err == MP_OKAY) {
  37830. err = sp_521_point_to_ecc_point_21(point, pub);
  37831. }
  37832. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  37833. if (k != NULL)
  37834. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  37835. if (point != NULL) {
  37836. /* point is not sensitive, so no need to zeroize */
  37837. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  37838. }
  37839. #endif
  37840. return err;
  37841. }
  37842. #ifdef HAVE_ECC_DHE
  37843. /* Write r as big endian to byte array.
  37844. * Fixed length number of bytes written: 66
  37845. *
  37846. * r A single precision integer.
  37847. * a Byte array.
  37848. */
  37849. static void sp_521_to_bin_21(sp_digit* r, byte* a)
  37850. {
  37851. int i;
  37852. int j;
  37853. int s = 0;
  37854. int b;
  37855. for (i=0; i<20; i++) {
  37856. r[i+1] += r[i] >> 25;
  37857. r[i] &= 0x1ffffff;
  37858. }
  37859. j = 528 / 8 - 1;
  37860. a[j] = 0;
  37861. for (i=0; i<21 && j>=0; i++) {
  37862. b = 0;
  37863. /* lint allow cast of mismatch sp_digit and int */
  37864. a[j--] |= (byte)(r[i] << s); /*lint !e9033*/
  37865. b += 8 - s;
  37866. if (j < 0) {
  37867. break;
  37868. }
  37869. while (b < 25) {
  37870. a[j--] = (byte)(r[i] >> b);
  37871. b += 8;
  37872. if (j < 0) {
  37873. break;
  37874. }
  37875. }
  37876. s = 8 - (b - 25);
  37877. if (j >= 0) {
  37878. a[j] = 0;
  37879. }
  37880. if (s != 0) {
  37881. j++;
  37882. }
  37883. }
  37884. }
  37885. /* Multiply the point by the scalar and serialize the X ordinate.
  37886. * The number is 0 padded to maximum size on output.
  37887. *
  37888. * priv Scalar to multiply the point by.
  37889. * pub Point to multiply.
  37890. * out Buffer to hold X ordinate.
  37891. * outLen On entry, size of the buffer in bytes.
  37892. * On exit, length of data in buffer in bytes.
  37893. * heap Heap to use for allocation.
  37894. * returns BUFFER_E if the buffer is to small for output size,
  37895. * MEMORY_E when memory allocation fails and MP_OKAY on success.
  37896. */
  37897. int sp_ecc_secret_gen_521(const mp_int* priv, const ecc_point* pub, byte* out,
  37898. word32* outLen, void* heap)
  37899. {
  37900. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  37901. sp_point_521* point = NULL;
  37902. sp_digit* k = NULL;
  37903. #else
  37904. sp_point_521 point[1];
  37905. sp_digit k[21];
  37906. #endif
  37907. int err = MP_OKAY;
  37908. if (*outLen < 65U) {
  37909. err = BUFFER_E;
  37910. }
  37911. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  37912. if (err == MP_OKAY) {
  37913. point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap,
  37914. DYNAMIC_TYPE_ECC);
  37915. if (point == NULL)
  37916. err = MEMORY_E;
  37917. }
  37918. if (err == MP_OKAY) {
  37919. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 21, heap,
  37920. DYNAMIC_TYPE_ECC);
  37921. if (k == NULL)
  37922. err = MEMORY_E;
  37923. }
  37924. #endif
  37925. if (err == MP_OKAY) {
  37926. sp_521_from_mp(k, 21, priv);
  37927. sp_521_point_from_ecc_point_21(point, pub);
  37928. err = sp_521_ecc_mulmod_21(point, point, k, 1, 1, heap);
  37929. }
  37930. if (err == MP_OKAY) {
  37931. sp_521_to_bin_21(point->x, out);
  37932. *outLen = 66;
  37933. }
  37934. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  37935. if (k != NULL)
  37936. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  37937. if (point != NULL)
  37938. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  37939. #endif
  37940. return err;
  37941. }
  37942. #endif /* HAVE_ECC_DHE */
  37943. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  37944. SP_NOINLINE static void sp_521_rshift_21(sp_digit* r, const sp_digit* a,
  37945. byte n)
  37946. {
  37947. int i;
  37948. #ifdef WOLFSSL_SP_SMALL
  37949. for (i=0; i<20; i++) {
  37950. r[i] = ((a[i] >> n) | (a[i + 1] << (25 - n))) & 0x1ffffff;
  37951. }
  37952. #else
  37953. for (i=0; i<16; i += 8) {
  37954. r[i+0] = (a[i+0] >> n) | ((a[i+1] << (25 - n)) & 0x1ffffff);
  37955. r[i+1] = (a[i+1] >> n) | ((a[i+2] << (25 - n)) & 0x1ffffff);
  37956. r[i+2] = (a[i+2] >> n) | ((a[i+3] << (25 - n)) & 0x1ffffff);
  37957. r[i+3] = (a[i+3] >> n) | ((a[i+4] << (25 - n)) & 0x1ffffff);
  37958. r[i+4] = (a[i+4] >> n) | ((a[i+5] << (25 - n)) & 0x1ffffff);
  37959. r[i+5] = (a[i+5] >> n) | ((a[i+6] << (25 - n)) & 0x1ffffff);
  37960. r[i+6] = (a[i+6] >> n) | ((a[i+7] << (25 - n)) & 0x1ffffff);
  37961. r[i+7] = (a[i+7] >> n) | ((a[i+8] << (25 - n)) & 0x1ffffff);
  37962. }
  37963. r[16] = (a[16] >> n) | ((a[17] << (25 - n)) & 0x1ffffff);
  37964. r[17] = (a[17] >> n) | ((a[18] << (25 - n)) & 0x1ffffff);
  37965. r[18] = (a[18] >> n) | ((a[19] << (25 - n)) & 0x1ffffff);
  37966. r[19] = (a[19] >> n) | ((a[20] << (25 - n)) & 0x1ffffff);
  37967. #endif /* WOLFSSL_SP_SMALL */
  37968. r[20] = a[20] >> n;
  37969. }
  37970. #endif
  37971. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  37972. /* Multiply a by scalar b into r. (r = a * b)
  37973. *
  37974. * r A single precision integer.
  37975. * a A single precision integer.
  37976. * b A scalar.
  37977. */
  37978. SP_NOINLINE static void sp_521_mul_d_21(sp_digit* r, const sp_digit* a,
  37979. sp_digit b)
  37980. {
  37981. #ifdef WOLFSSL_SP_SMALL
  37982. sp_int64 tb = b;
  37983. sp_int64 t = 0;
  37984. int i;
  37985. for (i = 0; i < 21; i++) {
  37986. t += tb * a[i];
  37987. r[i] = (sp_digit)(t & 0x1ffffff);
  37988. t >>= 25;
  37989. }
  37990. r[21] = (sp_digit)t;
  37991. #else
  37992. sp_int64 tb = b;
  37993. sp_int64 t = 0;
  37994. sp_digit t2;
  37995. sp_int64 p[4];
  37996. int i;
  37997. for (i = 0; i < 20; i += 4) {
  37998. p[0] = tb * a[i + 0];
  37999. p[1] = tb * a[i + 1];
  38000. p[2] = tb * a[i + 2];
  38001. p[3] = tb * a[i + 3];
  38002. t += p[0];
  38003. t2 = (sp_digit)(t & 0x1ffffff);
  38004. t >>= 25;
  38005. r[i + 0] = (sp_digit)t2;
  38006. t += p[1];
  38007. t2 = (sp_digit)(t & 0x1ffffff);
  38008. t >>= 25;
  38009. r[i + 1] = (sp_digit)t2;
  38010. t += p[2];
  38011. t2 = (sp_digit)(t & 0x1ffffff);
  38012. t >>= 25;
  38013. r[i + 2] = (sp_digit)t2;
  38014. t += p[3];
  38015. t2 = (sp_digit)(t & 0x1ffffff);
  38016. t >>= 25;
  38017. r[i + 3] = (sp_digit)t2;
  38018. }
  38019. t += tb * a[20];
  38020. r[20] = (sp_digit)(t & 0x1ffffff);
  38021. t >>= 25;
  38022. r[21] = (sp_digit)(t & 0x1ffffff);
  38023. #endif /* WOLFSSL_SP_SMALL */
  38024. }
  38025. SP_NOINLINE static void sp_521_lshift_42(sp_digit* r, const sp_digit* a,
  38026. byte n)
  38027. {
  38028. #ifdef WOLFSSL_SP_SMALL
  38029. int i;
  38030. r[42] = a[41] >> (25 - n);
  38031. for (i=41; i>0; i--) {
  38032. r[i] = ((a[i] << n) | (a[i-1] >> (25 - n))) & 0x1ffffff;
  38033. }
  38034. #else
  38035. sp_int_digit s;
  38036. sp_int_digit t;
  38037. s = (sp_int_digit)a[41];
  38038. r[42] = s >> (25U - n);
  38039. s = (sp_int_digit)(a[41]); t = (sp_int_digit)(a[40]);
  38040. r[41] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38041. s = (sp_int_digit)(a[40]); t = (sp_int_digit)(a[39]);
  38042. r[40] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38043. s = (sp_int_digit)(a[39]); t = (sp_int_digit)(a[38]);
  38044. r[39] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38045. s = (sp_int_digit)(a[38]); t = (sp_int_digit)(a[37]);
  38046. r[38] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38047. s = (sp_int_digit)(a[37]); t = (sp_int_digit)(a[36]);
  38048. r[37] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38049. s = (sp_int_digit)(a[36]); t = (sp_int_digit)(a[35]);
  38050. r[36] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38051. s = (sp_int_digit)(a[35]); t = (sp_int_digit)(a[34]);
  38052. r[35] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38053. s = (sp_int_digit)(a[34]); t = (sp_int_digit)(a[33]);
  38054. r[34] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38055. s = (sp_int_digit)(a[33]); t = (sp_int_digit)(a[32]);
  38056. r[33] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38057. s = (sp_int_digit)(a[32]); t = (sp_int_digit)(a[31]);
  38058. r[32] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38059. s = (sp_int_digit)(a[31]); t = (sp_int_digit)(a[30]);
  38060. r[31] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38061. s = (sp_int_digit)(a[30]); t = (sp_int_digit)(a[29]);
  38062. r[30] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38063. s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]);
  38064. r[29] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38065. s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]);
  38066. r[28] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38067. s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]);
  38068. r[27] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38069. s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]);
  38070. r[26] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38071. s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]);
  38072. r[25] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38073. s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]);
  38074. r[24] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38075. s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]);
  38076. r[23] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38077. s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]);
  38078. r[22] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38079. s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]);
  38080. r[21] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38081. s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]);
  38082. r[20] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38083. s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]);
  38084. r[19] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38085. s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]);
  38086. r[18] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38087. s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]);
  38088. r[17] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38089. s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]);
  38090. r[16] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38091. s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]);
  38092. r[15] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38093. s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]);
  38094. r[14] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38095. s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]);
  38096. r[13] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38097. s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]);
  38098. r[12] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38099. s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]);
  38100. r[11] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38101. s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]);
  38102. r[10] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38103. s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]);
  38104. r[9] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38105. s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]);
  38106. r[8] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38107. s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]);
  38108. r[7] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38109. s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]);
  38110. r[6] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38111. s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]);
  38112. r[5] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38113. s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]);
  38114. r[4] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38115. s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]);
  38116. r[3] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38117. s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]);
  38118. r[2] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38119. s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]);
  38120. r[1] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
  38121. #endif /* WOLFSSL_SP_SMALL */
  38122. r[0] = (a[0] << n) & 0x1ffffff;
  38123. }
  38124. /* Divide d in a and put remainder into r (m*d + r = a)
  38125. * m is not calculated as it is not needed at this time.
  38126. *
  38127. * Simplified based on top word of divisor being (1 << 25) - 1
  38128. *
  38129. * a Number to be divided.
  38130. * d Number to divide with.
  38131. * m Multiplier result.
  38132. * r Remainder from the division.
  38133. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  38134. */
  38135. static int sp_521_div_21(const sp_digit* a, const sp_digit* d,
  38136. const sp_digit* m, sp_digit* r)
  38137. {
  38138. int i;
  38139. sp_digit r1;
  38140. sp_digit mask;
  38141. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  38142. sp_digit* t1 = NULL;
  38143. #else
  38144. sp_digit t1[4 * 21 + 3];
  38145. #endif
  38146. sp_digit* t2 = NULL;
  38147. sp_digit* sd = NULL;
  38148. int err = MP_OKAY;
  38149. (void)m;
  38150. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  38151. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 21 + 3), NULL,
  38152. DYNAMIC_TYPE_TMP_BUFFER);
  38153. if (t1 == NULL)
  38154. err = MEMORY_E;
  38155. #endif
  38156. (void)m;
  38157. if (err == MP_OKAY) {
  38158. t2 = t1 + 42 + 1;
  38159. sd = t2 + 21 + 1;
  38160. sp_521_mul_d_21(sd, d, (sp_digit)1 << 4);
  38161. sp_521_lshift_42(t1, a, 4);
  38162. t1[21 + 21] += t1[21 + 21 - 1] >> 25;
  38163. t1[21 + 21 - 1] &= 0x1ffffff;
  38164. for (i=20; i>=0; i--) {
  38165. r1 = t1[21 + i];
  38166. sp_521_mul_d_21(t2, sd, r1);
  38167. (void)sp_521_sub_21(&t1[i], &t1[i], t2);
  38168. t1[21 + i] -= t2[21];
  38169. sp_521_norm_21(&t1[i + 1]);
  38170. mask = ~((t1[21 + i] - 1) >> 31);
  38171. sp_521_cond_sub_21(t1 + i, t1 + i, sd, mask);
  38172. sp_521_norm_21(&t1[i + 1]);
  38173. }
  38174. sp_521_norm_21(t1);
  38175. sp_521_rshift_21(r, t1, 4);
  38176. }
  38177. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  38178. if (t1 != NULL)
  38179. XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  38180. #endif
  38181. return err;
  38182. }
  38183. /* Reduce a modulo m into r. (r = a mod m)
  38184. *
  38185. * r A single precision number that is the reduced result.
  38186. * a A single precision number that is to be reduced.
  38187. * m A single precision number that is the modulus to reduce with.
  38188. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  38189. */
  38190. static int sp_521_mod_21(sp_digit* r, const sp_digit* a, const sp_digit* m)
  38191. {
  38192. return sp_521_div_21(a, m, NULL, r);
  38193. }
  38194. #endif
  38195. #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
  38196. /* Multiply two number mod the order of P521 curve. (r = a * b mod order)
  38197. *
  38198. * r Result of the multiplication.
  38199. * a First operand of the multiplication.
  38200. * b Second operand of the multiplication.
  38201. */
  38202. static void sp_521_mont_mul_order_21(sp_digit* r, const sp_digit* a, const sp_digit* b)
  38203. {
  38204. sp_521_mul_21(r, a, b);
  38205. sp_521_mont_reduce_order_21(r, p521_order, p521_mp_order);
  38206. }
  38207. #if defined(HAVE_ECC_SIGN) || (defined(HAVE_ECC_VERIFY) && defined(WOLFSSL_SP_SMALL))
  38208. #ifdef WOLFSSL_SP_SMALL
  38209. /* Order-2 for the P521 curve. */
  38210. static const uint32_t p521_order_minus_2[17] = {
  38211. 0x91386407U,0xbb6fb71eU,0x899c47aeU,0x3bb5c9b8U,0xf709a5d0U,0x7fcc0148U,
  38212. 0xbf2f966bU,0x51868783U,0xfffffffaU,0xffffffffU,0xffffffffU,0xffffffffU,
  38213. 0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0x000001ffU
  38214. };
  38215. #else
  38216. /* The low half of the order-2 of the P521 curve. */
  38217. static const uint32_t p521_order_low[9] = {
  38218. 0x91386407U,0xbb6fb71eU,0x899c47aeU,0x3bb5c9b8U,0xf709a5d0U,0x7fcc0148U,
  38219. 0xbf2f966bU,0x51868783U,0xfffffffaU
  38220. };
  38221. #endif /* WOLFSSL_SP_SMALL */
  38222. /* Square number mod the order of P521 curve. (r = a * a mod order)
  38223. *
  38224. * r Result of the squaring.
  38225. * a Number to square.
  38226. */
  38227. static void sp_521_mont_sqr_order_21(sp_digit* r, const sp_digit* a)
  38228. {
  38229. sp_521_sqr_21(r, a);
  38230. sp_521_mont_reduce_order_21(r, p521_order, p521_mp_order);
  38231. }
  38232. #ifndef WOLFSSL_SP_SMALL
  38233. /* Square number mod the order of P521 curve a number of times.
  38234. * (r = a ^ n mod order)
  38235. *
  38236. * r Result of the squaring.
  38237. * a Number to square.
  38238. */
  38239. static void sp_521_mont_sqr_n_order_21(sp_digit* r, const sp_digit* a, int n)
  38240. {
  38241. int i;
  38242. sp_521_mont_sqr_order_21(r, a);
  38243. for (i=1; i<n; i++) {
  38244. sp_521_mont_sqr_order_21(r, r);
  38245. }
  38246. }
  38247. #endif /* !WOLFSSL_SP_SMALL */
  38248. /* Invert the number, in Montgomery form, modulo the order of the P521 curve.
  38249. * (r = 1 / a mod order)
  38250. *
  38251. * r Inverse result.
  38252. * a Number to invert.
  38253. * td Temporary data.
  38254. */
  38255. #ifdef WOLFSSL_SP_NONBLOCK
  38256. typedef struct sp_521_mont_inv_order_21_ctx {
  38257. int state;
  38258. int i;
  38259. } sp_521_mont_inv_order_21_ctx;
  38260. static int sp_521_mont_inv_order_21_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a,
  38261. sp_digit* t)
  38262. {
  38263. int err = FP_WOULDBLOCK;
  38264. sp_521_mont_inv_order_21_ctx* ctx = (sp_521_mont_inv_order_21_ctx*)sp_ctx;
  38265. typedef char ctx_size_test[sizeof(sp_521_mont_inv_order_21_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  38266. (void)sizeof(ctx_size_test);
  38267. switch (ctx->state) {
  38268. case 0:
  38269. XMEMCPY(t, a, sizeof(sp_digit) * 21);
  38270. ctx->i = 519;
  38271. ctx->state = 1;
  38272. break;
  38273. case 1:
  38274. sp_521_mont_sqr_order_21(t, t);
  38275. ctx->state = 2;
  38276. break;
  38277. case 2:
  38278. if ((p521_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) {
  38279. sp_521_mont_mul_order_21(t, t, a);
  38280. }
  38281. ctx->i--;
  38282. ctx->state = (ctx->i == 0) ? 3 : 1;
  38283. break;
  38284. case 3:
  38285. XMEMCPY(r, t, sizeof(sp_digit) * 21U);
  38286. err = MP_OKAY;
  38287. break;
  38288. }
  38289. return err;
  38290. }
  38291. #endif /* WOLFSSL_SP_NONBLOCK */
  38292. static void sp_521_mont_inv_order_21(sp_digit* r, const sp_digit* a,
  38293. sp_digit* td)
  38294. {
  38295. #ifdef WOLFSSL_SP_SMALL
  38296. sp_digit* t = td;
  38297. int i;
  38298. XMEMCPY(t, a, sizeof(sp_digit) * 21);
  38299. for (i=519; i>=0; i--) {
  38300. sp_521_mont_sqr_order_21(t, t);
  38301. if ((p521_order_minus_2[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
  38302. sp_521_mont_mul_order_21(t, t, a);
  38303. }
  38304. }
  38305. XMEMCPY(r, t, sizeof(sp_digit) * 21U);
  38306. #else
  38307. sp_digit* t = td;
  38308. sp_digit* t2 = td + 2 * 21;
  38309. sp_digit* t3 = td + 4 * 21;
  38310. int i;
  38311. /* t = a^2 */
  38312. sp_521_mont_sqr_order_21(t, a);
  38313. /* t = a^3 = t * a */
  38314. sp_521_mont_mul_order_21(t, t, a);
  38315. /* t= a^c = t ^ 2 ^ 2 */
  38316. sp_521_mont_sqr_n_order_21(t2, t, 2);
  38317. /* t = a^f = t2 * t */
  38318. sp_521_mont_mul_order_21(t, t2, t);
  38319. /* t3 = a^1e */
  38320. sp_521_mont_sqr_order_21(t3, t);
  38321. /* t3 = a^1f = t3 * a */
  38322. sp_521_mont_mul_order_21(t3, t3, a);
  38323. /* t2= a^f0 = t ^ 2 ^ 4 */
  38324. sp_521_mont_sqr_n_order_21(t2, t, 4);
  38325. /* t = a^ff = t2 * t */
  38326. sp_521_mont_mul_order_21(t, t2, t);
  38327. /* t2= a^ff00 = t ^ 2 ^ 8 */
  38328. sp_521_mont_sqr_n_order_21(t2, t, 8);
  38329. /* t3= a^ffff = t2 * t */
  38330. sp_521_mont_mul_order_21(t, t2, t);
  38331. /* t2= a^ffff0000 = t ^ 2 ^ 16 */
  38332. sp_521_mont_sqr_n_order_21(t2, t, 16);
  38333. /* t = a^ffffffff = t2 * t */
  38334. sp_521_mont_mul_order_21(t, t2, t);
  38335. /* t2= a^ffffffff00000000 = t ^ 2 ^ 32 */
  38336. sp_521_mont_sqr_n_order_21(t2, t, 32);
  38337. /* t = a^ffffffffffffffff = t2 * t */
  38338. sp_521_mont_mul_order_21(t, t2, t);
  38339. /* t2= a^ffffffffffffffff0000000000000000 = t ^ 2 ^ 64 */
  38340. sp_521_mont_sqr_n_order_21(t2, t, 64);
  38341. /* t = a^ffffffffffffffffffffffffffffffff = t2 * t */
  38342. sp_521_mont_mul_order_21(t, t2, t);
  38343. /* t2= a^ffffffffffffffffffffffffffffffff00000000000000000000000000000000 = t ^ 2 ^ 128 */
  38344. sp_521_mont_sqr_n_order_21(t2, t, 128);
  38345. /* t = a^ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff = t2 * t */
  38346. sp_521_mont_mul_order_21(t, t2, t);
  38347. /* t2 = a^1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 */
  38348. sp_521_mont_sqr_n_order_21(t2, t, 5);
  38349. /* t2 = a^1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff = t * t3 */
  38350. sp_521_mont_mul_order_21(t2, t2, t3);
  38351. for (i=259; i>=1; i--) {
  38352. sp_521_mont_sqr_order_21(t2, t2);
  38353. if ((p521_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
  38354. sp_521_mont_mul_order_21(t2, t2, a);
  38355. }
  38356. }
  38357. sp_521_mont_sqr_order_21(t2, t2);
  38358. sp_521_mont_mul_order_21(r, t2, a);
  38359. #endif /* WOLFSSL_SP_SMALL */
  38360. }
  38361. #endif /* HAVE_ECC_SIGN || (HAVE_ECC_VERIFY && WOLFSSL_SP_SMALL) */
  38362. #endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
  38363. #ifdef HAVE_ECC_SIGN
  38364. #ifndef SP_ECC_MAX_SIG_GEN
  38365. #define SP_ECC_MAX_SIG_GEN 64
  38366. #endif
  38367. /* Calculate second signature value S from R, k and private value.
  38368. *
  38369. * s = (r * x + e) / k
  38370. *
  38371. * s Signature value.
  38372. * r First signature value.
  38373. * k Ephemeral private key.
  38374. * x Private key as a number.
  38375. * e Hash of message as a number.
  38376. * tmp Temporary storage for intermediate numbers.
  38377. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  38378. */
  38379. static int sp_521_calc_s_21(sp_digit* s, const sp_digit* r, sp_digit* k,
  38380. sp_digit* x, const sp_digit* e, sp_digit* tmp)
  38381. {
  38382. int err;
  38383. sp_digit carry;
  38384. sp_int32 c;
  38385. sp_digit* kInv = k;
  38386. /* Conv k to Montgomery form (mod order) */
  38387. sp_521_mul_21(k, k, p521_norm_order);
  38388. err = sp_521_mod_21(k, k, p521_order);
  38389. if (err == MP_OKAY) {
  38390. sp_521_norm_21(k);
  38391. /* kInv = 1/k mod order */
  38392. sp_521_mont_inv_order_21(kInv, k, tmp);
  38393. sp_521_norm_21(kInv);
  38394. /* s = r * x + e */
  38395. sp_521_mul_21(x, x, r);
  38396. err = sp_521_mod_21(x, x, p521_order);
  38397. }
  38398. if (err == MP_OKAY) {
  38399. sp_521_norm_21(x);
  38400. carry = sp_521_add_21(s, e, x);
  38401. sp_521_cond_sub_21(s, s, p521_order, 0 - carry);
  38402. sp_521_norm_21(s);
  38403. c = sp_521_cmp_21(s, p521_order);
  38404. sp_521_cond_sub_21(s, s, p521_order,
  38405. (sp_digit)0 - (sp_digit)(c >= 0));
  38406. sp_521_norm_21(s);
  38407. /* s = s * k^-1 mod order */
  38408. sp_521_mont_mul_order_21(s, s, kInv);
  38409. sp_521_norm_21(s);
  38410. }
  38411. return err;
  38412. }
  38413. /* Sign the hash using the private key.
  38414. * e = [hash, 521 bits] from binary
  38415. * r = (k.G)->x mod order
  38416. * s = (r * x + e) / k mod order
  38417. * The hash is truncated to the first 521 bits.
  38418. *
  38419. * hash Hash to sign.
  38420. * hashLen Length of the hash data.
  38421. * rng Random number generator.
  38422. * priv Private part of key - scalar.
  38423. * rm First part of result as an mp_int.
  38424. * sm Sirst part of result as an mp_int.
  38425. * heap Heap to use for allocation.
  38426. * returns RNG failures, MEMORY_E when memory allocation fails and
  38427. * MP_OKAY on success.
  38428. */
  38429. #ifdef WOLFSSL_SP_NONBLOCK
  38430. typedef struct sp_ecc_sign_521_ctx {
  38431. int state;
  38432. union {
  38433. sp_521_ecc_mulmod_21_ctx mulmod_ctx;
  38434. sp_521_mont_inv_order_21_ctx mont_inv_order_ctx;
  38435. };
  38436. sp_digit e[2*21];
  38437. sp_digit x[2*21];
  38438. sp_digit k[2*21];
  38439. sp_digit r[2*21];
  38440. sp_digit tmp[3 * 2*21];
  38441. sp_point_521 point;
  38442. sp_digit* s;
  38443. sp_digit* kInv;
  38444. int i;
  38445. } sp_ecc_sign_521_ctx;
  38446. int sp_ecc_sign_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng,
  38447. mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
  38448. {
  38449. int err = FP_WOULDBLOCK;
  38450. sp_ecc_sign_521_ctx* ctx = (sp_ecc_sign_521_ctx*)sp_ctx->data;
  38451. typedef char ctx_size_test[sizeof(sp_ecc_sign_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  38452. (void)sizeof(ctx_size_test);
  38453. (void)heap;
  38454. switch (ctx->state) {
  38455. case 0: /* INIT */
  38456. ctx->s = ctx->e;
  38457. ctx->kInv = ctx->k;
  38458. ctx->i = SP_ECC_MAX_SIG_GEN;
  38459. ctx->state = 1;
  38460. break;
  38461. case 1: /* GEN */
  38462. /* New random point. */
  38463. if (km == NULL || mp_iszero(km)) {
  38464. err = sp_521_ecc_gen_k_21(rng, ctx->k);
  38465. }
  38466. else {
  38467. sp_521_from_mp(ctx->k, 21, km);
  38468. mp_zero(km);
  38469. }
  38470. XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
  38471. ctx->state = 2;
  38472. break;
  38473. case 2: /* MULMOD */
  38474. err = sp_521_ecc_mulmod_21_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
  38475. &ctx->point, &p521_base, ctx->k, 1, 1, heap);
  38476. if (err == MP_OKAY) {
  38477. ctx->state = 3;
  38478. }
  38479. break;
  38480. case 3: /* MODORDER */
  38481. {
  38482. sp_int32 c;
  38483. /* r = point->x mod order */
  38484. XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 21U);
  38485. sp_521_norm_21(ctx->r);
  38486. c = sp_521_cmp_21(ctx->r, p521_order);
  38487. sp_521_cond_sub_21(ctx->r, ctx->r, p521_order,
  38488. (sp_digit)0 - (sp_digit)(c >= 0));
  38489. sp_521_norm_21(ctx->r);
  38490. if (hashLen > 66U) {
  38491. hashLen = 66U;
  38492. }
  38493. sp_521_from_mp(ctx->x, 21, priv);
  38494. sp_521_from_bin(ctx->e, 21, hash, (int)hashLen);
  38495. if (hashLen == 66U) {
  38496. sp_521_rshift_21(ctx->e, ctx->e, 7);
  38497. ctx->e[20] |= ((sp_digit)hash[0]) << 13;
  38498. }
  38499. ctx->state = 4;
  38500. break;
  38501. }
  38502. case 4: /* KMODORDER */
  38503. /* Conv k to Montgomery form (mod order) */
  38504. sp_521_mul_21(ctx->k, ctx->k, p521_norm_order);
  38505. err = sp_521_mod_21(ctx->k, ctx->k, p521_order);
  38506. if (err == MP_OKAY) {
  38507. sp_521_norm_21(ctx->k);
  38508. XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
  38509. ctx->state = 5;
  38510. }
  38511. break;
  38512. case 5: /* KINV */
  38513. /* kInv = 1/k mod order */
  38514. err = sp_521_mont_inv_order_21_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp);
  38515. if (err == MP_OKAY) {
  38516. XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
  38517. ctx->state = 6;
  38518. }
  38519. break;
  38520. case 6: /* KINVNORM */
  38521. sp_521_norm_21(ctx->kInv);
  38522. ctx->state = 7;
  38523. break;
  38524. case 7: /* R */
  38525. /* s = r * x + e */
  38526. sp_521_mul_21(ctx->x, ctx->x, ctx->r);
  38527. ctx->state = 8;
  38528. break;
  38529. case 8: /* S1 */
  38530. err = sp_521_mod_21(ctx->x, ctx->x, p521_order);
  38531. if (err == MP_OKAY)
  38532. ctx->state = 9;
  38533. break;
  38534. case 9: /* S2 */
  38535. {
  38536. sp_digit carry;
  38537. sp_int32 c;
  38538. sp_521_norm_21(ctx->x);
  38539. carry = sp_521_add_21(ctx->s, ctx->e, ctx->x);
  38540. sp_521_cond_sub_21(ctx->s, ctx->s,
  38541. p521_order, 0 - carry);
  38542. sp_521_norm_21(ctx->s);
  38543. c = sp_521_cmp_21(ctx->s, p521_order);
  38544. sp_521_cond_sub_21(ctx->s, ctx->s, p521_order,
  38545. (sp_digit)0 - (sp_digit)(c >= 0));
  38546. sp_521_norm_21(ctx->s);
  38547. /* s = s * k^-1 mod order */
  38548. sp_521_mont_mul_order_21(ctx->s, ctx->s, ctx->kInv);
  38549. sp_521_norm_21(ctx->s);
  38550. /* Check that signature is usable. */
  38551. if (sp_521_iszero_21(ctx->s) == 0) {
  38552. ctx->state = 10;
  38553. break;
  38554. }
  38555. #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
  38556. ctx->i = 1;
  38557. #endif
  38558. /* not usable gen, try again */
  38559. ctx->i--;
  38560. if (ctx->i == 0) {
  38561. err = RNG_FAILURE_E;
  38562. }
  38563. ctx->state = 1;
  38564. break;
  38565. }
  38566. case 10: /* RES */
  38567. err = sp_521_to_mp(ctx->r, rm);
  38568. if (err == MP_OKAY) {
  38569. err = sp_521_to_mp(ctx->s, sm);
  38570. }
  38571. break;
  38572. }
  38573. if (err == MP_OKAY && ctx->state != 10) {
  38574. err = FP_WOULDBLOCK;
  38575. }
  38576. if (err != FP_WOULDBLOCK) {
  38577. XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 21U);
  38578. XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 21U);
  38579. XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 21U);
  38580. XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 21U);
  38581. XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 21U);
  38582. }
  38583. return err;
  38584. }
  38585. #endif /* WOLFSSL_SP_NONBLOCK */
  38586. int sp_ecc_sign_521(const byte* hash, word32 hashLen, WC_RNG* rng,
  38587. const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
  38588. {
  38589. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  38590. sp_digit* e = NULL;
  38591. sp_point_521* point = NULL;
  38592. #else
  38593. sp_digit e[7 * 2 * 21];
  38594. sp_point_521 point[1];
  38595. #endif
  38596. sp_digit* x = NULL;
  38597. sp_digit* k = NULL;
  38598. sp_digit* r = NULL;
  38599. sp_digit* tmp = NULL;
  38600. sp_digit* s = NULL;
  38601. sp_int32 c;
  38602. int err = MP_OKAY;
  38603. int i;
  38604. (void)heap;
  38605. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  38606. if (err == MP_OKAY) {
  38607. point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap,
  38608. DYNAMIC_TYPE_ECC);
  38609. if (point == NULL)
  38610. err = MEMORY_E;
  38611. }
  38612. if (err == MP_OKAY) {
  38613. e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 21, heap,
  38614. DYNAMIC_TYPE_ECC);
  38615. if (e == NULL)
  38616. err = MEMORY_E;
  38617. }
  38618. #endif
  38619. if (err == MP_OKAY) {
  38620. x = e + 2 * 21;
  38621. k = e + 4 * 21;
  38622. r = e + 6 * 21;
  38623. tmp = e + 8 * 21;
  38624. s = e;
  38625. if (hashLen > 66U) {
  38626. hashLen = 66U;
  38627. }
  38628. }
  38629. for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) {
  38630. /* New random point. */
  38631. if (km == NULL || mp_iszero(km)) {
  38632. err = sp_521_ecc_gen_k_21(rng, k);
  38633. }
  38634. else {
  38635. sp_521_from_mp(k, 21, km);
  38636. mp_zero(km);
  38637. }
  38638. if (err == MP_OKAY) {
  38639. err = sp_521_ecc_mulmod_base_21(point, k, 1, 1, heap);
  38640. }
  38641. if (err == MP_OKAY) {
  38642. /* r = point->x mod order */
  38643. XMEMCPY(r, point->x, sizeof(sp_digit) * 21U);
  38644. sp_521_norm_21(r);
  38645. c = sp_521_cmp_21(r, p521_order);
  38646. sp_521_cond_sub_21(r, r, p521_order,
  38647. (sp_digit)0 - (sp_digit)(c >= 0));
  38648. sp_521_norm_21(r);
  38649. sp_521_from_mp(x, 21, priv);
  38650. sp_521_from_bin(e, 21, hash, (int)hashLen);
  38651. if (hashLen == 66U) {
  38652. sp_521_rshift_21(e, e, 7);
  38653. e[20] |= ((sp_digit)hash[0]) << 13;
  38654. }
  38655. err = sp_521_calc_s_21(s, r, k, x, e, tmp);
  38656. }
  38657. /* Check that signature is usable. */
  38658. if ((err == MP_OKAY) && (sp_521_iszero_21(s) == 0)) {
  38659. break;
  38660. }
  38661. #ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
  38662. i = 1;
  38663. #endif
  38664. }
  38665. if (i == 0) {
  38666. err = RNG_FAILURE_E;
  38667. }
  38668. if (err == MP_OKAY) {
  38669. err = sp_521_to_mp(r, rm);
  38670. }
  38671. if (err == MP_OKAY) {
  38672. err = sp_521_to_mp(s, sm);
  38673. }
  38674. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  38675. if (e != NULL)
  38676. #endif
  38677. {
  38678. ForceZero(e, sizeof(sp_digit) * 7 * 2 * 21);
  38679. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  38680. XFREE(e, heap, DYNAMIC_TYPE_ECC);
  38681. #endif
  38682. }
  38683. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  38684. if (point != NULL)
  38685. #endif
  38686. {
  38687. ForceZero(point, sizeof(sp_point_521));
  38688. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  38689. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  38690. #endif
  38691. }
  38692. return err;
  38693. }
  38694. #endif /* HAVE_ECC_SIGN */
  38695. #ifndef WOLFSSL_SP_SMALL
  38696. static const char sp_521_tab32_21[32] = {
  38697. 1, 10, 2, 11, 14, 22, 3, 30,
  38698. 12, 15, 17, 19, 23, 26, 4, 31,
  38699. 9, 13, 21, 29, 16, 18, 25, 8,
  38700. 20, 28, 24, 7, 27, 6, 5, 32};
  38701. static int sp_521_num_bits_25_21(sp_digit v)
  38702. {
  38703. v |= v >> 1;
  38704. v |= v >> 2;
  38705. v |= v >> 4;
  38706. v |= v >> 8;
  38707. v |= v >> 16;
  38708. return sp_521_tab32_21[(uint32_t)(v*0x07C4ACDD) >> 27];
  38709. }
  38710. static int sp_521_num_bits_21(const sp_digit* a)
  38711. {
  38712. int i;
  38713. int r = 0;
  38714. for (i = 20; i >= 0; i--) {
  38715. if (a[i] != 0) {
  38716. r = sp_521_num_bits_25_21(a[i]);
  38717. r += i * 25;
  38718. break;
  38719. }
  38720. }
  38721. return r;
  38722. }
  38723. /* Non-constant time modular inversion.
  38724. *
  38725. * @param [out] r Resulting number.
  38726. * @param [in] a Number to invert.
  38727. * @param [in] m Modulus.
  38728. * @return MP_OKAY on success.
  38729. * @return MEMEORY_E when dynamic memory allocation fails.
  38730. */
  38731. static int sp_521_mod_inv_21(sp_digit* r, const sp_digit* a, const sp_digit* m)
  38732. {
  38733. int err = MP_OKAY;
  38734. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  38735. sp_digit* u = NULL;
  38736. #else
  38737. sp_digit u[21 * 4];
  38738. #endif
  38739. sp_digit* v = NULL;
  38740. sp_digit* b = NULL;
  38741. sp_digit* d = NULL;
  38742. int ut;
  38743. int vt;
  38744. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  38745. u = (sp_digit*)XMALLOC(sizeof(sp_digit) * 21 * 4, NULL,
  38746. DYNAMIC_TYPE_ECC);
  38747. if (u == NULL)
  38748. err = MEMORY_E;
  38749. #endif
  38750. if (err == MP_OKAY) {
  38751. v = u + 21;
  38752. b = u + 2 * 21;
  38753. d = u + 3 * 21;
  38754. XMEMCPY(u, m, sizeof(sp_digit) * 21);
  38755. XMEMCPY(v, a, sizeof(sp_digit) * 21);
  38756. ut = sp_521_num_bits_21(u);
  38757. vt = sp_521_num_bits_21(v);
  38758. XMEMSET(b, 0, sizeof(sp_digit) * 21);
  38759. if ((v[0] & 1) == 0) {
  38760. sp_521_rshift1_21(v, v);
  38761. XMEMCPY(d, m, sizeof(sp_digit) * 21);
  38762. d[0]++;
  38763. sp_521_rshift1_21(d, d);
  38764. vt--;
  38765. while ((v[0] & 1) == 0) {
  38766. sp_521_rshift1_21(v, v);
  38767. if (d[0] & 1)
  38768. sp_521_add_21(d, d, m);
  38769. sp_521_rshift1_21(d, d);
  38770. vt--;
  38771. }
  38772. }
  38773. else {
  38774. XMEMSET(d+1, 0, sizeof(sp_digit) * (21 - 1));
  38775. d[0] = 1;
  38776. }
  38777. while (ut > 1 && vt > 1) {
  38778. if (ut > vt || (ut == vt &&
  38779. sp_521_cmp_21(u, v) >= 0)) {
  38780. sp_521_sub_21(u, u, v);
  38781. sp_521_norm_21(u);
  38782. sp_521_sub_21(b, b, d);
  38783. sp_521_norm_21(b);
  38784. if (b[20] < 0)
  38785. sp_521_add_21(b, b, m);
  38786. sp_521_norm_21(b);
  38787. ut = sp_521_num_bits_21(u);
  38788. do {
  38789. sp_521_rshift1_21(u, u);
  38790. if (b[0] & 1)
  38791. sp_521_add_21(b, b, m);
  38792. sp_521_rshift1_21(b, b);
  38793. ut--;
  38794. }
  38795. while (ut > 0 && (u[0] & 1) == 0);
  38796. }
  38797. else {
  38798. sp_521_sub_21(v, v, u);
  38799. sp_521_norm_21(v);
  38800. sp_521_sub_21(d, d, b);
  38801. sp_521_norm_21(d);
  38802. if (d[20] < 0)
  38803. sp_521_add_21(d, d, m);
  38804. sp_521_norm_21(d);
  38805. vt = sp_521_num_bits_21(v);
  38806. do {
  38807. sp_521_rshift1_21(v, v);
  38808. if (d[0] & 1)
  38809. sp_521_add_21(d, d, m);
  38810. sp_521_rshift1_21(d, d);
  38811. vt--;
  38812. }
  38813. while (vt > 0 && (v[0] & 1) == 0);
  38814. }
  38815. }
  38816. if (ut == 1)
  38817. XMEMCPY(r, b, sizeof(sp_digit) * 21);
  38818. else
  38819. XMEMCPY(r, d, sizeof(sp_digit) * 21);
  38820. }
  38821. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  38822. if (u != NULL)
  38823. XFREE(u, NULL, DYNAMIC_TYPE_ECC);
  38824. #endif
  38825. return err;
  38826. }
  38827. #endif /* WOLFSSL_SP_SMALL */
  38828. /* Add point p1 into point p2. Handles p1 == p2 and result at infinity.
  38829. *
  38830. * p1 First point to add and holds result.
  38831. * p2 Second point to add.
  38832. * tmp Temporary storage for intermediate numbers.
  38833. */
  38834. static void sp_521_add_points_21(sp_point_521* p1, const sp_point_521* p2,
  38835. sp_digit* tmp)
  38836. {
  38837. sp_521_proj_point_add_21(p1, p1, p2, tmp);
  38838. if (sp_521_iszero_21(p1->z)) {
  38839. if (sp_521_iszero_21(p1->x) && sp_521_iszero_21(p1->y)) {
  38840. sp_521_proj_point_dbl_21(p1, p2, tmp);
  38841. }
  38842. else {
  38843. /* Y ordinate is not used from here - don't set. */
  38844. p1->x[0] = 0;
  38845. p1->x[1] = 0;
  38846. p1->x[2] = 0;
  38847. p1->x[3] = 0;
  38848. p1->x[4] = 0;
  38849. p1->x[5] = 0;
  38850. p1->x[6] = 0;
  38851. p1->x[7] = 0;
  38852. p1->x[8] = 0;
  38853. p1->x[9] = 0;
  38854. p1->x[10] = 0;
  38855. p1->x[11] = 0;
  38856. p1->x[12] = 0;
  38857. p1->x[13] = 0;
  38858. p1->x[14] = 0;
  38859. p1->x[15] = 0;
  38860. p1->x[16] = 0;
  38861. p1->x[17] = 0;
  38862. p1->x[18] = 0;
  38863. p1->x[19] = 0;
  38864. p1->x[20] = 0;
  38865. XMEMCPY(p1->z, p521_norm_mod, sizeof(p521_norm_mod));
  38866. }
  38867. }
  38868. }
  38869. /* Calculate the verification point: [e/s]G + [r/s]Q
  38870. *
  38871. * p1 Calculated point.
  38872. * p2 Public point and temporary.
  38873. * s Second part of signature as a number.
  38874. * u1 Temporary number.
  38875. * u2 Temproray number.
  38876. * heap Heap to use for allocation.
  38877. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  38878. */
  38879. static int sp_521_calc_vfy_point_21(sp_point_521* p1, sp_point_521* p2,
  38880. sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap)
  38881. {
  38882. int err;
  38883. #ifndef WOLFSSL_SP_SMALL
  38884. err = sp_521_mod_inv_21(s, s, p521_order);
  38885. if (err == MP_OKAY)
  38886. #endif /* !WOLFSSL_SP_SMALL */
  38887. {
  38888. sp_521_mul_21(s, s, p521_norm_order);
  38889. err = sp_521_mod_21(s, s, p521_order);
  38890. }
  38891. if (err == MP_OKAY) {
  38892. sp_521_norm_21(s);
  38893. #ifdef WOLFSSL_SP_SMALL
  38894. {
  38895. sp_521_mont_inv_order_21(s, s, tmp);
  38896. sp_521_mont_mul_order_21(u1, u1, s);
  38897. sp_521_mont_mul_order_21(u2, u2, s);
  38898. }
  38899. #else
  38900. {
  38901. sp_521_mont_mul_order_21(u1, u1, s);
  38902. sp_521_mont_mul_order_21(u2, u2, s);
  38903. }
  38904. #endif /* WOLFSSL_SP_SMALL */
  38905. {
  38906. err = sp_521_ecc_mulmod_base_21(p1, u1, 0, 0, heap);
  38907. }
  38908. }
  38909. if ((err == MP_OKAY) && sp_521_iszero_21(p1->z)) {
  38910. p1->infinity = 1;
  38911. }
  38912. if (err == MP_OKAY) {
  38913. err = sp_521_ecc_mulmod_21(p2, p2, u2, 0, 0, heap);
  38914. }
  38915. if ((err == MP_OKAY) && sp_521_iszero_21(p2->z)) {
  38916. p2->infinity = 1;
  38917. }
  38918. if (err == MP_OKAY) {
  38919. sp_521_add_points_21(p1, p2, tmp);
  38920. }
  38921. return err;
  38922. }
  38923. #ifdef HAVE_ECC_VERIFY
  38924. /* Verify the signature values with the hash and public key.
  38925. * e = Truncate(hash, 521)
  38926. * u1 = e/s mod order
  38927. * u2 = r/s mod order
  38928. * r == (u1.G + u2.Q)->x mod order
  38929. * Optimization: Leave point in projective form.
  38930. * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z')
  38931. * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x'
  38932. * The hash is truncated to the first 521 bits.
  38933. *
  38934. * hash Hash to sign.
  38935. * hashLen Length of the hash data.
  38936. * rng Random number generator.
  38937. * priv Private part of key - scalar.
  38938. * rm First part of result as an mp_int.
  38939. * sm Sirst part of result as an mp_int.
  38940. * heap Heap to use for allocation.
  38941. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  38942. */
  38943. #ifdef WOLFSSL_SP_NONBLOCK
  38944. typedef struct sp_ecc_verify_521_ctx {
  38945. int state;
  38946. union {
  38947. sp_521_ecc_mulmod_21_ctx mulmod_ctx;
  38948. sp_521_mont_inv_order_21_ctx mont_inv_order_ctx;
  38949. sp_521_proj_point_dbl_21_ctx dbl_ctx;
  38950. sp_521_proj_point_add_21_ctx add_ctx;
  38951. };
  38952. sp_digit u1[2*21];
  38953. sp_digit u2[2*21];
  38954. sp_digit s[2*21];
  38955. sp_digit tmp[2*21 * 6];
  38956. sp_point_521 p1;
  38957. sp_point_521 p2;
  38958. } sp_ecc_verify_521_ctx;
  38959. int sp_ecc_verify_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash,
  38960. word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ,
  38961. const mp_int* rm, const mp_int* sm, int* res, void* heap)
  38962. {
  38963. int err = FP_WOULDBLOCK;
  38964. sp_ecc_verify_521_ctx* ctx = (sp_ecc_verify_521_ctx*)sp_ctx->data;
  38965. typedef char ctx_size_test[sizeof(sp_ecc_verify_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  38966. (void)sizeof(ctx_size_test);
  38967. switch (ctx->state) {
  38968. case 0: /* INIT */
  38969. if (hashLen > 66U) {
  38970. hashLen = 66U;
  38971. }
  38972. sp_521_from_bin(ctx->u1, 21, hash, (int)hashLen);
  38973. sp_521_from_mp(ctx->u2, 21, rm);
  38974. sp_521_from_mp(ctx->s, 21, sm);
  38975. sp_521_from_mp(ctx->p2.x, 21, pX);
  38976. sp_521_from_mp(ctx->p2.y, 21, pY);
  38977. sp_521_from_mp(ctx->p2.z, 21, pZ);
  38978. if (hashLen == 66U) {
  38979. sp_521_rshift_21(ctx->u1, ctx->u1, 7);
  38980. ctx->u1[20] |= ((sp_digit)hash[0]) << 13;
  38981. }
  38982. ctx->state = 1;
  38983. break;
  38984. case 1: /* NORMS0 */
  38985. sp_521_mul_21(ctx->s, ctx->s, p521_norm_order);
  38986. err = sp_521_mod_21(ctx->s, ctx->s, p521_order);
  38987. if (err == MP_OKAY)
  38988. ctx->state = 2;
  38989. break;
  38990. case 2: /* NORMS1 */
  38991. sp_521_norm_21(ctx->s);
  38992. XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
  38993. ctx->state = 3;
  38994. break;
  38995. case 3: /* NORMS2 */
  38996. err = sp_521_mont_inv_order_21_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp);
  38997. if (err == MP_OKAY) {
  38998. ctx->state = 4;
  38999. }
  39000. break;
  39001. case 4: /* NORMS3 */
  39002. sp_521_mont_mul_order_21(ctx->u1, ctx->u1, ctx->s);
  39003. ctx->state = 5;
  39004. break;
  39005. case 5: /* NORMS4 */
  39006. sp_521_mont_mul_order_21(ctx->u2, ctx->u2, ctx->s);
  39007. XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
  39008. ctx->state = 6;
  39009. break;
  39010. case 6: /* MULBASE */
  39011. err = sp_521_ecc_mulmod_21_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p521_base, ctx->u1, 0, 0, heap);
  39012. if (err == MP_OKAY) {
  39013. if (sp_521_iszero_21(ctx->p1.z)) {
  39014. ctx->p1.infinity = 1;
  39015. }
  39016. XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
  39017. ctx->state = 7;
  39018. }
  39019. break;
  39020. case 7: /* MULMOD */
  39021. err = sp_521_ecc_mulmod_21_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, 0, heap);
  39022. if (err == MP_OKAY) {
  39023. if (sp_521_iszero_21(ctx->p2.z)) {
  39024. ctx->p2.infinity = 1;
  39025. }
  39026. XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx));
  39027. ctx->state = 8;
  39028. }
  39029. break;
  39030. case 8: /* ADD */
  39031. err = sp_521_proj_point_add_21_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp);
  39032. if (err == MP_OKAY)
  39033. ctx->state = 9;
  39034. break;
  39035. case 9: /* MONT */
  39036. /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
  39037. /* Reload r and convert to Montgomery form. */
  39038. sp_521_from_mp(ctx->u2, 21, rm);
  39039. err = sp_521_mod_mul_norm_21(ctx->u2, ctx->u2, p521_mod);
  39040. if (err == MP_OKAY)
  39041. ctx->state = 10;
  39042. break;
  39043. case 10: /* SQR */
  39044. /* u1 = r.z'.z' mod prime */
  39045. sp_521_mont_sqr_21(ctx->p1.z, ctx->p1.z, p521_mod, p521_mp_mod);
  39046. ctx->state = 11;
  39047. break;
  39048. case 11: /* MUL */
  39049. sp_521_mont_mul_21(ctx->u1, ctx->u2, ctx->p1.z, p521_mod, p521_mp_mod);
  39050. ctx->state = 12;
  39051. break;
  39052. case 12: /* RES */
  39053. {
  39054. sp_int32 c = 0;
  39055. err = MP_OKAY; /* math okay, now check result */
  39056. *res = (int)(sp_521_cmp_21(ctx->p1.x, ctx->u1) == 0);
  39057. if (*res == 0) {
  39058. sp_digit carry;
  39059. /* Reload r and add order. */
  39060. sp_521_from_mp(ctx->u2, 21, rm);
  39061. carry = sp_521_add_21(ctx->u2, ctx->u2, p521_order);
  39062. /* Carry means result is greater than mod and is not valid. */
  39063. if (carry == 0) {
  39064. sp_521_norm_21(ctx->u2);
  39065. /* Compare with mod and if greater or equal then not valid. */
  39066. c = sp_521_cmp_21(ctx->u2, p521_mod);
  39067. }
  39068. }
  39069. if ((*res == 0) && (c < 0)) {
  39070. /* Convert to Montogomery form */
  39071. err = sp_521_mod_mul_norm_21(ctx->u2, ctx->u2, p521_mod);
  39072. if (err == MP_OKAY) {
  39073. /* u1 = (r + 1*order).z'.z' mod prime */
  39074. sp_521_mont_mul_21(ctx->u1, ctx->u2, ctx->p1.z, p521_mod,
  39075. p521_mp_mod);
  39076. *res = (int)(sp_521_cmp_21(ctx->p1.x, ctx->u1) == 0);
  39077. }
  39078. }
  39079. break;
  39080. }
  39081. } /* switch */
  39082. if (err == MP_OKAY && ctx->state != 12) {
  39083. err = FP_WOULDBLOCK;
  39084. }
  39085. return err;
  39086. }
  39087. #endif /* WOLFSSL_SP_NONBLOCK */
  39088. int sp_ecc_verify_521(const byte* hash, word32 hashLen, const mp_int* pX,
  39089. const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm,
  39090. int* res, void* heap)
  39091. {
  39092. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39093. sp_digit* u1 = NULL;
  39094. sp_point_521* p1 = NULL;
  39095. #else
  39096. sp_digit u1[18 * 21];
  39097. sp_point_521 p1[2];
  39098. #endif
  39099. sp_digit* u2 = NULL;
  39100. sp_digit* s = NULL;
  39101. sp_digit* tmp = NULL;
  39102. sp_point_521* p2 = NULL;
  39103. sp_digit carry;
  39104. sp_int32 c = 0;
  39105. int err = MP_OKAY;
  39106. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39107. if (err == MP_OKAY) {
  39108. p1 = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap,
  39109. DYNAMIC_TYPE_ECC);
  39110. if (p1 == NULL)
  39111. err = MEMORY_E;
  39112. }
  39113. if (err == MP_OKAY) {
  39114. u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 21, heap,
  39115. DYNAMIC_TYPE_ECC);
  39116. if (u1 == NULL)
  39117. err = MEMORY_E;
  39118. }
  39119. #endif
  39120. if (err == MP_OKAY) {
  39121. u2 = u1 + 2 * 21;
  39122. s = u1 + 4 * 21;
  39123. tmp = u1 + 6 * 21;
  39124. p2 = p1 + 1;
  39125. if (hashLen > 66U) {
  39126. hashLen = 66U;
  39127. }
  39128. sp_521_from_bin(u1, 21, hash, (int)hashLen);
  39129. sp_521_from_mp(u2, 21, rm);
  39130. sp_521_from_mp(s, 21, sm);
  39131. sp_521_from_mp(p2->x, 21, pX);
  39132. sp_521_from_mp(p2->y, 21, pY);
  39133. sp_521_from_mp(p2->z, 21, pZ);
  39134. if (hashLen == 66U) {
  39135. sp_521_rshift_21(u1, u1, 7);
  39136. u1[20] |= ((sp_digit)hash[0]) << 13;
  39137. }
  39138. err = sp_521_calc_vfy_point_21(p1, p2, s, u1, u2, tmp, heap);
  39139. }
  39140. if (err == MP_OKAY) {
  39141. /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
  39142. /* Reload r and convert to Montgomery form. */
  39143. sp_521_from_mp(u2, 21, rm);
  39144. err = sp_521_mod_mul_norm_21(u2, u2, p521_mod);
  39145. }
  39146. if (err == MP_OKAY) {
  39147. /* u1 = r.z'.z' mod prime */
  39148. sp_521_mont_sqr_21(p1->z, p1->z, p521_mod, p521_mp_mod);
  39149. sp_521_mont_mul_21(u1, u2, p1->z, p521_mod, p521_mp_mod);
  39150. *res = (int)(sp_521_cmp_21(p1->x, u1) == 0);
  39151. if (*res == 0) {
  39152. /* Reload r and add order. */
  39153. sp_521_from_mp(u2, 21, rm);
  39154. carry = sp_521_add_21(u2, u2, p521_order);
  39155. /* Carry means result is greater than mod and is not valid. */
  39156. if (carry == 0) {
  39157. sp_521_norm_21(u2);
  39158. /* Compare with mod and if greater or equal then not valid. */
  39159. c = sp_521_cmp_21(u2, p521_mod);
  39160. }
  39161. }
  39162. if ((*res == 0) && (c < 0)) {
  39163. /* Convert to Montogomery form */
  39164. err = sp_521_mod_mul_norm_21(u2, u2, p521_mod);
  39165. if (err == MP_OKAY) {
  39166. /* u1 = (r + 1*order).z'.z' mod prime */
  39167. {
  39168. sp_521_mont_mul_21(u1, u2, p1->z, p521_mod, p521_mp_mod);
  39169. }
  39170. *res = (sp_521_cmp_21(p1->x, u1) == 0);
  39171. }
  39172. }
  39173. }
  39174. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39175. if (u1 != NULL)
  39176. XFREE(u1, heap, DYNAMIC_TYPE_ECC);
  39177. if (p1 != NULL)
  39178. XFREE(p1, heap, DYNAMIC_TYPE_ECC);
  39179. #endif
  39180. return err;
  39181. }
  39182. #endif /* HAVE_ECC_VERIFY */
  39183. #ifdef HAVE_ECC_CHECK_KEY
  39184. /* Check that the x and y oridinates are a valid point on the curve.
  39185. *
  39186. * point EC point.
  39187. * heap Heap to use if dynamically allocating.
  39188. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  39189. * not on the curve and MP_OKAY otherwise.
  39190. */
  39191. static int sp_521_ecc_is_point_21(const sp_point_521* point,
  39192. void* heap)
  39193. {
  39194. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39195. sp_digit* t1 = NULL;
  39196. #else
  39197. sp_digit t1[21 * 4];
  39198. #endif
  39199. sp_digit* t2 = NULL;
  39200. int err = MP_OKAY;
  39201. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39202. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 21 * 4, heap, DYNAMIC_TYPE_ECC);
  39203. if (t1 == NULL)
  39204. err = MEMORY_E;
  39205. #endif
  39206. (void)heap;
  39207. if (err == MP_OKAY) {
  39208. t2 = t1 + 2 * 21;
  39209. sp_521_sqr_21(t1, point->y);
  39210. (void)sp_521_mod_21(t1, t1, p521_mod);
  39211. sp_521_sqr_21(t2, point->x);
  39212. (void)sp_521_mod_21(t2, t2, p521_mod);
  39213. sp_521_mul_21(t2, t2, point->x);
  39214. (void)sp_521_mod_21(t2, t2, p521_mod);
  39215. (void)sp_521_sub_21(t2, p521_mod, t2);
  39216. sp_521_mont_add_21(t1, t1, t2, p521_mod);
  39217. sp_521_mont_add_21(t1, t1, point->x, p521_mod);
  39218. sp_521_mont_add_21(t1, t1, point->x, p521_mod);
  39219. sp_521_mont_add_21(t1, t1, point->x, p521_mod);
  39220. if (sp_521_cmp_21(t1, p521_b) != 0) {
  39221. err = MP_VAL;
  39222. }
  39223. }
  39224. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39225. if (t1 != NULL)
  39226. XFREE(t1, heap, DYNAMIC_TYPE_ECC);
  39227. #endif
  39228. return err;
  39229. }
  39230. /* Check that the x and y oridinates are a valid point on the curve.
  39231. *
  39232. * pX X ordinate of EC point.
  39233. * pY Y ordinate of EC point.
  39234. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  39235. * not on the curve and MP_OKAY otherwise.
  39236. */
  39237. int sp_ecc_is_point_521(const mp_int* pX, const mp_int* pY)
  39238. {
  39239. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39240. sp_point_521* pub = NULL;
  39241. #else
  39242. sp_point_521 pub[1];
  39243. #endif
  39244. const byte one[1] = { 1 };
  39245. int err = MP_OKAY;
  39246. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39247. pub = (sp_point_521*)XMALLOC(sizeof(sp_point_521), NULL,
  39248. DYNAMIC_TYPE_ECC);
  39249. if (pub == NULL)
  39250. err = MEMORY_E;
  39251. #endif
  39252. if (err == MP_OKAY) {
  39253. sp_521_from_mp(pub->x, 21, pX);
  39254. sp_521_from_mp(pub->y, 21, pY);
  39255. sp_521_from_bin(pub->z, 21, one, (int)sizeof(one));
  39256. err = sp_521_ecc_is_point_21(pub, NULL);
  39257. }
  39258. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39259. if (pub != NULL)
  39260. XFREE(pub, NULL, DYNAMIC_TYPE_ECC);
  39261. #endif
  39262. return err;
  39263. }
  39264. /* Check that the private scalar generates the EC point (px, py), the point is
  39265. * on the curve and the point has the correct order.
  39266. *
  39267. * pX X ordinate of EC point.
  39268. * pY Y ordinate of EC point.
  39269. * privm Private scalar that generates EC point.
  39270. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  39271. * not on the curve, ECC_INF_E if the point does not have the correct order,
  39272. * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
  39273. * MP_OKAY otherwise.
  39274. */
  39275. int sp_ecc_check_key_521(const mp_int* pX, const mp_int* pY,
  39276. const mp_int* privm, void* heap)
  39277. {
  39278. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39279. sp_digit* priv = NULL;
  39280. sp_point_521* pub = NULL;
  39281. #else
  39282. sp_digit priv[21];
  39283. sp_point_521 pub[2];
  39284. #endif
  39285. sp_point_521* p = NULL;
  39286. const byte one[1] = { 1 };
  39287. int err = MP_OKAY;
  39288. /* Quick check the lengs of public key ordinates and private key are in
  39289. * range. Proper check later.
  39290. */
  39291. if (((mp_count_bits(pX) > 521) ||
  39292. (mp_count_bits(pY) > 521) ||
  39293. ((privm != NULL) && (mp_count_bits(privm) > 521)))) {
  39294. err = ECC_OUT_OF_RANGE_E;
  39295. }
  39296. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39297. if (err == MP_OKAY) {
  39298. pub = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap,
  39299. DYNAMIC_TYPE_ECC);
  39300. if (pub == NULL)
  39301. err = MEMORY_E;
  39302. }
  39303. if (err == MP_OKAY && privm) {
  39304. priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 21, heap,
  39305. DYNAMIC_TYPE_ECC);
  39306. if (priv == NULL)
  39307. err = MEMORY_E;
  39308. }
  39309. #endif
  39310. if (err == MP_OKAY) {
  39311. p = pub + 1;
  39312. sp_521_from_mp(pub->x, 21, pX);
  39313. sp_521_from_mp(pub->y, 21, pY);
  39314. sp_521_from_bin(pub->z, 21, one, (int)sizeof(one));
  39315. if (privm)
  39316. sp_521_from_mp(priv, 21, privm);
  39317. /* Check point at infinitiy. */
  39318. if ((sp_521_iszero_21(pub->x) != 0) &&
  39319. (sp_521_iszero_21(pub->y) != 0)) {
  39320. err = ECC_INF_E;
  39321. }
  39322. }
  39323. /* Check range of X and Y */
  39324. if ((err == MP_OKAY) &&
  39325. ((sp_521_cmp_21(pub->x, p521_mod) >= 0) ||
  39326. (sp_521_cmp_21(pub->y, p521_mod) >= 0))) {
  39327. err = ECC_OUT_OF_RANGE_E;
  39328. }
  39329. if (err == MP_OKAY) {
  39330. /* Check point is on curve */
  39331. err = sp_521_ecc_is_point_21(pub, heap);
  39332. }
  39333. if (err == MP_OKAY) {
  39334. /* Point * order = infinity */
  39335. err = sp_521_ecc_mulmod_21(p, pub, p521_order, 1, 1, heap);
  39336. }
  39337. /* Check result is infinity */
  39338. if ((err == MP_OKAY) && ((sp_521_iszero_21(p->x) == 0) ||
  39339. (sp_521_iszero_21(p->y) == 0))) {
  39340. err = ECC_INF_E;
  39341. }
  39342. if (privm) {
  39343. if (err == MP_OKAY) {
  39344. /* Base * private = point */
  39345. err = sp_521_ecc_mulmod_base_21(p, priv, 1, 1, heap);
  39346. }
  39347. /* Check result is public key */
  39348. if ((err == MP_OKAY) &&
  39349. ((sp_521_cmp_21(p->x, pub->x) != 0) ||
  39350. (sp_521_cmp_21(p->y, pub->y) != 0))) {
  39351. err = ECC_PRIV_KEY_E;
  39352. }
  39353. }
  39354. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39355. if (pub != NULL)
  39356. XFREE(pub, heap, DYNAMIC_TYPE_ECC);
  39357. if (priv != NULL)
  39358. XFREE(priv, heap, DYNAMIC_TYPE_ECC);
  39359. #endif
  39360. return err;
  39361. }
  39362. #endif
  39363. #ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL
  39364. /* Add two projective EC points together.
  39365. * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ)
  39366. *
  39367. * pX First EC point's X ordinate.
  39368. * pY First EC point's Y ordinate.
  39369. * pZ First EC point's Z ordinate.
  39370. * qX Second EC point's X ordinate.
  39371. * qY Second EC point's Y ordinate.
  39372. * qZ Second EC point's Z ordinate.
  39373. * rX Resultant EC point's X ordinate.
  39374. * rY Resultant EC point's Y ordinate.
  39375. * rZ Resultant EC point's Z ordinate.
  39376. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  39377. */
  39378. int sp_ecc_proj_add_point_521(mp_int* pX, mp_int* pY, mp_int* pZ,
  39379. mp_int* qX, mp_int* qY, mp_int* qZ,
  39380. mp_int* rX, mp_int* rY, mp_int* rZ)
  39381. {
  39382. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39383. sp_digit* tmp = NULL;
  39384. sp_point_521* p = NULL;
  39385. #else
  39386. sp_digit tmp[2 * 21 * 6];
  39387. sp_point_521 p[2];
  39388. #endif
  39389. sp_point_521* q = NULL;
  39390. int err = MP_OKAY;
  39391. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39392. if (err == MP_OKAY) {
  39393. p = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, NULL,
  39394. DYNAMIC_TYPE_ECC);
  39395. if (p == NULL)
  39396. err = MEMORY_E;
  39397. }
  39398. if (err == MP_OKAY) {
  39399. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 21 * 6, NULL,
  39400. DYNAMIC_TYPE_ECC);
  39401. if (tmp == NULL) {
  39402. err = MEMORY_E;
  39403. }
  39404. }
  39405. #endif
  39406. if (err == MP_OKAY) {
  39407. q = p + 1;
  39408. sp_521_from_mp(p->x, 21, pX);
  39409. sp_521_from_mp(p->y, 21, pY);
  39410. sp_521_from_mp(p->z, 21, pZ);
  39411. sp_521_from_mp(q->x, 21, qX);
  39412. sp_521_from_mp(q->y, 21, qY);
  39413. sp_521_from_mp(q->z, 21, qZ);
  39414. p->infinity = sp_521_iszero_21(p->x) &
  39415. sp_521_iszero_21(p->y);
  39416. q->infinity = sp_521_iszero_21(q->x) &
  39417. sp_521_iszero_21(q->y);
  39418. sp_521_proj_point_add_21(p, p, q, tmp);
  39419. }
  39420. if (err == MP_OKAY) {
  39421. err = sp_521_to_mp(p->x, rX);
  39422. }
  39423. if (err == MP_OKAY) {
  39424. err = sp_521_to_mp(p->y, rY);
  39425. }
  39426. if (err == MP_OKAY) {
  39427. err = sp_521_to_mp(p->z, rZ);
  39428. }
  39429. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39430. if (tmp != NULL)
  39431. XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
  39432. if (p != NULL)
  39433. XFREE(p, NULL, DYNAMIC_TYPE_ECC);
  39434. #endif
  39435. return err;
  39436. }
  39437. /* Double a projective EC point.
  39438. * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ)
  39439. *
  39440. * pX EC point's X ordinate.
  39441. * pY EC point's Y ordinate.
  39442. * pZ EC point's Z ordinate.
  39443. * rX Resultant EC point's X ordinate.
  39444. * rY Resultant EC point's Y ordinate.
  39445. * rZ Resultant EC point's Z ordinate.
  39446. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  39447. */
  39448. int sp_ecc_proj_dbl_point_521(mp_int* pX, mp_int* pY, mp_int* pZ,
  39449. mp_int* rX, mp_int* rY, mp_int* rZ)
  39450. {
  39451. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39452. sp_digit* tmp = NULL;
  39453. sp_point_521* p = NULL;
  39454. #else
  39455. sp_digit tmp[2 * 21 * 2];
  39456. sp_point_521 p[1];
  39457. #endif
  39458. int err = MP_OKAY;
  39459. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39460. if (err == MP_OKAY) {
  39461. p = (sp_point_521*)XMALLOC(sizeof(sp_point_521), NULL,
  39462. DYNAMIC_TYPE_ECC);
  39463. if (p == NULL)
  39464. err = MEMORY_E;
  39465. }
  39466. if (err == MP_OKAY) {
  39467. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 21 * 2, NULL,
  39468. DYNAMIC_TYPE_ECC);
  39469. if (tmp == NULL)
  39470. err = MEMORY_E;
  39471. }
  39472. #endif
  39473. if (err == MP_OKAY) {
  39474. sp_521_from_mp(p->x, 21, pX);
  39475. sp_521_from_mp(p->y, 21, pY);
  39476. sp_521_from_mp(p->z, 21, pZ);
  39477. p->infinity = sp_521_iszero_21(p->x) &
  39478. sp_521_iszero_21(p->y);
  39479. sp_521_proj_point_dbl_21(p, p, tmp);
  39480. }
  39481. if (err == MP_OKAY) {
  39482. err = sp_521_to_mp(p->x, rX);
  39483. }
  39484. if (err == MP_OKAY) {
  39485. err = sp_521_to_mp(p->y, rY);
  39486. }
  39487. if (err == MP_OKAY) {
  39488. err = sp_521_to_mp(p->z, rZ);
  39489. }
  39490. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39491. if (tmp != NULL)
  39492. XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
  39493. if (p != NULL)
  39494. XFREE(p, NULL, DYNAMIC_TYPE_ECC);
  39495. #endif
  39496. return err;
  39497. }
  39498. /* Map a projective EC point to affine in place.
  39499. * pZ will be one.
  39500. *
  39501. * pX EC point's X ordinate.
  39502. * pY EC point's Y ordinate.
  39503. * pZ EC point's Z ordinate.
  39504. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  39505. */
  39506. int sp_ecc_map_521(mp_int* pX, mp_int* pY, mp_int* pZ)
  39507. {
  39508. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39509. sp_digit* tmp = NULL;
  39510. sp_point_521* p = NULL;
  39511. #else
  39512. sp_digit tmp[2 * 21 * 5];
  39513. sp_point_521 p[1];
  39514. #endif
  39515. int err = MP_OKAY;
  39516. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39517. if (err == MP_OKAY) {
  39518. p = (sp_point_521*)XMALLOC(sizeof(sp_point_521), NULL,
  39519. DYNAMIC_TYPE_ECC);
  39520. if (p == NULL)
  39521. err = MEMORY_E;
  39522. }
  39523. if (err == MP_OKAY) {
  39524. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 21 * 5, NULL,
  39525. DYNAMIC_TYPE_ECC);
  39526. if (tmp == NULL)
  39527. err = MEMORY_E;
  39528. }
  39529. #endif
  39530. if (err == MP_OKAY) {
  39531. sp_521_from_mp(p->x, 21, pX);
  39532. sp_521_from_mp(p->y, 21, pY);
  39533. sp_521_from_mp(p->z, 21, pZ);
  39534. p->infinity = sp_521_iszero_21(p->x) &
  39535. sp_521_iszero_21(p->y);
  39536. sp_521_map_21(p, p, tmp);
  39537. }
  39538. if (err == MP_OKAY) {
  39539. err = sp_521_to_mp(p->x, pX);
  39540. }
  39541. if (err == MP_OKAY) {
  39542. err = sp_521_to_mp(p->y, pY);
  39543. }
  39544. if (err == MP_OKAY) {
  39545. err = sp_521_to_mp(p->z, pZ);
  39546. }
  39547. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39548. if (tmp != NULL)
  39549. XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
  39550. if (p != NULL)
  39551. XFREE(p, NULL, DYNAMIC_TYPE_ECC);
  39552. #endif
  39553. return err;
  39554. }
  39555. #endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */
  39556. #ifdef HAVE_COMP_KEY
  39557. /* Square root power for the P521 curve. */
  39558. static const uint32_t p521_sqrt_power[17] = {
  39559. 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
  39560. 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
  39561. 0x00000000,0x00000000,0x00000080
  39562. };
  39563. /* Find the square root of a number mod the prime of the curve.
  39564. *
  39565. * y The number to operate on and the result.
  39566. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  39567. */
  39568. static int sp_521_mont_sqrt_21(sp_digit* y)
  39569. {
  39570. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39571. sp_digit* t = NULL;
  39572. #else
  39573. sp_digit t[2 * 21];
  39574. #endif
  39575. int err = MP_OKAY;
  39576. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39577. t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 21, NULL, DYNAMIC_TYPE_ECC);
  39578. if (t == NULL)
  39579. err = MEMORY_E;
  39580. #endif
  39581. if (err == MP_OKAY) {
  39582. {
  39583. int i;
  39584. XMEMCPY(t, y, sizeof(sp_digit) * 21);
  39585. for (i=518; i>=0; i--) {
  39586. sp_521_mont_sqr_21(t, t, p521_mod, p521_mp_mod);
  39587. if (p521_sqrt_power[i / 32] & ((sp_digit)1 << (i % 32)))
  39588. sp_521_mont_mul_21(t, t, y, p521_mod, p521_mp_mod);
  39589. }
  39590. XMEMCPY(y, t, sizeof(sp_digit) * 21);
  39591. }
  39592. }
  39593. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39594. if (t != NULL)
  39595. XFREE(t, NULL, DYNAMIC_TYPE_ECC);
  39596. #endif
  39597. return err;
  39598. }
  39599. /* Uncompress the point given the X ordinate.
  39600. *
  39601. * xm X ordinate.
  39602. * odd Whether the Y ordinate is odd.
  39603. * ym Calculated Y ordinate.
  39604. * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
  39605. */
  39606. int sp_ecc_uncompress_521(mp_int* xm, int odd, mp_int* ym)
  39607. {
  39608. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39609. sp_digit* x = NULL;
  39610. #else
  39611. sp_digit x[4 * 21];
  39612. #endif
  39613. sp_digit* y = NULL;
  39614. int err = MP_OKAY;
  39615. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39616. x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 21, NULL, DYNAMIC_TYPE_ECC);
  39617. if (x == NULL)
  39618. err = MEMORY_E;
  39619. #endif
  39620. if (err == MP_OKAY) {
  39621. y = x + 2 * 21;
  39622. sp_521_from_mp(x, 21, xm);
  39623. err = sp_521_mod_mul_norm_21(x, x, p521_mod);
  39624. }
  39625. if (err == MP_OKAY) {
  39626. /* y = x^3 */
  39627. {
  39628. sp_521_mont_sqr_21(y, x, p521_mod, p521_mp_mod);
  39629. sp_521_mont_mul_21(y, y, x, p521_mod, p521_mp_mod);
  39630. }
  39631. /* y = x^3 - 3x */
  39632. sp_521_mont_sub_21(y, y, x, p521_mod);
  39633. sp_521_mont_sub_21(y, y, x, p521_mod);
  39634. sp_521_mont_sub_21(y, y, x, p521_mod);
  39635. /* y = x^3 - 3x + b */
  39636. err = sp_521_mod_mul_norm_21(x, p521_b, p521_mod);
  39637. }
  39638. if (err == MP_OKAY) {
  39639. sp_521_mont_add_21(y, y, x, p521_mod);
  39640. /* y = sqrt(x^3 - 3x + b) */
  39641. err = sp_521_mont_sqrt_21(y);
  39642. }
  39643. if (err == MP_OKAY) {
  39644. XMEMSET(y + 21, 0, 21U * sizeof(sp_digit));
  39645. sp_521_mont_reduce_21(y, p521_mod, p521_mp_mod);
  39646. if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) {
  39647. sp_521_mont_sub_21(y, p521_mod, y, p521_mod);
  39648. }
  39649. err = sp_521_to_mp(y, ym);
  39650. }
  39651. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  39652. if (x != NULL)
  39653. XFREE(x, NULL, DYNAMIC_TYPE_ECC);
  39654. #endif
  39655. return err;
  39656. }
  39657. #endif
  39658. #endif /* WOLFSSL_SP_521 */
  39659. #ifdef WOLFSSL_SP_1024
  39660. /* Point structure to use. */
  39661. typedef struct sp_point_1024 {
  39662. /* X ordinate of point. */
  39663. sp_digit x[2 * 42];
  39664. /* Y ordinate of point. */
  39665. sp_digit y[2 * 42];
  39666. /* Z ordinate of point. */
  39667. sp_digit z[2 * 42];
  39668. /* Indicates point is at infinity. */
  39669. int infinity;
  39670. } sp_point_1024;
  39671. #ifndef WOLFSSL_SP_SMALL
  39672. /* Multiply a and b into r. (r = a * b)
  39673. *
  39674. * r A single precision integer.
  39675. * a A single precision integer.
  39676. * b A single precision integer.
  39677. */
  39678. SP_NOINLINE static void sp_1024_mul_7(sp_digit* r, const sp_digit* a,
  39679. const sp_digit* b)
  39680. {
  39681. sp_int64 t0 = ((sp_int64)a[ 0]) * b[ 0];
  39682. sp_int64 t1 = ((sp_int64)a[ 0]) * b[ 1]
  39683. + ((sp_int64)a[ 1]) * b[ 0];
  39684. sp_int64 t2 = ((sp_int64)a[ 0]) * b[ 2]
  39685. + ((sp_int64)a[ 1]) * b[ 1]
  39686. + ((sp_int64)a[ 2]) * b[ 0];
  39687. sp_int64 t3 = ((sp_int64)a[ 0]) * b[ 3]
  39688. + ((sp_int64)a[ 1]) * b[ 2]
  39689. + ((sp_int64)a[ 2]) * b[ 1]
  39690. + ((sp_int64)a[ 3]) * b[ 0];
  39691. sp_int64 t4 = ((sp_int64)a[ 0]) * b[ 4]
  39692. + ((sp_int64)a[ 1]) * b[ 3]
  39693. + ((sp_int64)a[ 2]) * b[ 2]
  39694. + ((sp_int64)a[ 3]) * b[ 1]
  39695. + ((sp_int64)a[ 4]) * b[ 0];
  39696. sp_int64 t5 = ((sp_int64)a[ 0]) * b[ 5]
  39697. + ((sp_int64)a[ 1]) * b[ 4]
  39698. + ((sp_int64)a[ 2]) * b[ 3]
  39699. + ((sp_int64)a[ 3]) * b[ 2]
  39700. + ((sp_int64)a[ 4]) * b[ 1]
  39701. + ((sp_int64)a[ 5]) * b[ 0];
  39702. sp_int64 t6 = ((sp_int64)a[ 0]) * b[ 6]
  39703. + ((sp_int64)a[ 1]) * b[ 5]
  39704. + ((sp_int64)a[ 2]) * b[ 4]
  39705. + ((sp_int64)a[ 3]) * b[ 3]
  39706. + ((sp_int64)a[ 4]) * b[ 2]
  39707. + ((sp_int64)a[ 5]) * b[ 1]
  39708. + ((sp_int64)a[ 6]) * b[ 0];
  39709. sp_int64 t7 = ((sp_int64)a[ 1]) * b[ 6]
  39710. + ((sp_int64)a[ 2]) * b[ 5]
  39711. + ((sp_int64)a[ 3]) * b[ 4]
  39712. + ((sp_int64)a[ 4]) * b[ 3]
  39713. + ((sp_int64)a[ 5]) * b[ 2]
  39714. + ((sp_int64)a[ 6]) * b[ 1];
  39715. sp_int64 t8 = ((sp_int64)a[ 2]) * b[ 6]
  39716. + ((sp_int64)a[ 3]) * b[ 5]
  39717. + ((sp_int64)a[ 4]) * b[ 4]
  39718. + ((sp_int64)a[ 5]) * b[ 3]
  39719. + ((sp_int64)a[ 6]) * b[ 2];
  39720. sp_int64 t9 = ((sp_int64)a[ 3]) * b[ 6]
  39721. + ((sp_int64)a[ 4]) * b[ 5]
  39722. + ((sp_int64)a[ 5]) * b[ 4]
  39723. + ((sp_int64)a[ 6]) * b[ 3];
  39724. sp_int64 t10 = ((sp_int64)a[ 4]) * b[ 6]
  39725. + ((sp_int64)a[ 5]) * b[ 5]
  39726. + ((sp_int64)a[ 6]) * b[ 4];
  39727. sp_int64 t11 = ((sp_int64)a[ 5]) * b[ 6]
  39728. + ((sp_int64)a[ 6]) * b[ 5];
  39729. sp_int64 t12 = ((sp_int64)a[ 6]) * b[ 6];
  39730. t1 += t0 >> 25; r[ 0] = t0 & 0x1ffffff;
  39731. t2 += t1 >> 25; r[ 1] = t1 & 0x1ffffff;
  39732. t3 += t2 >> 25; r[ 2] = t2 & 0x1ffffff;
  39733. t4 += t3 >> 25; r[ 3] = t3 & 0x1ffffff;
  39734. t5 += t4 >> 25; r[ 4] = t4 & 0x1ffffff;
  39735. t6 += t5 >> 25; r[ 5] = t5 & 0x1ffffff;
  39736. t7 += t6 >> 25; r[ 6] = t6 & 0x1ffffff;
  39737. t8 += t7 >> 25; r[ 7] = t7 & 0x1ffffff;
  39738. t9 += t8 >> 25; r[ 8] = t8 & 0x1ffffff;
  39739. t10 += t9 >> 25; r[ 9] = t9 & 0x1ffffff;
  39740. t11 += t10 >> 25; r[10] = t10 & 0x1ffffff;
  39741. t12 += t11 >> 25; r[11] = t11 & 0x1ffffff;
  39742. r[13] = (sp_digit)(t12 >> 25);
  39743. r[12] = t12 & 0x1ffffff;
  39744. }
  39745. /* Square a and put result in r. (r = a * a)
  39746. *
  39747. * r A single precision integer.
  39748. * a A single precision integer.
  39749. */
  39750. SP_NOINLINE static void sp_1024_sqr_7(sp_digit* r, const sp_digit* a)
  39751. {
  39752. sp_int64 t0 = ((sp_int64)a[ 0]) * a[ 0];
  39753. sp_int64 t1 = (((sp_int64)a[ 0]) * a[ 1]) * 2;
  39754. sp_int64 t2 = (((sp_int64)a[ 0]) * a[ 2]) * 2
  39755. + ((sp_int64)a[ 1]) * a[ 1];
  39756. sp_int64 t3 = (((sp_int64)a[ 0]) * a[ 3]
  39757. + ((sp_int64)a[ 1]) * a[ 2]) * 2;
  39758. sp_int64 t4 = (((sp_int64)a[ 0]) * a[ 4]
  39759. + ((sp_int64)a[ 1]) * a[ 3]) * 2
  39760. + ((sp_int64)a[ 2]) * a[ 2];
  39761. sp_int64 t5 = (((sp_int64)a[ 0]) * a[ 5]
  39762. + ((sp_int64)a[ 1]) * a[ 4]
  39763. + ((sp_int64)a[ 2]) * a[ 3]) * 2;
  39764. sp_int64 t6 = (((sp_int64)a[ 0]) * a[ 6]
  39765. + ((sp_int64)a[ 1]) * a[ 5]
  39766. + ((sp_int64)a[ 2]) * a[ 4]) * 2
  39767. + ((sp_int64)a[ 3]) * a[ 3];
  39768. sp_int64 t7 = (((sp_int64)a[ 1]) * a[ 6]
  39769. + ((sp_int64)a[ 2]) * a[ 5]
  39770. + ((sp_int64)a[ 3]) * a[ 4]) * 2;
  39771. sp_int64 t8 = (((sp_int64)a[ 2]) * a[ 6]
  39772. + ((sp_int64)a[ 3]) * a[ 5]) * 2
  39773. + ((sp_int64)a[ 4]) * a[ 4];
  39774. sp_int64 t9 = (((sp_int64)a[ 3]) * a[ 6]
  39775. + ((sp_int64)a[ 4]) * a[ 5]) * 2;
  39776. sp_int64 t10 = (((sp_int64)a[ 4]) * a[ 6]) * 2
  39777. + ((sp_int64)a[ 5]) * a[ 5];
  39778. sp_int64 t11 = (((sp_int64)a[ 5]) * a[ 6]) * 2;
  39779. sp_int64 t12 = ((sp_int64)a[ 6]) * a[ 6];
  39780. t1 += t0 >> 25; r[ 0] = t0 & 0x1ffffff;
  39781. t2 += t1 >> 25; r[ 1] = t1 & 0x1ffffff;
  39782. t3 += t2 >> 25; r[ 2] = t2 & 0x1ffffff;
  39783. t4 += t3 >> 25; r[ 3] = t3 & 0x1ffffff;
  39784. t5 += t4 >> 25; r[ 4] = t4 & 0x1ffffff;
  39785. t6 += t5 >> 25; r[ 5] = t5 & 0x1ffffff;
  39786. t7 += t6 >> 25; r[ 6] = t6 & 0x1ffffff;
  39787. t8 += t7 >> 25; r[ 7] = t7 & 0x1ffffff;
  39788. t9 += t8 >> 25; r[ 8] = t8 & 0x1ffffff;
  39789. t10 += t9 >> 25; r[ 9] = t9 & 0x1ffffff;
  39790. t11 += t10 >> 25; r[10] = t10 & 0x1ffffff;
  39791. t12 += t11 >> 25; r[11] = t11 & 0x1ffffff;
  39792. r[13] = (sp_digit)(t12 >> 25);
  39793. r[12] = t12 & 0x1ffffff;
  39794. }
  39795. /* Add b to a into r. (r = a + b)
  39796. *
  39797. * r A single precision integer.
  39798. * a A single precision integer.
  39799. * b A single precision integer.
  39800. */
  39801. SP_NOINLINE static int sp_1024_add_7(sp_digit* r, const sp_digit* a,
  39802. const sp_digit* b)
  39803. {
  39804. r[ 0] = a[ 0] + b[ 0];
  39805. r[ 1] = a[ 1] + b[ 1];
  39806. r[ 2] = a[ 2] + b[ 2];
  39807. r[ 3] = a[ 3] + b[ 3];
  39808. r[ 4] = a[ 4] + b[ 4];
  39809. r[ 5] = a[ 5] + b[ 5];
  39810. r[ 6] = a[ 6] + b[ 6];
  39811. return 0;
  39812. }
  39813. /* Sub b from a into r. (r = a - b)
  39814. *
  39815. * r A single precision integer.
  39816. * a A single precision integer.
  39817. * b A single precision integer.
  39818. */
  39819. SP_NOINLINE static int sp_1024_sub_14(sp_digit* r, const sp_digit* a,
  39820. const sp_digit* b)
  39821. {
  39822. r[ 0] = a[ 0] - b[ 0];
  39823. r[ 1] = a[ 1] - b[ 1];
  39824. r[ 2] = a[ 2] - b[ 2];
  39825. r[ 3] = a[ 3] - b[ 3];
  39826. r[ 4] = a[ 4] - b[ 4];
  39827. r[ 5] = a[ 5] - b[ 5];
  39828. r[ 6] = a[ 6] - b[ 6];
  39829. r[ 7] = a[ 7] - b[ 7];
  39830. r[ 8] = a[ 8] - b[ 8];
  39831. r[ 9] = a[ 9] - b[ 9];
  39832. r[10] = a[10] - b[10];
  39833. r[11] = a[11] - b[11];
  39834. r[12] = a[12] - b[12];
  39835. r[13] = a[13] - b[13];
  39836. return 0;
  39837. }
  39838. /* Add b to a into r. (r = a + b)
  39839. *
  39840. * r A single precision integer.
  39841. * a A single precision integer.
  39842. * b A single precision integer.
  39843. */
  39844. SP_NOINLINE static int sp_1024_add_14(sp_digit* r, const sp_digit* a,
  39845. const sp_digit* b)
  39846. {
  39847. r[ 0] = a[ 0] + b[ 0];
  39848. r[ 1] = a[ 1] + b[ 1];
  39849. r[ 2] = a[ 2] + b[ 2];
  39850. r[ 3] = a[ 3] + b[ 3];
  39851. r[ 4] = a[ 4] + b[ 4];
  39852. r[ 5] = a[ 5] + b[ 5];
  39853. r[ 6] = a[ 6] + b[ 6];
  39854. r[ 7] = a[ 7] + b[ 7];
  39855. r[ 8] = a[ 8] + b[ 8];
  39856. r[ 9] = a[ 9] + b[ 9];
  39857. r[10] = a[10] + b[10];
  39858. r[11] = a[11] + b[11];
  39859. r[12] = a[12] + b[12];
  39860. r[13] = a[13] + b[13];
  39861. return 0;
  39862. }
  39863. /* Multiply a and b into r. (r = a * b)
  39864. *
  39865. * r A single precision integer.
  39866. * a A single precision integer.
  39867. * b A single precision integer.
  39868. */
  39869. SP_NOINLINE static void sp_1024_mul_21(sp_digit* r, const sp_digit* a,
  39870. const sp_digit* b)
  39871. {
  39872. sp_digit p0[14];
  39873. sp_digit p1[14];
  39874. sp_digit p2[14];
  39875. sp_digit p3[14];
  39876. sp_digit p4[14];
  39877. sp_digit p5[14];
  39878. sp_digit t0[14];
  39879. sp_digit t1[14];
  39880. sp_digit t2[14];
  39881. sp_digit a0[7];
  39882. sp_digit a1[7];
  39883. sp_digit a2[7];
  39884. sp_digit b0[7];
  39885. sp_digit b1[7];
  39886. sp_digit b2[7];
  39887. (void)sp_1024_add_7(a0, a, &a[7]);
  39888. (void)sp_1024_add_7(b0, b, &b[7]);
  39889. (void)sp_1024_add_7(a1, &a[7], &a[14]);
  39890. (void)sp_1024_add_7(b1, &b[7], &b[14]);
  39891. (void)sp_1024_add_7(a2, a0, &a[14]);
  39892. (void)sp_1024_add_7(b2, b0, &b[14]);
  39893. sp_1024_mul_7(p0, a, b);
  39894. sp_1024_mul_7(p2, &a[7], &b[7]);
  39895. sp_1024_mul_7(p4, &a[14], &b[14]);
  39896. sp_1024_mul_7(p1, a0, b0);
  39897. sp_1024_mul_7(p3, a1, b1);
  39898. sp_1024_mul_7(p5, a2, b2);
  39899. XMEMSET(r, 0, sizeof(*r)*2U*21U);
  39900. (void)sp_1024_sub_14(t0, p3, p2);
  39901. (void)sp_1024_sub_14(t1, p1, p2);
  39902. (void)sp_1024_sub_14(t2, p5, t0);
  39903. (void)sp_1024_sub_14(t2, t2, t1);
  39904. (void)sp_1024_sub_14(t0, t0, p4);
  39905. (void)sp_1024_sub_14(t1, t1, p0);
  39906. (void)sp_1024_add_14(r, r, p0);
  39907. (void)sp_1024_add_14(&r[7], &r[7], t1);
  39908. (void)sp_1024_add_14(&r[14], &r[14], t2);
  39909. (void)sp_1024_add_14(&r[21], &r[21], t0);
  39910. (void)sp_1024_add_14(&r[28], &r[28], p4);
  39911. }
  39912. /* Square a into r. (r = a * a)
  39913. *
  39914. * r A single precision integer.
  39915. * a A single precision integer.
  39916. */
  39917. SP_NOINLINE static void sp_1024_sqr_21(sp_digit* r, const sp_digit* a)
  39918. {
  39919. sp_digit p0[14];
  39920. sp_digit p1[14];
  39921. sp_digit p2[14];
  39922. sp_digit p3[14];
  39923. sp_digit p4[14];
  39924. sp_digit p5[14];
  39925. sp_digit t0[14];
  39926. sp_digit t1[14];
  39927. sp_digit t2[14];
  39928. sp_digit a0[7];
  39929. sp_digit a1[7];
  39930. sp_digit a2[7];
  39931. (void)sp_1024_add_7(a0, a, &a[7]);
  39932. (void)sp_1024_add_7(a1, &a[7], &a[14]);
  39933. (void)sp_1024_add_7(a2, a0, &a[14]);
  39934. sp_1024_sqr_7(p0, a);
  39935. sp_1024_sqr_7(p2, &a[7]);
  39936. sp_1024_sqr_7(p4, &a[14]);
  39937. sp_1024_sqr_7(p1, a0);
  39938. sp_1024_sqr_7(p3, a1);
  39939. sp_1024_sqr_7(p5, a2);
  39940. XMEMSET(r, 0, sizeof(*r)*2U*21U);
  39941. (void)sp_1024_sub_14(t0, p3, p2);
  39942. (void)sp_1024_sub_14(t1, p1, p2);
  39943. (void)sp_1024_sub_14(t2, p5, t0);
  39944. (void)sp_1024_sub_14(t2, t2, t1);
  39945. (void)sp_1024_sub_14(t0, t0, p4);
  39946. (void)sp_1024_sub_14(t1, t1, p0);
  39947. (void)sp_1024_add_14(r, r, p0);
  39948. (void)sp_1024_add_14(&r[7], &r[7], t1);
  39949. (void)sp_1024_add_14(&r[14], &r[14], t2);
  39950. (void)sp_1024_add_14(&r[21], &r[21], t0);
  39951. (void)sp_1024_add_14(&r[28], &r[28], p4);
  39952. }
  39953. /* Add b to a into r. (r = a + b)
  39954. *
  39955. * r A single precision integer.
  39956. * a A single precision integer.
  39957. * b A single precision integer.
  39958. */
  39959. SP_NOINLINE static int sp_1024_add_21(sp_digit* r, const sp_digit* a,
  39960. const sp_digit* b)
  39961. {
  39962. int i;
  39963. for (i = 0; i < 16; i += 8) {
  39964. r[i + 0] = a[i + 0] + b[i + 0];
  39965. r[i + 1] = a[i + 1] + b[i + 1];
  39966. r[i + 2] = a[i + 2] + b[i + 2];
  39967. r[i + 3] = a[i + 3] + b[i + 3];
  39968. r[i + 4] = a[i + 4] + b[i + 4];
  39969. r[i + 5] = a[i + 5] + b[i + 5];
  39970. r[i + 6] = a[i + 6] + b[i + 6];
  39971. r[i + 7] = a[i + 7] + b[i + 7];
  39972. }
  39973. r[16] = a[16] + b[16];
  39974. r[17] = a[17] + b[17];
  39975. r[18] = a[18] + b[18];
  39976. r[19] = a[19] + b[19];
  39977. r[20] = a[20] + b[20];
  39978. return 0;
  39979. }
  39980. /* Add b to a into r. (r = a + b)
  39981. *
  39982. * r A single precision integer.
  39983. * a A single precision integer.
  39984. * b A single precision integer.
  39985. */
  39986. SP_NOINLINE static int sp_1024_add_42(sp_digit* r, const sp_digit* a,
  39987. const sp_digit* b)
  39988. {
  39989. int i;
  39990. for (i = 0; i < 40; i += 8) {
  39991. r[i + 0] = a[i + 0] + b[i + 0];
  39992. r[i + 1] = a[i + 1] + b[i + 1];
  39993. r[i + 2] = a[i + 2] + b[i + 2];
  39994. r[i + 3] = a[i + 3] + b[i + 3];
  39995. r[i + 4] = a[i + 4] + b[i + 4];
  39996. r[i + 5] = a[i + 5] + b[i + 5];
  39997. r[i + 6] = a[i + 6] + b[i + 6];
  39998. r[i + 7] = a[i + 7] + b[i + 7];
  39999. }
  40000. r[40] = a[40] + b[40];
  40001. r[41] = a[41] + b[41];
  40002. return 0;
  40003. }
  40004. /* Sub b from a into r. (r = a - b)
  40005. *
  40006. * r A single precision integer.
  40007. * a A single precision integer.
  40008. * b A single precision integer.
  40009. */
  40010. SP_NOINLINE static int sp_1024_sub_42(sp_digit* r, const sp_digit* a,
  40011. const sp_digit* b)
  40012. {
  40013. int i;
  40014. for (i = 0; i < 40; i += 8) {
  40015. r[i + 0] = a[i + 0] - b[i + 0];
  40016. r[i + 1] = a[i + 1] - b[i + 1];
  40017. r[i + 2] = a[i + 2] - b[i + 2];
  40018. r[i + 3] = a[i + 3] - b[i + 3];
  40019. r[i + 4] = a[i + 4] - b[i + 4];
  40020. r[i + 5] = a[i + 5] - b[i + 5];
  40021. r[i + 6] = a[i + 6] - b[i + 6];
  40022. r[i + 7] = a[i + 7] - b[i + 7];
  40023. }
  40024. r[40] = a[40] - b[40];
  40025. r[41] = a[41] - b[41];
  40026. return 0;
  40027. }
  40028. /* Multiply a and b into r. (r = a * b)
  40029. *
  40030. * r A single precision integer.
  40031. * a A single precision integer.
  40032. * b A single precision integer.
  40033. */
  40034. SP_NOINLINE static void sp_1024_mul_42(sp_digit* r, const sp_digit* a,
  40035. const sp_digit* b)
  40036. {
  40037. sp_digit* z0 = r;
  40038. sp_digit z1[42];
  40039. sp_digit* a1 = z1;
  40040. sp_digit b1[21];
  40041. sp_digit* z2 = r + 42;
  40042. (void)sp_1024_add_21(a1, a, &a[21]);
  40043. (void)sp_1024_add_21(b1, b, &b[21]);
  40044. sp_1024_mul_21(z2, &a[21], &b[21]);
  40045. sp_1024_mul_21(z0, a, b);
  40046. sp_1024_mul_21(z1, a1, b1);
  40047. (void)sp_1024_sub_42(z1, z1, z2);
  40048. (void)sp_1024_sub_42(z1, z1, z0);
  40049. (void)sp_1024_add_42(r + 21, r + 21, z1);
  40050. }
  40051. /* Square a and put result in r. (r = a * a)
  40052. *
  40053. * r A single precision integer.
  40054. * a A single precision integer.
  40055. */
  40056. SP_NOINLINE static void sp_1024_sqr_42(sp_digit* r, const sp_digit* a)
  40057. {
  40058. sp_digit* z0 = r;
  40059. sp_digit z1[42];
  40060. sp_digit* a1 = z1;
  40061. sp_digit* z2 = r + 42;
  40062. (void)sp_1024_add_21(a1, a, &a[21]);
  40063. sp_1024_sqr_21(z2, &a[21]);
  40064. sp_1024_sqr_21(z0, a);
  40065. sp_1024_sqr_21(z1, a1);
  40066. (void)sp_1024_sub_42(z1, z1, z2);
  40067. (void)sp_1024_sub_42(z1, z1, z0);
  40068. (void)sp_1024_add_42(r + 21, r + 21, z1);
  40069. }
  40070. #else
  40071. /* Multiply a and b into r. (r = a * b)
  40072. *
  40073. * r A single precision integer.
  40074. * a A single precision integer.
  40075. * b A single precision integer.
  40076. */
  40077. SP_NOINLINE static void sp_1024_mul_42(sp_digit* r, const sp_digit* a,
  40078. const sp_digit* b)
  40079. {
  40080. int i;
  40081. int imax;
  40082. int k;
  40083. sp_uint64 c;
  40084. sp_uint64 lo;
  40085. c = ((sp_uint64)a[41]) * b[41];
  40086. r[83] = (sp_digit)(c >> 25);
  40087. c &= 0x1ffffff;
  40088. for (k = 81; k >= 0; k--) {
  40089. if (k >= 42) {
  40090. i = k - 41;
  40091. imax = 41;
  40092. }
  40093. else {
  40094. i = 0;
  40095. imax = k;
  40096. }
  40097. lo = 0;
  40098. for (; i <= imax; i++) {
  40099. lo += ((sp_uint64)a[i]) * b[k - i];
  40100. }
  40101. c += lo >> 25;
  40102. r[k + 2] += (sp_digit)(c >> 25);
  40103. r[k + 1] = (sp_digit)(c & 0x1ffffff);
  40104. c = lo & 0x1ffffff;
  40105. }
  40106. r[0] = (sp_digit)c;
  40107. }
  40108. /* Square a and put result in r. (r = a * a)
  40109. *
  40110. * r A single precision integer.
  40111. * a A single precision integer.
  40112. */
  40113. SP_NOINLINE static void sp_1024_sqr_42(sp_digit* r, const sp_digit* a)
  40114. {
  40115. int i;
  40116. int imax;
  40117. int k;
  40118. sp_uint64 c;
  40119. sp_uint64 t;
  40120. c = ((sp_uint64)a[41]) * a[41];
  40121. r[83] = (sp_digit)(c >> 25);
  40122. c = (c & 0x1ffffff) << 25;
  40123. for (k = 81; k >= 0; k--) {
  40124. i = (k + 1) / 2;
  40125. if ((k & 1) == 0) {
  40126. c += ((sp_uint64)a[i]) * a[i];
  40127. i++;
  40128. }
  40129. if (k < 41) {
  40130. imax = k;
  40131. }
  40132. else {
  40133. imax = 41;
  40134. }
  40135. t = 0;
  40136. for (; i <= imax; i++) {
  40137. t += ((sp_uint64)a[i]) * a[k - i];
  40138. }
  40139. c += t * 2;
  40140. r[k + 2] += (sp_digit) (c >> 50);
  40141. r[k + 1] = (sp_digit)((c >> 25) & 0x1ffffff);
  40142. c = (c & 0x1ffffff) << 25;
  40143. }
  40144. r[0] = (sp_digit)(c >> 25);
  40145. }
  40146. #endif /* !WOLFSSL_SP_SMALL */
  40147. /* The modulus (prime) of the curve P1024. */
  40148. static const sp_digit p1024_mod[42] = {
  40149. 0x0a85feb,0x0c03d7f,0x1a1d99b,0x0158f59,0x00c5df1,0x02bed84,0x1a08e26,
  40150. 0x03ff9c7,0x156971f,0x1ca6b57,0x1026aa7,0x18a4387,0x02a7cf3,0x18c2954,
  40151. 0x0bfd2a0,0x039c36d,0x1cd6568,0x0289562,0x09ad335,0x18c90e6,0x06d0e26,
  40152. 0x1a53335,0x0d5b49f,0x1911432,0x1b39ff7,0x05873c8,0x14c6967,0x050e61a,
  40153. 0x1c0f1b2,0x1593f17,0x0bbd02a,0x167c034,0x09ae358,0x04130df,0x138672d,
  40154. 0x1482d81,0x1ad0657,0x0308cc6,0x0ff6997,0x03e14ac,0x0997abb,0x0000000
  40155. };
  40156. /* The Montgomery normalizer for modulus of the curve P1024. */
  40157. static const sp_digit p1024_norm_mod[42] = {
  40158. 0x157a015,0x13fc280,0x05e2664,0x1ea70a6,0x1f3a20e,0x1d4127b,0x05f71d9,
  40159. 0x1c00638,0x0a968e0,0x03594a8,0x0fd9558,0x075bc78,0x1d5830c,0x073d6ab,
  40160. 0x1402d5f,0x1c63c92,0x0329a97,0x1d76a9d,0x1652cca,0x0736f19,0x192f1d9,
  40161. 0x05accca,0x12a4b60,0x06eebcd,0x04c6008,0x1a78c37,0x0b39698,0x1af19e5,
  40162. 0x03f0e4d,0x0a6c0e8,0x1442fd5,0x0983fcb,0x1651ca7,0x1becf20,0x0c798d2,
  40163. 0x0b7d27e,0x052f9a8,0x1cf7339,0x1009668,0x1c1eb53,0x0668544,0x0000000
  40164. };
  40165. /* The Montgomery multiplier for modulus of the curve P1024. */
  40166. static sp_digit p1024_mp_mod = 0x8f2f3d;
  40167. #if defined(WOLFSSL_SP_SMALL) || defined(HAVE_ECC_CHECK_KEY)
  40168. /* The order of the curve P1024. */
  40169. static const sp_digit p1024_order[42] = {
  40170. 0x1aa17fb,0x1b00f5f,0x0e87666,0x08563d6,0x003177c,0x10afb61,0x1e82389,
  40171. 0x18ffe71,0x1d5a5c7,0x1f29ad5,0x1c09aa9,0x1e290e1,0x00a9f3c,0x0630a55,
  40172. 0x0aff4a8,0x00e70db,0x173595a,0x08a2558,0x126b4cd,0x1632439,0x09b4389,
  40173. 0x1e94ccd,0x1356d27,0x1e4450c,0x06ce7fd,0x1961cf2,0x1531a59,0x1143986,
  40174. 0x1f03c6c,0x1564fc5,0x02ef40a,0x059f00d,0x1a6b8d6,0x0904c37,0x0ce19cb,
  40175. 0x1d20b60,0x16b4195,0x18c2331,0x03fda65,0x18f852b,0x0265eae,0x0000000
  40176. };
  40177. #endif
  40178. /* The base point of curve P1024. */
  40179. static const sp_point_1024 p1024_base = {
  40180. /* X ordinate */
  40181. {
  40182. 0x0e63895,0x0e455f5,0x05e6203,0x092cfc1,0x00ec46c,0x1fb9f64,0x18e96d8,
  40183. 0x10fdd22,0x080728d,0x0e7da66,0x1a44375,0x029b74c,0x14a7c15,0x1d306f3,
  40184. 0x00b0ce5,0x1e5c34e,0x0548b72,0x199be43,0x1756f32,0x015eecb,0x0890976,
  40185. 0x13a0367,0x1c62f67,0x13bf4aa,0x1f22cdb,0x10821ea,0x00c2c27,0x1621b72,
  40186. 0x0e2308a,0x1b607b6,0x0fed7b6,0x16dfef9,0x0b2f204,0x034e34c,0x1f582bb,
  40187. 0x1456345,0x1ed9b52,0x1cc8029,0x0a6b429,0x1dc6658,0x053fc09,0x0000000,
  40188. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40189. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40190. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40191. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40192. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40193. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40194. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40195. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40196. (sp_digit)0, (sp_digit)0
  40197. },
  40198. /* Y ordinate */
  40199. {
  40200. 0x1ef16d7,0x19feb8d,0x1379d55,0x00d4cfb,0x0db9b57,0x1da31b5,0x0b56b56,
  40201. 0x153017b,0x1e9cb99,0x1a8ad6b,0x1357c84,0x0f3f8b4,0x09492d9,0x0b2554c,
  40202. 0x1bc7a00,0x05fc158,0x0b5b765,0x0656b4b,0x1551f1b,0x15c22f5,0x12b970d,
  40203. 0x0654f01,0x105b3fc,0x028165c,0x18ccf9a,0x0fb35ac,0x17c3795,0x0fefebc,
  40204. 0x0ec2b9e,0x14fa32a,0x1e3d7a9,0x03c2822,0x1778d82,0x0834b1e,0x00580a6,
  40205. 0x0ba7d04,0x1634a13,0x18f8299,0x027c7e7,0x00c7ec0,0x00a8249,0x0000000,
  40206. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40207. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40208. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40209. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40210. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40211. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40212. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40213. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40214. (sp_digit)0, (sp_digit)0
  40215. },
  40216. /* Z ordinate */
  40217. {
  40218. 0x0000001,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
  40219. 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
  40220. 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
  40221. 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
  40222. 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
  40223. 0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
  40224. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40225. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40226. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40227. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40228. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40229. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40230. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40231. (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
  40232. (sp_digit)0, (sp_digit)0
  40233. },
  40234. /* infinity */
  40235. 0
  40236. };
  40237. /* Normalize the values in each word to 25 bits.
  40238. *
  40239. * a Array of sp_digit to normalize.
  40240. */
  40241. static void sp_1024_norm_41(sp_digit* a)
  40242. {
  40243. #ifdef WOLFSSL_SP_SMALL
  40244. int i;
  40245. for (i = 0; i < 40; i++) {
  40246. a[i+1] += a[i] >> 25;
  40247. a[i] &= 0x1ffffff;
  40248. }
  40249. #else
  40250. int i;
  40251. for (i = 0; i < 40; i += 8) {
  40252. a[i+1] += a[i+0] >> 25; a[i+0] &= 0x1ffffff;
  40253. a[i+2] += a[i+1] >> 25; a[i+1] &= 0x1ffffff;
  40254. a[i+3] += a[i+2] >> 25; a[i+2] &= 0x1ffffff;
  40255. a[i+4] += a[i+3] >> 25; a[i+3] &= 0x1ffffff;
  40256. a[i+5] += a[i+4] >> 25; a[i+4] &= 0x1ffffff;
  40257. a[i+6] += a[i+5] >> 25; a[i+5] &= 0x1ffffff;
  40258. a[i+7] += a[i+6] >> 25; a[i+6] &= 0x1ffffff;
  40259. a[i+8] += a[i+7] >> 25; a[i+7] &= 0x1ffffff;
  40260. }
  40261. #endif /* WOLFSSL_SP_SMALL */
  40262. }
  40263. /* Multiply a by scalar b into r. (r = a * b)
  40264. *
  40265. * r A single precision integer.
  40266. * a A single precision integer.
  40267. * b A scalar.
  40268. */
  40269. SP_NOINLINE static void sp_1024_mul_d_42(sp_digit* r, const sp_digit* a,
  40270. sp_digit b)
  40271. {
  40272. #ifdef WOLFSSL_SP_SMALL
  40273. sp_int64 tb = b;
  40274. sp_int64 t = 0;
  40275. int i;
  40276. for (i = 0; i < 42; i++) {
  40277. t += tb * a[i];
  40278. r[i] = (sp_digit)(t & 0x1ffffff);
  40279. t >>= 25;
  40280. }
  40281. r[42] = (sp_digit)t;
  40282. #else
  40283. sp_int64 tb = b;
  40284. sp_int64 t = 0;
  40285. sp_digit t2;
  40286. sp_int64 p[4];
  40287. int i;
  40288. for (i = 0; i < 40; i += 4) {
  40289. p[0] = tb * a[i + 0];
  40290. p[1] = tb * a[i + 1];
  40291. p[2] = tb * a[i + 2];
  40292. p[3] = tb * a[i + 3];
  40293. t += p[0];
  40294. t2 = (sp_digit)(t & 0x1ffffff);
  40295. t >>= 25;
  40296. r[i + 0] = (sp_digit)t2;
  40297. t += p[1];
  40298. t2 = (sp_digit)(t & 0x1ffffff);
  40299. t >>= 25;
  40300. r[i + 1] = (sp_digit)t2;
  40301. t += p[2];
  40302. t2 = (sp_digit)(t & 0x1ffffff);
  40303. t >>= 25;
  40304. r[i + 2] = (sp_digit)t2;
  40305. t += p[3];
  40306. t2 = (sp_digit)(t & 0x1ffffff);
  40307. t >>= 25;
  40308. r[i + 3] = (sp_digit)t2;
  40309. }
  40310. t += tb * a[40];
  40311. r[40] = (sp_digit)(t & 0x1ffffff);
  40312. t >>= 25;
  40313. t += tb * a[41];
  40314. r[41] = (sp_digit)(t & 0x1ffffff);
  40315. t >>= 25;
  40316. r[42] = (sp_digit)(t & 0x1ffffff);
  40317. #endif /* WOLFSSL_SP_SMALL */
  40318. }
  40319. /* Multiply a by scalar b into r. (r = a * b)
  40320. *
  40321. * r A single precision integer.
  40322. * a A single precision integer.
  40323. * b A scalar.
  40324. */
  40325. SP_NOINLINE static void sp_1024_mul_d_84(sp_digit* r, const sp_digit* a,
  40326. sp_digit b)
  40327. {
  40328. #ifdef WOLFSSL_SP_SMALL
  40329. sp_int64 tb = b;
  40330. sp_int64 t = 0;
  40331. int i;
  40332. for (i = 0; i < 84; i++) {
  40333. t += tb * a[i];
  40334. r[i] = (sp_digit)(t & 0x1ffffff);
  40335. t >>= 25;
  40336. }
  40337. r[84] = (sp_digit)t;
  40338. #else
  40339. sp_int64 tb = b;
  40340. sp_int64 t = 0;
  40341. sp_digit t2;
  40342. sp_int64 p[4];
  40343. int i;
  40344. for (i = 0; i < 84; i += 4) {
  40345. p[0] = tb * a[i + 0];
  40346. p[1] = tb * a[i + 1];
  40347. p[2] = tb * a[i + 2];
  40348. p[3] = tb * a[i + 3];
  40349. t += p[0];
  40350. t2 = (sp_digit)(t & 0x1ffffff);
  40351. t >>= 25;
  40352. r[i + 0] = (sp_digit)t2;
  40353. t += p[1];
  40354. t2 = (sp_digit)(t & 0x1ffffff);
  40355. t >>= 25;
  40356. r[i + 1] = (sp_digit)t2;
  40357. t += p[2];
  40358. t2 = (sp_digit)(t & 0x1ffffff);
  40359. t >>= 25;
  40360. r[i + 2] = (sp_digit)t2;
  40361. t += p[3];
  40362. t2 = (sp_digit)(t & 0x1ffffff);
  40363. t >>= 25;
  40364. r[i + 3] = (sp_digit)t2;
  40365. }
  40366. r[84] = (sp_digit)(t & 0x1ffffff);
  40367. #endif /* WOLFSSL_SP_SMALL */
  40368. }
  40369. #ifdef WOLFSSL_SP_SMALL
  40370. /* Conditionally add a and b using the mask m.
  40371. * m is -1 to add and 0 when not.
  40372. *
  40373. * r A single precision number representing conditional add result.
  40374. * a A single precision number to add with.
  40375. * b A single precision number to add.
  40376. * m Mask value to apply.
  40377. */
  40378. static void sp_1024_cond_add_42(sp_digit* r, const sp_digit* a,
  40379. const sp_digit* b, const sp_digit m)
  40380. {
  40381. int i;
  40382. for (i = 0; i < 42; i++) {
  40383. r[i] = a[i] + (b[i] & m);
  40384. }
  40385. }
  40386. #endif /* WOLFSSL_SP_SMALL */
  40387. #ifndef WOLFSSL_SP_SMALL
  40388. /* Conditionally add a and b using the mask m.
  40389. * m is -1 to add and 0 when not.
  40390. *
  40391. * r A single precision number representing conditional add result.
  40392. * a A single precision number to add with.
  40393. * b A single precision number to add.
  40394. * m Mask value to apply.
  40395. */
  40396. static void sp_1024_cond_add_42(sp_digit* r, const sp_digit* a,
  40397. const sp_digit* b, const sp_digit m)
  40398. {
  40399. int i;
  40400. for (i = 0; i < 40; i += 8) {
  40401. r[i + 0] = a[i + 0] + (b[i + 0] & m);
  40402. r[i + 1] = a[i + 1] + (b[i + 1] & m);
  40403. r[i + 2] = a[i + 2] + (b[i + 2] & m);
  40404. r[i + 3] = a[i + 3] + (b[i + 3] & m);
  40405. r[i + 4] = a[i + 4] + (b[i + 4] & m);
  40406. r[i + 5] = a[i + 5] + (b[i + 5] & m);
  40407. r[i + 6] = a[i + 6] + (b[i + 6] & m);
  40408. r[i + 7] = a[i + 7] + (b[i + 7] & m);
  40409. }
  40410. r[40] = a[40] + (b[40] & m);
  40411. r[41] = a[41] + (b[41] & m);
  40412. }
  40413. #endif /* !WOLFSSL_SP_SMALL */
  40414. #ifdef WOLFSSL_SP_SMALL
  40415. /* Sub b from a into r. (r = a - b)
  40416. *
  40417. * r A single precision integer.
  40418. * a A single precision integer.
  40419. * b A single precision integer.
  40420. */
  40421. SP_NOINLINE static int sp_1024_sub_42(sp_digit* r, const sp_digit* a,
  40422. const sp_digit* b)
  40423. {
  40424. int i;
  40425. for (i = 0; i < 42; i++) {
  40426. r[i] = a[i] - b[i];
  40427. }
  40428. return 0;
  40429. }
  40430. #endif
  40431. #ifdef WOLFSSL_SP_SMALL
  40432. /* Add b to a into r. (r = a + b)
  40433. *
  40434. * r A single precision integer.
  40435. * a A single precision integer.
  40436. * b A single precision integer.
  40437. */
  40438. SP_NOINLINE static int sp_1024_add_42(sp_digit* r, const sp_digit* a,
  40439. const sp_digit* b)
  40440. {
  40441. int i;
  40442. for (i = 0; i < 42; i++) {
  40443. r[i] = a[i] + b[i];
  40444. }
  40445. return 0;
  40446. }
  40447. #endif /* WOLFSSL_SP_SMALL */
  40448. SP_NOINLINE static void sp_1024_rshift_42(sp_digit* r, const sp_digit* a,
  40449. byte n)
  40450. {
  40451. int i;
  40452. #ifdef WOLFSSL_SP_SMALL
  40453. for (i=0; i<41; i++) {
  40454. r[i] = ((a[i] >> n) | (a[i + 1] << (25 - n))) & 0x1ffffff;
  40455. }
  40456. #else
  40457. for (i=0; i<40; i += 8) {
  40458. r[i+0] = (a[i+0] >> n) | ((a[i+1] << (25 - n)) & 0x1ffffff);
  40459. r[i+1] = (a[i+1] >> n) | ((a[i+2] << (25 - n)) & 0x1ffffff);
  40460. r[i+2] = (a[i+2] >> n) | ((a[i+3] << (25 - n)) & 0x1ffffff);
  40461. r[i+3] = (a[i+3] >> n) | ((a[i+4] << (25 - n)) & 0x1ffffff);
  40462. r[i+4] = (a[i+4] >> n) | ((a[i+5] << (25 - n)) & 0x1ffffff);
  40463. r[i+5] = (a[i+5] >> n) | ((a[i+6] << (25 - n)) & 0x1ffffff);
  40464. r[i+6] = (a[i+6] >> n) | ((a[i+7] << (25 - n)) & 0x1ffffff);
  40465. r[i+7] = (a[i+7] >> n) | ((a[i+8] << (25 - n)) & 0x1ffffff);
  40466. }
  40467. r[40] = (a[40] >> n) | ((a[41] << (25 - n)) & 0x1ffffff);
  40468. #endif /* WOLFSSL_SP_SMALL */
  40469. r[41] = a[41] >> n;
  40470. }
  40471. static WC_INLINE sp_digit sp_1024_div_word_42(sp_digit d1, sp_digit d0,
  40472. sp_digit div)
  40473. {
  40474. #ifdef SP_USE_DIVTI3
  40475. sp_int64 d = ((sp_int64)d1 << 25) + d0;
  40476. return d / div;
  40477. #elif defined(__x86_64__) || defined(__i386__)
  40478. sp_int64 d = ((sp_int64)d1 << 25) + d0;
  40479. sp_uint32 lo = (sp_uint32)d;
  40480. sp_digit hi = (sp_digit)(d >> 32);
  40481. __asm__ __volatile__ (
  40482. "idiv %2"
  40483. : "+a" (lo)
  40484. : "d" (hi), "r" (div)
  40485. : "cc"
  40486. );
  40487. return (sp_digit)lo;
  40488. #elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV)
  40489. sp_int64 d = ((sp_int64)d1 << 25) + d0;
  40490. sp_digit dv = (div >> 1) + 1;
  40491. sp_digit t1 = (sp_digit)(d >> 25);
  40492. sp_digit t0 = (sp_digit)(d & 0x1ffffff);
  40493. sp_digit t2;
  40494. sp_digit sign;
  40495. sp_digit r;
  40496. int i;
  40497. sp_int64 m;
  40498. r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
  40499. t1 -= dv & (0 - r);
  40500. for (i = 23; i >= 1; i--) {
  40501. t1 += t1 + (((sp_uint32)t0 >> 24) & 1);
  40502. t0 <<= 1;
  40503. t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
  40504. r += r + t2;
  40505. t1 -= dv & (0 - t2);
  40506. t1 += t2;
  40507. }
  40508. r += r + 1;
  40509. m = d - ((sp_int64)r * div);
  40510. r += (sp_digit)(m >> 25);
  40511. m = d - ((sp_int64)r * div);
  40512. r += (sp_digit)(m >> 50) - (sp_digit)(d >> 50);
  40513. m = d - ((sp_int64)r * div);
  40514. sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
  40515. m *= sign;
  40516. t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
  40517. r += sign * t2;
  40518. m = d - ((sp_int64)r * div);
  40519. sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
  40520. m *= sign;
  40521. t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
  40522. r += sign * t2;
  40523. return r;
  40524. #else
  40525. sp_int64 d = ((sp_int64)d1 << 25) + d0;
  40526. sp_digit r = 0;
  40527. sp_digit t;
  40528. sp_digit dv = (div >> 10) + 1;
  40529. t = (sp_digit)(d >> 20);
  40530. t = (t / dv) << 10;
  40531. r += t;
  40532. d -= (sp_int64)t * div;
  40533. t = (sp_digit)(d >> 5);
  40534. t = t / (dv << 5);
  40535. r += t;
  40536. d -= (sp_int64)t * div;
  40537. t = (sp_digit)d;
  40538. t = t / div;
  40539. r += t;
  40540. d -= (sp_int64)t * div;
  40541. return r;
  40542. #endif
  40543. }
  40544. static WC_INLINE sp_digit sp_1024_word_div_word_42(sp_digit d, sp_digit div)
  40545. {
  40546. #if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
  40547. defined(SP_DIV_WORD_USE_DIV)
  40548. return d / div;
  40549. #else
  40550. return (sp_digit)((sp_uint32)(div - d) >> 31);
  40551. #endif
  40552. }
  40553. /* Divide d in a and put remainder into r (m*d + r = a)
  40554. * m is not calculated as it is not needed at this time.
  40555. *
  40556. * Full implementation.
  40557. *
  40558. * a Number to be divided.
  40559. * d Number to divide with.
  40560. * m Multiplier result.
  40561. * r Remainder from the division.
  40562. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  40563. */
  40564. static int sp_1024_div_42(const sp_digit* a, const sp_digit* d,
  40565. const sp_digit* m, sp_digit* r)
  40566. {
  40567. int i;
  40568. #ifndef WOLFSSL_SP_DIV_32
  40569. #endif
  40570. sp_digit dv;
  40571. sp_digit r1;
  40572. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  40573. sp_digit* t1 = NULL;
  40574. #else
  40575. sp_digit t1[4 * 42 + 3];
  40576. #endif
  40577. sp_digit* t2 = NULL;
  40578. sp_digit* sd = NULL;
  40579. int err = MP_OKAY;
  40580. (void)m;
  40581. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  40582. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 42 + 3), NULL,
  40583. DYNAMIC_TYPE_TMP_BUFFER);
  40584. if (t1 == NULL)
  40585. err = MEMORY_E;
  40586. #endif
  40587. (void)m;
  40588. if (err == MP_OKAY) {
  40589. t2 = t1 + 84 + 1;
  40590. sd = t2 + 42 + 1;
  40591. sp_1024_mul_d_42(sd, d, (sp_digit)1 << 1);
  40592. sp_1024_mul_d_84(t1, a, (sp_digit)1 << 1);
  40593. dv = sd[40];
  40594. t1[41 + 41] += t1[41 + 41 - 1] >> 25;
  40595. t1[41 + 41 - 1] &= 0x1ffffff;
  40596. for (i=41; i>=0; i--) {
  40597. r1 = sp_1024_div_word_42(t1[41 + i], t1[41 + i - 1], dv);
  40598. sp_1024_mul_d_42(t2, sd, r1);
  40599. (void)sp_1024_sub_42(&t1[i], &t1[i], t2);
  40600. sp_1024_norm_41(&t1[i]);
  40601. t1[41 + i] += t1[41 + i - 1] >> 25;
  40602. t1[41 + i - 1] &= 0x1ffffff;
  40603. r1 = sp_1024_div_word_42(-t1[41 + i], -t1[41 + i - 1], dv);
  40604. r1 -= t1[41 + i];
  40605. sp_1024_mul_d_42(t2, sd, r1);
  40606. (void)sp_1024_add_42(&t1[i], &t1[i], t2);
  40607. t1[41 + i] += t1[41 + i - 1] >> 25;
  40608. t1[41 + i - 1] &= 0x1ffffff;
  40609. }
  40610. t1[41 - 1] += t1[41 - 2] >> 25;
  40611. t1[41 - 2] &= 0x1ffffff;
  40612. r1 = sp_1024_word_div_word_42(t1[41 - 1], dv);
  40613. sp_1024_mul_d_42(t2, sd, r1);
  40614. sp_1024_sub_42(t1, t1, t2);
  40615. XMEMCPY(r, t1, sizeof(*r) * 84U);
  40616. for (i=0; i<40; i++) {
  40617. r[i+1] += r[i] >> 25;
  40618. r[i] &= 0x1ffffff;
  40619. }
  40620. sp_1024_cond_add_42(r, r, sd, r[40] >> 31);
  40621. sp_1024_norm_41(r);
  40622. sp_1024_rshift_42(r, r, 1);
  40623. r[41] = 0;
  40624. }
  40625. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  40626. if (t1 != NULL)
  40627. XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  40628. #endif
  40629. return err;
  40630. }
  40631. /* Reduce a modulo m into r. (r = a mod m)
  40632. *
  40633. * r A single precision number that is the reduced result.
  40634. * a A single precision number that is to be reduced.
  40635. * m A single precision number that is the modulus to reduce with.
  40636. * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
  40637. */
  40638. static int sp_1024_mod_42(sp_digit* r, const sp_digit* a, const sp_digit* m)
  40639. {
  40640. return sp_1024_div_42(a, m, NULL, r);
  40641. }
  40642. /* Multiply a number by Montgomery normalizer mod modulus (prime).
  40643. *
  40644. * r The resulting Montgomery form number.
  40645. * a The number to convert.
  40646. * m The modulus (prime).
  40647. * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
  40648. */
  40649. static int sp_1024_mod_mul_norm_42(sp_digit* r, const sp_digit* a,
  40650. const sp_digit* m)
  40651. {
  40652. sp_1024_mul_42(r, a, p1024_norm_mod);
  40653. return sp_1024_mod_42(r, r, m);
  40654. }
  40655. #ifdef WOLFCRYPT_HAVE_SAKKE
  40656. /* Create a new point.
  40657. *
  40658. * heap [in] Buffer to allocate dynamic memory from.
  40659. * sp [in] Data for point - only if not allocating.
  40660. * p [out] New point.
  40661. * returns MEMORY_E when dynamic memory allocation fails and 0 otherwise.
  40662. */
  40663. static int sp_1024_point_new_ex_42(void* heap, sp_point_1024* sp,
  40664. sp_point_1024** p)
  40665. {
  40666. int ret = MP_OKAY;
  40667. (void)heap;
  40668. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
  40669. (void)sp;
  40670. *p = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, DYNAMIC_TYPE_ECC);
  40671. #else
  40672. *p = sp;
  40673. #endif
  40674. if (*p == NULL) {
  40675. ret = MEMORY_E;
  40676. }
  40677. return ret;
  40678. }
  40679. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
  40680. /* Allocate memory for point and return error. */
  40681. #define sp_1024_point_new_42(heap, sp, p) sp_1024_point_new_ex_42((heap), NULL, &(p))
  40682. #else
  40683. /* Set pointer to data and return no error. */
  40684. #define sp_1024_point_new_42(heap, sp, p) sp_1024_point_new_ex_42((heap), &(sp), &(p))
  40685. #endif
  40686. #endif /* WOLFCRYPT_HAVE_SAKKE */
  40687. #ifdef WOLFCRYPT_HAVE_SAKKE
  40688. /* Free the point.
  40689. *
  40690. * p [in,out] Point to free.
  40691. * clear [in] Indicates whether to zeroize point.
  40692. * heap [in] Buffer from which dynamic memory was allocate from.
  40693. */
  40694. static void sp_1024_point_free_42(sp_point_1024* p, int clear, void* heap)
  40695. {
  40696. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && !defined(WOLFSSL_SP_NO_MALLOC)
  40697. /* If valid pointer then clear point data if requested and free data. */
  40698. if (p != NULL) {
  40699. if (clear != 0) {
  40700. XMEMSET(p, 0, sizeof(*p));
  40701. }
  40702. XFREE(p, heap, DYNAMIC_TYPE_ECC);
  40703. }
  40704. #else
  40705. /* Clear point data if requested. */
  40706. if ((p != NULL) && (clear != 0)) {
  40707. XMEMSET(p, 0, sizeof(*p));
  40708. }
  40709. #endif
  40710. (void)heap;
  40711. }
  40712. #endif /* WOLFCRYPT_HAVE_SAKKE */
  40713. /* Convert an mp_int to an array of sp_digit.
  40714. *
  40715. * r A single precision integer.
  40716. * size Maximum number of bytes to convert
  40717. * a A multi-precision integer.
  40718. */
  40719. static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a)
  40720. {
  40721. #if DIGIT_BIT == 25
  40722. int j;
  40723. XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used);
  40724. for (j = a->used; j < size; j++) {
  40725. r[j] = 0;
  40726. }
  40727. #elif DIGIT_BIT > 25
  40728. int i;
  40729. int j = 0;
  40730. word32 s = 0;
  40731. r[0] = 0;
  40732. for (i = 0; i < a->used && j < size; i++) {
  40733. r[j] |= ((sp_digit)a->dp[i] << s);
  40734. r[j] &= 0x1ffffff;
  40735. s = 25U - s;
  40736. if (j + 1 >= size) {
  40737. break;
  40738. }
  40739. /* lint allow cast of mismatch word32 and mp_digit */
  40740. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  40741. while ((s + 25U) <= (word32)DIGIT_BIT) {
  40742. s += 25U;
  40743. r[j] &= 0x1ffffff;
  40744. if (j + 1 >= size) {
  40745. break;
  40746. }
  40747. if (s < (word32)DIGIT_BIT) {
  40748. /* lint allow cast of mismatch word32 and mp_digit */
  40749. r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
  40750. }
  40751. else {
  40752. r[++j] = (sp_digit)0;
  40753. }
  40754. }
  40755. s = (word32)DIGIT_BIT - s;
  40756. }
  40757. for (j++; j < size; j++) {
  40758. r[j] = 0;
  40759. }
  40760. #else
  40761. int i;
  40762. int j = 0;
  40763. int s = 0;
  40764. r[0] = 0;
  40765. for (i = 0; i < a->used && j < size; i++) {
  40766. r[j] |= ((sp_digit)a->dp[i]) << s;
  40767. if (s + DIGIT_BIT >= 25) {
  40768. r[j] &= 0x1ffffff;
  40769. if (j + 1 >= size) {
  40770. break;
  40771. }
  40772. s = 25 - s;
  40773. if (s == DIGIT_BIT) {
  40774. r[++j] = 0;
  40775. s = 0;
  40776. }
  40777. else {
  40778. r[++j] = a->dp[i] >> s;
  40779. s = DIGIT_BIT - s;
  40780. }
  40781. }
  40782. else {
  40783. s += DIGIT_BIT;
  40784. }
  40785. }
  40786. for (j++; j < size; j++) {
  40787. r[j] = 0;
  40788. }
  40789. #endif
  40790. }
  40791. /* Convert a point of type ecc_point to type sp_point_1024.
  40792. *
  40793. * p Point of type sp_point_1024 (result).
  40794. * pm Point of type ecc_point.
  40795. */
  40796. static void sp_1024_point_from_ecc_point_42(sp_point_1024* p,
  40797. const ecc_point* pm)
  40798. {
  40799. XMEMSET(p->x, 0, sizeof(p->x));
  40800. XMEMSET(p->y, 0, sizeof(p->y));
  40801. XMEMSET(p->z, 0, sizeof(p->z));
  40802. sp_1024_from_mp(p->x, 42, pm->x);
  40803. sp_1024_from_mp(p->y, 42, pm->y);
  40804. sp_1024_from_mp(p->z, 42, pm->z);
  40805. p->infinity = 0;
  40806. }
  40807. /* Convert an array of sp_digit to an mp_int.
  40808. *
  40809. * a A single precision integer.
  40810. * r A multi-precision integer.
  40811. */
  40812. static int sp_1024_to_mp(const sp_digit* a, mp_int* r)
  40813. {
  40814. int err;
  40815. err = mp_grow(r, (1024 + DIGIT_BIT - 1) / DIGIT_BIT);
  40816. if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
  40817. #if DIGIT_BIT == 25
  40818. XMEMCPY(r->dp, a, sizeof(sp_digit) * 42);
  40819. r->used = 42;
  40820. mp_clamp(r);
  40821. #elif DIGIT_BIT < 25
  40822. int i;
  40823. int j = 0;
  40824. int s = 0;
  40825. r->dp[0] = 0;
  40826. for (i = 0; i < 42; i++) {
  40827. r->dp[j] |= (mp_digit)(a[i] << s);
  40828. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  40829. s = DIGIT_BIT - s;
  40830. r->dp[++j] = (mp_digit)(a[i] >> s);
  40831. while (s + DIGIT_BIT <= 25) {
  40832. s += DIGIT_BIT;
  40833. r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  40834. if (s == SP_WORD_SIZE) {
  40835. r->dp[j] = 0;
  40836. }
  40837. else {
  40838. r->dp[j] = (mp_digit)(a[i] >> s);
  40839. }
  40840. }
  40841. s = 25 - s;
  40842. }
  40843. r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT;
  40844. mp_clamp(r);
  40845. #else
  40846. int i;
  40847. int j = 0;
  40848. int s = 0;
  40849. r->dp[0] = 0;
  40850. for (i = 0; i < 42; i++) {
  40851. r->dp[j] |= ((mp_digit)a[i]) << s;
  40852. if (s + 25 >= DIGIT_BIT) {
  40853. #if DIGIT_BIT != 32 && DIGIT_BIT != 64
  40854. r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
  40855. #endif
  40856. s = DIGIT_BIT - s;
  40857. r->dp[++j] = a[i] >> s;
  40858. s = 25 - s;
  40859. }
  40860. else {
  40861. s += 25;
  40862. }
  40863. }
  40864. r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT;
  40865. mp_clamp(r);
  40866. #endif
  40867. }
  40868. return err;
  40869. }
  40870. /* Convert a point of type sp_point_1024 to type ecc_point.
  40871. *
  40872. * p Point of type sp_point_1024.
  40873. * pm Point of type ecc_point (result).
  40874. * returns MEMORY_E when allocation of memory in ecc_point fails otherwise
  40875. * MP_OKAY.
  40876. */
  40877. static int sp_1024_point_to_ecc_point_42(const sp_point_1024* p, ecc_point* pm)
  40878. {
  40879. int err;
  40880. err = sp_1024_to_mp(p->x, pm->x);
  40881. if (err == MP_OKAY) {
  40882. err = sp_1024_to_mp(p->y, pm->y);
  40883. }
  40884. if (err == MP_OKAY) {
  40885. err = sp_1024_to_mp(p->z, pm->z);
  40886. }
  40887. return err;
  40888. }
  40889. /* Compare a with b in constant time.
  40890. *
  40891. * a A single precision integer.
  40892. * b A single precision integer.
  40893. * return -ve, 0 or +ve if a is less than, equal to or greater than b
  40894. * respectively.
  40895. */
  40896. static sp_digit sp_1024_cmp_42(const sp_digit* a, const sp_digit* b)
  40897. {
  40898. sp_digit r = 0;
  40899. #ifdef WOLFSSL_SP_SMALL
  40900. int i;
  40901. for (i=41; i>=0; i--) {
  40902. r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 24);
  40903. }
  40904. #else
  40905. int i;
  40906. r |= (a[41] - b[41]) & (0 - (sp_digit)1);
  40907. r |= (a[40] - b[40]) & ~(((sp_digit)0 - r) >> 24);
  40908. for (i = 32; i >= 0; i -= 8) {
  40909. r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 24);
  40910. r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 24);
  40911. r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 24);
  40912. r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 24);
  40913. r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 24);
  40914. r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 24);
  40915. r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 24);
  40916. r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 24);
  40917. }
  40918. #endif /* WOLFSSL_SP_SMALL */
  40919. return r;
  40920. }
  40921. /* Conditionally subtract b from a using the mask m.
  40922. * m is -1 to subtract and 0 when not.
  40923. *
  40924. * r A single precision number representing condition subtract result.
  40925. * a A single precision number to subtract from.
  40926. * b A single precision number to subtract.
  40927. * m Mask value to apply.
  40928. */
  40929. static void sp_1024_cond_sub_42(sp_digit* r, const sp_digit* a,
  40930. const sp_digit* b, const sp_digit m)
  40931. {
  40932. #ifdef WOLFSSL_SP_SMALL
  40933. int i;
  40934. for (i = 0; i < 42; i++) {
  40935. r[i] = a[i] - (b[i] & m);
  40936. }
  40937. #else
  40938. int i;
  40939. for (i = 0; i < 40; i += 8) {
  40940. r[i + 0] = a[i + 0] - (b[i + 0] & m);
  40941. r[i + 1] = a[i + 1] - (b[i + 1] & m);
  40942. r[i + 2] = a[i + 2] - (b[i + 2] & m);
  40943. r[i + 3] = a[i + 3] - (b[i + 3] & m);
  40944. r[i + 4] = a[i + 4] - (b[i + 4] & m);
  40945. r[i + 5] = a[i + 5] - (b[i + 5] & m);
  40946. r[i + 6] = a[i + 6] - (b[i + 6] & m);
  40947. r[i + 7] = a[i + 7] - (b[i + 7] & m);
  40948. }
  40949. r[40] = a[40] - (b[40] & m);
  40950. r[41] = a[41] - (b[41] & m);
  40951. #endif /* WOLFSSL_SP_SMALL */
  40952. }
  40953. /* Mul a by scalar b and add into r. (r += a * b)
  40954. *
  40955. * r A single precision integer.
  40956. * a A single precision integer.
  40957. * b A scalar.
  40958. */
  40959. SP_NOINLINE static void sp_1024_mul_add_42(sp_digit* r, const sp_digit* a,
  40960. const sp_digit b)
  40961. {
  40962. #ifdef WOLFSSL_SP_SMALL
  40963. sp_int64 tb = b;
  40964. sp_int64 t[4];
  40965. int i;
  40966. t[0] = 0;
  40967. for (i = 0; i < 40; i += 4) {
  40968. t[0] += (tb * a[i+0]) + r[i+0];
  40969. t[1] = (tb * a[i+1]) + r[i+1];
  40970. t[2] = (tb * a[i+2]) + r[i+2];
  40971. t[3] = (tb * a[i+3]) + r[i+3];
  40972. r[i+0] = t[0] & 0x1ffffff;
  40973. t[1] += t[0] >> 25;
  40974. r[i+1] = t[1] & 0x1ffffff;
  40975. t[2] += t[1] >> 25;
  40976. r[i+2] = t[2] & 0x1ffffff;
  40977. t[3] += t[2] >> 25;
  40978. r[i+3] = t[3] & 0x1ffffff;
  40979. t[0] = t[3] >> 25;
  40980. }
  40981. t[0] += (tb * a[40]) + r[40];
  40982. t[1] = (tb * a[41]) + r[41];
  40983. r[40] = t[0] & 0x1ffffff;
  40984. t[1] += t[0] >> 25;
  40985. r[41] = t[1] & 0x1ffffff;
  40986. r[42] += (sp_digit)(t[1] >> 25);
  40987. #else
  40988. sp_int64 tb = b;
  40989. sp_int64 t[8];
  40990. int i;
  40991. t[0] = tb * a[0]; r[0] += (sp_digit)(t[0] & 0x1ffffff);
  40992. for (i = 0; i < 40; i += 8) {
  40993. t[1] = tb * a[i+1];
  40994. r[i+1] += (sp_digit)((t[0] >> 25) + (t[1] & 0x1ffffff));
  40995. t[2] = tb * a[i+2];
  40996. r[i+2] += (sp_digit)((t[1] >> 25) + (t[2] & 0x1ffffff));
  40997. t[3] = tb * a[i+3];
  40998. r[i+3] += (sp_digit)((t[2] >> 25) + (t[3] & 0x1ffffff));
  40999. t[4] = tb * a[i+4];
  41000. r[i+4] += (sp_digit)((t[3] >> 25) + (t[4] & 0x1ffffff));
  41001. t[5] = tb * a[i+5];
  41002. r[i+5] += (sp_digit)((t[4] >> 25) + (t[5] & 0x1ffffff));
  41003. t[6] = tb * a[i+6];
  41004. r[i+6] += (sp_digit)((t[5] >> 25) + (t[6] & 0x1ffffff));
  41005. t[7] = tb * a[i+7];
  41006. r[i+7] += (sp_digit)((t[6] >> 25) + (t[7] & 0x1ffffff));
  41007. t[0] = tb * a[i+8];
  41008. r[i+8] += (sp_digit)((t[7] >> 25) + (t[0] & 0x1ffffff));
  41009. }
  41010. t[1] = tb * a[41];
  41011. r[41] += (sp_digit)((t[0] >> 25) + (t[1] & 0x1ffffff));
  41012. r[42] += (sp_digit)(t[1] >> 25);
  41013. #endif /* WOLFSSL_SP_SMALL */
  41014. }
  41015. /* Normalize the values in each word to 25 bits.
  41016. *
  41017. * a Array of sp_digit to normalize.
  41018. */
  41019. static void sp_1024_norm_42(sp_digit* a)
  41020. {
  41021. #ifdef WOLFSSL_SP_SMALL
  41022. int i;
  41023. for (i = 0; i < 41; i++) {
  41024. a[i+1] += a[i] >> 25;
  41025. a[i] &= 0x1ffffff;
  41026. }
  41027. #else
  41028. int i;
  41029. for (i = 0; i < 40; i += 8) {
  41030. a[i+1] += a[i+0] >> 25; a[i+0] &= 0x1ffffff;
  41031. a[i+2] += a[i+1] >> 25; a[i+1] &= 0x1ffffff;
  41032. a[i+3] += a[i+2] >> 25; a[i+2] &= 0x1ffffff;
  41033. a[i+4] += a[i+3] >> 25; a[i+3] &= 0x1ffffff;
  41034. a[i+5] += a[i+4] >> 25; a[i+4] &= 0x1ffffff;
  41035. a[i+6] += a[i+5] >> 25; a[i+5] &= 0x1ffffff;
  41036. a[i+7] += a[i+6] >> 25; a[i+6] &= 0x1ffffff;
  41037. a[i+8] += a[i+7] >> 25; a[i+7] &= 0x1ffffff;
  41038. }
  41039. a[41] += a[40] >> 25; a[40] &= 0x1ffffff;
  41040. #endif /* WOLFSSL_SP_SMALL */
  41041. }
  41042. /* Shift the result in the high 1024 bits down to the bottom.
  41043. *
  41044. * r A single precision number.
  41045. * a A single precision number.
  41046. */
  41047. static void sp_1024_mont_shift_42(sp_digit* r, const sp_digit* a)
  41048. {
  41049. #ifdef WOLFSSL_SP_SMALL
  41050. int i;
  41051. sp_uint32 n;
  41052. n = a[40] >> 24;
  41053. for (i = 0; i < 40; i++) {
  41054. n += (sp_uint32)a[41 + i] << 1;
  41055. r[i] = n & 0x1ffffff;
  41056. n >>= 25;
  41057. }
  41058. n += (sp_uint32)a[81] << 1;
  41059. r[40] = n;
  41060. #else
  41061. sp_uint32 n;
  41062. int i;
  41063. n = (sp_uint32)a[40];
  41064. n = n >> 24U;
  41065. for (i = 0; i < 40; i += 8) {
  41066. n += (sp_uint32)a[i+41] << 1U; r[i+0] = n & 0x1ffffff; n >>= 25U;
  41067. n += (sp_uint32)a[i+42] << 1U; r[i+1] = n & 0x1ffffff; n >>= 25U;
  41068. n += (sp_uint32)a[i+43] << 1U; r[i+2] = n & 0x1ffffff; n >>= 25U;
  41069. n += (sp_uint32)a[i+44] << 1U; r[i+3] = n & 0x1ffffff; n >>= 25U;
  41070. n += (sp_uint32)a[i+45] << 1U; r[i+4] = n & 0x1ffffff; n >>= 25U;
  41071. n += (sp_uint32)a[i+46] << 1U; r[i+5] = n & 0x1ffffff; n >>= 25U;
  41072. n += (sp_uint32)a[i+47] << 1U; r[i+6] = n & 0x1ffffff; n >>= 25U;
  41073. n += (sp_uint32)a[i+48] << 1U; r[i+7] = n & 0x1ffffff; n >>= 25U;
  41074. }
  41075. n += (sp_uint32)a[81] << 1U; r[40] = n;
  41076. #endif /* WOLFSSL_SP_SMALL */
  41077. XMEMSET(&r[41], 0, sizeof(*r) * 41U);
  41078. }
  41079. /* Reduce the number back to 1024 bits using Montgomery reduction.
  41080. *
  41081. * a A single precision number to reduce in place.
  41082. * m The single precision number representing the modulus.
  41083. * mp The digit representing the negative inverse of m mod 2^n.
  41084. */
  41085. static void sp_1024_mont_reduce_42(sp_digit* a, const sp_digit* m, sp_digit mp)
  41086. {
  41087. int i;
  41088. sp_digit mu;
  41089. sp_digit over;
  41090. sp_1024_norm_42(a + 41);
  41091. if (mp != 1) {
  41092. for (i=0; i<40; i++) {
  41093. mu = (a[i] * mp) & 0x1ffffff;
  41094. sp_1024_mul_add_42(a+i, m, mu);
  41095. a[i+1] += a[i] >> 25;
  41096. }
  41097. mu = (a[i] * mp) & 0xffffffL;
  41098. sp_1024_mul_add_42(a+i, m, mu);
  41099. a[i+1] += a[i] >> 25;
  41100. a[i] &= 0x1ffffff;
  41101. }
  41102. else {
  41103. for (i=0; i<40; i++) {
  41104. mu = a[i] & 0x1ffffff;
  41105. sp_1024_mul_add_42(a+i, m, mu);
  41106. a[i+1] += a[i] >> 25;
  41107. }
  41108. mu = a[i] & 0xffffffL;
  41109. sp_1024_mul_add_42(a+i, m, mu);
  41110. a[i+1] += a[i] >> 25;
  41111. a[i] &= 0x1ffffff;
  41112. }
  41113. sp_1024_norm_42(a + 41);
  41114. sp_1024_mont_shift_42(a, a);
  41115. over = a[40] - m[40];
  41116. sp_1024_cond_sub_42(a, a, m, ~((over - 1) >> 31));
  41117. sp_1024_norm_42(a);
  41118. }
  41119. /* Multiply two Montgomery form numbers mod the modulus (prime).
  41120. * (r = a * b mod m)
  41121. *
  41122. * r Result of multiplication.
  41123. * a First number to multiply in Montgomery form.
  41124. * b Second number to multiply in Montgomery form.
  41125. * m Modulus (prime).
  41126. * mp Montgomery mulitplier.
  41127. */
  41128. SP_NOINLINE static void sp_1024_mont_mul_42(sp_digit* r, const sp_digit* a,
  41129. const sp_digit* b, const sp_digit* m, sp_digit mp)
  41130. {
  41131. sp_1024_mul_42(r, a, b);
  41132. sp_1024_mont_reduce_42(r, m, mp);
  41133. }
  41134. /* Square the Montgomery form number. (r = a * a mod m)
  41135. *
  41136. * r Result of squaring.
  41137. * a Number to square in Montgomery form.
  41138. * m Modulus (prime).
  41139. * mp Montgomery mulitplier.
  41140. */
  41141. SP_NOINLINE static void sp_1024_mont_sqr_42(sp_digit* r, const sp_digit* a,
  41142. const sp_digit* m, sp_digit mp)
  41143. {
  41144. sp_1024_sqr_42(r, a);
  41145. sp_1024_mont_reduce_42(r, m, mp);
  41146. }
  41147. /* Mod-2 for the P1024 curve. */
  41148. static const uint8_t p1024_mod_minus_2[] = {
  41149. 6,0x06, 7,0x0f, 7,0x0b, 6,0x0c, 7,0x1e, 9,0x09, 7,0x0c, 7,0x1f,
  41150. 6,0x16, 6,0x06, 7,0x0e, 8,0x10, 6,0x03, 8,0x11, 6,0x0d, 7,0x14,
  41151. 9,0x12, 6,0x0f, 7,0x04, 9,0x0d, 6,0x00, 7,0x13, 6,0x01, 6,0x07,
  41152. 8,0x0d, 8,0x00, 6,0x06, 9,0x17, 6,0x14, 6,0x15, 6,0x11, 6,0x0b,
  41153. 9,0x0c, 6,0x1e, 13,0x14, 7,0x0e, 6,0x1d, 12,0x0a, 6,0x0b, 8,0x07,
  41154. 6,0x18, 6,0x0f, 6,0x10, 8,0x1c, 7,0x16, 7,0x02, 6,0x01, 6,0x13,
  41155. 10,0x15, 7,0x06, 8,0x14, 6,0x0c, 6,0x19, 7,0x10, 6,0x19, 6,0x19,
  41156. 9,0x16, 7,0x19, 6,0x1f, 6,0x17, 6,0x12, 8,0x02, 6,0x01, 6,0x04,
  41157. 6,0x15, 7,0x16, 6,0x04, 6,0x1f, 6,0x09, 7,0x06, 7,0x13, 7,0x09,
  41158. 6,0x0d, 10,0x18, 6,0x06, 6,0x11, 6,0x04, 6,0x01, 6,0x13, 8,0x06,
  41159. 6,0x0d, 8,0x13, 7,0x08, 6,0x08, 6,0x05, 7,0x0c, 7,0x0e, 7,0x15,
  41160. 6,0x05, 7,0x14, 10,0x19, 6,0x10, 6,0x16, 6,0x15, 7,0x1f, 6,0x14,
  41161. 6,0x0a, 10,0x11, 6,0x01, 7,0x05, 7,0x08, 8,0x0a, 7,0x1e, 7,0x1c,
  41162. 6,0x1c, 7,0x09, 10,0x18, 7,0x1c, 10,0x06, 6,0x0a, 6,0x07, 6,0x19,
  41163. 7,0x06, 6,0x0d, 7,0x0f, 7,0x0b, 7,0x05, 6,0x11, 6,0x1c, 7,0x1f,
  41164. 6,0x1e, 7,0x18, 6,0x1e, 6,0x00, 6,0x03, 6,0x02, 7,0x10, 6,0x0b,
  41165. 6,0x1b, 7,0x10, 6,0x00, 8,0x11, 7,0x1b, 6,0x18, 6,0x01, 7,0x0c,
  41166. 7,0x1d, 7,0x13, 6,0x08, 7,0x1b, 8,0x13, 7,0x16, 13,0x1d, 7,0x1f,
  41167. 6,0x0a, 6,0x01, 7,0x1f, 6,0x14, 1,0x01
  41168. };
  41169. /* Invert the number, in Montgomery form, modulo the modulus (prime) of the
  41170. * P1024 curve. (r = 1 / a mod m)
  41171. *
  41172. * r Inverse result.
  41173. * a Number to invert.
  41174. * td Temporary data.
  41175. */
  41176. static void sp_1024_mont_inv_42(sp_digit* r, const sp_digit* a,
  41177. sp_digit* td)
  41178. {
  41179. sp_digit* t = td;
  41180. int i;
  41181. int j;
  41182. sp_digit table[32][2 * 42];
  41183. XMEMCPY(table[0], a, sizeof(sp_digit) * 42);
  41184. for (i = 1; i < 6; i++) {
  41185. sp_1024_mont_sqr_42(table[0], table[0], p1024_mod, p1024_mp_mod);
  41186. }
  41187. for (i = 1; i < 32; i++) {
  41188. sp_1024_mont_mul_42(table[i], table[i-1], a, p1024_mod, p1024_mp_mod);
  41189. }
  41190. XMEMCPY(t, table[p1024_mod_minus_2[1]], sizeof(sp_digit) * 42);
  41191. for (i = 2; i < (int)sizeof(p1024_mod_minus_2) - 2; i += 2) {
  41192. for (j = 0; j < p1024_mod_minus_2[i]; j++) {
  41193. sp_1024_mont_sqr_42(t, t, p1024_mod, p1024_mp_mod);
  41194. }
  41195. sp_1024_mont_mul_42(t, t, table[p1024_mod_minus_2[i+1]], p1024_mod,
  41196. p1024_mp_mod);
  41197. }
  41198. sp_1024_mont_sqr_42(t, t, p1024_mod, p1024_mp_mod);
  41199. sp_1024_mont_mul_42(r, t, a, p1024_mod, p1024_mp_mod);
  41200. }
  41201. /* Map the Montgomery form projective coordinate point to an affine point.
  41202. *
  41203. * r Resulting affine coordinate point.
  41204. * p Montgomery form projective coordinate point.
  41205. * t Temporary ordinate data.
  41206. */
  41207. static void sp_1024_map_42(sp_point_1024* r, const sp_point_1024* p,
  41208. sp_digit* t)
  41209. {
  41210. sp_digit* t1 = t;
  41211. sp_digit* t2 = t + 2*42;
  41212. sp_int32 n;
  41213. sp_1024_mont_inv_42(t1, p->z, t + 2*42);
  41214. sp_1024_mont_sqr_42(t2, t1, p1024_mod, p1024_mp_mod);
  41215. sp_1024_mont_mul_42(t1, t2, t1, p1024_mod, p1024_mp_mod);
  41216. /* x /= z^2 */
  41217. sp_1024_mont_mul_42(r->x, p->x, t2, p1024_mod, p1024_mp_mod);
  41218. XMEMSET(r->x + 42, 0, sizeof(r->x) / 2U);
  41219. sp_1024_mont_reduce_42(r->x, p1024_mod, p1024_mp_mod);
  41220. /* Reduce x to less than modulus */
  41221. n = sp_1024_cmp_42(r->x, p1024_mod);
  41222. sp_1024_cond_sub_42(r->x, r->x, p1024_mod, ~(n >> 24));
  41223. sp_1024_norm_42(r->x);
  41224. /* y /= z^3 */
  41225. sp_1024_mont_mul_42(r->y, p->y, t1, p1024_mod, p1024_mp_mod);
  41226. XMEMSET(r->y + 42, 0, sizeof(r->y) / 2U);
  41227. sp_1024_mont_reduce_42(r->y, p1024_mod, p1024_mp_mod);
  41228. /* Reduce y to less than modulus */
  41229. n = sp_1024_cmp_42(r->y, p1024_mod);
  41230. sp_1024_cond_sub_42(r->y, r->y, p1024_mod, ~(n >> 24));
  41231. sp_1024_norm_42(r->y);
  41232. XMEMSET(r->z, 0, sizeof(r->z) / 2);
  41233. r->z[0] = 1;
  41234. }
  41235. /* Add two Montgomery form numbers (r = a + b % m).
  41236. *
  41237. * r Result of addition.
  41238. * a First number to add in Montgomery form.
  41239. * b Second number to add in Montgomery form.
  41240. * m Modulus (prime).
  41241. */
  41242. static void sp_1024_mont_add_42(sp_digit* r, const sp_digit* a, const sp_digit* b,
  41243. const sp_digit* m)
  41244. {
  41245. sp_digit over;
  41246. (void)sp_1024_add_42(r, a, b);
  41247. sp_1024_norm_42(r);
  41248. over = r[40] - m[40];
  41249. sp_1024_cond_sub_42(r, r, m, ~((over - 1) >> 31));
  41250. sp_1024_norm_42(r);
  41251. }
  41252. /* Double a Montgomery form number (r = a + a % m).
  41253. *
  41254. * r Result of doubling.
  41255. * a Number to double in Montgomery form.
  41256. * m Modulus (prime).
  41257. */
  41258. static void sp_1024_mont_dbl_42(sp_digit* r, const sp_digit* a, const sp_digit* m)
  41259. {
  41260. sp_digit over;
  41261. (void)sp_1024_add_42(r, a, a);
  41262. sp_1024_norm_42(r);
  41263. over = r[40] - m[40];
  41264. sp_1024_cond_sub_42(r, r, m, ~((over - 1) >> 31));
  41265. sp_1024_norm_42(r);
  41266. }
  41267. /* Triple a Montgomery form number (r = a + a + a % m).
  41268. *
  41269. * r Result of Tripling.
  41270. * a Number to triple in Montgomery form.
  41271. * m Modulus (prime).
  41272. */
  41273. static void sp_1024_mont_tpl_42(sp_digit* r, const sp_digit* a, const sp_digit* m)
  41274. {
  41275. sp_digit over;
  41276. (void)sp_1024_add_42(r, a, a);
  41277. sp_1024_norm_42(r);
  41278. over = r[40] - m[40];
  41279. sp_1024_cond_sub_42(r, r, m, ~((over - 1) >> 31));
  41280. sp_1024_norm_42(r);
  41281. (void)sp_1024_add_42(r, r, a);
  41282. sp_1024_norm_42(r);
  41283. over = r[40] - m[40];
  41284. sp_1024_cond_sub_42(r, r, m, ~((over - 1) >> 31));
  41285. sp_1024_norm_42(r);
  41286. }
  41287. /* Subtract two Montgomery form numbers (r = a - b % m).
  41288. *
  41289. * r Result of subtration.
  41290. * a Number to subtract from in Montgomery form.
  41291. * b Number to subtract with in Montgomery form.
  41292. * m Modulus (prime).
  41293. */
  41294. static void sp_1024_mont_sub_42(sp_digit* r, const sp_digit* a, const sp_digit* b,
  41295. const sp_digit* m)
  41296. {
  41297. (void)sp_1024_sub_42(r, a, b);
  41298. sp_1024_norm_42(r);
  41299. sp_1024_cond_add_42(r, r, m, r[41] >> 7);
  41300. sp_1024_norm_42(r);
  41301. }
  41302. #define sp_1024_mont_sub_lower_42 sp_1024_mont_sub_42
  41303. /* Shift number left one bit.
  41304. * Bottom bit is lost.
  41305. *
  41306. * r Result of shift.
  41307. * a Number to shift.
  41308. */
  41309. SP_NOINLINE static void sp_1024_rshift1_42(sp_digit* r, const sp_digit* a)
  41310. {
  41311. #ifdef WOLFSSL_SP_SMALL
  41312. int i;
  41313. for (i=0; i<41; i++) {
  41314. r[i] = (a[i] >> 1) + ((a[i + 1] << 24) & 0x1ffffff);
  41315. }
  41316. #else
  41317. r[0] = (a[0] >> 1) + ((a[1] << 24) & 0x1ffffff);
  41318. r[1] = (a[1] >> 1) + ((a[2] << 24) & 0x1ffffff);
  41319. r[2] = (a[2] >> 1) + ((a[3] << 24) & 0x1ffffff);
  41320. r[3] = (a[3] >> 1) + ((a[4] << 24) & 0x1ffffff);
  41321. r[4] = (a[4] >> 1) + ((a[5] << 24) & 0x1ffffff);
  41322. r[5] = (a[5] >> 1) + ((a[6] << 24) & 0x1ffffff);
  41323. r[6] = (a[6] >> 1) + ((a[7] << 24) & 0x1ffffff);
  41324. r[7] = (a[7] >> 1) + ((a[8] << 24) & 0x1ffffff);
  41325. r[8] = (a[8] >> 1) + ((a[9] << 24) & 0x1ffffff);
  41326. r[9] = (a[9] >> 1) + ((a[10] << 24) & 0x1ffffff);
  41327. r[10] = (a[10] >> 1) + ((a[11] << 24) & 0x1ffffff);
  41328. r[11] = (a[11] >> 1) + ((a[12] << 24) & 0x1ffffff);
  41329. r[12] = (a[12] >> 1) + ((a[13] << 24) & 0x1ffffff);
  41330. r[13] = (a[13] >> 1) + ((a[14] << 24) & 0x1ffffff);
  41331. r[14] = (a[14] >> 1) + ((a[15] << 24) & 0x1ffffff);
  41332. r[15] = (a[15] >> 1) + ((a[16] << 24) & 0x1ffffff);
  41333. r[16] = (a[16] >> 1) + ((a[17] << 24) & 0x1ffffff);
  41334. r[17] = (a[17] >> 1) + ((a[18] << 24) & 0x1ffffff);
  41335. r[18] = (a[18] >> 1) + ((a[19] << 24) & 0x1ffffff);
  41336. r[19] = (a[19] >> 1) + ((a[20] << 24) & 0x1ffffff);
  41337. r[20] = (a[20] >> 1) + ((a[21] << 24) & 0x1ffffff);
  41338. r[21] = (a[21] >> 1) + ((a[22] << 24) & 0x1ffffff);
  41339. r[22] = (a[22] >> 1) + ((a[23] << 24) & 0x1ffffff);
  41340. r[23] = (a[23] >> 1) + ((a[24] << 24) & 0x1ffffff);
  41341. r[24] = (a[24] >> 1) + ((a[25] << 24) & 0x1ffffff);
  41342. r[25] = (a[25] >> 1) + ((a[26] << 24) & 0x1ffffff);
  41343. r[26] = (a[26] >> 1) + ((a[27] << 24) & 0x1ffffff);
  41344. r[27] = (a[27] >> 1) + ((a[28] << 24) & 0x1ffffff);
  41345. r[28] = (a[28] >> 1) + ((a[29] << 24) & 0x1ffffff);
  41346. r[29] = (a[29] >> 1) + ((a[30] << 24) & 0x1ffffff);
  41347. r[30] = (a[30] >> 1) + ((a[31] << 24) & 0x1ffffff);
  41348. r[31] = (a[31] >> 1) + ((a[32] << 24) & 0x1ffffff);
  41349. r[32] = (a[32] >> 1) + ((a[33] << 24) & 0x1ffffff);
  41350. r[33] = (a[33] >> 1) + ((a[34] << 24) & 0x1ffffff);
  41351. r[34] = (a[34] >> 1) + ((a[35] << 24) & 0x1ffffff);
  41352. r[35] = (a[35] >> 1) + ((a[36] << 24) & 0x1ffffff);
  41353. r[36] = (a[36] >> 1) + ((a[37] << 24) & 0x1ffffff);
  41354. r[37] = (a[37] >> 1) + ((a[38] << 24) & 0x1ffffff);
  41355. r[38] = (a[38] >> 1) + ((a[39] << 24) & 0x1ffffff);
  41356. r[39] = (a[39] >> 1) + ((a[40] << 24) & 0x1ffffff);
  41357. r[40] = (a[40] >> 1) + ((a[41] << 24) & 0x1ffffff);
  41358. #endif
  41359. r[41] = a[41] >> 1;
  41360. }
  41361. /* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
  41362. *
  41363. * r Result of division by 2.
  41364. * a Number to divide.
  41365. * m Modulus (prime).
  41366. */
  41367. static void sp_1024_div2_42(sp_digit* r, const sp_digit* a, const sp_digit* m)
  41368. {
  41369. sp_1024_cond_add_42(r, a, m, 0 - (a[0] & 1));
  41370. sp_1024_norm_42(r);
  41371. sp_1024_rshift1_42(r, r);
  41372. }
  41373. /* Double the Montgomery form projective point p.
  41374. *
  41375. * r Result of doubling point.
  41376. * p Point to double.
  41377. * t Temporary ordinate data.
  41378. */
  41379. #ifdef WOLFSSL_SP_NONBLOCK
  41380. typedef struct sp_1024_proj_point_dbl_42_ctx {
  41381. int state;
  41382. sp_digit* t1;
  41383. sp_digit* t2;
  41384. sp_digit* x;
  41385. sp_digit* y;
  41386. sp_digit* z;
  41387. } sp_1024_proj_point_dbl_42_ctx;
  41388. static int sp_1024_proj_point_dbl_42_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, const sp_point_1024* p, sp_digit* t)
  41389. {
  41390. int err = FP_WOULDBLOCK;
  41391. sp_1024_proj_point_dbl_42_ctx* ctx = (sp_1024_proj_point_dbl_42_ctx*)sp_ctx->data;
  41392. typedef char ctx_size_test[sizeof(sp_1024_proj_point_dbl_42_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  41393. (void)sizeof(ctx_size_test);
  41394. switch (ctx->state) {
  41395. case 0:
  41396. ctx->t1 = t;
  41397. ctx->t2 = t + 2*42;
  41398. ctx->x = r->x;
  41399. ctx->y = r->y;
  41400. ctx->z = r->z;
  41401. /* Put infinity into result. */
  41402. if (r != p) {
  41403. r->infinity = p->infinity;
  41404. }
  41405. ctx->state = 1;
  41406. break;
  41407. case 1:
  41408. /* T1 = Z * Z */
  41409. sp_1024_mont_sqr_42(ctx->t1, p->z, p1024_mod, p1024_mp_mod);
  41410. ctx->state = 2;
  41411. break;
  41412. case 2:
  41413. /* Z = Y * Z */
  41414. sp_1024_mont_mul_42(ctx->z, p->y, p->z, p1024_mod, p1024_mp_mod);
  41415. ctx->state = 3;
  41416. break;
  41417. case 3:
  41418. /* Z = 2Z */
  41419. sp_1024_mont_dbl_42(ctx->z, ctx->z, p1024_mod);
  41420. ctx->state = 4;
  41421. break;
  41422. case 4:
  41423. /* T2 = X - T1 */
  41424. sp_1024_mont_sub_42(ctx->t2, p->x, ctx->t1, p1024_mod);
  41425. ctx->state = 5;
  41426. break;
  41427. case 5:
  41428. /* T1 = X + T1 */
  41429. sp_1024_mont_add_42(ctx->t1, p->x, ctx->t1, p1024_mod);
  41430. ctx->state = 6;
  41431. break;
  41432. case 6:
  41433. /* T2 = T1 * T2 */
  41434. sp_1024_mont_mul_42(ctx->t2, ctx->t1, ctx->t2, p1024_mod, p1024_mp_mod);
  41435. ctx->state = 7;
  41436. break;
  41437. case 7:
  41438. /* T1 = 3T2 */
  41439. sp_1024_mont_tpl_42(ctx->t1, ctx->t2, p1024_mod);
  41440. ctx->state = 8;
  41441. break;
  41442. case 8:
  41443. /* Y = 2Y */
  41444. sp_1024_mont_dbl_42(ctx->y, p->y, p1024_mod);
  41445. ctx->state = 9;
  41446. break;
  41447. case 9:
  41448. /* Y = Y * Y */
  41449. sp_1024_mont_sqr_42(ctx->y, ctx->y, p1024_mod, p1024_mp_mod);
  41450. ctx->state = 10;
  41451. break;
  41452. case 10:
  41453. /* T2 = Y * Y */
  41454. sp_1024_mont_sqr_42(ctx->t2, ctx->y, p1024_mod, p1024_mp_mod);
  41455. ctx->state = 11;
  41456. break;
  41457. case 11:
  41458. /* T2 = T2/2 */
  41459. sp_1024_div2_42(ctx->t2, ctx->t2, p1024_mod);
  41460. ctx->state = 12;
  41461. break;
  41462. case 12:
  41463. /* Y = Y * X */
  41464. sp_1024_mont_mul_42(ctx->y, ctx->y, p->x, p1024_mod, p1024_mp_mod);
  41465. ctx->state = 13;
  41466. break;
  41467. case 13:
  41468. /* X = T1 * T1 */
  41469. sp_1024_mont_sqr_42(ctx->x, ctx->t1, p1024_mod, p1024_mp_mod);
  41470. ctx->state = 14;
  41471. break;
  41472. case 14:
  41473. /* X = X - Y */
  41474. sp_1024_mont_sub_42(ctx->x, ctx->x, ctx->y, p1024_mod);
  41475. ctx->state = 15;
  41476. break;
  41477. case 15:
  41478. /* X = X - Y */
  41479. sp_1024_mont_sub_42(ctx->x, ctx->x, ctx->y, p1024_mod);
  41480. ctx->state = 16;
  41481. break;
  41482. case 16:
  41483. /* Y = Y - X */
  41484. sp_1024_mont_sub_lower_42(ctx->y, ctx->y, ctx->x, p1024_mod);
  41485. ctx->state = 17;
  41486. break;
  41487. case 17:
  41488. /* Y = Y * T1 */
  41489. sp_1024_mont_mul_42(ctx->y, ctx->y, ctx->t1, p1024_mod, p1024_mp_mod);
  41490. ctx->state = 18;
  41491. break;
  41492. case 18:
  41493. /* Y = Y - T2 */
  41494. sp_1024_mont_sub_42(ctx->y, ctx->y, ctx->t2, p1024_mod);
  41495. ctx->state = 19;
  41496. /* fall-through */
  41497. case 19:
  41498. err = MP_OKAY;
  41499. break;
  41500. }
  41501. if (err == MP_OKAY && ctx->state != 19) {
  41502. err = FP_WOULDBLOCK;
  41503. }
  41504. return err;
  41505. }
  41506. #endif /* WOLFSSL_SP_NONBLOCK */
  41507. static void sp_1024_proj_point_dbl_42(sp_point_1024* r, const sp_point_1024* p,
  41508. sp_digit* t)
  41509. {
  41510. sp_digit* t1 = t;
  41511. sp_digit* t2 = t + 2*42;
  41512. sp_digit* x;
  41513. sp_digit* y;
  41514. sp_digit* z;
  41515. x = r->x;
  41516. y = r->y;
  41517. z = r->z;
  41518. /* Put infinity into result. */
  41519. if (r != p) {
  41520. r->infinity = p->infinity;
  41521. }
  41522. /* T1 = Z * Z */
  41523. sp_1024_mont_sqr_42(t1, p->z, p1024_mod, p1024_mp_mod);
  41524. /* Z = Y * Z */
  41525. sp_1024_mont_mul_42(z, p->y, p->z, p1024_mod, p1024_mp_mod);
  41526. /* Z = 2Z */
  41527. sp_1024_mont_dbl_42(z, z, p1024_mod);
  41528. /* T2 = X - T1 */
  41529. sp_1024_mont_sub_42(t2, p->x, t1, p1024_mod);
  41530. /* T1 = X + T1 */
  41531. sp_1024_mont_add_42(t1, p->x, t1, p1024_mod);
  41532. /* T2 = T1 * T2 */
  41533. sp_1024_mont_mul_42(t2, t1, t2, p1024_mod, p1024_mp_mod);
  41534. /* T1 = 3T2 */
  41535. sp_1024_mont_tpl_42(t1, t2, p1024_mod);
  41536. /* Y = 2Y */
  41537. sp_1024_mont_dbl_42(y, p->y, p1024_mod);
  41538. /* Y = Y * Y */
  41539. sp_1024_mont_sqr_42(y, y, p1024_mod, p1024_mp_mod);
  41540. /* T2 = Y * Y */
  41541. sp_1024_mont_sqr_42(t2, y, p1024_mod, p1024_mp_mod);
  41542. /* T2 = T2/2 */
  41543. sp_1024_div2_42(t2, t2, p1024_mod);
  41544. /* Y = Y * X */
  41545. sp_1024_mont_mul_42(y, y, p->x, p1024_mod, p1024_mp_mod);
  41546. /* X = T1 * T1 */
  41547. sp_1024_mont_sqr_42(x, t1, p1024_mod, p1024_mp_mod);
  41548. /* X = X - Y */
  41549. sp_1024_mont_sub_42(x, x, y, p1024_mod);
  41550. /* X = X - Y */
  41551. sp_1024_mont_sub_42(x, x, y, p1024_mod);
  41552. /* Y = Y - X */
  41553. sp_1024_mont_sub_lower_42(y, y, x, p1024_mod);
  41554. /* Y = Y * T1 */
  41555. sp_1024_mont_mul_42(y, y, t1, p1024_mod, p1024_mp_mod);
  41556. /* Y = Y - T2 */
  41557. sp_1024_mont_sub_42(y, y, t2, p1024_mod);
  41558. }
  41559. /* Compare two numbers to determine if they are equal.
  41560. * Constant time implementation.
  41561. *
  41562. * a First number to compare.
  41563. * b Second number to compare.
  41564. * returns 1 when equal and 0 otherwise.
  41565. */
  41566. static int sp_1024_cmp_equal_42(const sp_digit* a, const sp_digit* b)
  41567. {
  41568. return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) |
  41569. (a[3] ^ b[3]) | (a[4] ^ b[4]) | (a[5] ^ b[5]) |
  41570. (a[6] ^ b[6]) | (a[7] ^ b[7]) | (a[8] ^ b[8]) |
  41571. (a[9] ^ b[9]) | (a[10] ^ b[10]) | (a[11] ^ b[11]) |
  41572. (a[12] ^ b[12]) | (a[13] ^ b[13]) | (a[14] ^ b[14]) |
  41573. (a[15] ^ b[15]) | (a[16] ^ b[16]) | (a[17] ^ b[17]) |
  41574. (a[18] ^ b[18]) | (a[19] ^ b[19]) | (a[20] ^ b[20]) |
  41575. (a[21] ^ b[21]) | (a[22] ^ b[22]) | (a[23] ^ b[23]) |
  41576. (a[24] ^ b[24]) | (a[25] ^ b[25]) | (a[26] ^ b[26]) |
  41577. (a[27] ^ b[27]) | (a[28] ^ b[28]) | (a[29] ^ b[29]) |
  41578. (a[30] ^ b[30]) | (a[31] ^ b[31]) | (a[32] ^ b[32]) |
  41579. (a[33] ^ b[33]) | (a[34] ^ b[34]) | (a[35] ^ b[35]) |
  41580. (a[36] ^ b[36]) | (a[37] ^ b[37]) | (a[38] ^ b[38]) |
  41581. (a[39] ^ b[39]) | (a[40] ^ b[40]) | (a[41] ^ b[41])) == 0;
  41582. }
  41583. /* Returns 1 if the number of zero.
  41584. * Implementation is constant time.
  41585. *
  41586. * a Number to check.
  41587. * returns 1 if the number is zero and 0 otherwise.
  41588. */
  41589. static int sp_1024_iszero_42(const sp_digit* a)
  41590. {
  41591. return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] |
  41592. a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14] | a[15] |
  41593. a[16] | a[17] | a[18] | a[19] | a[20] | a[21] | a[22] | a[23] |
  41594. a[24] | a[25] | a[26] | a[27] | a[28] | a[29] | a[30] | a[31] |
  41595. a[32] | a[33] | a[34] | a[35] | a[36] | a[37] | a[38] | a[39] |
  41596. a[40] | a[41]) == 0;
  41597. }
  41598. /* Add two Montgomery form projective points.
  41599. *
  41600. * r Result of addition.
  41601. * p First point to add.
  41602. * q Second point to add.
  41603. * t Temporary ordinate data.
  41604. */
  41605. #ifdef WOLFSSL_SP_NONBLOCK
  41606. typedef struct sp_1024_proj_point_add_42_ctx {
  41607. int state;
  41608. sp_1024_proj_point_dbl_42_ctx dbl_ctx;
  41609. const sp_point_1024* ap[2];
  41610. sp_point_1024* rp[2];
  41611. sp_digit* t1;
  41612. sp_digit* t2;
  41613. sp_digit* t3;
  41614. sp_digit* t4;
  41615. sp_digit* t5;
  41616. sp_digit* t6;
  41617. sp_digit* x;
  41618. sp_digit* y;
  41619. sp_digit* z;
  41620. } sp_1024_proj_point_add_42_ctx;
  41621. static int sp_1024_proj_point_add_42_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r,
  41622. const sp_point_1024* p, const sp_point_1024* q, sp_digit* t)
  41623. {
  41624. int err = FP_WOULDBLOCK;
  41625. sp_1024_proj_point_add_42_ctx* ctx = (sp_1024_proj_point_add_42_ctx*)sp_ctx->data;
  41626. /* Ensure only the first point is the same as the result. */
  41627. if (q == r) {
  41628. const sp_point_1024* a = p;
  41629. p = q;
  41630. q = a;
  41631. }
  41632. typedef char ctx_size_test[sizeof(sp_1024_proj_point_add_42_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  41633. (void)sizeof(ctx_size_test);
  41634. switch (ctx->state) {
  41635. case 0: /* INIT */
  41636. ctx->t1 = t;
  41637. ctx->t2 = t + 2*42;
  41638. ctx->t3 = t + 4*42;
  41639. ctx->t4 = t + 6*42;
  41640. ctx->t5 = t + 8*42;
  41641. ctx->t6 = t + 10*42;
  41642. ctx->x = ctx->t6;
  41643. ctx->y = ctx->t1;
  41644. ctx->z = ctx->t2;
  41645. ctx->state = 1;
  41646. break;
  41647. case 1:
  41648. /* Check double */
  41649. (void)sp_1024_sub_42(ctx->t1, p1024_mod, q->y);
  41650. sp_1024_norm_42(ctx->t1);
  41651. if ((~p->infinity & ~q->infinity &
  41652. sp_1024_cmp_equal_42(p->x, q->x) & sp_1024_cmp_equal_42(p->z, q->z) &
  41653. (sp_1024_cmp_equal_42(p->y, q->y) | sp_1024_cmp_equal_42(p->y, ctx->t1))) != 0)
  41654. {
  41655. XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
  41656. ctx->state = 2;
  41657. }
  41658. else {
  41659. ctx->state = 3;
  41660. }
  41661. break;
  41662. case 2:
  41663. err = sp_1024_proj_point_dbl_42_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t);
  41664. if (err == MP_OKAY)
  41665. ctx->state = 27; /* done */
  41666. break;
  41667. case 3:
  41668. {
  41669. ctx->state = 4;
  41670. break;
  41671. }
  41672. case 4:
  41673. /* U1 = X1*Z2^2 */
  41674. sp_1024_mont_sqr_42(ctx->t1, q->z, p1024_mod, p1024_mp_mod);
  41675. ctx->state = 5;
  41676. break;
  41677. case 5:
  41678. sp_1024_mont_mul_42(ctx->t3, ctx->t1, q->z, p1024_mod, p1024_mp_mod);
  41679. ctx->state = 6;
  41680. break;
  41681. case 6:
  41682. sp_1024_mont_mul_42(ctx->t1, ctx->t1, p->x, p1024_mod, p1024_mp_mod);
  41683. ctx->state = 7;
  41684. break;
  41685. case 7:
  41686. /* U2 = X2*Z1^2 */
  41687. sp_1024_mont_sqr_42(ctx->t2, p->z, p1024_mod, p1024_mp_mod);
  41688. ctx->state = 8;
  41689. break;
  41690. case 8:
  41691. sp_1024_mont_mul_42(ctx->t4, ctx->t2, p->z, p1024_mod, p1024_mp_mod);
  41692. ctx->state = 9;
  41693. break;
  41694. case 9:
  41695. sp_1024_mont_mul_42(ctx->t2, ctx->t2, q->x, p1024_mod, p1024_mp_mod);
  41696. ctx->state = 10;
  41697. break;
  41698. case 10:
  41699. /* S1 = Y1*Z2^3 */
  41700. sp_1024_mont_mul_42(ctx->t3, ctx->t3, p->y, p1024_mod, p1024_mp_mod);
  41701. ctx->state = 11;
  41702. break;
  41703. case 11:
  41704. /* S2 = Y2*Z1^3 */
  41705. sp_1024_mont_mul_42(ctx->t4, ctx->t4, q->y, p1024_mod, p1024_mp_mod);
  41706. ctx->state = 12;
  41707. break;
  41708. case 12:
  41709. /* H = U2 - U1 */
  41710. sp_1024_mont_sub_42(ctx->t2, ctx->t2, ctx->t1, p1024_mod);
  41711. ctx->state = 13;
  41712. break;
  41713. case 13:
  41714. /* R = S2 - S1 */
  41715. sp_1024_mont_sub_42(ctx->t4, ctx->t4, ctx->t3, p1024_mod);
  41716. ctx->state = 14;
  41717. break;
  41718. case 14:
  41719. /* X3 = R^2 - H^3 - 2*U1*H^2 */
  41720. sp_1024_mont_sqr_42(ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod);
  41721. ctx->state = 15;
  41722. break;
  41723. case 15:
  41724. sp_1024_mont_mul_42(ctx->y, ctx->t1, ctx->t5, p1024_mod, p1024_mp_mod);
  41725. ctx->state = 16;
  41726. break;
  41727. case 16:
  41728. sp_1024_mont_mul_42(ctx->t5, ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod);
  41729. ctx->state = 17;
  41730. break;
  41731. case 17:
  41732. /* Z3 = H*Z1*Z2 */
  41733. sp_1024_mont_mul_42(ctx->z, p->z, ctx->t2, p1024_mod, p1024_mp_mod);
  41734. ctx->state = 18;
  41735. break;
  41736. case 18:
  41737. sp_1024_mont_mul_42(ctx->z, ctx->z, q->z, p1024_mod, p1024_mp_mod);
  41738. ctx->state = 19;
  41739. break;
  41740. case 19:
  41741. sp_1024_mont_sqr_42(ctx->x, ctx->t4, p1024_mod, p1024_mp_mod);
  41742. ctx->state = 20;
  41743. break;
  41744. case 20:
  41745. sp_1024_mont_sub_42(ctx->x, ctx->x, ctx->t5, p1024_mod);
  41746. ctx->state = 21;
  41747. break;
  41748. case 21:
  41749. sp_1024_mont_mul_42(ctx->t5, ctx->t5, ctx->t3, p1024_mod, p1024_mp_mod);
  41750. ctx->state = 22;
  41751. break;
  41752. case 22:
  41753. sp_1024_mont_dbl_42(ctx->t3, ctx->y, p1024_mod);
  41754. ctx->state = 23;
  41755. break;
  41756. case 23:
  41757. sp_1024_mont_sub_42(ctx->x, ctx->x, ctx->t3, p1024_mod);
  41758. ctx->state = 24;
  41759. break;
  41760. case 24:
  41761. /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
  41762. sp_1024_mont_sub_lower_42(ctx->y, ctx->y, ctx->x, p1024_mod);
  41763. ctx->state = 25;
  41764. break;
  41765. case 25:
  41766. sp_1024_mont_mul_42(ctx->y, ctx->y, ctx->t4, p1024_mod, p1024_mp_mod);
  41767. ctx->state = 26;
  41768. break;
  41769. case 26:
  41770. sp_1024_mont_sub_42(ctx->y, ctx->y, ctx->t5, p1024_mod);
  41771. ctx->state = 27;
  41772. /* fall-through */
  41773. case 27:
  41774. {
  41775. int i;
  41776. sp_digit maskp = 0 - (q->infinity & (!p->infinity));
  41777. sp_digit maskq = 0 - (p->infinity & (!q->infinity));
  41778. sp_digit maskt = ~(maskp | maskq);
  41779. for (i = 0; i < 42; i++) {
  41780. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) |
  41781. (ctx->x[i] & maskt);
  41782. }
  41783. for (i = 0; i < 42; i++) {
  41784. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) |
  41785. (ctx->y[i] & maskt);
  41786. }
  41787. for (i = 0; i < 42; i++) {
  41788. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) |
  41789. (ctx->z[i] & maskt);
  41790. }
  41791. r->z[0] |= p->infinity & q->infinity;
  41792. r->infinity = p->infinity & q->infinity;
  41793. err = MP_OKAY;
  41794. break;
  41795. }
  41796. }
  41797. if (err == MP_OKAY && ctx->state != 27) {
  41798. err = FP_WOULDBLOCK;
  41799. }
  41800. return err;
  41801. }
  41802. #endif /* WOLFSSL_SP_NONBLOCK */
  41803. static void sp_1024_proj_point_add_42(sp_point_1024* r,
  41804. const sp_point_1024* p, const sp_point_1024* q, sp_digit* t)
  41805. {
  41806. sp_digit* t1 = t;
  41807. sp_digit* t2 = t + 2*42;
  41808. sp_digit* t3 = t + 4*42;
  41809. sp_digit* t4 = t + 6*42;
  41810. sp_digit* t5 = t + 8*42;
  41811. sp_digit* t6 = t + 10*42;
  41812. /* Check double */
  41813. (void)sp_1024_mont_sub_42(t1, p1024_mod, q->y, p1024_mod);
  41814. sp_1024_norm_42(t1);
  41815. if ((~p->infinity & ~q->infinity &
  41816. sp_1024_cmp_equal_42(p->x, q->x) & sp_1024_cmp_equal_42(p->z, q->z) &
  41817. (sp_1024_cmp_equal_42(p->y, q->y) | sp_1024_cmp_equal_42(p->y, t1))) != 0) {
  41818. sp_1024_proj_point_dbl_42(r, p, t);
  41819. }
  41820. else {
  41821. sp_digit maskp;
  41822. sp_digit maskq;
  41823. sp_digit maskt;
  41824. sp_digit* x = t6;
  41825. sp_digit* y = t1;
  41826. sp_digit* z = t2;
  41827. int i;
  41828. maskp = 0 - (q->infinity & (!p->infinity));
  41829. maskq = 0 - (p->infinity & (!q->infinity));
  41830. maskt = ~(maskp | maskq);
  41831. /* U1 = X1*Z2^2 */
  41832. sp_1024_mont_sqr_42(t1, q->z, p1024_mod, p1024_mp_mod);
  41833. sp_1024_mont_mul_42(t3, t1, q->z, p1024_mod, p1024_mp_mod);
  41834. sp_1024_mont_mul_42(t1, t1, p->x, p1024_mod, p1024_mp_mod);
  41835. /* U2 = X2*Z1^2 */
  41836. sp_1024_mont_sqr_42(t2, p->z, p1024_mod, p1024_mp_mod);
  41837. sp_1024_mont_mul_42(t4, t2, p->z, p1024_mod, p1024_mp_mod);
  41838. sp_1024_mont_mul_42(t2, t2, q->x, p1024_mod, p1024_mp_mod);
  41839. /* S1 = Y1*Z2^3 */
  41840. sp_1024_mont_mul_42(t3, t3, p->y, p1024_mod, p1024_mp_mod);
  41841. /* S2 = Y2*Z1^3 */
  41842. sp_1024_mont_mul_42(t4, t4, q->y, p1024_mod, p1024_mp_mod);
  41843. /* H = U2 - U1 */
  41844. sp_1024_mont_sub_42(t2, t2, t1, p1024_mod);
  41845. /* R = S2 - S1 */
  41846. sp_1024_mont_sub_42(t4, t4, t3, p1024_mod);
  41847. if (~p->infinity & ~q->infinity &
  41848. sp_1024_iszero_42(t2) & sp_1024_iszero_42(t4) & maskt) {
  41849. sp_1024_proj_point_dbl_42(r, p, t);
  41850. }
  41851. else {
  41852. /* X3 = R^2 - H^3 - 2*U1*H^2 */
  41853. sp_1024_mont_sqr_42(t5, t2, p1024_mod, p1024_mp_mod);
  41854. sp_1024_mont_mul_42(y, t1, t5, p1024_mod, p1024_mp_mod);
  41855. sp_1024_mont_mul_42(t5, t5, t2, p1024_mod, p1024_mp_mod);
  41856. /* Z3 = H*Z1*Z2 */
  41857. sp_1024_mont_mul_42(z, p->z, t2, p1024_mod, p1024_mp_mod);
  41858. sp_1024_mont_mul_42(z, z, q->z, p1024_mod, p1024_mp_mod);
  41859. sp_1024_mont_sqr_42(x, t4, p1024_mod, p1024_mp_mod);
  41860. sp_1024_mont_sub_42(x, x, t5, p1024_mod);
  41861. sp_1024_mont_mul_42(t5, t5, t3, p1024_mod, p1024_mp_mod);
  41862. sp_1024_mont_dbl_42(t3, y, p1024_mod);
  41863. sp_1024_mont_sub_42(x, x, t3, p1024_mod);
  41864. /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
  41865. sp_1024_mont_sub_lower_42(y, y, x, p1024_mod);
  41866. sp_1024_mont_mul_42(y, y, t4, p1024_mod, p1024_mp_mod);
  41867. sp_1024_mont_sub_42(y, y, t5, p1024_mod);
  41868. for (i = 0; i < 42; i++) {
  41869. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) |
  41870. (x[i] & maskt);
  41871. }
  41872. for (i = 0; i < 42; i++) {
  41873. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) |
  41874. (y[i] & maskt);
  41875. }
  41876. for (i = 0; i < 42; i++) {
  41877. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) |
  41878. (z[i] & maskt);
  41879. }
  41880. r->z[0] |= p->infinity & q->infinity;
  41881. r->infinity = p->infinity & q->infinity;
  41882. }
  41883. }
  41884. }
  41885. #ifdef WOLFSSL_SP_SMALL
  41886. /* Multiply the point by the scalar and return the result.
  41887. * If map is true then convert result to affine coordinates.
  41888. *
  41889. * Small implementation using add and double that is cache attack resistant but
  41890. * allocates memory rather than use large stacks.
  41891. * 1024 adds and doubles.
  41892. *
  41893. * r Resulting point.
  41894. * g Point to multiply.
  41895. * k Scalar to multiply by.
  41896. * map Indicates whether to convert result to affine.
  41897. * ct Constant time required.
  41898. * heap Heap to use for allocation.
  41899. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  41900. */
  41901. #ifdef WOLFSSL_SP_NONBLOCK
  41902. typedef struct sp_1024_ecc_mulmod_42_ctx {
  41903. int state;
  41904. union {
  41905. sp_1024_proj_point_dbl_42_ctx dbl_ctx;
  41906. sp_1024_proj_point_add_42_ctx add_ctx;
  41907. };
  41908. sp_point_1024 t[3];
  41909. sp_digit tmp[2 * 42 * 6];
  41910. sp_digit n;
  41911. int i;
  41912. int c;
  41913. int y;
  41914. } sp_1024_ecc_mulmod_42_ctx;
  41915. static int sp_1024_ecc_mulmod_42_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r,
  41916. const sp_point_1024* g, const sp_digit* k, int map, int ct, void* heap)
  41917. {
  41918. int err = FP_WOULDBLOCK;
  41919. sp_1024_ecc_mulmod_42_ctx* ctx = (sp_1024_ecc_mulmod_42_ctx*)sp_ctx->data;
  41920. typedef char ctx_size_test[sizeof(sp_1024_ecc_mulmod_42_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
  41921. (void)sizeof(ctx_size_test);
  41922. /* Implementation is constant time. */
  41923. (void)ct;
  41924. switch (ctx->state) {
  41925. case 0: /* INIT */
  41926. XMEMSET(ctx->t, 0, sizeof(sp_point_1024) * 3);
  41927. ctx->i = 40;
  41928. ctx->c = 24;
  41929. ctx->n = k[ctx->i--] << (25 - ctx->c);
  41930. /* t[0] = {0, 0, 1} * norm */
  41931. ctx->t[0].infinity = 1;
  41932. ctx->state = 1;
  41933. break;
  41934. case 1: /* T1X */
  41935. /* t[1] = {g->x, g->y, g->z} * norm */
  41936. err = sp_1024_mod_mul_norm_42(ctx->t[1].x, g->x, p1024_mod);
  41937. ctx->state = 2;
  41938. break;
  41939. case 2: /* T1Y */
  41940. err = sp_1024_mod_mul_norm_42(ctx->t[1].y, g->y, p1024_mod);
  41941. ctx->state = 3;
  41942. break;
  41943. case 3: /* T1Z */
  41944. err = sp_1024_mod_mul_norm_42(ctx->t[1].z, g->z, p1024_mod);
  41945. ctx->state = 4;
  41946. break;
  41947. case 4: /* ADDPREP */
  41948. if (ctx->c == 0) {
  41949. if (ctx->i == -1) {
  41950. ctx->state = 7;
  41951. break;
  41952. }
  41953. ctx->n = k[ctx->i--];
  41954. ctx->c = 25;
  41955. }
  41956. ctx->y = (ctx->n >> 24) & 1;
  41957. ctx->n <<= 1;
  41958. XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx));
  41959. ctx->state = 5;
  41960. break;
  41961. case 5: /* ADD */
  41962. err = sp_1024_proj_point_add_42_nb((sp_ecc_ctx_t*)&ctx->add_ctx,
  41963. &ctx->t[ctx->y^1], &ctx->t[0], &ctx->t[1], ctx->tmp);
  41964. if (err == MP_OKAY) {
  41965. XMEMCPY(&ctx->t[2], (void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) +
  41966. ((size_t)&ctx->t[1] & addr_mask[ctx->y])),
  41967. sizeof(sp_point_1024));
  41968. XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
  41969. ctx->state = 6;
  41970. }
  41971. break;
  41972. case 6: /* DBL */
  41973. err = sp_1024_proj_point_dbl_42_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->t[2],
  41974. &ctx->t[2], ctx->tmp);
  41975. if (err == MP_OKAY) {
  41976. XMEMCPY((void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) +
  41977. ((size_t)&ctx->t[1] & addr_mask[ctx->y])), &ctx->t[2],
  41978. sizeof(sp_point_1024));
  41979. ctx->state = 4;
  41980. ctx->c--;
  41981. }
  41982. break;
  41983. case 7: /* MAP */
  41984. if (map != 0) {
  41985. sp_1024_map_42(r, &ctx->t[0], ctx->tmp);
  41986. }
  41987. else {
  41988. XMEMCPY(r, &ctx->t[0], sizeof(sp_point_1024));
  41989. }
  41990. err = MP_OKAY;
  41991. break;
  41992. }
  41993. if (err == MP_OKAY && ctx->state != 7) {
  41994. err = FP_WOULDBLOCK;
  41995. }
  41996. if (err != FP_WOULDBLOCK) {
  41997. ForceZero(ctx->tmp, sizeof(ctx->tmp));
  41998. ForceZero(ctx->t, sizeof(ctx->t));
  41999. }
  42000. (void)heap;
  42001. return err;
  42002. }
  42003. #endif /* WOLFSSL_SP_NONBLOCK */
  42004. static int sp_1024_ecc_mulmod_42(sp_point_1024* r, const sp_point_1024* g,
  42005. const sp_digit* k, int map, int ct, void* heap)
  42006. {
  42007. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  42008. sp_point_1024* t = NULL;
  42009. sp_digit* tmp = NULL;
  42010. #else
  42011. sp_point_1024 t[3];
  42012. sp_digit tmp[2 * 42 * 6];
  42013. #endif
  42014. sp_digit n;
  42015. int i;
  42016. int c;
  42017. int y;
  42018. int err = MP_OKAY;
  42019. /* Implementation is constant time. */
  42020. (void)ct;
  42021. (void)heap;
  42022. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  42023. t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap,
  42024. DYNAMIC_TYPE_ECC);
  42025. if (t == NULL)
  42026. err = MEMORY_E;
  42027. if (err == MP_OKAY) {
  42028. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 42 * 6, heap,
  42029. DYNAMIC_TYPE_ECC);
  42030. if (tmp == NULL)
  42031. err = MEMORY_E;
  42032. }
  42033. #endif
  42034. if (err == MP_OKAY) {
  42035. XMEMSET(t, 0, sizeof(sp_point_1024) * 3);
  42036. /* t[0] = {0, 0, 1} * norm */
  42037. t[0].infinity = 1;
  42038. /* t[1] = {g->x, g->y, g->z} * norm */
  42039. err = sp_1024_mod_mul_norm_42(t[1].x, g->x, p1024_mod);
  42040. }
  42041. if (err == MP_OKAY)
  42042. err = sp_1024_mod_mul_norm_42(t[1].y, g->y, p1024_mod);
  42043. if (err == MP_OKAY)
  42044. err = sp_1024_mod_mul_norm_42(t[1].z, g->z, p1024_mod);
  42045. if (err == MP_OKAY) {
  42046. i = 40;
  42047. c = 24;
  42048. n = k[i--] << (25 - c);
  42049. for (; ; c--) {
  42050. if (c == 0) {
  42051. if (i == -1)
  42052. break;
  42053. n = k[i--];
  42054. c = 25;
  42055. }
  42056. y = (n >> 24) & 1;
  42057. n <<= 1;
  42058. sp_1024_proj_point_add_42(&t[y^1], &t[0], &t[1], tmp);
  42059. XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) +
  42060. ((size_t)&t[1] & addr_mask[y])),
  42061. sizeof(sp_point_1024));
  42062. sp_1024_proj_point_dbl_42(&t[2], &t[2], tmp);
  42063. XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) +
  42064. ((size_t)&t[1] & addr_mask[y])), &t[2],
  42065. sizeof(sp_point_1024));
  42066. }
  42067. if (map != 0) {
  42068. sp_1024_map_42(r, &t[0], tmp);
  42069. }
  42070. else {
  42071. XMEMCPY(r, &t[0], sizeof(sp_point_1024));
  42072. }
  42073. }
  42074. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  42075. if (tmp != NULL)
  42076. #endif
  42077. {
  42078. ForceZero(tmp, sizeof(sp_digit) * 2 * 42 * 6);
  42079. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  42080. XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
  42081. #endif
  42082. }
  42083. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  42084. if (t != NULL)
  42085. #endif
  42086. {
  42087. ForceZero(t, sizeof(sp_point_1024) * 3);
  42088. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  42089. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  42090. #endif
  42091. }
  42092. return err;
  42093. }
  42094. #else
  42095. /* A table entry for pre-computed points. */
  42096. typedef struct sp_table_entry_1024 {
  42097. sp_digit x[42];
  42098. sp_digit y[42];
  42099. } sp_table_entry_1024;
  42100. /* Conditionally copy a into r using the mask m.
  42101. * m is -1 to copy and 0 when not.
  42102. *
  42103. * r A single precision number to copy over.
  42104. * a A single precision number to copy.
  42105. * m Mask value to apply.
  42106. */
  42107. static void sp_1024_cond_copy_42(sp_digit* r, const sp_digit* a, const sp_digit m)
  42108. {
  42109. sp_digit t[42];
  42110. #ifdef WOLFSSL_SP_SMALL
  42111. int i;
  42112. for (i = 0; i < 42; i++) {
  42113. t[i] = r[i] ^ a[i];
  42114. }
  42115. for (i = 0; i < 42; i++) {
  42116. r[i] ^= t[i] & m;
  42117. }
  42118. #else
  42119. t[ 0] = r[ 0] ^ a[ 0];
  42120. t[ 1] = r[ 1] ^ a[ 1];
  42121. t[ 2] = r[ 2] ^ a[ 2];
  42122. t[ 3] = r[ 3] ^ a[ 3];
  42123. t[ 4] = r[ 4] ^ a[ 4];
  42124. t[ 5] = r[ 5] ^ a[ 5];
  42125. t[ 6] = r[ 6] ^ a[ 6];
  42126. t[ 7] = r[ 7] ^ a[ 7];
  42127. t[ 8] = r[ 8] ^ a[ 8];
  42128. t[ 9] = r[ 9] ^ a[ 9];
  42129. t[10] = r[10] ^ a[10];
  42130. t[11] = r[11] ^ a[11];
  42131. t[12] = r[12] ^ a[12];
  42132. t[13] = r[13] ^ a[13];
  42133. t[14] = r[14] ^ a[14];
  42134. t[15] = r[15] ^ a[15];
  42135. t[16] = r[16] ^ a[16];
  42136. t[17] = r[17] ^ a[17];
  42137. t[18] = r[18] ^ a[18];
  42138. t[19] = r[19] ^ a[19];
  42139. t[20] = r[20] ^ a[20];
  42140. t[21] = r[21] ^ a[21];
  42141. t[22] = r[22] ^ a[22];
  42142. t[23] = r[23] ^ a[23];
  42143. t[24] = r[24] ^ a[24];
  42144. t[25] = r[25] ^ a[25];
  42145. t[26] = r[26] ^ a[26];
  42146. t[27] = r[27] ^ a[27];
  42147. t[28] = r[28] ^ a[28];
  42148. t[29] = r[29] ^ a[29];
  42149. t[30] = r[30] ^ a[30];
  42150. t[31] = r[31] ^ a[31];
  42151. t[32] = r[32] ^ a[32];
  42152. t[33] = r[33] ^ a[33];
  42153. t[34] = r[34] ^ a[34];
  42154. t[35] = r[35] ^ a[35];
  42155. t[36] = r[36] ^ a[36];
  42156. t[37] = r[37] ^ a[37];
  42157. t[38] = r[38] ^ a[38];
  42158. t[39] = r[39] ^ a[39];
  42159. t[40] = r[40] ^ a[40];
  42160. t[41] = r[41] ^ a[41];
  42161. r[ 0] ^= t[ 0] & m;
  42162. r[ 1] ^= t[ 1] & m;
  42163. r[ 2] ^= t[ 2] & m;
  42164. r[ 3] ^= t[ 3] & m;
  42165. r[ 4] ^= t[ 4] & m;
  42166. r[ 5] ^= t[ 5] & m;
  42167. r[ 6] ^= t[ 6] & m;
  42168. r[ 7] ^= t[ 7] & m;
  42169. r[ 8] ^= t[ 8] & m;
  42170. r[ 9] ^= t[ 9] & m;
  42171. r[10] ^= t[10] & m;
  42172. r[11] ^= t[11] & m;
  42173. r[12] ^= t[12] & m;
  42174. r[13] ^= t[13] & m;
  42175. r[14] ^= t[14] & m;
  42176. r[15] ^= t[15] & m;
  42177. r[16] ^= t[16] & m;
  42178. r[17] ^= t[17] & m;
  42179. r[18] ^= t[18] & m;
  42180. r[19] ^= t[19] & m;
  42181. r[20] ^= t[20] & m;
  42182. r[21] ^= t[21] & m;
  42183. r[22] ^= t[22] & m;
  42184. r[23] ^= t[23] & m;
  42185. r[24] ^= t[24] & m;
  42186. r[25] ^= t[25] & m;
  42187. r[26] ^= t[26] & m;
  42188. r[27] ^= t[27] & m;
  42189. r[28] ^= t[28] & m;
  42190. r[29] ^= t[29] & m;
  42191. r[30] ^= t[30] & m;
  42192. r[31] ^= t[31] & m;
  42193. r[32] ^= t[32] & m;
  42194. r[33] ^= t[33] & m;
  42195. r[34] ^= t[34] & m;
  42196. r[35] ^= t[35] & m;
  42197. r[36] ^= t[36] & m;
  42198. r[37] ^= t[37] & m;
  42199. r[38] ^= t[38] & m;
  42200. r[39] ^= t[39] & m;
  42201. r[40] ^= t[40] & m;
  42202. r[41] ^= t[41] & m;
  42203. #endif /* WOLFSSL_SP_SMALL */
  42204. }
  42205. #define sp_1024_mont_dbl_lower_42 sp_1024_mont_dbl_42
  42206. #define sp_1024_mont_tpl_lower_42 sp_1024_mont_tpl_42
  42207. /* Double the Montgomery form projective point p a number of times.
  42208. *
  42209. * r Result of repeated doubling of point.
  42210. * p Point to double.
  42211. * n Number of times to double
  42212. * t Temporary ordinate data.
  42213. */
  42214. static void sp_1024_proj_point_dbl_n_42(sp_point_1024* p, int i,
  42215. sp_digit* t)
  42216. {
  42217. sp_digit* w = t;
  42218. sp_digit* a = t + 2*42;
  42219. sp_digit* b = t + 4*42;
  42220. sp_digit* t1 = t + 6*42;
  42221. sp_digit* t2 = t + 8*42;
  42222. sp_digit* x;
  42223. sp_digit* y;
  42224. sp_digit* z;
  42225. volatile int n = i;
  42226. x = p->x;
  42227. y = p->y;
  42228. z = p->z;
  42229. /* Y = 2*Y */
  42230. sp_1024_mont_dbl_42(y, y, p1024_mod);
  42231. /* W = Z^4 */
  42232. sp_1024_mont_sqr_42(w, z, p1024_mod, p1024_mp_mod);
  42233. sp_1024_mont_sqr_42(w, w, p1024_mod, p1024_mp_mod);
  42234. #ifndef WOLFSSL_SP_SMALL
  42235. while (--n > 0)
  42236. #else
  42237. while (--n >= 0)
  42238. #endif
  42239. {
  42240. /* A = 3*(X^2 - W) */
  42241. sp_1024_mont_sqr_42(t1, x, p1024_mod, p1024_mp_mod);
  42242. sp_1024_mont_sub_42(t1, t1, w, p1024_mod);
  42243. sp_1024_mont_tpl_lower_42(a, t1, p1024_mod);
  42244. /* B = X*Y^2 */
  42245. sp_1024_mont_sqr_42(t1, y, p1024_mod, p1024_mp_mod);
  42246. sp_1024_mont_mul_42(b, t1, x, p1024_mod, p1024_mp_mod);
  42247. /* X = A^2 - 2B */
  42248. sp_1024_mont_sqr_42(x, a, p1024_mod, p1024_mp_mod);
  42249. sp_1024_mont_dbl_42(t2, b, p1024_mod);
  42250. sp_1024_mont_sub_42(x, x, t2, p1024_mod);
  42251. /* b = 2.(B - X) */
  42252. sp_1024_mont_sub_lower_42(t2, b, x, p1024_mod);
  42253. sp_1024_mont_dbl_lower_42(b, t2, p1024_mod);
  42254. /* Z = Z*Y */
  42255. sp_1024_mont_mul_42(z, z, y, p1024_mod, p1024_mp_mod);
  42256. /* t1 = Y^4 */
  42257. sp_1024_mont_sqr_42(t1, t1, p1024_mod, p1024_mp_mod);
  42258. #ifdef WOLFSSL_SP_SMALL
  42259. if (n != 0)
  42260. #endif
  42261. {
  42262. /* W = W*Y^4 */
  42263. sp_1024_mont_mul_42(w, w, t1, p1024_mod, p1024_mp_mod);
  42264. }
  42265. /* y = 2*A*(B - X) - Y^4 */
  42266. sp_1024_mont_mul_42(y, b, a, p1024_mod, p1024_mp_mod);
  42267. sp_1024_mont_sub_42(y, y, t1, p1024_mod);
  42268. }
  42269. #ifndef WOLFSSL_SP_SMALL
  42270. /* A = 3*(X^2 - W) */
  42271. sp_1024_mont_sqr_42(t1, x, p1024_mod, p1024_mp_mod);
  42272. sp_1024_mont_sub_42(t1, t1, w, p1024_mod);
  42273. sp_1024_mont_tpl_lower_42(a, t1, p1024_mod);
  42274. /* B = X*Y^2 */
  42275. sp_1024_mont_sqr_42(t1, y, p1024_mod, p1024_mp_mod);
  42276. sp_1024_mont_mul_42(b, t1, x, p1024_mod, p1024_mp_mod);
  42277. /* X = A^2 - 2B */
  42278. sp_1024_mont_sqr_42(x, a, p1024_mod, p1024_mp_mod);
  42279. sp_1024_mont_dbl_42(t2, b, p1024_mod);
  42280. sp_1024_mont_sub_42(x, x, t2, p1024_mod);
  42281. /* b = 2.(B - X) */
  42282. sp_1024_mont_sub_lower_42(t2, b, x, p1024_mod);
  42283. sp_1024_mont_dbl_lower_42(b, t2, p1024_mod);
  42284. /* Z = Z*Y */
  42285. sp_1024_mont_mul_42(z, z, y, p1024_mod, p1024_mp_mod);
  42286. /* t1 = Y^4 */
  42287. sp_1024_mont_sqr_42(t1, t1, p1024_mod, p1024_mp_mod);
  42288. /* y = 2*A*(B - X) - Y^4 */
  42289. sp_1024_mont_mul_42(y, b, a, p1024_mod, p1024_mp_mod);
  42290. sp_1024_mont_sub_42(y, y, t1, p1024_mod);
  42291. #endif
  42292. /* Y = Y/2 */
  42293. sp_1024_div2_42(y, y, p1024_mod);
  42294. }
  42295. /* Double the Montgomery form projective point p a number of times.
  42296. *
  42297. * r Result of repeated doubling of point.
  42298. * p Point to double.
  42299. * n Number of times to double
  42300. * t Temporary ordinate data.
  42301. */
  42302. static void sp_1024_proj_point_dbl_n_store_42(sp_point_1024* r,
  42303. const sp_point_1024* p, int n, int m, sp_digit* t)
  42304. {
  42305. sp_digit* w = t;
  42306. sp_digit* a = t + 2*42;
  42307. sp_digit* b = t + 4*42;
  42308. sp_digit* t1 = t + 6*42;
  42309. sp_digit* t2 = t + 8*42;
  42310. sp_digit* x = r[2*m].x;
  42311. sp_digit* y = r[(1<<n)*m].y;
  42312. sp_digit* z = r[2*m].z;
  42313. int i;
  42314. int j;
  42315. for (i=0; i<42; i++) {
  42316. x[i] = p->x[i];
  42317. }
  42318. for (i=0; i<42; i++) {
  42319. y[i] = p->y[i];
  42320. }
  42321. for (i=0; i<42; i++) {
  42322. z[i] = p->z[i];
  42323. }
  42324. /* Y = 2*Y */
  42325. sp_1024_mont_dbl_42(y, y, p1024_mod);
  42326. /* W = Z^4 */
  42327. sp_1024_mont_sqr_42(w, z, p1024_mod, p1024_mp_mod);
  42328. sp_1024_mont_sqr_42(w, w, p1024_mod, p1024_mp_mod);
  42329. j = m;
  42330. for (i=1; i<=n; i++) {
  42331. j *= 2;
  42332. /* A = 3*(X^2 - W) */
  42333. sp_1024_mont_sqr_42(t1, x, p1024_mod, p1024_mp_mod);
  42334. sp_1024_mont_sub_42(t1, t1, w, p1024_mod);
  42335. sp_1024_mont_tpl_lower_42(a, t1, p1024_mod);
  42336. /* B = X*Y^2 */
  42337. sp_1024_mont_sqr_42(t1, y, p1024_mod, p1024_mp_mod);
  42338. sp_1024_mont_mul_42(b, t1, x, p1024_mod, p1024_mp_mod);
  42339. x = r[j].x;
  42340. /* X = A^2 - 2B */
  42341. sp_1024_mont_sqr_42(x, a, p1024_mod, p1024_mp_mod);
  42342. sp_1024_mont_dbl_42(t2, b, p1024_mod);
  42343. sp_1024_mont_sub_42(x, x, t2, p1024_mod);
  42344. /* b = 2.(B - X) */
  42345. sp_1024_mont_sub_lower_42(t2, b, x, p1024_mod);
  42346. sp_1024_mont_dbl_lower_42(b, t2, p1024_mod);
  42347. /* Z = Z*Y */
  42348. sp_1024_mont_mul_42(r[j].z, z, y, p1024_mod, p1024_mp_mod);
  42349. z = r[j].z;
  42350. /* t1 = Y^4 */
  42351. sp_1024_mont_sqr_42(t1, t1, p1024_mod, p1024_mp_mod);
  42352. if (i != n) {
  42353. /* W = W*Y^4 */
  42354. sp_1024_mont_mul_42(w, w, t1, p1024_mod, p1024_mp_mod);
  42355. }
  42356. /* y = 2*A*(B - X) - Y^4 */
  42357. sp_1024_mont_mul_42(y, b, a, p1024_mod, p1024_mp_mod);
  42358. sp_1024_mont_sub_42(y, y, t1, p1024_mod);
  42359. /* Y = Y/2 */
  42360. sp_1024_div2_42(r[j].y, y, p1024_mod);
  42361. r[j].infinity = 0;
  42362. }
  42363. }
  42364. /* Add two Montgomery form projective points.
  42365. *
  42366. * ra Result of addition.
  42367. * rs Result of subtraction.
  42368. * p First point to add.
  42369. * q Second point to add.
  42370. * t Temporary ordinate data.
  42371. */
  42372. static void sp_1024_proj_point_add_sub_42(sp_point_1024* ra,
  42373. sp_point_1024* rs, const sp_point_1024* p, const sp_point_1024* q,
  42374. sp_digit* t)
  42375. {
  42376. sp_digit* t1 = t;
  42377. sp_digit* t2 = t + 2*42;
  42378. sp_digit* t3 = t + 4*42;
  42379. sp_digit* t4 = t + 6*42;
  42380. sp_digit* t5 = t + 8*42;
  42381. sp_digit* t6 = t + 10*42;
  42382. sp_digit* xa = ra->x;
  42383. sp_digit* ya = ra->y;
  42384. sp_digit* za = ra->z;
  42385. sp_digit* xs = rs->x;
  42386. sp_digit* ys = rs->y;
  42387. sp_digit* zs = rs->z;
  42388. XMEMCPY(xa, p->x, sizeof(p->x) / 2);
  42389. XMEMCPY(ya, p->y, sizeof(p->y) / 2);
  42390. XMEMCPY(za, p->z, sizeof(p->z) / 2);
  42391. ra->infinity = 0;
  42392. rs->infinity = 0;
  42393. /* U1 = X1*Z2^2 */
  42394. sp_1024_mont_sqr_42(t1, q->z, p1024_mod, p1024_mp_mod);
  42395. sp_1024_mont_mul_42(t3, t1, q->z, p1024_mod, p1024_mp_mod);
  42396. sp_1024_mont_mul_42(t1, t1, xa, p1024_mod, p1024_mp_mod);
  42397. /* U2 = X2*Z1^2 */
  42398. sp_1024_mont_sqr_42(t2, za, p1024_mod, p1024_mp_mod);
  42399. sp_1024_mont_mul_42(t4, t2, za, p1024_mod, p1024_mp_mod);
  42400. sp_1024_mont_mul_42(t2, t2, q->x, p1024_mod, p1024_mp_mod);
  42401. /* S1 = Y1*Z2^3 */
  42402. sp_1024_mont_mul_42(t3, t3, ya, p1024_mod, p1024_mp_mod);
  42403. /* S2 = Y2*Z1^3 */
  42404. sp_1024_mont_mul_42(t4, t4, q->y, p1024_mod, p1024_mp_mod);
  42405. /* H = U2 - U1 */
  42406. sp_1024_mont_sub_42(t2, t2, t1, p1024_mod);
  42407. /* RS = S2 + S1 */
  42408. sp_1024_mont_add_42(t6, t4, t3, p1024_mod);
  42409. /* R = S2 - S1 */
  42410. sp_1024_mont_sub_42(t4, t4, t3, p1024_mod);
  42411. /* Z3 = H*Z1*Z2 */
  42412. /* ZS = H*Z1*Z2 */
  42413. sp_1024_mont_mul_42(za, za, q->z, p1024_mod, p1024_mp_mod);
  42414. sp_1024_mont_mul_42(za, za, t2, p1024_mod, p1024_mp_mod);
  42415. XMEMCPY(zs, za, sizeof(p->z)/2);
  42416. /* X3 = R^2 - H^3 - 2*U1*H^2 */
  42417. /* XS = RS^2 - H^3 - 2*U1*H^2 */
  42418. sp_1024_mont_sqr_42(xa, t4, p1024_mod, p1024_mp_mod);
  42419. sp_1024_mont_sqr_42(xs, t6, p1024_mod, p1024_mp_mod);
  42420. sp_1024_mont_sqr_42(t5, t2, p1024_mod, p1024_mp_mod);
  42421. sp_1024_mont_mul_42(ya, t1, t5, p1024_mod, p1024_mp_mod);
  42422. sp_1024_mont_mul_42(t5, t5, t2, p1024_mod, p1024_mp_mod);
  42423. sp_1024_mont_sub_42(xa, xa, t5, p1024_mod);
  42424. sp_1024_mont_sub_42(xs, xs, t5, p1024_mod);
  42425. sp_1024_mont_dbl_42(t1, ya, p1024_mod);
  42426. sp_1024_mont_sub_42(xa, xa, t1, p1024_mod);
  42427. sp_1024_mont_sub_42(xs, xs, t1, p1024_mod);
  42428. /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
  42429. /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */
  42430. sp_1024_mont_sub_lower_42(ys, ya, xs, p1024_mod);
  42431. sp_1024_mont_sub_lower_42(ya, ya, xa, p1024_mod);
  42432. sp_1024_mont_mul_42(ya, ya, t4, p1024_mod, p1024_mp_mod);
  42433. sp_1024_mont_sub_42(t6, p1024_mod, t6, p1024_mod);
  42434. sp_1024_mont_mul_42(ys, ys, t6, p1024_mod, p1024_mp_mod);
  42435. sp_1024_mont_mul_42(t5, t5, t3, p1024_mod, p1024_mp_mod);
  42436. sp_1024_mont_sub_42(ya, ya, t5, p1024_mod);
  42437. sp_1024_mont_sub_42(ys, ys, t5, p1024_mod);
  42438. }
  42439. /* Structure used to describe recoding of scalar multiplication. */
  42440. typedef struct ecc_recode_1024 {
  42441. /* Index into pre-computation table. */
  42442. uint8_t i;
  42443. /* Use the negative of the point. */
  42444. uint8_t neg;
  42445. } ecc_recode_1024;
  42446. /* The index into pre-computation table to use. */
  42447. static const uint8_t recode_index_42_7[130] = {
  42448. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
  42449. 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
  42450. 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
  42451. 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
  42452. 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49,
  42453. 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33,
  42454. 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
  42455. 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
  42456. 0, 1,
  42457. };
  42458. /* Whether to negate y-ordinate. */
  42459. static const uint8_t recode_neg_42_7[130] = {
  42460. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  42461. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  42462. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  42463. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  42464. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  42465. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  42466. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  42467. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  42468. 0, 0,
  42469. };
  42470. /* Recode the scalar for multiplication using pre-computed values and
  42471. * subtraction.
  42472. *
  42473. * k Scalar to multiply by.
  42474. * v Vector of operations to perform.
  42475. */
  42476. static void sp_1024_ecc_recode_7_42(const sp_digit* k, ecc_recode_1024* v)
  42477. {
  42478. int i;
  42479. int j;
  42480. uint8_t y;
  42481. int carry = 0;
  42482. int o;
  42483. sp_digit n;
  42484. j = 0;
  42485. n = k[j];
  42486. o = 0;
  42487. for (i=0; i<147; i++) {
  42488. y = (int8_t)n;
  42489. if (o + 7 < 25) {
  42490. y &= 0x7f;
  42491. n >>= 7;
  42492. o += 7;
  42493. }
  42494. else if (o + 7 == 25) {
  42495. n >>= 7;
  42496. if (++j < 42)
  42497. n = k[j];
  42498. o = 0;
  42499. }
  42500. else if (++j < 42) {
  42501. n = k[j];
  42502. y |= (uint8_t)((n << (25 - o)) & 0x7f);
  42503. o -= 18;
  42504. n >>= o;
  42505. }
  42506. y += (uint8_t)carry;
  42507. v[i].i = recode_index_42_7[y];
  42508. v[i].neg = recode_neg_42_7[y];
  42509. carry = (y >> 7) + v[i].neg;
  42510. }
  42511. }
  42512. /* Multiply the point by the scalar and return the result.
  42513. * If map is true then convert result to affine coordinates.
  42514. *
  42515. * Window technique of 7 bits. (Add-Sub variation.)
  42516. * Calculate 0..64 times the point. Use function that adds and
  42517. * subtracts the same two points.
  42518. * Recode to add or subtract one of the computed points.
  42519. * Double to push up.
  42520. * NOT a sliding window.
  42521. *
  42522. * r Resulting point.
  42523. * g Point to multiply.
  42524. * k Scalar to multiply by.
  42525. * map Indicates whether to convert result to affine.
  42526. * ct Constant time required.
  42527. * heap Heap to use for allocation.
  42528. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  42529. */
  42530. static int sp_1024_ecc_mulmod_win_add_sub_42(sp_point_1024* r, const sp_point_1024* g,
  42531. const sp_digit* k, int map, int ct, void* heap)
  42532. {
  42533. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  42534. sp_point_1024* t = NULL;
  42535. sp_digit* tmp = NULL;
  42536. #else
  42537. sp_point_1024 t[65+2];
  42538. sp_digit tmp[2 * 42 * 6];
  42539. #endif
  42540. sp_point_1024* rt = NULL;
  42541. sp_point_1024* p = NULL;
  42542. sp_digit* negy;
  42543. int i;
  42544. ecc_recode_1024 v[147];
  42545. int err = MP_OKAY;
  42546. /* Constant time used for cache attack resistance implementation. */
  42547. (void)ct;
  42548. (void)heap;
  42549. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  42550. t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) *
  42551. (65+2), heap, DYNAMIC_TYPE_ECC);
  42552. if (t == NULL)
  42553. err = MEMORY_E;
  42554. if (err == MP_OKAY) {
  42555. tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 42 * 6,
  42556. heap, DYNAMIC_TYPE_ECC);
  42557. if (tmp == NULL)
  42558. err = MEMORY_E;
  42559. }
  42560. #endif
  42561. if (err == MP_OKAY) {
  42562. rt = t + 65;
  42563. p = t + 65+1;
  42564. /* t[0] = {0, 0, 1} * norm */
  42565. XMEMSET(&t[0], 0, sizeof(t[0]));
  42566. t[0].infinity = 1;
  42567. /* t[1] = {g->x, g->y, g->z} * norm */
  42568. err = sp_1024_mod_mul_norm_42(t[1].x, g->x, p1024_mod);
  42569. }
  42570. if (err == MP_OKAY) {
  42571. err = sp_1024_mod_mul_norm_42(t[1].y, g->y, p1024_mod);
  42572. }
  42573. if (err == MP_OKAY) {
  42574. err = sp_1024_mod_mul_norm_42(t[1].z, g->z, p1024_mod);
  42575. }
  42576. if (err == MP_OKAY) {
  42577. t[1].infinity = 0;
  42578. /* t[2] ... t[64] */
  42579. sp_1024_proj_point_dbl_n_store_42(t, &t[ 1], 6, 1, tmp);
  42580. sp_1024_proj_point_add_42(&t[ 3], &t[ 2], &t[ 1], tmp);
  42581. sp_1024_proj_point_dbl_42(&t[ 6], &t[ 3], tmp);
  42582. sp_1024_proj_point_add_sub_42(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp);
  42583. sp_1024_proj_point_dbl_42(&t[10], &t[ 5], tmp);
  42584. sp_1024_proj_point_add_sub_42(&t[11], &t[ 9], &t[10], &t[ 1], tmp);
  42585. sp_1024_proj_point_dbl_42(&t[12], &t[ 6], tmp);
  42586. sp_1024_proj_point_dbl_42(&t[14], &t[ 7], tmp);
  42587. sp_1024_proj_point_add_sub_42(&t[15], &t[13], &t[14], &t[ 1], tmp);
  42588. sp_1024_proj_point_dbl_42(&t[18], &t[ 9], tmp);
  42589. sp_1024_proj_point_add_sub_42(&t[19], &t[17], &t[18], &t[ 1], tmp);
  42590. sp_1024_proj_point_dbl_42(&t[20], &t[10], tmp);
  42591. sp_1024_proj_point_dbl_42(&t[22], &t[11], tmp);
  42592. sp_1024_proj_point_add_sub_42(&t[23], &t[21], &t[22], &t[ 1], tmp);
  42593. sp_1024_proj_point_dbl_42(&t[24], &t[12], tmp);
  42594. sp_1024_proj_point_dbl_42(&t[26], &t[13], tmp);
  42595. sp_1024_proj_point_add_sub_42(&t[27], &t[25], &t[26], &t[ 1], tmp);
  42596. sp_1024_proj_point_dbl_42(&t[28], &t[14], tmp);
  42597. sp_1024_proj_point_dbl_42(&t[30], &t[15], tmp);
  42598. sp_1024_proj_point_add_sub_42(&t[31], &t[29], &t[30], &t[ 1], tmp);
  42599. sp_1024_proj_point_dbl_42(&t[34], &t[17], tmp);
  42600. sp_1024_proj_point_add_sub_42(&t[35], &t[33], &t[34], &t[ 1], tmp);
  42601. sp_1024_proj_point_dbl_42(&t[36], &t[18], tmp);
  42602. sp_1024_proj_point_dbl_42(&t[38], &t[19], tmp);
  42603. sp_1024_proj_point_add_sub_42(&t[39], &t[37], &t[38], &t[ 1], tmp);
  42604. sp_1024_proj_point_dbl_42(&t[40], &t[20], tmp);
  42605. sp_1024_proj_point_dbl_42(&t[42], &t[21], tmp);
  42606. sp_1024_proj_point_add_sub_42(&t[43], &t[41], &t[42], &t[ 1], tmp);
  42607. sp_1024_proj_point_dbl_42(&t[44], &t[22], tmp);
  42608. sp_1024_proj_point_dbl_42(&t[46], &t[23], tmp);
  42609. sp_1024_proj_point_add_sub_42(&t[47], &t[45], &t[46], &t[ 1], tmp);
  42610. sp_1024_proj_point_dbl_42(&t[48], &t[24], tmp);
  42611. sp_1024_proj_point_dbl_42(&t[50], &t[25], tmp);
  42612. sp_1024_proj_point_add_sub_42(&t[51], &t[49], &t[50], &t[ 1], tmp);
  42613. sp_1024_proj_point_dbl_42(&t[52], &t[26], tmp);
  42614. sp_1024_proj_point_dbl_42(&t[54], &t[27], tmp);
  42615. sp_1024_proj_point_add_sub_42(&t[55], &t[53], &t[54], &t[ 1], tmp);
  42616. sp_1024_proj_point_dbl_42(&t[56], &t[28], tmp);
  42617. sp_1024_proj_point_dbl_42(&t[58], &t[29], tmp);
  42618. sp_1024_proj_point_add_sub_42(&t[59], &t[57], &t[58], &t[ 1], tmp);
  42619. sp_1024_proj_point_dbl_42(&t[60], &t[30], tmp);
  42620. sp_1024_proj_point_dbl_42(&t[62], &t[31], tmp);
  42621. sp_1024_proj_point_add_sub_42(&t[63], &t[61], &t[62], &t[ 1], tmp);
  42622. negy = t[0].y;
  42623. sp_1024_ecc_recode_7_42(k, v);
  42624. i = 146;
  42625. XMEMCPY(rt, &t[v[i].i], sizeof(sp_point_1024));
  42626. for (--i; i>=0; i--) {
  42627. sp_1024_proj_point_dbl_n_42(rt, 7, tmp);
  42628. XMEMCPY(p, &t[v[i].i], sizeof(sp_point_1024));
  42629. sp_1024_mont_sub_42(negy, p1024_mod, p->y, p1024_mod);
  42630. sp_1024_norm_42(negy);
  42631. sp_1024_cond_copy_42(p->y, negy, (sp_digit)0 - v[i].neg);
  42632. sp_1024_proj_point_add_42(rt, rt, p, tmp);
  42633. }
  42634. if (map != 0) {
  42635. sp_1024_map_42(r, rt, tmp);
  42636. }
  42637. else {
  42638. XMEMCPY(r, rt, sizeof(sp_point_1024));
  42639. }
  42640. }
  42641. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  42642. if (t != NULL)
  42643. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  42644. if (tmp != NULL)
  42645. XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
  42646. #endif
  42647. return err;
  42648. }
  42649. #ifdef FP_ECC
  42650. #endif /* FP_ECC */
  42651. /* Add two Montgomery form projective points. The second point has a q value of
  42652. * one.
  42653. * Only the first point can be the same pointer as the result point.
  42654. *
  42655. * r Result of addition.
  42656. * p First point to add.
  42657. * q Second point to add.
  42658. * t Temporary ordinate data.
  42659. */
  42660. static void sp_1024_proj_point_add_qz1_42(sp_point_1024* r, const sp_point_1024* p,
  42661. const sp_point_1024* q, sp_digit* t)
  42662. {
  42663. sp_digit* t1 = t;
  42664. sp_digit* t2 = t + 2*42;
  42665. sp_digit* t3 = t + 4*42;
  42666. sp_digit* t4 = t + 6*42;
  42667. sp_digit* t5 = t + 8*42;
  42668. sp_digit* t6 = t + 10*42;
  42669. /* Check double */
  42670. (void)sp_1024_mont_sub_42(t1, p1024_mod, q->y, p1024_mod);
  42671. sp_1024_norm_42(t1);
  42672. if ((~p->infinity & ~q->infinity &
  42673. sp_1024_cmp_equal_42(p->x, q->x) & sp_1024_cmp_equal_42(p->z, q->z) &
  42674. (sp_1024_cmp_equal_42(p->y, q->y) | sp_1024_cmp_equal_42(p->y, t1))) != 0) {
  42675. sp_1024_proj_point_dbl_42(r, p, t);
  42676. }
  42677. else {
  42678. sp_digit maskp;
  42679. sp_digit maskq;
  42680. sp_digit maskt;
  42681. sp_digit* x = t2;
  42682. sp_digit* y = t5;
  42683. sp_digit* z = t6;
  42684. int i;
  42685. /* U2 = X2*Z1^2 */
  42686. sp_1024_mont_sqr_42(t2, p->z, p1024_mod, p1024_mp_mod);
  42687. sp_1024_mont_mul_42(t4, t2, p->z, p1024_mod, p1024_mp_mod);
  42688. sp_1024_mont_mul_42(t2, t2, q->x, p1024_mod, p1024_mp_mod);
  42689. /* S2 = Y2*Z1^3 */
  42690. sp_1024_mont_mul_42(t4, t4, q->y, p1024_mod, p1024_mp_mod);
  42691. /* H = U2 - X1 */
  42692. sp_1024_mont_sub_42(t2, t2, p->x, p1024_mod);
  42693. /* R = S2 - Y1 */
  42694. sp_1024_mont_sub_42(t4, t4, p->y, p1024_mod);
  42695. /* Z3 = H*Z1 */
  42696. sp_1024_mont_mul_42(z, p->z, t2, p1024_mod, p1024_mp_mod);
  42697. /* X3 = R^2 - H^3 - 2*X1*H^2 */
  42698. sp_1024_mont_sqr_42(t1, t4, p1024_mod, p1024_mp_mod);
  42699. sp_1024_mont_sqr_42(t5, t2, p1024_mod, p1024_mp_mod);
  42700. sp_1024_mont_mul_42(t3, p->x, t5, p1024_mod, p1024_mp_mod);
  42701. sp_1024_mont_mul_42(t5, t5, t2, p1024_mod, p1024_mp_mod);
  42702. sp_1024_mont_sub_42(x, t1, t5, p1024_mod);
  42703. sp_1024_mont_dbl_42(t1, t3, p1024_mod);
  42704. sp_1024_mont_sub_42(x, x, t1, p1024_mod);
  42705. /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */
  42706. sp_1024_mont_sub_lower_42(t3, t3, x, p1024_mod);
  42707. sp_1024_mont_mul_42(t3, t3, t4, p1024_mod, p1024_mp_mod);
  42708. sp_1024_mont_mul_42(t5, t5, p->y, p1024_mod, p1024_mp_mod);
  42709. sp_1024_mont_sub_42(y, t3, t5, p1024_mod);
  42710. maskp = 0 - (q->infinity & (!p->infinity));
  42711. maskq = 0 - (p->infinity & (!q->infinity));
  42712. maskt = ~(maskp | maskq);
  42713. for (i = 0; i < 42; i++) {
  42714. r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | (x[i] & maskt);
  42715. }
  42716. for (i = 0; i < 42; i++) {
  42717. r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | (y[i] & maskt);
  42718. }
  42719. for (i = 0; i < 42; i++) {
  42720. r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | (z[i] & maskt);
  42721. }
  42722. r->z[0] |= p->infinity & q->infinity;
  42723. r->infinity = p->infinity & q->infinity;
  42724. }
  42725. }
  42726. #if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL)
  42727. /* Convert the projective point to affine.
  42728. * Ordinates are in Montgomery form.
  42729. *
  42730. * a Point to convert.
  42731. * t Temporary data.
  42732. */
  42733. static void sp_1024_proj_to_affine_42(sp_point_1024* a, sp_digit* t)
  42734. {
  42735. sp_digit* t1 = t;
  42736. sp_digit* t2 = t + 2 * 42;
  42737. sp_digit* tmp = t + 4 * 42;
  42738. sp_1024_mont_inv_42(t1, a->z, tmp);
  42739. sp_1024_mont_sqr_42(t2, t1, p1024_mod, p1024_mp_mod);
  42740. sp_1024_mont_mul_42(t1, t2, t1, p1024_mod, p1024_mp_mod);
  42741. sp_1024_mont_mul_42(a->x, a->x, t2, p1024_mod, p1024_mp_mod);
  42742. sp_1024_mont_mul_42(a->y, a->y, t1, p1024_mod, p1024_mp_mod);
  42743. XMEMCPY(a->z, p1024_norm_mod, sizeof(p1024_norm_mod));
  42744. }
  42745. /* Generate the pre-computed table of points for the base point.
  42746. *
  42747. * width = 8
  42748. * 256 entries
  42749. * 128 bits between
  42750. *
  42751. * a The base point.
  42752. * table Place to store generated point data.
  42753. * tmp Temporary data.
  42754. * heap Heap to use for allocation.
  42755. */
  42756. static int sp_1024_gen_stripe_table_42(const sp_point_1024* a,
  42757. sp_table_entry_1024* table, sp_digit* tmp, void* heap)
  42758. {
  42759. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  42760. sp_point_1024* t = NULL;
  42761. #else
  42762. sp_point_1024 t[3];
  42763. #endif
  42764. sp_point_1024* s1 = NULL;
  42765. sp_point_1024* s2 = NULL;
  42766. int i;
  42767. int j;
  42768. int err = MP_OKAY;
  42769. (void)heap;
  42770. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  42771. t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap,
  42772. DYNAMIC_TYPE_ECC);
  42773. if (t == NULL)
  42774. err = MEMORY_E;
  42775. #endif
  42776. if (err == MP_OKAY) {
  42777. s1 = t + 1;
  42778. s2 = t + 2;
  42779. err = sp_1024_mod_mul_norm_42(t->x, a->x, p1024_mod);
  42780. }
  42781. if (err == MP_OKAY) {
  42782. err = sp_1024_mod_mul_norm_42(t->y, a->y, p1024_mod);
  42783. }
  42784. if (err == MP_OKAY) {
  42785. err = sp_1024_mod_mul_norm_42(t->z, a->z, p1024_mod);
  42786. }
  42787. if (err == MP_OKAY) {
  42788. t->infinity = 0;
  42789. sp_1024_proj_to_affine_42(t, tmp);
  42790. XMEMCPY(s1->z, p1024_norm_mod, sizeof(p1024_norm_mod));
  42791. s1->infinity = 0;
  42792. XMEMCPY(s2->z, p1024_norm_mod, sizeof(p1024_norm_mod));
  42793. s2->infinity = 0;
  42794. /* table[0] = {0, 0, infinity} */
  42795. XMEMSET(&table[0], 0, sizeof(sp_table_entry_1024));
  42796. /* table[1] = Affine version of 'a' in Montgomery form */
  42797. XMEMCPY(table[1].x, t->x, sizeof(table->x));
  42798. XMEMCPY(table[1].y, t->y, sizeof(table->y));
  42799. for (i=1; i<8; i++) {
  42800. sp_1024_proj_point_dbl_n_42(t, 128, tmp);
  42801. sp_1024_proj_to_affine_42(t, tmp);
  42802. XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
  42803. XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
  42804. }
  42805. for (i=1; i<8; i++) {
  42806. XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
  42807. XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
  42808. for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
  42809. XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
  42810. XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
  42811. sp_1024_proj_point_add_qz1_42(t, s1, s2, tmp);
  42812. sp_1024_proj_to_affine_42(t, tmp);
  42813. XMEMCPY(table[j].x, t->x, sizeof(table->x));
  42814. XMEMCPY(table[j].y, t->y, sizeof(table->y));
  42815. }
  42816. }
  42817. }
  42818. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  42819. if (t != NULL)
  42820. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  42821. #endif
  42822. return err;
  42823. }
  42824. #endif /* FP_ECC | !WOLFSSL_SP_SMALL */
  42825. /* Multiply the point by the scalar and return the result.
  42826. * If map is true then convert result to affine coordinates.
  42827. *
  42828. * Stripe implementation.
  42829. * Pre-generated: 2^0, 2^128, ...
  42830. * Pre-generated: products of all combinations of above.
  42831. * 8 doubles and adds (with qz=1)
  42832. *
  42833. * r Resulting point.
  42834. * k Scalar to multiply by.
  42835. * table Pre-computed table.
  42836. * map Indicates whether to convert result to affine.
  42837. * ct Constant time required.
  42838. * heap Heap to use for allocation.
  42839. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  42840. */
  42841. static int sp_1024_ecc_mulmod_stripe_42(sp_point_1024* r, const sp_point_1024* g,
  42842. const sp_table_entry_1024* table, const sp_digit* k, int map,
  42843. int ct, void* heap)
  42844. {
  42845. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  42846. sp_point_1024* rt = NULL;
  42847. sp_digit* t = NULL;
  42848. #else
  42849. sp_point_1024 rt[2];
  42850. sp_digit t[2 * 42 * 6];
  42851. #endif
  42852. sp_point_1024* p = NULL;
  42853. int i;
  42854. int j;
  42855. int y;
  42856. int x;
  42857. int err = MP_OKAY;
  42858. (void)g;
  42859. /* Constant time used for cache attack resistance implementation. */
  42860. (void)ct;
  42861. (void)heap;
  42862. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  42863. rt = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap,
  42864. DYNAMIC_TYPE_ECC);
  42865. if (rt == NULL)
  42866. err = MEMORY_E;
  42867. if (err == MP_OKAY) {
  42868. t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 42 * 6, heap,
  42869. DYNAMIC_TYPE_ECC);
  42870. if (t == NULL)
  42871. err = MEMORY_E;
  42872. }
  42873. #endif
  42874. if (err == MP_OKAY) {
  42875. p = rt + 1;
  42876. XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod));
  42877. XMEMCPY(rt->z, p1024_norm_mod, sizeof(p1024_norm_mod));
  42878. y = 0;
  42879. x = 127;
  42880. for (j=0; j<8; j++) {
  42881. y |= (int)(((k[x / 25] >> (x % 25)) & 1) << j);
  42882. x += 128;
  42883. }
  42884. XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
  42885. XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
  42886. rt->infinity = !y;
  42887. for (i=126; i>=0; i--) {
  42888. y = 0;
  42889. x = i;
  42890. for (j=0; j<8; j++) {
  42891. y |= (int)(((k[x / 25] >> (x % 25)) & 1) << j);
  42892. x += 128;
  42893. }
  42894. sp_1024_proj_point_dbl_42(rt, rt, t);
  42895. XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
  42896. XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
  42897. p->infinity = !y;
  42898. sp_1024_proj_point_add_qz1_42(rt, rt, p, t);
  42899. }
  42900. if (map != 0) {
  42901. sp_1024_map_42(r, rt, t);
  42902. }
  42903. else {
  42904. XMEMCPY(r, rt, sizeof(sp_point_1024));
  42905. }
  42906. }
  42907. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  42908. if (t != NULL)
  42909. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  42910. if (rt != NULL)
  42911. XFREE(rt, heap, DYNAMIC_TYPE_ECC);
  42912. #endif
  42913. return err;
  42914. }
  42915. #ifdef FP_ECC
  42916. #ifndef FP_ENTRIES
  42917. #define FP_ENTRIES 16
  42918. #endif
  42919. /* Cache entry - holds precomputation tables for a point. */
  42920. typedef struct sp_cache_1024_t {
  42921. /* X ordinate of point that table was generated from. */
  42922. sp_digit x[42];
  42923. /* Y ordinate of point that table was generated from. */
  42924. sp_digit y[42];
  42925. /* Precomputation table for point. */
  42926. sp_table_entry_1024 table[256];
  42927. /* Count of entries in table. */
  42928. uint32_t cnt;
  42929. /* Point and table set in entry. */
  42930. int set;
  42931. } sp_cache_1024_t;
  42932. /* Cache of tables. */
  42933. static THREAD_LS_T sp_cache_1024_t sp_cache_1024[FP_ENTRIES];
  42934. /* Index of last entry in cache. */
  42935. static THREAD_LS_T int sp_cache_1024_last = -1;
  42936. /* Cache has been initialized. */
  42937. static THREAD_LS_T int sp_cache_1024_inited = 0;
  42938. #ifndef HAVE_THREAD_LS
  42939. static volatile int initCacheMutex_1024 = 0;
  42940. static wolfSSL_Mutex sp_cache_1024_lock;
  42941. #endif
  42942. /* Get the cache entry for the point.
  42943. *
  42944. * g [in] Point scalar multipling.
  42945. * cache [out] Cache table to use.
  42946. */
  42947. static void sp_ecc_get_cache_1024(const sp_point_1024* g, sp_cache_1024_t** cache)
  42948. {
  42949. int i;
  42950. int j;
  42951. uint32_t least;
  42952. if (sp_cache_1024_inited == 0) {
  42953. for (i=0; i<FP_ENTRIES; i++) {
  42954. sp_cache_1024[i].set = 0;
  42955. }
  42956. sp_cache_1024_inited = 1;
  42957. }
  42958. /* Compare point with those in cache. */
  42959. for (i=0; i<FP_ENTRIES; i++) {
  42960. if (!sp_cache_1024[i].set)
  42961. continue;
  42962. if (sp_1024_cmp_equal_42(g->x, sp_cache_1024[i].x) &
  42963. sp_1024_cmp_equal_42(g->y, sp_cache_1024[i].y)) {
  42964. sp_cache_1024[i].cnt++;
  42965. break;
  42966. }
  42967. }
  42968. /* No match. */
  42969. if (i == FP_ENTRIES) {
  42970. /* Find empty entry. */
  42971. i = (sp_cache_1024_last + 1) % FP_ENTRIES;
  42972. for (; i != sp_cache_1024_last; i=(i+1)%FP_ENTRIES) {
  42973. if (!sp_cache_1024[i].set) {
  42974. break;
  42975. }
  42976. }
  42977. /* Evict least used. */
  42978. if (i == sp_cache_1024_last) {
  42979. least = sp_cache_1024[0].cnt;
  42980. for (j=1; j<FP_ENTRIES; j++) {
  42981. if (sp_cache_1024[j].cnt < least) {
  42982. i = j;
  42983. least = sp_cache_1024[i].cnt;
  42984. }
  42985. }
  42986. }
  42987. XMEMCPY(sp_cache_1024[i].x, g->x, sizeof(sp_cache_1024[i].x));
  42988. XMEMCPY(sp_cache_1024[i].y, g->y, sizeof(sp_cache_1024[i].y));
  42989. sp_cache_1024[i].set = 1;
  42990. sp_cache_1024[i].cnt = 1;
  42991. }
  42992. *cache = &sp_cache_1024[i];
  42993. sp_cache_1024_last = i;
  42994. }
  42995. #endif /* FP_ECC */
  42996. /* Multiply the base point of P1024 by the scalar and return the result.
  42997. * If map is true then convert result to affine coordinates.
  42998. *
  42999. * r Resulting point.
  43000. * g Point to multiply.
  43001. * k Scalar to multiply by.
  43002. * map Indicates whether to convert result to affine.
  43003. * ct Constant time required.
  43004. * heap Heap to use for allocation.
  43005. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  43006. */
  43007. static int sp_1024_ecc_mulmod_42(sp_point_1024* r, const sp_point_1024* g, const sp_digit* k,
  43008. int map, int ct, void* heap)
  43009. {
  43010. #ifndef FP_ECC
  43011. return sp_1024_ecc_mulmod_win_add_sub_42(r, g, k, map, ct, heap);
  43012. #else
  43013. sp_digit tmp[2 * 42 * 6];
  43014. sp_cache_1024_t* cache;
  43015. int err = MP_OKAY;
  43016. #ifndef HAVE_THREAD_LS
  43017. if (initCacheMutex_1024 == 0) {
  43018. wc_InitMutex(&sp_cache_1024_lock);
  43019. initCacheMutex_1024 = 1;
  43020. }
  43021. if (wc_LockMutex(&sp_cache_1024_lock) != 0)
  43022. err = BAD_MUTEX_E;
  43023. #endif /* HAVE_THREAD_LS */
  43024. if (err == MP_OKAY) {
  43025. sp_ecc_get_cache_1024(g, &cache);
  43026. if (cache->cnt == 2)
  43027. sp_1024_gen_stripe_table_42(g, cache->table, tmp, heap);
  43028. #ifndef HAVE_THREAD_LS
  43029. wc_UnLockMutex(&sp_cache_1024_lock);
  43030. #endif /* HAVE_THREAD_LS */
  43031. if (cache->cnt < 2) {
  43032. err = sp_1024_ecc_mulmod_win_add_sub_42(r, g, k, map, ct, heap);
  43033. }
  43034. else {
  43035. err = sp_1024_ecc_mulmod_stripe_42(r, g, cache->table, k,
  43036. map, ct, heap);
  43037. }
  43038. }
  43039. return err;
  43040. #endif
  43041. }
  43042. #endif
  43043. /* Multiply the point by the scalar and return the result.
  43044. * If map is true then convert result to affine coordinates.
  43045. *
  43046. * km Scalar to multiply by.
  43047. * p Point to multiply.
  43048. * r Resulting point.
  43049. * map Indicates whether to convert result to affine.
  43050. * heap Heap to use for allocation.
  43051. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  43052. */
  43053. int sp_ecc_mulmod_1024(const mp_int* km, const ecc_point* gm, ecc_point* r,
  43054. int map, void* heap)
  43055. {
  43056. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  43057. sp_point_1024* point = NULL;
  43058. sp_digit* k = NULL;
  43059. #else
  43060. sp_point_1024 point[1];
  43061. sp_digit k[42];
  43062. #endif
  43063. int err = MP_OKAY;
  43064. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  43065. point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap,
  43066. DYNAMIC_TYPE_ECC);
  43067. if (point == NULL)
  43068. err = MEMORY_E;
  43069. if (err == MP_OKAY) {
  43070. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 42, heap,
  43071. DYNAMIC_TYPE_ECC);
  43072. if (k == NULL)
  43073. err = MEMORY_E;
  43074. }
  43075. #endif
  43076. if (err == MP_OKAY) {
  43077. sp_1024_from_mp(k, 42, km);
  43078. sp_1024_point_from_ecc_point_42(point, gm);
  43079. err = sp_1024_ecc_mulmod_42(point, point, k, map, 1, heap);
  43080. }
  43081. if (err == MP_OKAY) {
  43082. err = sp_1024_point_to_ecc_point_42(point, r);
  43083. }
  43084. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  43085. if (k != NULL)
  43086. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  43087. if (point != NULL)
  43088. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  43089. #endif
  43090. return err;
  43091. }
  43092. #ifdef WOLFSSL_SP_SMALL
  43093. /* Multiply the base point of P1024 by the scalar and return the result.
  43094. * If map is true then convert result to affine coordinates.
  43095. *
  43096. * r Resulting point.
  43097. * k Scalar to multiply by.
  43098. * map Indicates whether to convert result to affine.
  43099. * heap Heap to use for allocation.
  43100. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  43101. */
  43102. static int sp_1024_ecc_mulmod_base_42(sp_point_1024* r, const sp_digit* k,
  43103. int map, int ct, void* heap)
  43104. {
  43105. /* No pre-computed values. */
  43106. return sp_1024_ecc_mulmod_42(r, &p1024_base, k, map, ct, heap);
  43107. }
  43108. #else
  43109. /* Striping precomputation table.
  43110. * 8 points combined into a table of 256 points.
  43111. * Distance of 128 between points.
  43112. */
  43113. static const sp_table_entry_1024 p1024_table[256] = {
  43114. /* 0 */
  43115. { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  43116. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  43117. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  43118. 0x00, 0x00, 0x00, 0x00, 0x00 },
  43119. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  43120. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  43121. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  43122. 0x00, 0x00, 0x00, 0x00, 0x00 } },
  43123. /* 1 */
  43124. { { 0x0162bc2,0x03f6370,0x0a26fe7,0x0621512,0x1decc6e,0x04cec0e,
  43125. 0x077c279,0x030bab3,0x06d3582,0x14b7514,0x17e36e6,0x0fa6e18,
  43126. 0x0601aec,0x067ae83,0x0b92656,0x1aff1ce,0x17d3e91,0x1617394,
  43127. 0x0a7cbd6,0x03b725b,0x19ed862,0x13ad2b3,0x12c9b21,0x0ad5582,
  43128. 0x185df2c,0x1cc9199,0x131a84f,0x111ce9a,0x08ec11b,0x18b9ffd,
  43129. 0x1bc4852,0x03e7f3f,0x0386a27,0x1da2750,0x0d3b039,0x0d7b363,
  43130. 0x0ecd349,0x12946e7,0x1e02ebf,0x0d43893,0x08dfff9 },
  43131. { 0x03c0c83,0x03a9d60,0x15d6d29,0x11579b9,0x08e69d1,0x1adb24b,
  43132. 0x06e23dd,0x0a5c707,0x0bf58f3,0x01fca4d,0x0f05720,0x0cf37a1,
  43133. 0x025f702,0x07f94c6,0x0fd745a,0x12edd0b,0x198c6c7,0x01fb75e,
  43134. 0x178f86d,0x0315e88,0x0093206,0x072a732,0x19f5566,0x09fdb3c,
  43135. 0x1283b50,0x08bd823,0x15c361d,0x0a1957f,0x1addbe4,0x145f9fa,
  43136. 0x1291f58,0x0f19699,0x037ef30,0x0248400,0x14f1ac7,0x0e9c291,
  43137. 0x0fcfd83,0x0b6994a,0x007cf89,0x0f7bc78,0x02aa120 } },
  43138. /* 2 */
  43139. { { 0x1900955,0x1b6d700,0x15b6a56,0x039d68c,0x05dc9cc,0x17f4add,
  43140. 0x0241f9c,0x068a18f,0x1a040c3,0x0d72a23,0x0ba9ba8,0x06e0f2a,
  43141. 0x0591191,0x1684b98,0x1fdcd0d,0x1a21ea9,0x074bda4,0x0526d80,
  43142. 0x059101c,0x060de32,0x122cfd5,0x19c5922,0x052e7f9,0x093eec4,
  43143. 0x0dad678,0x1720a34,0x02c3734,0x0f65343,0x1ad4928,0x18d0af0,
  43144. 0x06ab75f,0x1b77454,0x0c63a81,0x119bccd,0x116e048,0x10026f3,
  43145. 0x10e53bc,0x0159785,0x0ed87d0,0x0fe17e2,0x08c3eb2 },
  43146. { 0x113696f,0x169f0f2,0x1fea692,0x1831903,0x0350ba5,0x019e898,
  43147. 0x104d8f0,0x1783c5f,0x117a531,0x1ed3738,0x1584354,0x092035d,
  43148. 0x0742ec6,0x14cffab,0x0fa37df,0x1a255a6,0x13e3dee,0x1f2556b,
  43149. 0x003d37a,0x0768ca3,0x10b4d98,0x14a8179,0x064d949,0x1231aff,
  43150. 0x199aba8,0x1cd3f13,0x19c03f1,0x1ffd096,0x1fd8c20,0x006b205,
  43151. 0x0f5ed10,0x0ba4c83,0x1a21d21,0x110e5e1,0x110b0c9,0x06f3072,
  43152. 0x11401e8,0x132805d,0x10c42b3,0x07c4a38,0x07bf416 } },
  43153. /* 3 */
  43154. { { 0x1fd589e,0x1a7c471,0x080c705,0x01bf2e9,0x1b50179,0x182a4fe,
  43155. 0x08f8cf9,0x069a12c,0x115924f,0x0848f7f,0x196b163,0x195bf36,
  43156. 0x0feef79,0x1fb4e16,0x1310988,0x10579a5,0x03252cd,0x0c0bec8,
  43157. 0x17c7777,0x09e9b34,0x16bdacf,0x1aa808d,0x1418498,0x1a28193,
  43158. 0x0490d2e,0x1694fba,0x1136da1,0x08125d1,0x0b0fcc6,0x178b3bb,
  43159. 0x0d8897b,0x1be2d5d,0x08c01e9,0x1ec1507,0x1d0612e,0x0ec506c,
  43160. 0x0956e33,0x1aba714,0x1fc1dd5,0x18ce0b4,0x09871ed },
  43161. { 0x16535f7,0x1bb6abb,0x0ee2f42,0x044c6b6,0x1214d60,0x10b7b22,
  43162. 0x16b6674,0x0eb8184,0x15515bf,0x0a6f9d3,0x1c59d7f,0x0b78bd3,
  43163. 0x0724a62,0x003439f,0x0d7bedd,0x0b89478,0x033bb2e,0x177ae4d,
  43164. 0x01ac662,0x0366bd0,0x10eda97,0x12d1e34,0x07d7032,0x03c4683,
  43165. 0x1dd898e,0x0f2546a,0x1a556b6,0x19d9799,0x0d34164,0x0203924,
  43166. 0x1b8bb3d,0x08b815e,0x0bb3811,0x007ff8d,0x1a0871e,0x0e7e97d,
  43167. 0x0272ed5,0x06fbb46,0x0deb745,0x0146e2c,0x0397ed1 } },
  43168. /* 4 */
  43169. { { 0x15c2a27,0x105d93a,0x11133cf,0x12b2b0b,0x138e42f,0x142f306,
  43170. 0x0f83c64,0x01e8d62,0x076273d,0x1f66860,0x115a6b0,0x010a327,
  43171. 0x0a7800f,0x01a8c0c,0x139d2ad,0x06c77e0,0x0388496,0x1492c55,
  43172. 0x032253f,0x0cc2f97,0x09a0845,0x15157cb,0x02f18aa,0x08cd1b3,
  43173. 0x0280b5a,0x07d3361,0x1aa64bd,0x193beb1,0x001e99b,0x1bec9fa,
  43174. 0x03976c2,0x1898718,0x0614fe1,0x0fb59f0,0x1470b33,0x11aa622,
  43175. 0x0143b61,0x1abaf67,0x0629071,0x10bbf27,0x0402479 },
  43176. { 0x1055746,0x128bc47,0x1b83ee8,0x001563c,0x05ba004,0x14934be,
  43177. 0x053eeb0,0x081c363,0x15b4f47,0x18a908c,0x1ee951d,0x03a1376,
  43178. 0x0425009,0x1cd09cd,0x19d2186,0x154fcf4,0x1b3f353,0x15d4209,
  43179. 0x110f3bb,0x0ee3244,0x1bd0afe,0x1b1c23d,0x0511a34,0x149285a,
  43180. 0x19ff63d,0x02b30fb,0x075096d,0x0ac7438,0x1f46301,0x07e6baf,
  43181. 0x124f09c,0x1d65005,0x0072090,0x0380221,0x172f217,0x08d1e19,
  43182. 0x1a032e7,0x01b97df,0x0760329,0x1cd916f,0x01a6fd1 } },
  43183. /* 5 */
  43184. { { 0x15116a3,0x1480d46,0x11fe59e,0x0965ebe,0x0b84439,0x15d79d8,
  43185. 0x1514983,0x019c735,0x160ccfc,0x10df30b,0x1d4fc87,0x07a5987,
  43186. 0x16ac07e,0x0f688dd,0x00e3838,0x16185bb,0x1071c15,0x022a3a9,
  43187. 0x083f96e,0x1a8e912,0x096d70d,0x16f238c,0x06882f8,0x04ed8f8,
  43188. 0x1ad8a59,0x1039e1f,0x0f221bb,0x04d4398,0x031ac40,0x179bb74,
  43189. 0x1967f6d,0x158a03a,0x0a35d1a,0x142ba13,0x0415036,0x0a15d31,
  43190. 0x0bd734e,0x0ef0525,0x11d4197,0x1b82ac2,0x029b7d4 },
  43191. { 0x1f4e20b,0x1e165e5,0x131512c,0x1eb1988,0x1c3f548,0x06560f8,
  43192. 0x06d516c,0x0427301,0x100f806,0x007815a,0x0417803,0x11200cd,
  43193. 0x0ce612b,0x01a80c4,0x0563b5e,0x0ed651e,0x0583f55,0x0600ee2,
  43194. 0x11524b8,0x0064e54,0x0443298,0x1d07fc9,0x1de9588,0x1a1b882,
  43195. 0x02b0029,0x03d6895,0x049e03a,0x0824a8b,0x13f272b,0x1c8186a,
  43196. 0x0347af3,0x048603d,0x0e6ea40,0x083cc5d,0x1cbe8df,0x183cbe7,
  43197. 0x02b4126,0x0161881,0x125fa4d,0x004a704,0x05d0928 } },
  43198. /* 6 */
  43199. { { 0x12f780d,0x115bf7f,0x0c7560e,0x01afaed,0x14d2682,0x1ba5761,
  43200. 0x0a11e1b,0x1d7c786,0x010823f,0x1ea1109,0x19efd03,0x02fdf6b,
  43201. 0x0d227e4,0x12b47c6,0x03526da,0x177d8a2,0x1d61781,0x1a9de73,
  43202. 0x1cdc62d,0x1c7e445,0x0c1f9cf,0x0fecef3,0x1fd13a2,0x15936aa,
  43203. 0x0553f3f,0x05e78e6,0x1b9bcc0,0x1a5a108,0x0ae6b19,0x01514f8,
  43204. 0x1825db2,0x0497177,0x03dbf5e,0x12d53f3,0x1d165ce,0x0e9958f,
  43205. 0x04dd33c,0x15b11bc,0x1b9771b,0x068285f,0x00a26e4 },
  43206. { 0x0aa9a08,0x099cfd6,0x1386020,0x0aa48dd,0x00f3110,0x1c9ba3a,
  43207. 0x005c184,0x1c31259,0x1242f02,0x0c6a081,0x17a62a3,0x1a4076b,
  43208. 0x12482bf,0x0d5df4a,0x1be51ad,0x1049313,0x0b93769,0x15c690c,
  43209. 0x1985f1e,0x0d1d12c,0x0b91d52,0x08c5be9,0x058b9d5,0x11acf87,
  43210. 0x07973fe,0x028962e,0x08ac05f,0x05c62a1,0x0294694,0x0f5e60d,
  43211. 0x00dbd39,0x0a638e1,0x19910ce,0x1cf2851,0x1ad2dde,0x015e9ed,
  43212. 0x1a120ad,0x05d8bae,0x0dbb1a3,0x0c3724c,0x019497c } },
  43213. /* 7 */
  43214. { { 0x17659a8,0x0586320,0x03fda48,0x0f25965,0x077ab9c,0x03bcbfe,
  43215. 0x1c602da,0x0c6ab6c,0x1e77593,0x057ac60,0x06c6193,0x1b6caac,
  43216. 0x065155b,0x1c07a4a,0x1938d55,0x116405c,0x1b7229a,0x0758564,
  43217. 0x15c6f58,0x129af04,0x18f9885,0x1cf1fd3,0x1773024,0x185a6f2,
  43218. 0x148302a,0x0223dc5,0x02e43c5,0x00bf7ec,0x04b3c15,0x07409e7,
  43219. 0x062b184,0x1ab36b8,0x1a4f27a,0x101111c,0x05cdf3a,0x16bf467,
  43220. 0x0dff1c7,0x1c3985c,0x1de9b95,0x116a2f7,0x096b91b },
  43221. { 0x0ac087c,0x0c8fa4d,0x0a3706a,0x1cd9fb6,0x0e62f74,0x1b006b6,
  43222. 0x1fe697d,0x19211ad,0x0f917f9,0x1c0e682,0x14b6ff5,0x0bec7bc,
  43223. 0x007796f,0x176b90c,0x16d9380,0x026fbcf,0x0f66fa4,0x107843b,
  43224. 0x1287dc5,0x03dcc87,0x18a3327,0x0c3e255,0x12e6c81,0x090208f,
  43225. 0x1710739,0x01be5d0,0x1566317,0x1f34321,0x00e125d,0x1395379,
  43226. 0x0b432db,0x1e9e520,0x1142204,0x16e7dd1,0x12e5f38,0x0285a51,
  43227. 0x03d3c35,0x130dc55,0x092777c,0x02b9ff8,0x073f3d3 } },
  43228. /* 8 */
  43229. { { 0x0fd3673,0x142adf3,0x0ded761,0x1f3a429,0x109b70a,0x0236699,
  43230. 0x0be4373,0x1bd1a66,0x1595510,0x0a9e00a,0x0494739,0x012c718,
  43231. 0x095746a,0x02e60de,0x1f3a96e,0x1751f9a,0x068002e,0x027fd0a,
  43232. 0x0bf35df,0x0796e04,0x05e310a,0x1de2750,0x0da6677,0x1f4eadd,
  43233. 0x1a0d04e,0x1ec19ba,0x1b73b57,0x1b204f3,0x1fd56e4,0x1201928,
  43234. 0x1c52064,0x105498b,0x07633a4,0x0082df4,0x04c06cd,0x1062e1a,
  43235. 0x1247e57,0x0cc587b,0x087ea4e,0x0c886d7,0x088934f },
  43236. { 0x113eabc,0x1a1d823,0x145fc27,0x03599b8,0x0ca7dd9,0x09e53e2,
  43237. 0x098efbc,0x0964fb5,0x0258818,0x1972d3d,0x1709a62,0x0c25b2b,
  43238. 0x0c0a8cb,0x10f978a,0x1a5d68b,0x126b868,0x0ede172,0x18f94dc,
  43239. 0x102f078,0x17fadda,0x03dac3c,0x1f89931,0x14fd1ac,0x016ed03,
  43240. 0x1be6dfb,0x1a2608a,0x155b690,0x1c63868,0x043d985,0x1f8c547,
  43241. 0x1aa9f18,0x097bb69,0x1cb2083,0x07ac62a,0x10e1295,0x1362d41,
  43242. 0x06fd69d,0x1566512,0x12385d3,0x1762a6a,0x00d1898 } },
  43243. /* 9 */
  43244. { { 0x15ef043,0x19a30f1,0x15913a9,0x12692d6,0x107b67d,0x1c1d1e0,
  43245. 0x05cef43,0x06bac58,0x051d29c,0x16a581c,0x070693e,0x1054e36,
  43246. 0x1e3f428,0x0a5a1dc,0x0af3d99,0x1ea86ba,0x1aa2abd,0x0e3bd8a,
  43247. 0x0af8f70,0x071501b,0x073b5cb,0x175240b,0x057f682,0x1721d7c,
  43248. 0x16b4de7,0x1ec434c,0x14af23c,0x09f0fc4,0x04e4248,0x01eb1be,
  43249. 0x162b7b4,0x1af4f5f,0x1ede666,0x05c9d72,0x168a873,0x0301bb2,
  43250. 0x06fba39,0x0e7e92a,0x0b98295,0x1b88df0,0x02bdab1 },
  43251. { 0x06fed61,0x0f115fd,0x0539e93,0x0b991bb,0x0a458aa,0x09117ae,
  43252. 0x0b7c41c,0x0ee7c6e,0x1e5aff3,0x1525a27,0x0e39b41,0x174e94e,
  43253. 0x16bc2d0,0x0f98f89,0x11c3875,0x1522234,0x13ae102,0x0bbffc9,
  43254. 0x0431e21,0x1014a06,0x05ac8b3,0x143c1fe,0x07cf008,0x0e4ba0d,
  43255. 0x0892544,0x110f633,0x196b210,0x0f1e1c2,0x1a6e8a8,0x18d7e7e,
  43256. 0x0ea68eb,0x0f19a55,0x183ed37,0x0875700,0x158209b,0x0a659b7,
  43257. 0x0bee641,0x11a330e,0x00482cc,0x1257382,0x0353eb8 } },
  43258. /* 10 */
  43259. { { 0x0b5521e,0x0e56b08,0x0bc323f,0x00a5ce0,0x1a11b44,0x1ed24e0,
  43260. 0x1a0363f,0x15ac604,0x0cbf36b,0x0dcb2a5,0x028b5f3,0x1c22982,
  43261. 0x007b58c,0x131873f,0x1747df7,0x150263c,0x17d6760,0x1c65f1e,
  43262. 0x12035df,0x0b0cd6c,0x0219eb3,0x19bf81b,0x161ca33,0x1514eae,
  43263. 0x065ed42,0x0386eac,0x1641a8a,0x107e3e3,0x1f906b2,0x1fd2528,
  43264. 0x0a1e788,0x0a87641,0x0ac6e83,0x13baa79,0x0de6e07,0x1c9e16c,
  43265. 0x040016e,0x1de06a4,0x0d9f55f,0x0e3cc43,0x08da207 },
  43266. { 0x0ce65ec,0x0a80276,0x0178f21,0x1f6e903,0x16d10d1,0x1cbd693,
  43267. 0x1ef29e1,0x15ac97c,0x077e54a,0x1a226d8,0x17c3fd0,0x01937c1,
  43268. 0x0417b6b,0x02a8435,0x11095b0,0x1ab471f,0x03bfd74,0x07ca962,
  43269. 0x0713b6e,0x1c00b40,0x0328501,0x1e252bf,0x1545cb7,0x0baddc7,
  43270. 0x0ce4e53,0x08c6da0,0x1031942,0x15de3cb,0x1561fcb,0x02f3c2b,
  43271. 0x11ba145,0x0694449,0x068536a,0x0705172,0x089c3b0,0x18d351c,
  43272. 0x042b03f,0x1a91239,0x0f57ecf,0x1c5877d,0x0862f55 } },
  43273. /* 11 */
  43274. { { 0x06049fe,0x11c8791,0x07ecb5a,0x11b9779,0x0c92a57,0x11a7dbe,
  43275. 0x1b2925d,0x1274a5f,0x03dea58,0x19a065b,0x07a458a,0x0714549,
  43276. 0x13a39f3,0x0a4f20f,0x0cb7cf6,0x0fc804d,0x0db065a,0x1638e3e,
  43277. 0x1a0a068,0x1709408,0x0eca4a9,0x01b98f7,0x18fbad4,0x1976e4a,
  43278. 0x0913476,0x1c67368,0x06e5299,0x19f2f35,0x0fd9f10,0x061dc04,
  43279. 0x0e6d136,0x1c15f8b,0x00da613,0x0df34f3,0x1f78fa9,0x1ea5b9c,
  43280. 0x1c1ee74,0x0eb4326,0x01e40e9,0x1227790,0x071ab28 },
  43281. { 0x15b60ad,0x0c7e21d,0x06133d8,0x0094186,0x0afb5e3,0x0019810,
  43282. 0x00732f1,0x0cda447,0x1db1c0c,0x1e7c4a9,0x04aa34c,0x1c9b4c2,
  43283. 0x069c994,0x08cb3d4,0x0ab8b0f,0x19a53af,0x0935b7a,0x1e146aa,
  43284. 0x12695fe,0x0b7a26d,0x07f9807,0x1f4e421,0x12700dc,0x0644beb,
  43285. 0x0a18d19,0x0c6165e,0x0d10b00,0x06eefa2,0x13a7277,0x16a3fdd,
  43286. 0x063af97,0x032c5b8,0x0437d49,0x0440338,0x1824b70,0x19e7383,
  43287. 0x15fff35,0x14e37b8,0x029940f,0x16cbc6c,0x08d087b } },
  43288. /* 12 */
  43289. { { 0x1dc1844,0x091811f,0x115af88,0x1e20bd5,0x0eca27e,0x1451a43,
  43290. 0x0981bc5,0x1964307,0x1e1d7a4,0x0afc03e,0x1750f8a,0x0c64fde,
  43291. 0x077246a,0x03b812e,0x050c817,0x09c7d5c,0x1caf348,0x0a5efe3,
  43292. 0x1d4b01d,0x07312bb,0x0ac0ec9,0x1b6bd4e,0x00b9957,0x15dbb61,
  43293. 0x1fe208b,0x198cc2e,0x1149f79,0x13902fc,0x1de1ea7,0x07de189,
  43294. 0x0ecc338,0x1989ed9,0x1f95b89,0x19066ce,0x1c7bd6e,0x03e55db,
  43295. 0x1a8cfb0,0x0f05448,0x0dfb3f0,0x094c7db,0x0225ed3 },
  43296. { 0x0bb1a85,0x18aa6dd,0x1968f84,0x0e3cd4a,0x13d8dae,0x058807e,
  43297. 0x1f55aad,0x035a642,0x0ebc78e,0x026c9a7,0x1cf4df5,0x043691c,
  43298. 0x0b02153,0x100f21e,0x1242fe8,0x0120b77,0x1d02750,0x09e11f8,
  43299. 0x019a468,0x1ca0019,0x041c2a2,0x093032c,0x022caeb,0x004d6c0,
  43300. 0x01caf30,0x1308aea,0x1149db3,0x0e2585e,0x132ffb1,0x01f38ac,
  43301. 0x1c80713,0x0d4e995,0x094e13d,0x09bd23c,0x177c301,0x1c05ade,
  43302. 0x02b1c97,0x1dbb016,0x1f1eea3,0x1cba110,0x0612b60 } },
  43303. /* 13 */
  43304. { { 0x0245d6b,0x04ae7dd,0x1fdbbf5,0x0f459c7,0x1cf0cbb,0x1aff772,
  43305. 0x0ab037f,0x14649b4,0x0cf28c6,0x0648a7c,0x0295ae4,0x0a1a861,
  43306. 0x1472fdb,0x09eb901,0x16fdde4,0x193d207,0x091822a,0x0e7d2f6,
  43307. 0x0ba8fa0,0x1ce7907,0x11390dd,0x1133144,0x1516ea5,0x0d597a6,
  43308. 0x1648bca,0x01d5297,0x1a6281a,0x1ede4ed,0x18ed52f,0x09d651b,
  43309. 0x16494db,0x110b583,0x13c2c54,0x042539a,0x0b6802f,0x0f95fea,
  43310. 0x1768416,0x18fc0e1,0x061b8e5,0x1c3a5af,0x00f7334 },
  43311. { 0x196067e,0x1ae41b2,0x001abee,0x1271833,0x13e54e1,0x0586e61,
  43312. 0x1659ce7,0x1f3050b,0x1424035,0x1a9fa1e,0x1e4254a,0x03f1bfd,
  43313. 0x1a38c53,0x0d87ab8,0x1efa393,0x14f0f21,0x0d2a39c,0x04d060f,
  43314. 0x01bc988,0x1983acc,0x0b4a2fe,0x18b95be,0x0772242,0x176f0d1,
  43315. 0x0a6fbcc,0x124e19e,0x0bf9cfb,0x0362210,0x166c48d,0x1e8bfe5,
  43316. 0x1cd642d,0x10dc28a,0x156b0a6,0x156c2c9,0x0b1014f,0x16ebad0,
  43317. 0x054d30f,0x172afd6,0x1a526ca,0x0e5f15d,0x067636a } },
  43318. /* 14 */
  43319. { { 0x11d6bea,0x031de5c,0x0e598e0,0x1d247d9,0x0e263a2,0x13d6535,
  43320. 0x0264b18,0x0fd3af6,0x077af9e,0x176800d,0x0bfaef1,0x199e495,
  43321. 0x109214a,0x1c02ad4,0x1592e59,0x0933b46,0x11ce027,0x0804ccd,
  43322. 0x11a81a9,0x0749c3c,0x0fe7e41,0x1b1728f,0x081744f,0x150877d,
  43323. 0x07d349b,0x0cf1af4,0x14c60c5,0x14c6704,0x0019230,0x145d2a3,
  43324. 0x1c9808f,0x16ffa39,0x1107721,0x17ea9cd,0x10aff7c,0x108d6aa,
  43325. 0x1c18af3,0x0a7a7c0,0x02596cc,0x0ecc159,0x0086f98 },
  43326. { 0x0bb9850,0x00caa46,0x1231d9c,0x01441a5,0x0210b73,0x1ab3863,
  43327. 0x1415d4c,0x1d48109,0x10324ba,0x166e2ca,0x1ba6d0f,0x0be58ed,
  43328. 0x04607fc,0x0207fd3,0x04f403d,0x08c79e7,0x1962dc1,0x1f0088b,
  43329. 0x11dc979,0x1704a33,0x1186f00,0x1b2de8e,0x0d7981c,0x1ee5558,
  43330. 0x0554c2c,0x0bef9ec,0x1bbe8d2,0x09ba1fb,0x06ad11b,0x13467b2,
  43331. 0x0b75c48,0x13ef71d,0x1c20afb,0x16ff283,0x0753f01,0x14c612d,
  43332. 0x1245549,0x1bef8e3,0x1a041da,0x007cc35,0x0681f94 } },
  43333. /* 15 */
  43334. { { 0x1a0623b,0x0a8b1e4,0x0351f2b,0x0ecff57,0x1bf8295,0x17be3e6,
  43335. 0x0c3b206,0x1845995,0x0e966d5,0x14f1c64,0x1390711,0x1aa5e1a,
  43336. 0x1c34430,0x12959ac,0x181d68a,0x0024e84,0x1e333bd,0x09216e9,
  43337. 0x1fb48d0,0x07ec6b3,0x0ffacda,0x186bea9,0x137ccdc,0x08187de,
  43338. 0x156f076,0x0be2fff,0x106ef79,0x0f07843,0x0bb3364,0x051575c,
  43339. 0x01761e1,0x1d5a108,0x0c7c533,0x115ea0f,0x108fe6d,0x1e96fe2,
  43340. 0x1075d4a,0x018a2e3,0x1642955,0x09574c0,0x00c9de9 },
  43341. { 0x1d5682b,0x1939aca,0x1bb63b5,0x065d84e,0x111c428,0x1b50693,
  43342. 0x0bb562c,0x11fa3e9,0x08498a8,0x155a062,0x03d1458,0x18c4890,
  43343. 0x0258c8f,0x1bce7ff,0x123292e,0x06b3b17,0x03c701a,0x0c855ac,
  43344. 0x1f57457,0x0634e67,0x133caee,0x1de4891,0x00a9565,0x187c784,
  43345. 0x1cae4b6,0x044080c,0x10a64e0,0x0a26085,0x1c8199e,0x141efa3,
  43346. 0x0483800,0x1e5401d,0x0d68e58,0x0d71dc8,0x1d069dd,0x04d3c5b,
  43347. 0x071c30b,0x097652c,0x18e5ae3,0x01d763b,0x0733dca } },
  43348. /* 16 */
  43349. { { 0x159213a,0x04ae825,0x003bd6d,0x131ae04,0x0a67203,0x13b8e0e,
  43350. 0x02698ad,0x1969796,0x02b9eb0,0x156f76a,0x0e88489,0x0ea919b,
  43351. 0x11eb544,0x1844486,0x06aff37,0x08d681c,0x163698e,0x029284c,
  43352. 0x0ba704e,0x1fe1610,0x1a71e1b,0x06a884c,0x0862793,0x172398f,
  43353. 0x0c9bcc9,0x05f11b0,0x104dfb1,0x17a9afb,0x119f6e9,0x1290e8a,
  43354. 0x00f40d5,0x19f064a,0x15f6d78,0x1515a5f,0x00c637b,0x19c8602,
  43355. 0x0f4c319,0x09924a7,0x09f5f0c,0x08e1e3f,0x02ab3bd },
  43356. { 0x02c9fbb,0x1db4049,0x1b455d4,0x101e2d8,0x069e7dc,0x00b77e4,
  43357. 0x144d6eb,0x1370688,0x0846d1d,0x19351da,0x18b0850,0x1dc765a,
  43358. 0x15b517f,0x0594956,0x016be88,0x15826d2,0x11a2cad,0x0952b89,
  43359. 0x0f6f2a3,0x009b1fd,0x1fb2cd9,0x179f9b2,0x17fb6a1,0x0fd5439,
  43360. 0x1b208dc,0x1e0384b,0x129179d,0x1346b50,0x1d118e8,0x031667a,
  43361. 0x1a105e8,0x03edd33,0x00c04a8,0x1043e9e,0x12c2e9e,0x05888e0,
  43362. 0x1ea22ad,0x0513e89,0x148a5be,0x02c984f,0x093a4b4 } },
  43363. /* 17 */
  43364. { { 0x11efb7a,0x18de08f,0x1037509,0x0c67f99,0x0e4e68e,0x0fa8545,
  43365. 0x123c6c4,0x1133b37,0x1af0760,0x0181cc7,0x14380d5,0x05f6887,
  43366. 0x0145e24,0x1b71ea6,0x1b09467,0x15a12e7,0x190ba9b,0x1d5b87b,
  43367. 0x06b7443,0x0255abf,0x02b4de6,0x070a74a,0x0e0df95,0x1716d15,
  43368. 0x056d3dd,0x0040bad,0x106b0a9,0x10b6467,0x080f94e,0x1618786,
  43369. 0x1e7e3fd,0x1131b69,0x17f3fb7,0x1ee6ea5,0x113d169,0x0b458c0,
  43370. 0x1e3d389,0x15d97b7,0x1dd8fce,0x1ae65dc,0x0342ce0 },
  43371. { 0x1491b1f,0x109ca67,0x0e57ac9,0x0e3213c,0x1caaeed,0x126df56,
  43372. 0x0156a7f,0x09bb988,0x1493d60,0x1d3308e,0x17afbc5,0x147439c,
  43373. 0x15ba445,0x11cc4e5,0x0b8a163,0x1080dd0,0x08283f5,0x0dcb7a1,
  43374. 0x055b3d5,0x0ef7334,0x0a0e998,0x13270b3,0x0be41a9,0x12eda27,
  43375. 0x1d353b2,0x100e750,0x1cdb186,0x1f82de4,0x155d86e,0x0219d87,
  43376. 0x0076c13,0x11d6698,0x0b4b269,0x101401e,0x1de0ab9,0x0a71a0f,
  43377. 0x03be3ec,0x161de5a,0x1f4810e,0x1e7c2ad,0x0455f4a } },
  43378. /* 18 */
  43379. { { 0x14ec21c,0x1f9313a,0x08e3015,0x13c7437,0x1eacd4c,0x160ff49,
  43380. 0x0434445,0x16c7404,0x0eacc8a,0x075274a,0x1ccb2b9,0x1935d4d,
  43381. 0x0e31c00,0x035cbae,0x0d88e76,0x143d2b9,0x18ca14e,0x1b2a6ae,
  43382. 0x019ff22,0x1a63e8a,0x1ecb230,0x05b1aaf,0x122ee43,0x02e5d1c,
  43383. 0x01ecedc,0x19bbc7c,0x032c019,0x1107015,0x02d0122,0x1700f0b,
  43384. 0x17066c0,0x18b5e28,0x0087a06,0x0e1aa07,0x02dedcb,0x0de09b9,
  43385. 0x0de3c06,0x07790a4,0x07edfdc,0x0862601,0x04f1482 },
  43386. { 0x02055e2,0x027e737,0x019d780,0x150d864,0x09e247e,0x0ed5514,
  43387. 0x0f6557e,0x0769d79,0x1ceb7f6,0x0af9097,0x1e12834,0x183f0c6,
  43388. 0x115ecc5,0x1abb012,0x0ce002d,0x052a8a7,0x1c38a6a,0x0f5c980,
  43389. 0x04f3746,0x0d74314,0x0d240f1,0x08c43e1,0x00c4f49,0x12827ed,
  43390. 0x035859a,0x1e2fcc9,0x1bf8ff5,0x04680bc,0x00ee054,0x159a0b7,
  43391. 0x0c19e2b,0x07f5b55,0x13be7bb,0x022388f,0x08b20a2,0x0cf203f,
  43392. 0x0d662ff,0x086d982,0x05c2f25,0x1a87802,0x074d5d2 } },
  43393. /* 19 */
  43394. { { 0x15bfe11,0x016e015,0x079e8c0,0x1aa5a64,0x0733410,0x1cdd448,
  43395. 0x03d9659,0x0dc2b24,0x0685b23,0x112460a,0x1d81003,0x0b2868d,
  43396. 0x108cfab,0x00638bf,0x15ebedd,0x08aed3e,0x08c6604,0x186dd59,
  43397. 0x1370c91,0x0132d13,0x0d050fa,0x1161187,0x10780ab,0x0b7dee8,
  43398. 0x01554e4,0x1b786cb,0x0b3935e,0x0d11530,0x02d22e9,0x1d63af3,
  43399. 0x0a3eb7b,0x17a5974,0x11512a6,0x03a4fd7,0x198af9f,0x16f10d1,
  43400. 0x0e9f5a6,0x0246c0d,0x1e8a620,0x0858b0a,0x06b1a54 },
  43401. { 0x1242066,0x15cd6a1,0x0aba7d6,0x0a59994,0x0afef1b,0x076e270,
  43402. 0x0fb1e62,0x1ab6368,0x10341b0,0x0860078,0x0aacdc3,0x11ef6a1,
  43403. 0x194d68b,0x19d3254,0x03939bf,0x0d09d35,0x0fb7f1a,0x00cc19c,
  43404. 0x14683d7,0x01ce906,0x05158bc,0x06ed622,0x0b2b3cb,0x13feed6,
  43405. 0x139995e,0x02ae0a6,0x1c58e4c,0x0940367,0x0d83765,0x1752c44,
  43406. 0x0c5ab0f,0x0e464ef,0x04d9a9a,0x0dddfdc,0x1a47847,0x1132264,
  43407. 0x0bb6717,0x1b8bd75,0x12b2165,0x04d1762,0x04c2135 } },
  43408. /* 20 */
  43409. { { 0x1532833,0x1f0534a,0x019cb9b,0x1dac4da,0x0bca228,0x0f39ded,
  43410. 0x1cf6592,0x018455d,0x0f03c4c,0x041d43d,0x1a6d148,0x0eba6a2,
  43411. 0x09e954e,0x1a28354,0x1d427b9,0x19f20ae,0x16e2aea,0x0a4e593,
  43412. 0x09027e4,0x0ebaeff,0x16b9082,0x1ef85de,0x187adbc,0x0264e08,
  43413. 0x002cbe4,0x058ca41,0x06c7126,0x0be7f84,0x1fee593,0x05d41b0,
  43414. 0x1cddb1a,0x0a1c0a3,0x18cbbd9,0x1382150,0x01e4c63,0x1647095,
  43415. 0x00dd1e8,0x155f56c,0x10cd0a4,0x052b86f,0x065713c },
  43416. { 0x0b77b9a,0x05474e7,0x11a7733,0x0e476d2,0x0f97e72,0x0eb5941,
  43417. 0x0fb9a80,0x1fd8ed5,0x15abecd,0x092901e,0x0435c0e,0x0104525,
  43418. 0x1889448,0x1818a21,0x04c5092,0x08f87f3,0x1f17cd4,0x182104e,
  43419. 0x0157209,0x1e40b39,0x00697c6,0x112b607,0x165f5e1,0x05b2989,
  43420. 0x1b6fe41,0x0eead4e,0x0665310,0x134c8b2,0x1e21a31,0x0550e44,
  43421. 0x03848d2,0x18d407e,0x0904b50,0x17f566b,0x055a985,0x16ab82a,
  43422. 0x1cc7693,0x1b68dab,0x0f0e138,0x0d8775c,0x06b0e99 } },
  43423. /* 21 */
  43424. { { 0x0eced00,0x04fd5e6,0x0998c9e,0x15cb6f5,0x1237e71,0x0f5e6f9,
  43425. 0x189a4b7,0x11f0f65,0x0b61dad,0x1922890,0x1e00f2d,0x1c91a6b,
  43426. 0x0de11e5,0x0c72878,0x137d75e,0x15725f6,0x0b4bcd2,0x0b07734,
  43427. 0x138cd8f,0x165eb83,0x064798a,0x0d3e6a1,0x056e8e7,0x1e9f67e,
  43428. 0x172eb83,0x06d8d32,0x0395bc2,0x1eefbd1,0x0562c20,0x1b0f0b9,
  43429. 0x1d05d0d,0x114b1e1,0x0349ff8,0x0eb715f,0x1c6e134,0x09c09b4,
  43430. 0x1e9ff3b,0x0781a14,0x08fe0da,0x00acf04,0x04022a2 },
  43431. { 0x1847375,0x1de82c1,0x0bc149e,0x047e8a3,0x1ae56b6,0x163f8c1,
  43432. 0x1c9352c,0x11ac331,0x14525b9,0x1191fad,0x0212d7b,0x07341c1,
  43433. 0x16a9d8d,0x1d8963b,0x0175fdb,0x182a9a0,0x03e708b,0x06b8e24,
  43434. 0x109506f,0x0dfa50e,0x1ddb8ca,0x06fc1cb,0x02bcf73,0x199e486,
  43435. 0x131253e,0x1c6dc06,0x0163606,0x0e87421,0x191f68c,0x1590b89,
  43436. 0x1fcfd23,0x06776ca,0x13aff88,0x03f18a4,0x15981f9,0x0c3a2bd,
  43437. 0x008279f,0x0acd88f,0x0a55840,0x196494d,0x0312179 } },
  43438. /* 22 */
  43439. { { 0x1615ac2,0x061e503,0x1606a53,0x082435a,0x05865e6,0x0c35bcc,
  43440. 0x185be9e,0x03b5c8e,0x19d5e0f,0x0ad2075,0x115fa8e,0x04c87b2,
  43441. 0x19a9143,0x1d1432e,0x19b5a8f,0x15d191b,0x1961014,0x183b8ed,
  43442. 0x1daa1f2,0x0f99cd2,0x0f6077a,0x108a1d0,0x09f790b,0x127b269,
  43443. 0x1cc09d9,0x01ef101,0x0e63b13,0x04030d2,0x05df4b9,0x036c1d1,
  43444. 0x1af5dd5,0x0c5605a,0x0d9eb47,0x138c485,0x0823416,0x17f555e,
  43445. 0x031221b,0x1c0c0fa,0x047a948,0x0f0e66a,0x0417d6c },
  43446. { 0x091e9a8,0x0c0db87,0x1accf2f,0x1186e1a,0x1334041,0x1511b9b,
  43447. 0x0c42a3a,0x0ad04bb,0x06c7d67,0x19584f2,0x0cf7b63,0x1d37298,
  43448. 0x1be288e,0x0b4af1f,0x0109aec,0x1d1119b,0x086dce9,0x1530bb6,
  43449. 0x05978d8,0x191244c,0x1b093f4,0x0fb031f,0x1453904,0x1f3c098,
  43450. 0x1ac20c8,0x0b0b483,0x137f4ab,0x1dee8d3,0x12199ac,0x1d72422,
  43451. 0x18ae8c2,0x0255868,0x0681293,0x0a41698,0x01cf24b,0x0a0237d,
  43452. 0x0833099,0x065fc4f,0x0282bfd,0x0a5a28e,0x002189d } },
  43453. /* 23 */
  43454. { { 0x0599c69,0x00ceec9,0x0b29cf9,0x16ffd86,0x1b94221,0x1dfdfea,
  43455. 0x06f4826,0x0b7657f,0x063ed89,0x0f54bd2,0x01bde58,0x08d67e9,
  43456. 0x1966091,0x1e8a0d1,0x071e817,0x0826b7a,0x0cf83d6,0x1e3cf64,
  43457. 0x020d41e,0x1fa85f3,0x10277f8,0x1b8bd9e,0x0bf2d4e,0x194b443,
  43458. 0x18dcd67,0x1c34332,0x1334525,0x0d4d815,0x195067a,0x0b871a5,
  43459. 0x0305bcf,0x1be892b,0x11208e3,0x001091b,0x139bb0a,0x03a5bac,
  43460. 0x10782c7,0x1962559,0x1dbe8ce,0x17aa422,0x07bbf8a },
  43461. { 0x18b981a,0x12557d3,0x00a2fa7,0x0c609d9,0x188b4e3,0x0cef51b,
  43462. 0x13ce4e5,0x18e188b,0x1240b39,0x054dee9,0x00edf5c,0x0fba507,
  43463. 0x06499cd,0x183d081,0x1a42cb8,0x1e36660,0x198ee92,0x011316a,
  43464. 0x11c9692,0x1aefbd6,0x0a0ec62,0x1e3de1d,0x085bc96,0x0bdeff5,
  43465. 0x18b65d1,0x147b16e,0x142e5b5,0x12f2443,0x0f1906d,0x02e1d00,
  43466. 0x102e4a2,0x1d6e98e,0x0476b9b,0x1b1117d,0x0ed71d5,0x1e42fbb,
  43467. 0x1788504,0x1c16182,0x1c5af09,0x0d9f024,0x0860d09 } },
  43468. /* 24 */
  43469. { { 0x179bbf9,0x019bea6,0x1e03faf,0x10d3ee9,0x1d53eab,0x0826a9a,
  43470. 0x08254cc,0x12ffe6d,0x0196f8b,0x15c106d,0x19a424a,0x1a3eeb9,
  43471. 0x14961d3,0x02341ba,0x05fb010,0x1973763,0x1bf93a6,0x1d34670,
  43472. 0x17c0868,0x08adff8,0x1fdb503,0x18c4a07,0x0d428b6,0x0008413,
  43473. 0x10f8fef,0x03abbe2,0x1c12596,0x0c6ba2e,0x18770ad,0x136cc5d,
  43474. 0x0f9c95d,0x140f1ca,0x019b028,0x041bc47,0x132be7f,0x006c9a9,
  43475. 0x10dd39a,0x1efa08f,0x1e48068,0x084075b,0x07e80e4 },
  43476. { 0x19a1ddf,0x1c52ba9,0x15892d7,0x1ddc90c,0x1248e7a,0x1010f0e,
  43477. 0x1247605,0x18838f6,0x1fd36d2,0x13dc38d,0x100364b,0x0a0815d,
  43478. 0x13da38b,0x10c9f8d,0x009d849,0x0f1ade5,0x086fb1f,0x1b4e1ff,
  43479. 0x009eb0c,0x116f0dd,0x08f756c,0x039a43e,0x05a1fdb,0x1bdcb78,
  43480. 0x1221719,0x00c55c7,0x1ffce65,0x09d08e7,0x027c800,0x000a548,
  43481. 0x0a3ce13,0x1543a5c,0x167be9a,0x0f778cc,0x1b4f819,0x190d2d0,
  43482. 0x07bd837,0x1e35846,0x1618dcd,0x1a33d17,0x05dcab5 } },
  43483. /* 25 */
  43484. { { 0x07d772b,0x0141d4d,0x166c1e1,0x0bca812,0x0b49e52,0x00a55ab,
  43485. 0x0c02219,0x152a8d7,0x09d74b2,0x02240b1,0x0c2c6f5,0x015a407,
  43486. 0x0b26789,0x0469fc3,0x1ea0af3,0x1078e3c,0x1b5d85a,0x189a95f,
  43487. 0x0b41f33,0x1e2dc7f,0x043ff29,0x1c20f06,0x100a98e,0x06f3fdf,
  43488. 0x122c56b,0x1934827,0x0ec4913,0x13b14ca,0x08bdea1,0x1b6f9d1,
  43489. 0x13998d6,0x1eda8ab,0x0b68851,0x19b9a8c,0x006273f,0x16e9585,
  43490. 0x0b2cbda,0x007cefc,0x15262b5,0x13d5b93,0x008cc2d },
  43491. { 0x170c84b,0x1343360,0x1210b9a,0x16b4934,0x1b989e8,0x0644c95,
  43492. 0x0038341,0x046f61c,0x061b3a4,0x0d69a3c,0x0062655,0x08a161a,
  43493. 0x133c952,0x1188065,0x0488557,0x0eda1c7,0x16ef032,0x18c932d,
  43494. 0x1b50ad4,0x10b2b4e,0x13b60fe,0x107e31a,0x02a5b7b,0x0df127c,
  43495. 0x00dc824,0x05d3b0f,0x1bc29d3,0x1d92057,0x1fad9b4,0x03421fe,
  43496. 0x1d58402,0x09fb6d2,0x16a60e4,0x1ac852e,0x0b21fbd,0x0e7ea75,
  43497. 0x12870a3,0x0f35f00,0x156c34a,0x182ab54,0x0991fad } },
  43498. /* 26 */
  43499. { { 0x0844ffe,0x02587da,0x01c60af,0x08c1f17,0x1392271,0x11f8f9b,
  43500. 0x0038933,0x1d91580,0x0163519,0x06aa45a,0x022d7fc,0x0857105,
  43501. 0x107aaf8,0x15ee4d3,0x02c3130,0x1facf3d,0x1524ba5,0x1d036a8,
  43502. 0x04f37b0,0x035f41f,0x18f0d0b,0x1d6fc4f,0x0a02556,0x1465924,
  43503. 0x1e92dee,0x1f24365,0x04ff816,0x195c7f3,0x0919aa0,0x184afd3,
  43504. 0x02fc981,0x0dc1e37,0x154741e,0x07cc407,0x1dd0c3b,0x0e55da3,
  43505. 0x134991d,0x0b7bb5b,0x03fa64a,0x0504b3e,0x066cf8d },
  43506. { 0x06f5868,0x0c82d91,0x1a7a6c0,0x182d213,0x0102e88,0x1bf5aa6,
  43507. 0x0245928,0x04657a1,0x0c98163,0x19129f4,0x0b14f3d,0x1d3b0d7,
  43508. 0x1737f84,0x17f5557,0x0d49152,0x008dc5c,0x1772ca0,0x133e437,
  43509. 0x198cdcb,0x19ca1cc,0x0a0486b,0x105b4a8,0x1da8ea5,0x0357527,
  43510. 0x194d7fc,0x13730fc,0x0f04c9b,0x12af825,0x16b0051,0x07f2172,
  43511. 0x0326d96,0x10b24e8,0x0d297fc,0x19352ce,0x1a6c5df,0x16eca99,
  43512. 0x079d2eb,0x134cedd,0x19122aa,0x0b41d96,0x05fca0c } },
  43513. /* 27 */
  43514. { { 0x09a6663,0x112f9ab,0x129f89b,0x0fcd549,0x09597ee,0x0c5c060,
  43515. 0x1369a34,0x0604b49,0x1229267,0x083015a,0x01c8251,0x0ca00e7,
  43516. 0x139af5f,0x13399d2,0x1bb6cd0,0x052a3fd,0x1688657,0x107ae73,
  43517. 0x0e62ba6,0x146c170,0x16c3872,0x0015987,0x180d1ea,0x02c42b0,
  43518. 0x13b231a,0x0f66908,0x0bb9b1b,0x1fb39f2,0x1cf9e66,0x12d42e5,
  43519. 0x01217c2,0x05747fd,0x1a5a6e4,0x06b93eb,0x1c8147b,0x0155fcc,
  43520. 0x02081a1,0x0e35d95,0x0c2d382,0x1e172e7,0x0657acb },
  43521. { 0x074c8d4,0x02337e1,0x1344c4c,0x0c61532,0x0276517,0x1ca1afa,
  43522. 0x16329c1,0x00c42e4,0x0eb897a,0x0428203,0x1b84c11,0x1ddcac3,
  43523. 0x1bf38df,0x150bbc5,0x1d3eb3e,0x173d223,0x017b9ab,0x13b2e33,
  43524. 0x03c424c,0x0a9337b,0x1159b13,0x1bd39dc,0x103ad8c,0x0fd16d5,
  43525. 0x1ccf16f,0x1a9f960,0x0861f7b,0x1665807,0x0b9c625,0x0ea4c18,
  43526. 0x0e226b4,0x05e21ca,0x135eae3,0x1aade0b,0x070a757,0x1b6397b,
  43527. 0x0539db0,0x014623f,0x0ceed09,0x02590a5,0x03d2da4 } },
  43528. /* 28 */
  43529. { { 0x11f2865,0x015b743,0x035a5dc,0x1e28524,0x16cb639,0x1ac308a,
  43530. 0x08a8116,0x024650a,0x1f3b138,0x1ca1d68,0x081ba3c,0x0014e24,
  43531. 0x0ae6c22,0x11a6acf,0x024396a,0x1eeb385,0x140f6b7,0x1d5a97e,
  43532. 0x002fd59,0x0591bc3,0x0396f52,0x1956677,0x0607a5e,0x1d4b976,
  43533. 0x15819c4,0x1f7f01b,0x02ad474,0x1b330bd,0x150fd80,0x0b655e5,
  43534. 0x03789b2,0x12fc390,0x19d6b13,0x11abefd,0x0053de5,0x16b0563,
  43535. 0x07f4c7f,0x13c1108,0x1f98626,0x05b806a,0x002aeef },
  43536. { 0x07ec9be,0x1c93796,0x0804ae9,0x1ce4b16,0x092f307,0x1d35a51,
  43537. 0x0a8431b,0x156e9cc,0x1e2bcc5,0x06042a4,0x0301ce0,0x1b70f77,
  43538. 0x0db4160,0x194f8ca,0x1bc14a4,0x09539ab,0x0146dda,0x0875c6d,
  43539. 0x17a88f4,0x1a87a42,0x1fae0b5,0x017e1a5,0x1b3afbc,0x10eaf4e,
  43540. 0x164d084,0x051d669,0x00b4d33,0x028026d,0x0d95e2c,0x13a10e9,
  43541. 0x0a02729,0x0f0dd54,0x1fd1d6e,0x12ff661,0x0db68a5,0x073d622,
  43542. 0x0077920,0x038dd56,0x0bac122,0x002962b,0x06b446c } },
  43543. /* 29 */
  43544. { { 0x1e8fe80,0x0f59712,0x085f206,0x0d30471,0x0b5f790,0x120c249,
  43545. 0x1a65a07,0x08bade3,0x098ea6d,0x056c56b,0x00b9016,0x15a97fa,
  43546. 0x0d5bae5,0x140920b,0x1b70c9e,0x0f94202,0x185a334,0x0c598d4,
  43547. 0x0a994e4,0x1b4c210,0x15fb0b4,0x16da461,0x072e46c,0x155f188,
  43548. 0x0817cd2,0x0e04f4b,0x0f37f73,0x14c6090,0x1692541,0x09b0895,
  43549. 0x05dc156,0x1f14541,0x1dcd712,0x02940af,0x08e8d73,0x0ab356c,
  43550. 0x132b609,0x0475f04,0x014bcc3,0x097611c,0x0861342 },
  43551. { 0x0231d8a,0x01031d9,0x199ca24,0x13b34c2,0x10f6232,0x0d4f93d,
  43552. 0x03f9c1c,0x0fd55f4,0x0603f04,0x1e6c4b0,0x0a870da,0x14edfb2,
  43553. 0x16118cc,0x18ea41d,0x05398ad,0x0a4c468,0x0ddba70,0x15091e6,
  43554. 0x166d716,0x0ec86ff,0x0fa31a5,0x0126468,0x094c06f,0x0484f9b,
  43555. 0x0ad4410,0x0014b78,0x034ea9b,0x1cdf6bc,0x0a39960,0x0440039,
  43556. 0x0b73631,0x1081a7f,0x1afca12,0x0eaa0a6,0x08f77a4,0x1a53e99,
  43557. 0x0441734,0x1be2cc4,0x195f000,0x133399f,0x086333a } },
  43558. /* 30 */
  43559. { { 0x0f53b40,0x1d3a8f6,0x150b484,0x045ef14,0x0ff2c6f,0x1d72b6e,
  43560. 0x1c38bc4,0x11c1eb3,0x10e6174,0x0fc665f,0x1105164,0x1973ae5,
  43561. 0x170aade,0x064e6e5,0x0bb6149,0x1f8e0d6,0x12c1eaf,0x147005b,
  43562. 0x09ca040,0x04850b5,0x0afa89b,0x105b3ce,0x0a9fa9f,0x014dedf,
  43563. 0x18c264f,0x1cbae95,0x0c3a010,0x1daf62e,0x1730497,0x15a2e42,
  43564. 0x0f96a4f,0x0130dd2,0x12bf5d4,0x06057e4,0x0a71a88,0x1ea4d6b,
  43565. 0x199dc3a,0x0fa3e4d,0x0b3242b,0x1c57440,0x012b25f },
  43566. { 0x1eea395,0x06bc519,0x117026e,0x11ec67f,0x07a9361,0x076777e,
  43567. 0x058a49c,0x018fd04,0x0c628ed,0x123bcdc,0x1a24e54,0x194343a,
  43568. 0x1091db5,0x0c376e4,0x09b8639,0x1e77f0c,0x08bfeb3,0x07f011f,
  43569. 0x09405c7,0x13fbc20,0x12de627,0x0e2af0b,0x194bb1f,0x1a9948b,
  43570. 0x08695c6,0x078a22f,0x02f6f04,0x05bc70f,0x03835e4,0x06f437e,
  43571. 0x148ac45,0x0fc216c,0x1aba456,0x13c7f4f,0x00a8e43,0x148223b,
  43572. 0x0edf0ac,0x15b0e15,0x12dd15d,0x152e959,0x0216279 } },
  43573. /* 31 */
  43574. { { 0x047f747,0x06d5fa0,0x087b053,0x1b8262b,0x03ca233,0x12e8538,
  43575. 0x12f4d03,0x0d2b3cf,0x1bb4138,0x1e86274,0x07ef607,0x11621e0,
  43576. 0x1d189d0,0x13b5c11,0x112710a,0x00142a0,0x0a1398b,0x040e112,
  43577. 0x1a05e79,0x109c9f1,0x01e9080,0x0a34c72,0x1f62be6,0x0217e5d,
  43578. 0x0e37c56,0x0878f18,0x1e9f49e,0x1cd4087,0x1953884,0x1306598,
  43579. 0x1f6765b,0x006f33b,0x15f986d,0x1c817f3,0x1c47e3f,0x1c76951,
  43580. 0x1588416,0x0a29bc3,0x14d7bea,0x07f304e,0x020683e },
  43581. { 0x0378878,0x0171368,0x1e1f2d6,0x074f28a,0x1e214c2,0x134459c,
  43582. 0x002fe3d,0x0e027a0,0x1405152,0x0a46a7a,0x047d75d,0x02ba802,
  43583. 0x027113c,0x145ffc8,0x1d6949a,0x08b9877,0x0109b49,0x0ded358,
  43584. 0x10bce81,0x198e9d7,0x1fa183d,0x0221f7e,0x0abbd8a,0x0b8b7e8,
  43585. 0x00ee956,0x01d6973,0x1564bc9,0x1e1f421,0x03bf514,0x05990de,
  43586. 0x1d1ab96,0x0c0aed4,0x13b0868,0x1840d40,0x0fe135c,0x1217804,
  43587. 0x12dcee5,0x081d501,0x11e567f,0x1ea4fad,0x05e416b } },
  43588. /* 32 */
  43589. { { 0x06cc23c,0x09bb001,0x016090c,0x1d6b652,0x1819aae,0x09770bf,
  43590. 0x1cbe317,0x0055244,0x1ee5cc4,0x02473e5,0x1bc1f60,0x0ddcefb,
  43591. 0x1edbc7d,0x1b57c10,0x15a4913,0x17712c3,0x0ed996c,0x02fbcb3,
  43592. 0x1a85569,0x162fd52,0x0d56f81,0x1801f9f,0x0cb67bd,0x1054b65,
  43593. 0x05906e8,0x0c02f37,0x0aba51c,0x0df420e,0x0c76f48,0x1e28b2c,
  43594. 0x080d367,0x19606b5,0x1603dc0,0x13240cf,0x1fadd6f,0x1f6f673,
  43595. 0x0f04a9e,0x03aaa56,0x1f78f2a,0x1d90f69,0x04ff682 },
  43596. { 0x0a10ad5,0x0b13fe8,0x1d14c49,0x052d1cd,0x1fd45c7,0x1508b1b,
  43597. 0x0f5ae01,0x1c65303,0x1de5033,0x096f0e6,0x1e2622e,0x08bd7e9,
  43598. 0x1c3b44b,0x0d73f0e,0x06e625b,0x1b0f194,0x05a0778,0x1a90b37,
  43599. 0x1445a11,0x08e57d4,0x144582d,0x157944a,0x1ef74e0,0x0dd8993,
  43600. 0x116025d,0x1811176,0x12d954a,0x0c29d63,0x06210f3,0x0fb9d0f,
  43601. 0x09d8f17,0x00434e9,0x1160285,0x05ea6f4,0x1003197,0x1348994,
  43602. 0x0f15e29,0x058c3f0,0x141f123,0x11c6804,0x051eb81 } },
  43603. /* 33 */
  43604. { { 0x12100ab,0x0e8bc5c,0x00e47f0,0x012c0b7,0x1f2e3d6,0x0f2ce86,
  43605. 0x10956dc,0x008254f,0x114fcbe,0x1c5b33a,0x141abcf,0x126ab3f,
  43606. 0x070e8a3,0x0901068,0x0c99408,0x0f7caac,0x0d1528e,0x0334b7e,
  43607. 0x11edd95,0x10a2961,0x05b5658,0x062c895,0x033603e,0x04996fe,
  43608. 0x1ef04f3,0x0bac5d7,0x1f1b68f,0x16a7dd9,0x11df2f6,0x046c18e,
  43609. 0x1b7b7bd,0x0e70256,0x136b965,0x13018f9,0x192bb98,0x17905d5,
  43610. 0x1244f09,0x055e996,0x191fcc0,0x0aa63b2,0x08b0af9 },
  43611. { 0x0603544,0x00c0517,0x167addc,0x0644359,0x0b573ac,0x0038191,
  43612. 0x1d99589,0x07a742f,0x1b89abc,0x09f3a56,0x0c896ab,0x1c75af2,
  43613. 0x0b8a3d2,0x17812b2,0x1eee813,0x1a56a8a,0x12ffc2d,0x0443ab2,
  43614. 0x19c50fa,0x00ba2bc,0x0d70d29,0x0101724,0x1b6212d,0x0c6d4ae,
  43615. 0x19219c7,0x06f837c,0x04d78de,0x11b8684,0x064a02a,0x0b9e886,
  43616. 0x19a5707,0x1982af4,0x16a4ece,0x051aa66,0x0722389,0x1b75b98,
  43617. 0x1839329,0x1278d94,0x02b4200,0x0929b49,0x05363e5 } },
  43618. /* 34 */
  43619. { { 0x03fc641,0x091dbf1,0x018c7d5,0x1f0ccce,0x1e54e72,0x004e97f,
  43620. 0x057d638,0x1c25294,0x18c57f5,0x101ccbf,0x159373c,0x049962d,
  43621. 0x1ba2297,0x05d517f,0x1ef93f5,0x11dacd2,0x0460a6e,0x11fa83f,
  43622. 0x014214d,0x1c74baf,0x02080af,0x0ecaa04,0x1bbbdb3,0x18846f9,
  43623. 0x1d889f2,0x129b80f,0x0970e14,0x12db107,0x0212f14,0x13f6b95,
  43624. 0x1378971,0x03fef1f,0x1416783,0x1a0a325,0x001305b,0x0fd32ce,
  43625. 0x045b069,0x02e1d0e,0x0c30fe9,0x0307f7a,0x0633340 },
  43626. { 0x0fbbbce,0x0d06651,0x1d10e72,0x1954196,0x076f6e5,0x1c7671c,
  43627. 0x00438d0,0x10539cc,0x013802d,0x1568a47,0x11686c2,0x18c139a,
  43628. 0x009c3e5,0x1de7e0f,0x172e165,0x09ba10e,0x190d858,0x1d8cffb,
  43629. 0x0070a8a,0x11703db,0x07e3259,0x17815f0,0x0462f7c,0x0ecb9d2,
  43630. 0x1c8eeb9,0x0d703a7,0x02c93e5,0x04bd3b1,0x18f09d1,0x166e064,
  43631. 0x09ceec4,0x1416e96,0x06aee07,0x03be725,0x0be7020,0x1e8e47a,
  43632. 0x1ea8026,0x0a23eb5,0x02dce56,0x0b82c50,0x093a707 } },
  43633. /* 35 */
  43634. { { 0x15b27f9,0x1f7f138,0x048c9ae,0x0454501,0x0935a5e,0x0c51355,
  43635. 0x08ebff5,0x128bbbe,0x07c1386,0x0641f0b,0x08854d5,0x1793125,
  43636. 0x1544799,0x0dc684f,0x1b91c42,0x1d4d09c,0x016d588,0x1631d7b,
  43637. 0x00eac6d,0x12ce0d1,0x13365e8,0x101e904,0x0f04e4e,0x1847bb4,
  43638. 0x1292192,0x121e817,0x0b73dba,0x16e196f,0x1559e1a,0x07543c8,
  43639. 0x02c490d,0x0dae1fe,0x00680db,0x15d2282,0x1948a0c,0x1e3421f,
  43640. 0x05f0cb8,0x0fce047,0x107f75a,0x1588962,0x01a7422 },
  43641. { 0x140b675,0x0ee974f,0x1ce70ea,0x07f98e3,0x0a7c660,0x0471a11,
  43642. 0x0698465,0x1083127,0x0ed0ab4,0x19db0ac,0x0729ae3,0x1b2fdc6,
  43643. 0x03a3aa7,0x1bd46db,0x07a197b,0x0c5c978,0x0092c7c,0x198afc6,
  43644. 0x1d71b43,0x00f11f3,0x1ec5a26,0x14a5b79,0x0c60cc4,0x169b093,
  43645. 0x1bcd636,0x14db9d6,0x02f1a66,0x0dc2912,0x1175e76,0x086c150,
  43646. 0x13efcde,0x1f8a794,0x143605a,0x1b048bf,0x111e1ff,0x0caefed,
  43647. 0x000c82b,0x1e3aa93,0x1667209,0x0613a4a,0x00944d6 } },
  43648. /* 36 */
  43649. { { 0x0ab9620,0x15b1f73,0x00233f7,0x1af0d9b,0x1ff4fa6,0x119059e,
  43650. 0x1760915,0x02a28bd,0x0c49439,0x172fc31,0x0cfe1ca,0x10276e7,
  43651. 0x099508e,0x1297cbd,0x16017cf,0x136c477,0x028c982,0x07b8dae,
  43652. 0x1b833bf,0x098e1d0,0x136eb39,0x1491ded,0x14d3ec6,0x1c4fcb4,
  43653. 0x15862db,0x0b4eb27,0x0e0ead8,0x15c47be,0x0828cbb,0x18d893e,
  43654. 0x02b75b7,0x07460f5,0x101899f,0x0efb30c,0x1966047,0x0e6d990,
  43655. 0x19943b7,0x05bbba3,0x195da8f,0x106dfb0,0x07d89f3 },
  43656. { 0x1f92b2b,0x1212164,0x0af7e15,0x0b88dc6,0x100c6a7,0x0cd2e2b,
  43657. 0x1a2ddfe,0x0d127ce,0x0031495,0x177f42c,0x199c26d,0x1433859,
  43658. 0x13bbfe8,0x1737624,0x068ec6f,0x1851ae4,0x0a9c371,0x0937777,
  43659. 0x145df87,0x1022bc2,0x05a5d79,0x0758345,0x15efcef,0x1a56965,
  43660. 0x1a22046,0x0fe6fc6,0x0d66fa7,0x1be132b,0x040b793,0x0bde3bb,
  43661. 0x11725a2,0x0b457a7,0x00cf4c2,0x1f3a267,0x15ba26b,0x162de8b,
  43662. 0x1a8509b,0x1f9d659,0x09b9ad4,0x03ec7e5,0x0449af8 } },
  43663. /* 37 */
  43664. { { 0x16d9377,0x0789950,0x1e7b0bf,0x06fc345,0x1ab377b,0x08cd72c,
  43665. 0x084ba1b,0x162e5c3,0x0d013bb,0x1589733,0x1d9aeb4,0x00ab96b,
  43666. 0x100972e,0x1ccf55a,0x0778700,0x0bd85a2,0x0fdc65f,0x1e0f98a,
  43667. 0x0a7fd64,0x0230831,0x06e6fc3,0x1670292,0x17dcf07,0x04a0adb,
  43668. 0x1136316,0x10ce146,0x1dbec97,0x0153b7a,0x1cd2d73,0x0922422,
  43669. 0x0b4127b,0x1a6dd0a,0x179b83f,0x04541e3,0x1f1fda3,0x070b46b,
  43670. 0x095e803,0x0df8f0e,0x06bd4a6,0x1864112,0x00e8617 },
  43671. { 0x1c81b5c,0x1030133,0x1cf14dc,0x1bce6f0,0x0fa89dc,0x0a27e81,
  43672. 0x0c2c2a0,0x10654e8,0x126208c,0x00362d3,0x0903d4c,0x0cc1b1d,
  43673. 0x044e066,0x04b209d,0x14097e6,0x0293f3b,0x0cc46b9,0x15ef9c0,
  43674. 0x0849730,0x0acc321,0x1c37801,0x1ba93c9,0x0135a8e,0x0f4c5e4,
  43675. 0x013746b,0x0bc5b00,0x0161756,0x139fc4d,0x15fe66a,0x065c41c,
  43676. 0x1db72b4,0x08d64c3,0x0b468fc,0x0c90c5d,0x17be767,0x05941de,
  43677. 0x1e45240,0x03ea542,0x1da1f14,0x1e264d9,0x06f4404 } },
  43678. /* 38 */
  43679. { { 0x1ebd3ff,0x0c905a7,0x0eea8f8,0x11fbfa5,0x0a6234d,0x0d4c14e,
  43680. 0x0bcab86,0x0416fa3,0x0c6f5bc,0x1ef0b08,0x0e72a48,0x17e7b54,
  43681. 0x0be204d,0x16c6385,0x0b7a6e1,0x06e1654,0x0377c9d,0x1139706,
  43682. 0x1595443,0x02980dc,0x16b0809,0x142be5d,0x0d8479e,0x04cd4dd,
  43683. 0x1c6efd8,0x00e03b7,0x18c2560,0x1f5869d,0x024063d,0x00515cf,
  43684. 0x115a7fd,0x0f0f54b,0x1ba31a9,0x1866953,0x1f7ccf1,0x081c9a3,
  43685. 0x0895f07,0x1f18993,0x1c78a40,0x1f0ff6c,0x0905771 },
  43686. { 0x0062bee,0x0dd06d2,0x07e5466,0x1929afb,0x18e7238,0x0491600,
  43687. 0x0a6f078,0x0bfea7e,0x1b12d85,0x14d9540,0x0328a77,0x1ddadad,
  43688. 0x1f649f3,0x028604b,0x0b7f0d3,0x13140c9,0x0b99db3,0x040cb25,
  43689. 0x0961c89,0x0b388ef,0x103a00d,0x0b3a62c,0x027fa8e,0x0087ba0,
  43690. 0x1d8ee15,0x0103557,0x197c7b3,0x0ae434d,0x19b7b4c,0x124186d,
  43691. 0x0aadb5a,0x0cd91aa,0x0ffc617,0x0151383,0x075ab32,0x107bc48,
  43692. 0x07f2f7a,0x02f8291,0x17b3018,0x076c809,0x06a2295 } },
  43693. /* 39 */
  43694. { { 0x0fce389,0x096c7ba,0x1592491,0x0055f4a,0x059634c,0x16bc128,
  43695. 0x132efc3,0x01b26ef,0x137718e,0x0fa022d,0x1a69362,0x1cfb3f4,
  43696. 0x1a11074,0x194ad85,0x1c2ec1d,0x1dbccba,0x0adf107,0x1d916aa,
  43697. 0x068a71e,0x1347b14,0x03ab5c3,0x016bcaf,0x0dc8db0,0x0b132a2,
  43698. 0x02d002b,0x1717b94,0x195e42f,0x1c44cb7,0x065ea25,0x1508d47,
  43699. 0x0f64783,0x0c0039d,0x071a708,0x02a0107,0x1d68b07,0x022d201,
  43700. 0x157f698,0x196ae01,0x0d09f0e,0x140c33c,0x0528c9e },
  43701. { 0x126c577,0x0435a2f,0x15147b7,0x1128717,0x1807470,0x12c153f,
  43702. 0x0404de4,0x13e5bfc,0x0de1e56,0x0475650,0x168d5b8,0x1df534a,
  43703. 0x165f952,0x124bb10,0x1602d4f,0x0e3e549,0x055cd5d,0x0695b2c,
  43704. 0x1b3a8fc,0x0e097ec,0x03ca246,0x0fa4919,0x064fd90,0x1b6264a,
  43705. 0x1855c9a,0x1295340,0x18b4675,0x0daa459,0x02ed7b8,0x0f882dc,
  43706. 0x0a54d82,0x11c2a1a,0x10f0094,0x1f4489d,0x0fec2c4,0x12475b1,
  43707. 0x1794b44,0x18aab67,0x13d5f2e,0x126e717,0x0200f90 } },
  43708. /* 40 */
  43709. { { 0x188387f,0x117e2c1,0x0f17e6c,0x0051d10,0x0f26f17,0x1bcb9e6,
  43710. 0x0ae4346,0x0e288f9,0x0f6ec91,0x0aea751,0x136f023,0x0931861,
  43711. 0x0b2e16f,0x04311e1,0x04a4431,0x18a8bb9,0x1b030db,0x0758a48,
  43712. 0x137886c,0x1bd65c2,0x10f4631,0x1317f41,0x0128841,0x1383e7e,
  43713. 0x0979c37,0x1cad263,0x03ec1a9,0x14e656d,0x19dfa98,0x193d0b0,
  43714. 0x06ce910,0x11b7c59,0x1a307d3,0x04ff548,0x03480e6,0x1f27379,
  43715. 0x0f4a331,0x155d790,0x15770f6,0x131ba1e,0x05c307e },
  43716. { 0x1b233da,0x070621a,0x0616ef1,0x0a45edf,0x03d2908,0x1812347,
  43717. 0x0b486a2,0x1cf33ba,0x1a96916,0x1c7a074,0x0f33b65,0x10d8c29,
  43718. 0x0c0327d,0x19483b1,0x1a5540a,0x1e5db2b,0x197a879,0x187fe90,
  43719. 0x0382f4c,0x0ca26ea,0x04c4c43,0x050413e,0x09b0c52,0x19f8164,
  43720. 0x012a83f,0x0c4e3cc,0x18c64a1,0x07b1a2f,0x10f42dc,0x167f441,
  43721. 0x0fe2d5c,0x0960ff0,0x0d9ff92,0x08a47be,0x0540294,0x1866395,
  43722. 0x0c59f9a,0x029cb42,0x11e1743,0x1f58286,0x01df16d } },
  43723. /* 41 */
  43724. { { 0x0bcacc3,0x1da5634,0x033f31e,0x1e861eb,0x06ded34,0x10c2ad0,
  43725. 0x07d3f51,0x1798b3f,0x045c9f0,0x0a48cca,0x17224bd,0x1d8c86e,
  43726. 0x1adc5f7,0x1e42cc1,0x01c23c4,0x1a10e37,0x0c482fc,0x1d9952e,
  43727. 0x15ad303,0x19b86a5,0x1b2defd,0x0245637,0x12ec93c,0x120c8e2,
  43728. 0x0d4f533,0x1622cc1,0x1ee0e8e,0x0c5d6a5,0x17a2231,0x0f94119,
  43729. 0x14dc4c3,0x19787b7,0x0e7b802,0x1d6076e,0x0564919,0x1d1672b,
  43730. 0x1b56717,0x09e9740,0x0985c87,0x0a08ca2,0x0729a7f },
  43731. { 0x020f90a,0x168d542,0x01561d3,0x1c1fc99,0x0368e19,0x1f3a57b,
  43732. 0x12aaac2,0x1536c5a,0x08ca60c,0x17e6240,0x16a19dd,0x0b4aec8,
  43733. 0x0cf310b,0x0ed8d92,0x06eb26f,0x0b68826,0x11d2dea,0x177bbeb,
  43734. 0x0bf3193,0x0da420e,0x17f0470,0x08b39eb,0x0a6e49a,0x13c0cc6,
  43735. 0x00bf3e8,0x0a01170,0x0dd01df,0x0e5a19a,0x1232e24,0x0206c14,
  43736. 0x0ccf884,0x071b90a,0x1916dfb,0x07b3397,0x166c52e,0x1a91776,
  43737. 0x144be19,0x0f4fa56,0x0757067,0x092465b,0x07f6d36 } },
  43738. /* 42 */
  43739. { { 0x0794819,0x0326f37,0x1684ef4,0x1df05d7,0x1a6b694,0x0f14022,
  43740. 0x1ff82e4,0x1a43e02,0x107a43c,0x08698f9,0x10cfa46,0x044cc60,
  43741. 0x146c26f,0x055fee5,0x1222a9c,0x0238174,0x085a464,0x020c6c8,
  43742. 0x1fed620,0x069fcd7,0x18491b9,0x1bf1007,0x1d74788,0x0a827b6,
  43743. 0x0d63fa5,0x1bbef82,0x1788ecf,0x042ddae,0x11bd30e,0x136587c,
  43744. 0x0268161,0x0ee538a,0x0c395d9,0x1596bc2,0x062114a,0x0dd92fc,
  43745. 0x0093d68,0x1be0fc8,0x021b232,0x12ac51e,0x02d0323 },
  43746. { 0x044b4c5,0x04a03a5,0x1262a07,0x1398e05,0x1984687,0x186e4bd,
  43747. 0x08a1f3a,0x04396a0,0x06e3aa3,0x0180893,0x095b08c,0x0ec7c98,
  43748. 0x05c0ac8,0x12ada42,0x00d3483,0x1e6b6ca,0x040f240,0x0554b50,
  43749. 0x13dfbb7,0x1a4da6f,0x0656046,0x109dc08,0x18a96a3,0x1ae1856,
  43750. 0x04b9783,0x147c302,0x0167936,0x1f75ff1,0x17f5d12,0x080d2a2,
  43751. 0x15e4a76,0x16a636e,0x09e1eb2,0x14b9ce9,0x0f72793,0x12429b5,
  43752. 0x0eaa9bd,0x0b927e2,0x0ee6d6f,0x1663df3,0x0734c12 } },
  43753. /* 43 */
  43754. { { 0x0f9b086,0x11e1749,0x151263f,0x1d67fa8,0x0641b93,0x01632e2,
  43755. 0x0822d70,0x0848f9c,0x1c4f032,0x1296e50,0x14a7da2,0x0fb2cf3,
  43756. 0x14b5ec1,0x0a037af,0x14bfb42,0x1502223,0x1dc0d9b,0x19307b1,
  43757. 0x151ca8f,0x160ade2,0x10e6de2,0x0f80394,0x06c5c36,0x16b91f2,
  43758. 0x03e8db6,0x1f75171,0x073cd30,0x08b4507,0x173ee23,0x0a308dc,
  43759. 0x1166f71,0x17649a3,0x1bda6c2,0x0a0d0b2,0x0e8cf18,0x032faa5,
  43760. 0x1d2eb20,0x1d8b094,0x1927d1e,0x10e43f7,0x07c558a },
  43761. { 0x1350fec,0x02d291f,0x1302e52,0x0ad471a,0x016678c,0x0d53268,
  43762. 0x11a8835,0x1c91de6,0x0d96da2,0x02ed501,0x11ecf2e,0x09d49ec,
  43763. 0x0c845ec,0x06af4a3,0x1469b28,0x1e95781,0x1c14fa9,0x1a0ec68,
  43764. 0x122c4c0,0x0e598b3,0x1bfb439,0x06a1a7f,0x19f87d2,0x13a4630,
  43765. 0x0e93a81,0x11f9a86,0x01b77bc,0x13ea612,0x0cf12c4,0x167c900,
  43766. 0x1f0f0b9,0x0c80865,0x0691cc1,0x0b5a921,0x12d1c92,0x1d7ffee,
  43767. 0x020a97b,0x093e4f8,0x10d2111,0x194f678,0x034cd7d } },
  43768. /* 44 */
  43769. { { 0x1e7fe87,0x0bb0d2c,0x15cbc0c,0x14008f9,0x11eae31,0x1187b15,
  43770. 0x0b9a3eb,0x0864f20,0x1b71db1,0x1337a46,0x00e3d29,0x0cf01c0,
  43771. 0x0d75ee6,0x015eebb,0x116b19c,0x19ab876,0x028a0d6,0x08697dc,
  43772. 0x16316c4,0x1cfe3b3,0x1e9627c,0x120905a,0x0507f83,0x04cf86e,
  43773. 0x1b984b9,0x166cad0,0x07580c4,0x040dcb1,0x1493565,0x1a176d2,
  43774. 0x0b0619c,0x00e18e9,0x14520b9,0x1d8599b,0x0ed6555,0x084e079,
  43775. 0x06ed8c1,0x10face5,0x0e21fd8,0x18557ef,0x07ceb1c },
  43776. { 0x17fd65b,0x1d2dded,0x15f0191,0x006d928,0x18d45cc,0x0938c56,
  43777. 0x0676e78,0x1638db5,0x0e93a7f,0x08eddfa,0x159a87b,0x12b97a2,
  43778. 0x194512c,0x0de0648,0x186e803,0x0a4d290,0x0989e7f,0x11e3661,
  43779. 0x0506aab,0x12c2a01,0x18e3671,0x07e4629,0x0ff3d74,0x0b4aa3f,
  43780. 0x09929a2,0x19356b7,0x145f283,0x00e2130,0x09ef7e9,0x1c757d4,
  43781. 0x125d0ed,0x0e3568a,0x1d5ea31,0x0e1b69c,0x0fcf9b4,0x1ae885e,
  43782. 0x059d568,0x1341f00,0x1b57096,0x13244f9,0x01f629a } },
  43783. /* 45 */
  43784. { { 0x05a1c3e,0x0eed672,0x117e249,0x0a83eea,0x12d2936,0x13fc143,
  43785. 0x0bf2cdf,0x1a48ac4,0x13e4c79,0x011a289,0x19175a2,0x1f09384,
  43786. 0x195dffa,0x0ca4015,0x1e3d376,0x13f4060,0x1f09d33,0x02b3493,
  43787. 0x1f64773,0x00143d3,0x0bd79a5,0x0005585,0x1380206,0x129cbbf,
  43788. 0x135a381,0x0446cb8,0x1e62b7c,0x1d0ec60,0x05a2a79,0x00dc4d2,
  43789. 0x064eebc,0x0f11687,0x1ed6154,0x14cbeb7,0x1c8b9de,0x1b301ca,
  43790. 0x0a378ee,0x0487fd1,0x0168aab,0x14517b0,0x04a75fd },
  43791. { 0x1e74cbc,0x147ddaa,0x1c97426,0x1df5631,0x137738c,0x12761d3,
  43792. 0x0eb5a5d,0x0621f84,0x1e7e0ad,0x0d3e9ad,0x07326f1,0x0d1dc90,
  43793. 0x14e75e0,0x1ea5761,0x10baa64,0x0c789e1,0x1e80d4a,0x0789927,
  43794. 0x06c164b,0x16f82d3,0x146b5db,0x06d3f07,0x110b59d,0x001f5d4,
  43795. 0x166c7a3,0x041ad2e,0x04ccceb,0x107b904,0x008496e,0x0097462,
  43796. 0x105c3be,0x133debf,0x0e1dcb6,0x074314b,0x1c6c5cd,0x10dc56e,
  43797. 0x183507d,0x114e6e2,0x05e6811,0x15c47b0,0x05819f9 } },
  43798. /* 46 */
  43799. { { 0x0a78811,0x14890b5,0x1f0f665,0x084207c,0x164ee8f,0x1cf34c7,
  43800. 0x041c08a,0x1bdbbe0,0x04f582c,0x1000fcf,0x1eb06b9,0x115e5d9,
  43801. 0x0924a60,0x031c980,0x1d31e10,0x05222dd,0x0e6ebf7,0x0293175,
  43802. 0x113b968,0x1a15eb1,0x1bc7ddb,0x08766c3,0x01d6bfe,0x049e229,
  43803. 0x1b34c6f,0x0b917ee,0x07a197c,0x1020850,0x0c1b9a4,0x1213443,
  43804. 0x07e55a4,0x13de846,0x15f3208,0x1f41737,0x0b3f429,0x115eb0f,
  43805. 0x1ac395c,0x0b8c8bc,0x09d4359,0x07826c9,0x0745960 },
  43806. { 0x01ae519,0x03adffa,0x0944709,0x0295f1e,0x14401fb,0x1d961e9,
  43807. 0x1f34abb,0x010e1bb,0x151cdaf,0x1969c2d,0x02ec666,0x04ad041,
  43808. 0x168531c,0x0619f9f,0x12277d9,0x02ed22d,0x0992457,0x1611e7d,
  43809. 0x1b4042e,0x136a3d0,0x0313233,0x069131c,0x0236c3a,0x1fdbd6e,
  43810. 0x1e17900,0x178fbb4,0x0e8da1f,0x1fb2db9,0x0764753,0x1591c8a,
  43811. 0x1773411,0x0188b91,0x1ff2064,0x01ebc79,0x1ef6e0d,0x01dfa2c,
  43812. 0x0b77ee9,0x1e65b6a,0x1ed1524,0x027679e,0x0330255 } },
  43813. /* 47 */
  43814. { { 0x1eaaca1,0x002349a,0x0408dbc,0x0b12232,0x0c384b7,0x094aa60,
  43815. 0x159979b,0x1af966e,0x1b1e9d6,0x1c8ccdc,0x109d5f2,0x0693853,
  43816. 0x1075852,0x1c739c6,0x12f46ea,0x1484f13,0x0905923,0x0cdc6df,
  43817. 0x03f8622,0x0ef27c3,0x0083a23,0x0bd3a17,0x0909c5d,0x1d7ac27,
  43818. 0x179d24e,0x1bbc624,0x1353cb3,0x0064a0a,0x0705de4,0x1048cac,
  43819. 0x0ea8ee2,0x067b333,0x1191bd9,0x1f70f0d,0x0e90ec3,0x0975fdf,
  43820. 0x1facdf1,0x1d68c21,0x15872ce,0x160870e,0x09328ad },
  43821. { 0x106b872,0x027407c,0x1996afa,0x00f04c4,0x105523a,0x0c667bb,
  43822. 0x1a9f8ce,0x047b138,0x1f55b53,0x1d5aa8e,0x137aa0b,0x1d940aa,
  43823. 0x0da0578,0x1baac4e,0x09948f4,0x1aea1de,0x042864a,0x16c7eb1,
  43824. 0x1e3f87f,0x04ff8a2,0x142293f,0x184efc3,0x1ecf9bc,0x0a1a0a8,
  43825. 0x0e49e37,0x0509431,0x097700e,0x1b218d6,0x1b682b7,0x1711426,
  43826. 0x02b0686,0x1310326,0x1f3dab7,0x1f05223,0x154aebc,0x0a61cd7,
  43827. 0x162d25c,0x00012df,0x1579c1a,0x19f5ba1,0x00aa1f3 } },
  43828. /* 48 */
  43829. { { 0x0a10453,0x110c811,0x042ea60,0x1854074,0x1d1eb91,0x12379de,
  43830. 0x1765659,0x18d5f76,0x0f38b6f,0x0c6f1a2,0x1f28769,0x07cb719,
  43831. 0x04ce47c,0x07b86d0,0x16385b4,0x05dadf9,0x09bda26,0x156221a,
  43832. 0x15b8be3,0x01b0f78,0x0e58932,0x040c89c,0x0738fa8,0x1646d81,
  43833. 0x02dffa2,0x186d2c3,0x1239fbe,0x161f34b,0x0c78eb6,0x01958b5,
  43834. 0x0bd2d4d,0x0e136a3,0x1f43105,0x0cb1437,0x1be23d4,0x1a11c46,
  43835. 0x0ed403a,0x09f8bb7,0x151787e,0x1c12c6c,0x0559337 },
  43836. { 0x0fd807a,0x0fb9c6c,0x0888c37,0x1b56262,0x14e0ec9,0x0d7de1f,
  43837. 0x1d36d89,0x12a2945,0x09f12f8,0x0db8302,0x0113f75,0x1847586,
  43838. 0x0fb46f3,0x1aa00a4,0x08cb47f,0x1caa836,0x0f539b4,0x0b0da2c,
  43839. 0x175c2dd,0x0964941,0x01d9f69,0x0c944ac,0x03f190a,0x0bfc45a,
  43840. 0x149beee,0x1b1e02e,0x1da862f,0x15e688f,0x1929d67,0x0ee13f8,
  43841. 0x033a5a8,0x182aa3d,0x0fe6028,0x0a7d135,0x0bccad7,0x084fb59,
  43842. 0x145c2cb,0x0b18de2,0x0534d28,0x1f36192,0x0930070 } },
  43843. /* 49 */
  43844. { { 0x1a9bc05,0x1962f34,0x0dcf4bc,0x0cb1389,0x0a5c19c,0x132fce0,
  43845. 0x0797a51,0x07212b9,0x1bcfb4c,0x1587949,0x0df0c62,0x10ee3bb,
  43846. 0x08b9070,0x1359c02,0x13a5961,0x1b37b12,0x0cf606b,0x0f8cd48,
  43847. 0x1bf4b5a,0x1ab1bf6,0x0a69cc1,0x07230ec,0x021b731,0x19c9063,
  43848. 0x1c277f9,0x141622a,0x19d97e2,0x0934b32,0x1adc8d7,0x134661d,
  43849. 0x0acbff1,0x122259b,0x0018396,0x1e3e59c,0x170ec90,0x09530f2,
  43850. 0x010a222,0x1af9880,0x178521d,0x082b0f6,0x0043a21 },
  43851. { 0x0873752,0x14ede1d,0x1fb9eef,0x085e885,0x0e1493f,0x0610c0f,
  43852. 0x08b2306,0x1cf3039,0x0e29769,0x0671848,0x1a317c0,0x1591bce,
  43853. 0x1eb4626,0x1a6bb3b,0x1a73918,0x129cc67,0x0ade0fa,0x1fc4e16,
  43854. 0x07d6d6f,0x0b98228,0x012c04f,0x1b11146,0x09597dc,0x00b99ca,
  43855. 0x1706a0c,0x027f8df,0x1ef921f,0x1a0ffff,0x19f1a45,0x1e04d24,
  43856. 0x000fb10,0x131b290,0x14e79bb,0x1897c27,0x08581cf,0x1b1466b,
  43857. 0x0f970d6,0x1af57b8,0x02ba12e,0x0f7e49a,0x018d074 } },
  43858. /* 50 */
  43859. { { 0x0601faf,0x1e3be42,0x1dc9634,0x055e383,0x09465be,0x0b6c036,
  43860. 0x19e6344,0x079fec4,0x0d5b0d9,0x0cb6063,0x19c8e8e,0x1aeabd8,
  43861. 0x092fa1a,0x01dd29a,0x1aa0510,0x09b152c,0x0222ac3,0x0ee264a,
  43862. 0x159d619,0x08e3bdd,0x128fddf,0x0bca9ea,0x162b296,0x1d7ecfb,
  43863. 0x063b524,0x069d972,0x05f896d,0x0b0490e,0x159daa2,0x16dd218,
  43864. 0x1008f16,0x1066aea,0x058f9c6,0x058d32a,0x169fe4e,0x039ed0b,
  43865. 0x0efed23,0x0d27ed6,0x1796660,0x1da1176,0x0711093 },
  43866. { 0x01f161a,0x11fe320,0x1a1c4aa,0x012e98b,0x1735856,0x1aefc17,
  43867. 0x14bec5e,0x1329544,0x1a48e62,0x05c1583,0x1611f6c,0x02ae53b,
  43868. 0x0600234,0x0294e2d,0x1953401,0x1ea71e3,0x19e6d98,0x1e60e29,
  43869. 0x034eaf2,0x0c56a65,0x10cd361,0x1c15427,0x1d68de4,0x1dce908,
  43870. 0x1a81b4d,0x18dfb8b,0x0d308ef,0x0d9e6bf,0x1e8b3e1,0x014fbc3,
  43871. 0x0c1ff47,0x0b36f35,0x1da7e68,0x16305db,0x028217d,0x0a0e420,
  43872. 0x07ed48b,0x0200acf,0x05f50c6,0x1b49b39,0x017898b } },
  43873. /* 51 */
  43874. { { 0x01b8cf8,0x041ec57,0x015b361,0x05d3451,0x123d4b4,0x0525e11,
  43875. 0x1613c81,0x1f4ec66,0x0ca7a69,0x1059114,0x1eeac93,0x1517eea,
  43876. 0x0a8afbd,0x1662fce,0x0c90221,0x12b870b,0x013d41a,0x1a3fda4,
  43877. 0x0aaaf9a,0x178a798,0x199d3f1,0x1f8d68a,0x1c8b368,0x03d5363,
  43878. 0x0c081c3,0x1608d97,0x0c05852,0x091e609,0x0fa7ab0,0x0774e35,
  43879. 0x0f738c7,0x08281b8,0x1af7633,0x055dd2a,0x0cdf73a,0x1d096f5,
  43880. 0x07cf3ef,0x0f3b246,0x1aac943,0x19e2a6a,0x073a88d },
  43881. { 0x0e83b39,0x1414403,0x0df4fe1,0x073e880,0x077a441,0x0de420a,
  43882. 0x02c3c5f,0x093f20b,0x154d175,0x0db27a7,0x01fff8b,0x14d5e46,
  43883. 0x01a23ce,0x0789313,0x0fbf555,0x0fe4c72,0x18a10f3,0x097a732,
  43884. 0x13b878d,0x06f9c7e,0x1e8ba44,0x13d49e6,0x193bd0a,0x1355202,
  43885. 0x1c9f493,0x06a0ef5,0x08f5ed7,0x08447ad,0x0a3acc4,0x1508fc4,
  43886. 0x0b5e269,0x058c114,0x0fb9df8,0x0b6032b,0x038eefd,0x01cf3b7,
  43887. 0x068fa30,0x02b5793,0x1a879cf,0x02f5c72,0x052f32b } },
  43888. /* 52 */
  43889. { { 0x114f71a,0x09260f3,0x14655bd,0x0535bb0,0x01be126,0x056df1e,
  43890. 0x0276197,0x0935b23,0x05a0fb6,0x045fae4,0x064b676,0x152443a,
  43891. 0x0f9efa6,0x17b925b,0x1fa0e25,0x02339c7,0x024b250,0x0761fd7,
  43892. 0x0b834f0,0x15f3ec5,0x024d4b6,0x05eb0cb,0x03f3ae8,0x1b6dc75,
  43893. 0x1092b2f,0x094bee1,0x18c98f3,0x123b46e,0x1c43bdc,0x1b0f7ca,
  43894. 0x164c301,0x19bd689,0x1136400,0x0698ec4,0x1a110f0,0x1ffafb9,
  43895. 0x1871899,0x1f61d8c,0x16305e3,0x051dfbe,0x079e14d },
  43896. { 0x1b40c55,0x1111acd,0x090b8e0,0x1a1da0f,0x0a27202,0x1c60fa0,
  43897. 0x106a520,0x11c91cd,0x1d864a7,0x1af9253,0x115724a,0x081418d,
  43898. 0x087e7f1,0x07096a8,0x0b0412b,0x03c21cc,0x07ec11b,0x0cd850d,
  43899. 0x1eecf75,0x144ebf5,0x0b30fd8,0x1f4d1db,0x17fcd53,0x0c05403,
  43900. 0x05d9e46,0x0fbad08,0x164eed9,0x1a6e369,0x02fdeb3,0x1f8587c,
  43901. 0x1176972,0x1bc8d0a,0x001229b,0x0a8bf23,0x02e71cf,0x04a0bc2,
  43902. 0x072ff49,0x07d2a0b,0x1b389df,0x11532ac,0x00d8ec2 } },
  43903. /* 53 */
  43904. { { 0x1eee995,0x07b9f65,0x0030053,0x19a923d,0x12eb88b,0x15d2ea5,
  43905. 0x1b2b766,0x09ac2b4,0x19304c8,0x1bea319,0x00f268b,0x03a5156,
  43906. 0x14ba050,0x08dd5dc,0x1dc8f7a,0x0aee591,0x1775040,0x06442fc,
  43907. 0x1ff2c25,0x03a5678,0x071ab5e,0x0aefcb6,0x187b9e6,0x0c8933c,
  43908. 0x0daab34,0x0995c64,0x157d81e,0x1684bbb,0x043587d,0x0e50d89,
  43909. 0x101c094,0x13f8e86,0x0d7d3be,0x1564493,0x0c43240,0x1f182f2,
  43910. 0x0559a74,0x09160aa,0x12bf1c9,0x04f86e6,0x086001e },
  43911. { 0x1693947,0x005d2f3,0x18ac4ec,0x1c02580,0x0478641,0x0a48543,
  43912. 0x0e383a1,0x0bdc348,0x1d9574d,0x0b9eddf,0x0ee9854,0x171937a,
  43913. 0x159532e,0x0f9f503,0x106f2e1,0x125723e,0x0478cbb,0x0560e61,
  43914. 0x1be406d,0x08c91c3,0x12ee0f3,0x0f6959d,0x1764a74,0x1aeb7f9,
  43915. 0x11eabc3,0x0692387,0x1c4e73d,0x19b78de,0x0249535,0x02a6f82,
  43916. 0x00f3619,0x08ff967,0x0079812,0x1c9860f,0x06d05f7,0x0173e41,
  43917. 0x114ebc0,0x12fe188,0x11b0508,0x19668f2,0x0020591 } },
  43918. /* 54 */
  43919. { { 0x15e0af4,0x01b9093,0x092f8c0,0x1fcf149,0x121141e,0x1aba42b,
  43920. 0x1f3db45,0x13cccd9,0x1168e65,0x1d0eb9b,0x010bb97,0x1ca81c5,
  43921. 0x16263e3,0x0a45eaf,0x1b30f52,0x020955b,0x03d246b,0x000cef0,
  43922. 0x0d0f606,0x13d207e,0x0d31f8a,0x052d860,0x12d5ee9,0x1c4ecbf,
  43923. 0x0c50651,0x1b3c123,0x1d9466f,0x018aea3,0x119a018,0x0100790,
  43924. 0x1d17c17,0x0f043a9,0x06487b8,0x01d033f,0x12a8987,0x044c5f2,
  43925. 0x1214605,0x07f244b,0x017bd5b,0x0bf43be,0x0511998 },
  43926. { 0x18586c0,0x0a4bed8,0x0989606,0x0d8ddd5,0x004415d,0x06d1458,
  43927. 0x11ada5f,0x128f8d4,0x07c1945,0x10a4d94,0x0e941a6,0x13f49da,
  43928. 0x14b5636,0x01e4a65,0x04aa999,0x1ddc4e1,0x13aa9e9,0x0aade73,
  43929. 0x1e24d42,0x1650e0e,0x132634b,0x180375a,0x02be57e,0x071e90b,
  43930. 0x1032396,0x1fc43e6,0x016e9d6,0x126ec4d,0x02d5812,0x179ecea,
  43931. 0x137ccb5,0x0cb8dac,0x0cad574,0x0f6a0d2,0x03eecb3,0x0f30bea,
  43932. 0x1006a06,0x1a67074,0x1fe6b3c,0x0cab14a,0x059eaf2 } },
  43933. /* 55 */
  43934. { { 0x0c3876f,0x03f7db7,0x1921ed0,0x07e1e90,0x180c612,0x04981cb,
  43935. 0x15bfefe,0x1605576,0x045a91a,0x0c97550,0x046e0a5,0x09aef10,
  43936. 0x09ce5b8,0x0fcf9fe,0x09c68d0,0x1c2770d,0x186f0e7,0x060bfee,
  43937. 0x1568220,0x1b052ec,0x066688e,0x1a40eaf,0x1d75b71,0x02e2f2e,
  43938. 0x09df61d,0x10ff7fe,0x178fde7,0x0d5a991,0x06192e3,0x18be902,
  43939. 0x18b6c54,0x04e9fb4,0x0c9fa7a,0x0cc8a3c,0x093e0b7,0x1809d92,
  43940. 0x1a64971,0x0e8f1c1,0x0efec16,0x1d44c41,0x03b4450 },
  43941. { 0x176dcdb,0x1d4aae3,0x091cf6d,0x1903917,0x15c4a57,0x0bb07d9,
  43942. 0x1400d41,0x0a75c50,0x1b3aec3,0x1f40348,0x05ef978,0x0b7c8e2,
  43943. 0x0138033,0x02b667b,0x111f8e8,0x0f22dc3,0x1eb3397,0x0929e7e,
  43944. 0x172dfb8,0x19bf75e,0x17043de,0x07be7a5,0x1cf25e5,0x1f028c5,
  43945. 0x1680c9f,0x14f9200,0x06f8f6a,0x1c881c2,0x191d8a4,0x01bbb4f,
  43946. 0x1771741,0x196bd38,0x106c7a8,0x1e926a0,0x0684ced,0x0432321,
  43947. 0x1764b4a,0x09e41c1,0x0d853a2,0x0198853,0x04a7fe3 } },
  43948. /* 56 */
  43949. { { 0x055c7c5,0x19d3812,0x1d539e3,0x10e02ae,0x1b7636e,0x1193162,
  43950. 0x11491d8,0x18fe658,0x01bc780,0x04c588f,0x1b61dcb,0x1d5922b,
  43951. 0x14d48ea,0x0cc932f,0x0134f00,0x0401f76,0x19bcfa5,0x035a958,
  43952. 0x0fa8ffa,0x1413032,0x0059c46,0x1edd3ac,0x160b1cc,0x12d5599,
  43953. 0x0bbd618,0x0a8e992,0x133a3b3,0x181345f,0x1c44b3a,0x0c7e817,
  43954. 0x12d4a64,0x15542f0,0x0c45e4a,0x1042e78,0x0d03f88,0x026ac4c,
  43955. 0x050c7d6,0x05db3b6,0x1ac8d4f,0x146ca24,0x083fa1e },
  43956. { 0x0ccc646,0x0436d08,0x07a582b,0x1ef608a,0x0ce0637,0x0443081,
  43957. 0x1d8c228,0x1057779,0x1203499,0x1e0c80c,0x0f36808,0x0739f81,
  43958. 0x1d707fc,0x0dea7eb,0x1347c54,0x07776fe,0x0744471,0x06b5327,
  43959. 0x16b2798,0x1b8ced8,0x116957b,0x019bdb0,0x115b14c,0x1e8143a,
  43960. 0x11396dc,0x163e9a2,0x15265f4,0x07dbd84,0x04a739f,0x14d2616,
  43961. 0x1894d2b,0x0d4d5a5,0x001397e,0x0afc08a,0x15348fa,0x1e40ed3,
  43962. 0x1e98fab,0x1003e36,0x147833b,0x0f32638,0x0614097 } },
  43963. /* 57 */
  43964. { { 0x1156623,0x1996d8a,0x1f08f76,0x1956f4c,0x08137fb,0x0cf1e13,
  43965. 0x07d41bc,0x0c24c02,0x089924c,0x010c581,0x013070d,0x161f8d0,
  43966. 0x07492a0,0x17d5735,0x16f9c1a,0x17cc3ac,0x03e0d01,0x09d89e9,
  43967. 0x01fd31a,0x08b68ff,0x1aa3445,0x11026e0,0x15088db,0x0a2c3d9,
  43968. 0x1261d3c,0x003b09a,0x0ef622f,0x1d68d4c,0x19d7201,0x0c1b0ac,
  43969. 0x1cde31b,0x0d375e1,0x0955fe1,0x194107b,0x0f585c1,0x148cfdd,
  43970. 0x1e3a340,0x0dc5151,0x17e20bc,0x0ec5a16,0x0636dac },
  43971. { 0x0c80af3,0x006dcda,0x0aae50a,0x029c712,0x1a189cd,0x03beee4,
  43972. 0x00b8345,0x09e4dce,0x068f9f1,0x08d771c,0x0a82cba,0x0c75017,
  43973. 0x092864f,0x05b8a51,0x1607dce,0x0f96d59,0x070c5fe,0x09870dc,
  43974. 0x0420dff,0x1d43876,0x089f883,0x09b5902,0x0b689e5,0x145b4be,
  43975. 0x12a6858,0x10a1d75,0x080ea3e,0x046617e,0x10b1c4e,0x045aee3,
  43976. 0x1d2d712,0x0532cf1,0x078c4d9,0x1b3ae05,0x0260977,0x104677a,
  43977. 0x1b67d36,0x1ae03b3,0x1bcfcde,0x1fc9a17,0x02f6dbd } },
  43978. /* 58 */
  43979. { { 0x04da7c7,0x0397e97,0x04c8be1,0x035ccef,0x108cfc9,0x0134713,
  43980. 0x1c228f7,0x0486c95,0x0799a24,0x1886ff0,0x162ffc3,0x1ab0e3a,
  43981. 0x06ef912,0x0c44b17,0x1cd77f2,0x1d414d7,0x1a95f47,0x0945cb7,
  43982. 0x0b4c230,0x14f3d55,0x1bba734,0x1bcfa1b,0x055cc0c,0x1ea9eeb,
  43983. 0x0bd8e6c,0x1760016,0x1f9d8cb,0x0ec0db9,0x1931044,0x0f65a98,
  43984. 0x075012d,0x0159ee5,0x0e0897c,0x0f8ef05,0x0e18ef7,0x1112c51,
  43985. 0x187d744,0x168aa77,0x1753bb3,0x12e8b1a,0x05cb6e1 },
  43986. { 0x08c75ed,0x178cb80,0x0be2633,0x1deddd5,0x1cf49d3,0x1af4b6b,
  43987. 0x0780861,0x1143adf,0x0dd9b0d,0x076167f,0x1db6abf,0x19fd72a,
  43988. 0x1838a61,0x1b53edd,0x000fce4,0x029e820,0x06823b8,0x1d9be1c,
  43989. 0x0038c54,0x0cdb977,0x07a89fb,0x1d02cc2,0x079f8ba,0x14e4ee1,
  43990. 0x063fd35,0x1685276,0x07f2783,0x023e7b2,0x15baa43,0x004a6a8,
  43991. 0x18cf077,0x14119a9,0x1a06ebc,0x0f7553a,0x08e0bb5,0x1f56c2e,
  43992. 0x01f52c1,0x015dd87,0x15b94ba,0x060a2eb,0x02149d6 } },
  43993. /* 59 */
  43994. { { 0x19311f6,0x14737af,0x1e17b86,0x1f75783,0x097e3c9,0x0a104d6,
  43995. 0x114bad2,0x1c29f4f,0x019774f,0x0617a8e,0x16113c1,0x02450aa,
  43996. 0x135cefd,0x1ac39d5,0x0e18a8e,0x033f96a,0x1d6cbed,0x13b477e,
  43997. 0x19611a6,0x0248f3d,0x009ccdc,0x189ec06,0x0448df8,0x0898518,
  43998. 0x0a290c0,0x143eeba,0x0af51f8,0x1dcca2f,0x0ffeef9,0x0914568,
  43999. 0x07f0908,0x1031a50,0x073088f,0x006f0a1,0x12f10fb,0x07d78e8,
  44000. 0x1415bd7,0x137667d,0x109b16c,0x0a1960f,0x014e2f3 },
  44001. { 0x016946b,0x0950821,0x04b5523,0x0ef497b,0x0e801f0,0x14a8b03,
  44002. 0x1428d0d,0x192b32d,0x163a197,0x18dae17,0x1ddf243,0x189e0c3,
  44003. 0x0279da3,0x09ffbd9,0x07358d2,0x0247e38,0x050a234,0x02f30db,
  44004. 0x0a100cf,0x16698be,0x0214826,0x146179a,0x1c62e43,0x100dd8a,
  44005. 0x15620ae,0x0da52f9,0x178c92a,0x05f5c68,0x13cb51a,0x1caf45a,
  44006. 0x1e2302e,0x1f32cae,0x14f6ac2,0x0f79964,0x01f5ae7,0x0e0fd8c,
  44007. 0x10ed8f2,0x1f8edd6,0x0793d8e,0x005b96c,0x058537e } },
  44008. /* 60 */
  44009. { { 0x0f80ba2,0x0583232,0x116c7d9,0x0e0ab34,0x08e055e,0x1a5b1a7,
  44010. 0x0acd3c7,0x105864c,0x1de8c84,0x1a7beaf,0x11e02bb,0x1d41861,
  44011. 0x139d55d,0x07d0f34,0x102bee7,0x186962e,0x0667460,0x1167f35,
  44012. 0x061f07b,0x12b2822,0x0d94f66,0x1bafcba,0x04e0bc9,0x08a93d6,
  44013. 0x0ace400,0x0810e50,0x1eeaf7b,0x1048967,0x1653eaf,0x0683271,
  44014. 0x00f0dbd,0x18ab8bf,0x0b9f0dc,0x1e74875,0x13beb3a,0x0bb2773,
  44015. 0x1906142,0x12c7390,0x05c3459,0x0bf05af,0x0485783 },
  44016. { 0x0576210,0x092de69,0x110f735,0x0faa36a,0x1f378aa,0x0c1cca4,
  44017. 0x0fc5c6f,0x043fd2f,0x1f38ac6,0x18687b1,0x1023324,0x182f030,
  44018. 0x16af8f2,0x1307a9f,0x04b21f8,0x0ebc84d,0x007db0a,0x187722a,
  44019. 0x1f6c6cd,0x08f5cbf,0x044b0ec,0x0e3d535,0x1da44a7,0x0816eba,
  44020. 0x132b22e,0x1bbdb7c,0x0257bce,0x00cec9a,0x1c63e8e,0x03fab45,
  44021. 0x100a3f5,0x1380029,0x1810494,0x0aec768,0x0ff75e6,0x1f21c5a,
  44022. 0x0c2a85a,0x1cd02eb,0x0c4a3ac,0x17b443e,0x06c0277 } },
  44023. /* 61 */
  44024. { { 0x109e7ef,0x1b8435a,0x1e47906,0x167aff3,0x0842ec7,0x135c45c,
  44025. 0x17e5154,0x1579a50,0x0051dd0,0x1227032,0x1c73adb,0x1820ee9,
  44026. 0x1b90198,0x091f330,0x12afa60,0x08fb2dd,0x13632f6,0x1224088,
  44027. 0x1b14abb,0x10568a4,0x09d51dd,0x1fc9cee,0x1594241,0x1a8ab7f,
  44028. 0x0eef2fc,0x0be5eaf,0x1634b97,0x102b49b,0x1c9f2a7,0x1649445,
  44029. 0x0896b53,0x0af4766,0x0f10d0b,0x0e5ede3,0x079c82e,0x11d1a18,
  44030. 0x1b774ee,0x05838d4,0x13e3d68,0x135e45f,0x03067bc },
  44031. { 0x1ca9326,0x0c4f95b,0x1d8f839,0x1b62449,0x17a106f,0x1d2bde8,
  44032. 0x11485d1,0x05d646a,0x162b088,0x10a4c16,0x07ff3c9,0x0a88872,
  44033. 0x0d7f3af,0x1427220,0x0a8cdee,0x160e235,0x1b0941b,0x014751b,
  44034. 0x1929fd5,0x0fb9685,0x15fba95,0x160d356,0x19ead98,0x186d441,
  44035. 0x1e381f7,0x1b5e89a,0x126ea82,0x05cf301,0x04671f4,0x01864a7,
  44036. 0x18d08dc,0x1161245,0x0cc63ff,0x12c4f92,0x09e5116,0x19a21aa,
  44037. 0x0870ff6,0x0ce98b5,0x10656ee,0x195532d,0x0390c83 } },
  44038. /* 62 */
  44039. { { 0x1c4a73f,0x1fd417f,0x0c0d434,0x0a77aa6,0x0665d63,0x05dbbe9,
  44040. 0x1be2899,0x1090140,0x022d73d,0x0e02537,0x0ee2aa0,0x1fea064,
  44041. 0x1a2409c,0x062626a,0x173885e,0x1383263,0x00e0c0f,0x01ba554,
  44042. 0x0061aee,0x0b470e0,0x087f0b2,0x085578a,0x142dde8,0x0931bc3,
  44043. 0x19ad5ab,0x08b0af9,0x186a830,0x05c65b4,0x025ce89,0x1edecb7,
  44044. 0x1448a38,0x0bd0c8d,0x17c88dc,0x18e345a,0x059099e,0x0ace562,
  44045. 0x000bdec,0x06c03fb,0x15ce974,0x0fa447c,0x03ea400 },
  44046. { 0x195d0a3,0x0f5e852,0x0ed35db,0x175fe16,0x06bd76c,0x0dedcbd,
  44047. 0x0553e6c,0x0e37e58,0x04c714c,0x158cd5a,0x0bd98d8,0x0772443,
  44048. 0x16c9bf3,0x064a0f7,0x161f126,0x01eda47,0x0c3d79f,0x092ac02,
  44049. 0x09eb2f0,0x14200a5,0x08af6f1,0x0caa829,0x176ade7,0x1a2c426,
  44050. 0x1a6f0c8,0x014febb,0x1779784,0x00a116d,0x1da12b4,0x00797ca,
  44051. 0x087656b,0x0eb1517,0x060af71,0x0647dc4,0x120dc58,0x0816329,
  44052. 0x0e004d3,0x0736406,0x0aa8290,0x02ed629,0x009f82a } },
  44053. /* 63 */
  44054. { { 0x01366dc,0x1f2c461,0x0be582a,0x1f5eebb,0x129c0a4,0x1c9f6a3,
  44055. 0x07f66b2,0x0e0e0a0,0x087a16d,0x0bf3a27,0x1cd86ee,0x14f531c,
  44056. 0x13a42e0,0x145aa67,0x136bfc8,0x120f035,0x0bbb7bd,0x1f843e6,
  44057. 0x18c9439,0x1e7306c,0x1c09da6,0x175d783,0x19b5a4f,0x175e2ae,
  44058. 0x0f4c38c,0x0e83cdd,0x1f7f2a6,0x15309c0,0x0d8dab5,0x1923f93,
  44059. 0x1e6ad34,0x0fd746d,0x10be701,0x0e90b26,0x19943a3,0x066f773,
  44060. 0x131c4f0,0x1527122,0x16169ca,0x1096ea7,0x077d1e9 },
  44061. { 0x0e62367,0x1991cec,0x13c764d,0x1773041,0x1361848,0x0e4be21,
  44062. 0x18d116a,0x1f8018f,0x014f960,0x10764d7,0x11d2d66,0x019ee80,
  44063. 0x15cf41f,0x167032e,0x1bb7a3f,0x10c214b,0x04e9e80,0x0d8ef2d,
  44064. 0x1833dd7,0x0895c95,0x0d0b17c,0x11b58a4,0x0be958c,0x13fe5b8,
  44065. 0x0740fd2,0x097327d,0x0a232c8,0x0c0bd71,0x063016c,0x18d6b54,
  44066. 0x05fcb1d,0x0c0f698,0x16112e7,0x04bc2b6,0x101d035,0x0bfd21d,
  44067. 0x0256e0e,0x0df0c5f,0x0b6c166,0x1d994a9,0x04e6eab } },
  44068. /* 64 */
  44069. { { 0x199cfe6,0x191e9fd,0x05e2540,0x0d92668,0x1b09bc2,0x1efdb7b,
  44070. 0x07905f2,0x0c0c822,0x089a757,0x08a0ba2,0x0672c24,0x1bf2212,
  44071. 0x0f4c633,0x1cb5fe9,0x17f1f1c,0x0c5b6e2,0x1128cab,0x04650ca,
  44072. 0x16e06ab,0x0e48e69,0x054a306,0x15da626,0x199e891,0x0452c8d,
  44073. 0x0a0fabf,0x0b86bbf,0x07e96d7,0x17da2be,0x1192f35,0x16d2e17,
  44074. 0x0b695a1,0x0fecd21,0x0cac72a,0x085beef,0x0a8b2a9,0x1e1895e,
  44075. 0x0049ad2,0x0318e0b,0x1c15bd1,0x12c09d9,0x0325d27 },
  44076. { 0x048c144,0x0fdaaa4,0x1ccbb84,0x0b6d4f5,0x0e06292,0x0f07cd2,
  44077. 0x1a384da,0x03c24b6,0x0ca53b2,0x0cded73,0x03a86eb,0x00b85d3,
  44078. 0x15f50d6,0x0f97d1c,0x0e7854e,0x065eb7b,0x12de915,0x1a2b871,
  44079. 0x1a89435,0x0d315c8,0x1145810,0x1656cec,0x1ff6551,0x1d2f4bc,
  44080. 0x0772111,0x174d5fb,0x14927e0,0x1453efa,0x11df63c,0x1cd4cc2,
  44081. 0x196a714,0x0e3a1c7,0x184d54b,0x095ab7e,0x1670107,0x15a3c08,
  44082. 0x1d80096,0x19f5b77,0x1e74f3a,0x08dc654,0x019d485 } },
  44083. /* 65 */
  44084. { { 0x140f5e5,0x0f747da,0x145ff86,0x1e09cd1,0x06d2a52,0x1ee438c,
  44085. 0x036c2b6,0x191a464,0x0d03a7f,0x01d6ad4,0x12e45aa,0x078e117,
  44086. 0x0054bf8,0x1728f42,0x084cfa8,0x1bbbe12,0x024cb52,0x1de71c2,
  44087. 0x0418d60,0x0f7c806,0x1176d5c,0x0fa2c71,0x107aee7,0x09b577f,
  44088. 0x19639bc,0x0d457d8,0x13015c9,0x0c6a1fc,0x01cd243,0x031a427,
  44089. 0x17ab128,0x1828b71,0x1f73154,0x0191bd6,0x167acd2,0x00154db,
  44090. 0x0bff272,0x1a2e1ee,0x14ec28c,0x0d969c8,0x01b3ace },
  44091. { 0x0a8bdc5,0x1f2f4c8,0x02240d0,0x1ac60d4,0x0203bf9,0x0429075,
  44092. 0x068d639,0x00d3091,0x0de7d1d,0x08bef5f,0x0574fef,0x0daebef,
  44093. 0x1f8fafa,0x1c3d851,0x13ad8c0,0x1d5f549,0x132ffdd,0x1700b35,
  44094. 0x19d9380,0x1c40a8f,0x1304a2f,0x127438f,0x156ae60,0x05d88bc,
  44095. 0x136bb95,0x065515e,0x12a4348,0x1698290,0x1cfb537,0x19c3bad,
  44096. 0x1954c67,0x0d30589,0x0238a4a,0x1490e9a,0x071e840,0x1d4576c,
  44097. 0x1b3ab17,0x030db26,0x0285078,0x07c325e,0x0538ec3 } },
  44098. /* 66 */
  44099. { { 0x19b56cf,0x04b7f50,0x0b3464d,0x08f7733,0x063d77f,0x085440b,
  44100. 0x0bea15f,0x1fb1e09,0x0082835,0x0769ed1,0x0b3b1f3,0x15dabb0,
  44101. 0x057e21f,0x1c004e4,0x05d6e67,0x1460edc,0x11b2d05,0x16ce371,
  44102. 0x0521f60,0x091a950,0x0655969,0x196a37b,0x01baf4f,0x0799893,
  44103. 0x11aa877,0x0534342,0x0a2c590,0x1c441e4,0x020b753,0x11d420d,
  44104. 0x1be7c1b,0x1215814,0x0fffe5e,0x159fd96,0x076a3af,0x13eb536,
  44105. 0x0e08e2c,0x03eccbb,0x1d00496,0x13007d3,0x06fd602 },
  44106. { 0x0b7516a,0x04fc6c7,0x02ad51c,0x097b8b3,0x03058a7,0x1400e74,
  44107. 0x176621f,0x12da469,0x0d17b8a,0x087cec8,0x03daaff,0x093edd2,
  44108. 0x1baa1e5,0x0d3f6aa,0x05bfe01,0x0983249,0x17a6c25,0x086cfb2,
  44109. 0x025895d,0x1d49397,0x07de3cd,0x1816ff9,0x0da168f,0x1178097,
  44110. 0x0e7fddb,0x1581e28,0x1e61c8d,0x009fe1f,0x0d50559,0x0c7edd8,
  44111. 0x141250a,0x1c297d1,0x0b3386d,0x0986b1a,0x1a71f0f,0x12f5a69,
  44112. 0x0159fdd,0x15995ef,0x197007c,0x0798ec3,0x084cfa2 } },
  44113. /* 67 */
  44114. { { 0x199b964,0x008f5c5,0x111c4ef,0x14b1c5f,0x0e280c0,0x04d2a5c,
  44115. 0x0f12753,0x1f50e1f,0x0bf6e20,0x1d19a51,0x0233e8d,0x1a1baf9,
  44116. 0x1aee583,0x17a578e,0x180a6a3,0x1f14c0b,0x0340c2e,0x136aaf1,
  44117. 0x027a6d8,0x0dfbfc4,0x080f61b,0x135dc70,0x0ec76b4,0x125f834,
  44118. 0x1c16293,0x1a72d6d,0x182ab8f,0x05581fc,0x1f4d5b0,0x000d615,
  44119. 0x14a3666,0x18505fd,0x133f93f,0x0d99f91,0x0432d4b,0x0e2db96,
  44120. 0x055752e,0x1c87c26,0x0363827,0x0a39094,0x0287d4c },
  44121. { 0x09867da,0x0c10087,0x13697e9,0x06350e9,0x014589b,0x0f71173,
  44122. 0x09f17ef,0x15000bc,0x1e612bd,0x1abff7a,0x18d7e78,0x1dbe5a6,
  44123. 0x064e0db,0x17892d4,0x0f9c391,0x145cac5,0x0840d94,0x0d04dcc,
  44124. 0x02d7974,0x13342a5,0x08b57eb,0x173a881,0x086e505,0x0da5988,
  44125. 0x17fd7e0,0x0228d89,0x1ffa826,0x1f43ea2,0x0ecbd76,0x14b37fe,
  44126. 0x0f8ee87,0x1065e8a,0x0c89a4a,0x147d0ea,0x0abfb29,0x060f63c,
  44127. 0x0bd395a,0x1da229a,0x0784f43,0x1b9b1df,0x00132a3 } },
  44128. /* 68 */
  44129. { { 0x16374c2,0x03bc2ab,0x010394f,0x0308e4e,0x060526d,0x0650227,
  44130. 0x1b7208a,0x027140c,0x0f1ce13,0x1f0e0d9,0x0c31747,0x10659bd,
  44131. 0x0f2aeec,0x0e5fc13,0x1659a66,0x14b134e,0x081de77,0x0668c47,
  44132. 0x0634495,0x1c1fc02,0x186ae5c,0x0203c85,0x0850aa6,0x158519d,
  44133. 0x1043f39,0x0027147,0x021f796,0x1ddf052,0x19a8c54,0x0d997b1,
  44134. 0x13e0f0c,0x0b10ef2,0x10454a7,0x0d9c8eb,0x154062c,0x0b94c6b,
  44135. 0x11d9c79,0x1f503b1,0x0a8973b,0x0ed6df1,0x013cbee },
  44136. { 0x13f34f3,0x15f07c6,0x1f8de72,0x1946c2f,0x1da9c31,0x0a1350d,
  44137. 0x1b88f76,0x00964db,0x1f29c91,0x0eecb13,0x1b34efa,0x02d3c58,
  44138. 0x16033eb,0x1e5d10c,0x1cfd24b,0x1907914,0x00bb858,0x1c971bf,
  44139. 0x0ecfeed,0x05594c4,0x00a2e4f,0x0f325f0,0x00407ec,0x11ec891,
  44140. 0x1826a94,0x073c8d3,0x1241c98,0x0280cf6,0x0bb8354,0x1528718,
  44141. 0x1bbddd2,0x1933380,0x122ca80,0x04288fc,0x16e42e8,0x00d70c6,
  44142. 0x05fa04f,0x09b5ae1,0x0259efe,0x1b5c05d,0x04e0a1a } },
  44143. /* 69 */
  44144. { { 0x1a29c4d,0x1333845,0x0250032,0x1c45310,0x008240c,0x0ed3a96,
  44145. 0x1299c5b,0x068438b,0x1abbbfa,0x04e0722,0x0a2dc9a,0x0bfa7da,
  44146. 0x141d754,0x0be2b55,0x0884663,0x13acabe,0x1743875,0x0a59ec7,
  44147. 0x1f942e2,0x121bf71,0x1a16934,0x0bf4075,0x0d907d7,0x1596a6f,
  44148. 0x1a5eb79,0x12f3d86,0x1c30757,0x16d6292,0x1a429aa,0x1346d2e,
  44149. 0x0948ce3,0x05eda5e,0x010c437,0x079d3f0,0x1b4994c,0x1844de2,
  44150. 0x0bef08b,0x187bdb6,0x12667be,0x1b33f33,0x0733e30 },
  44151. { 0x02a38f9,0x10ac152,0x1403b3f,0x1c8e616,0x0ec2d58,0x0bb5965,
  44152. 0x1ca9f7a,0x1765dc5,0x1a969c1,0x029ceda,0x136d2bc,0x02d1f9d,
  44153. 0x0231954,0x13d4748,0x1dcd22b,0x0a83fe5,0x1cc3121,0x10eac6b,
  44154. 0x080ab94,0x0b6eb84,0x15a75d2,0x0d7a041,0x17aa659,0x1369c8d,
  44155. 0x16a4152,0x0cd9ff5,0x1ef49eb,0x192ff6d,0x1f900b5,0x0a60130,
  44156. 0x07b61d5,0x009ab63,0x03031d9,0x0cdce5a,0x06e32c8,0x1e67abd,
  44157. 0x1ee00bc,0x01ea491,0x17031e9,0x0736f34,0x056facb } },
  44158. /* 70 */
  44159. { { 0x1018bfa,0x0b2d151,0x0610064,0x093ff5b,0x100c6b2,0x1a0d4d8,
  44160. 0x0c7d954,0x19377e3,0x125dc4c,0x15e8ecb,0x1ff9839,0x1daa57f,
  44161. 0x0b52850,0x1f2a84d,0x1a64b31,0x0b3e249,0x02e4ceb,0x07fb628,
  44162. 0x0a9f452,0x166ae63,0x0a462f0,0x0ef3f1d,0x1a43077,0x0285101,
  44163. 0x09f45d1,0x0eadd76,0x1996f97,0x0eb9fa4,0x0bce134,0x18a70ff,
  44164. 0x0c20eae,0x101285a,0x0ba4829,0x1416435,0x0d74a5f,0x1a3c364,
  44165. 0x10d8218,0x18e6df2,0x1b2eedd,0x0cdb29a,0x0885992 },
  44166. { 0x15ccaf2,0x039480a,0x1cf8221,0x0ef8b6e,0x0679ebc,0x0e8476c,
  44167. 0x0b746cb,0x1b75116,0x087d475,0x1050c07,0x1340aa5,0x0d6ecd2,
  44168. 0x1680fdb,0x1f9fcf4,0x01d6324,0x06d887d,0x0fa4ad8,0x0ded1fb,
  44169. 0x0bece1f,0x018b026,0x000f940,0x0112a81,0x0969e15,0x0dd9e30,
  44170. 0x1c35177,0x0cd154b,0x1959b6d,0x07d7e8d,0x145eda0,0x1140132,
  44171. 0x1111d0e,0x19ee956,0x1169d84,0x19fb4f6,0x0c76232,0x0d75572,
  44172. 0x1825719,0x1749966,0x05c65c2,0x14d4181,0x0797224 } },
  44173. /* 71 */
  44174. { { 0x01f3567,0x091fc22,0x1c758ca,0x105c497,0x011c316,0x138fffe,
  44175. 0x1c9aedd,0x044972e,0x17a5e1a,0x00ba353,0x16d05d8,0x1d4075b,
  44176. 0x0653ddd,0x1facdc2,0x019e8f1,0x0ffeeaf,0x18756cd,0x0580954,
  44177. 0x066ea6a,0x0bfd93e,0x07481bd,0x117c183,0x1d40de6,0x1180ba2,
  44178. 0x1445dab,0x0153bb1,0x0de40fd,0x1afe883,0x03e46d5,0x13a6d48,
  44179. 0x1070045,0x15ba24d,0x11d3c4d,0x0ada00d,0x0ab1851,0x1d44ea5,
  44180. 0x155c356,0x1215342,0x014b136,0x02bb041,0x03ff09c },
  44181. { 0x1cb7784,0x10de77c,0x0c15302,0x184845e,0x0ec539b,0x00a553d,
  44182. 0x1e7f431,0x188be81,0x0ffd42b,0x1d518b6,0x1638574,0x09865e6,
  44183. 0x0242f5a,0x0b713b4,0x0f7367b,0x1d9dc01,0x09ff8a5,0x0834fbc,
  44184. 0x17853d7,0x10031c0,0x0741807,0x09c5a06,0x0aecf92,0x02fee5a,
  44185. 0x08c1d79,0x0862ede,0x13315c5,0x01dd4cc,0x1a8920e,0x062d61f,
  44186. 0x192897b,0x038f2e2,0x021b0f5,0x168b59e,0x0bc98d2,0x151e134,
  44187. 0x18391d9,0x1987e2a,0x0b93239,0x00a9fbf,0x047ef18 } },
  44188. /* 72 */
  44189. { { 0x1a285e4,0x0f9e89e,0x0fd2659,0x147403c,0x1a7d4db,0x10a5685,
  44190. 0x104e984,0x0928e70,0x1223975,0x1dbea9a,0x0c2e4b4,0x1b9eb4e,
  44191. 0x1da53db,0x19968b2,0x0c364ac,0x0fde862,0x14182f9,0x1225142,
  44192. 0x137386d,0x0444388,0x0ec9bf6,0x0c3f150,0x0ee84e1,0x1f5b331,
  44193. 0x12c8dcb,0x02599f9,0x1ed7fb5,0x013cbe7,0x0217bb4,0x0632e33,
  44194. 0x0a570ca,0x1f9bee3,0x00db69f,0x103c458,0x0886e24,0x1744785,
  44195. 0x1ae6464,0x1594731,0x02187e2,0x13971bc,0x01a6b6e },
  44196. { 0x0af77aa,0x1615b03,0x0196bdb,0x1b510fe,0x0e60f5c,0x04c62b1,
  44197. 0x050027d,0x0970fa4,0x1fcbaaf,0x1acadac,0x0ae1576,0x05424e3,
  44198. 0x0c0fb59,0x0a1a4d8,0x1384397,0x1193941,0x1d8887d,0x1ceb0c3,
  44199. 0x152f5b6,0x1d2bf22,0x099903e,0x09ae836,0x03f94c8,0x0d4c9a1,
  44200. 0x1bc30fb,0x1b07a53,0x159a932,0x1a455e1,0x17367c3,0x1677ae9,
  44201. 0x1545a54,0x132fb1c,0x10ea734,0x1996837,0x1c3dcc5,0x05688f8,
  44202. 0x09cb394,0x15981a5,0x03f4002,0x10050a2,0x079dd01 } },
  44203. /* 73 */
  44204. { { 0x0c7424e,0x0019d1d,0x1340138,0x10c1fb4,0x1b06b68,0x1bb97de,
  44205. 0x05d9af2,0x14846d5,0x1f297cd,0x0a54715,0x04f1b8a,0x170bb60,
  44206. 0x0d4b0aa,0x0391d1d,0x0abb262,0x094d67a,0x0cd13c8,0x1065719,
  44207. 0x03b05a7,0x111ebce,0x0262218,0x1ea1544,0x1ce58ce,0x0c1b370,
  44208. 0x0792e7b,0x1f0b456,0x0841da7,0x13e56e4,0x0bed348,0x07f3692,
  44209. 0x0aa3cff,0x147d649,0x15efb88,0x03835e9,0x08fd213,0x1bbbd9f,
  44210. 0x129ece0,0x008cd4c,0x150d9f3,0x08b1a80,0x087e5ad },
  44211. { 0x11000a7,0x0d54ebe,0x00ceea6,0x195d047,0x0b94aff,0x1c1ee2c,
  44212. 0x058a37e,0x11b9045,0x1845a41,0x1acff08,0x05c150b,0x01f0ba8,
  44213. 0x01a8b97,0x195b8ac,0x0630995,0x1ba2f12,0x17dc0d1,0x07277a3,
  44214. 0x0beb5f0,0x1699e67,0x0a5bb50,0x1c80c38,0x086eba9,0x07450d0,
  44215. 0x087f9bb,0x0e6e3b8,0x1849296,0x10aea63,0x1432397,0x0137abf,
  44216. 0x12bb5d3,0x002c992,0x1f5ae25,0x05fba6a,0x1f8bc25,0x04cc116,
  44217. 0x1dceea3,0x06dadd7,0x10117d3,0x0333219,0x00b7125 } },
  44218. /* 74 */
  44219. { { 0x0d5c64d,0x08650c4,0x14d168a,0x134e924,0x0596d74,0x0074928,
  44220. 0x034f4a8,0x0d74096,0x0caf7b6,0x0166816,0x17b60c2,0x0185d9b,
  44221. 0x0e912b5,0x1f98b23,0x0f3a77b,0x1ff2b02,0x0c7c75f,0x0b15738,
  44222. 0x18a9185,0x10a5c0f,0x0fd16f6,0x0801c02,0x0c83f5f,0x031d1b2,
  44223. 0x0a4dd82,0x0ebd8d1,0x0ebf191,0x12314df,0x19fdbe4,0x07d0f46,
  44224. 0x1bbec20,0x088e16d,0x1d4d08a,0x1a77b99,0x01ddb65,0x05a5744,
  44225. 0x09dae5d,0x05cad3b,0x165b63b,0x074fad2,0x07a3f42 },
  44226. { 0x0929387,0x096534d,0x1ffcd8b,0x0396383,0x0bdb758,0x08db65d,
  44227. 0x1b27df9,0x03fb125,0x03a4e13,0x146c319,0x01d587b,0x07e2b7b,
  44228. 0x124680e,0x0a73f39,0x0965f87,0x1fdfdc7,0x17c5581,0x19e6395,
  44229. 0x0a32b82,0x0eff159,0x14aff3e,0x0e2f17e,0x1f31f5f,0x06ab6f3,
  44230. 0x0455221,0x0bbee9d,0x0a8b01c,0x08d649e,0x09621f5,0x0996834,
  44231. 0x0f9056d,0x07ef02c,0x1e9af51,0x1f69095,0x0e6ccf5,0x064fac7,
  44232. 0x1680294,0x00cf794,0x1ebd2ac,0x0aa2c47,0x02da5fc } },
  44233. /* 75 */
  44234. { { 0x0a5c600,0x14e79e4,0x19f1890,0x047fc67,0x07a80c2,0x0beee5d,
  44235. 0x09d0029,0x0e93ffb,0x1925b0c,0x0d70ab6,0x003ac34,0x07f2d62,
  44236. 0x01097a4,0x17ca1e4,0x07a5173,0x19e482d,0x0e51128,0x1d0fb9a,
  44237. 0x067c04c,0x10f8948,0x0024043,0x0580822,0x1001e1a,0x06b39e5,
  44238. 0x16abf90,0x071f2a0,0x191e355,0x138edfd,0x02173ef,0x0ed3215,
  44239. 0x1059886,0x13fc602,0x1e03156,0x1923f30,0x138e4fb,0x0541feb,
  44240. 0x072b659,0x0bc95d0,0x1534e04,0x032e190,0x0855f02 },
  44241. { 0x07314c4,0x1fdb642,0x05a987e,0x0bd68b7,0x1790615,0x1157d64,
  44242. 0x18519ae,0x102e205,0x1ab9497,0x0a8fcba,0x0313fbb,0x162f822,
  44243. 0x079d2f5,0x17fabb3,0x12339c2,0x089cef5,0x0216eb2,0x1f39b35,
  44244. 0x1471971,0x1779d8a,0x19dedd1,0x0570d42,0x0d49418,0x14fa5cf,
  44245. 0x081748b,0x0623d02,0x06ae3aa,0x03458a8,0x1ff078e,0x1261b7e,
  44246. 0x011b9e0,0x0290e96,0x1b49fc7,0x0fb99bc,0x0dfc1ac,0x1e455c6,
  44247. 0x0f8fe6c,0x1a90c93,0x01e5c70,0x19ea4ba,0x0292236 } },
  44248. /* 76 */
  44249. { { 0x18b29dc,0x06c053e,0x122b36e,0x0811d4c,0x117a202,0x095f48e,
  44250. 0x0b17aba,0x178fb62,0x0fda72f,0x19a3e8c,0x1831bc7,0x16813ce,
  44251. 0x1111374,0x0c71c6c,0x187a3c7,0x183e8e6,0x09d739a,0x13b8a5f,
  44252. 0x137d713,0x12e0396,0x0ae1c1f,0x0c37b96,0x1644e3b,0x1a30189,
  44253. 0x1e1f76a,0x1ce0e3f,0x1a78b6f,0x11830b7,0x10c44df,0x1934be3,
  44254. 0x17e0d76,0x161a2b6,0x197cfea,0x12a2f7c,0x1169879,0x1ca2028,
  44255. 0x05184e5,0x1834421,0x19ea85a,0x0b2ea43,0x07cfac3 },
  44256. { 0x00bc53a,0x010b39e,0x0d9e046,0x06fcea2,0x04b5ede,0x12bd0c4,
  44257. 0x157f68d,0x1307944,0x0ba1fdd,0x0b55dfa,0x09df602,0x0d3f8bb,
  44258. 0x059ce83,0x1559a16,0x1ee6b9e,0x0b3e3e4,0x1d69720,0x083648d,
  44259. 0x053b3fa,0x1b56612,0x1f12ee0,0x1dc9fa9,0x0ed91fe,0x14afc1d,
  44260. 0x18a7aff,0x1039861,0x1e7cab5,0x02fa0dd,0x19dcc95,0x06c3ddc,
  44261. 0x08525ca,0x088c101,0x0034af1,0x0e0bed8,0x10fc4ae,0x0199021,
  44262. 0x172a22a,0x12f8a7b,0x00af5c8,0x0fe3bbf,0x06ce3dc } },
  44263. /* 77 */
  44264. { { 0x0397830,0x06c1ad2,0x0c1b01f,0x19e8e66,0x0dd9290,0x0c4f462,
  44265. 0x14ea0a6,0x0a5ba6b,0x1563d81,0x0c812ac,0x17986de,0x1223d0f,
  44266. 0x1cf278d,0x081271a,0x1cd031c,0x01cb338,0x0614a0d,0x096a222,
  44267. 0x0c989a8,0x0ec11fe,0x1aa963e,0x14e264d,0x189e8df,0x1fffa4a,
  44268. 0x0dc5176,0x0e6862b,0x033bca8,0x16dbdf9,0x0559d9c,0x06ab77e,
  44269. 0x04b2f30,0x008396d,0x05f3fc5,0x10f04f2,0x08e7945,0x199a0b8,
  44270. 0x1c3b559,0x198f74a,0x085b4a9,0x04547a1,0x0851511 },
  44271. { 0x0ff19e2,0x0819ac3,0x180de0b,0x143b450,0x02c60da,0x1e3f76e,
  44272. 0x033f955,0x16165cf,0x01bc4e8,0x07b7cc2,0x0d719ea,0x16967be,
  44273. 0x0acc1f9,0x03b2231,0x184d80d,0x1c1612d,0x1977c7a,0x15fc885,
  44274. 0x050d655,0x0fe60aa,0x0ae527c,0x0e7b18f,0x10536c5,0x0d36699,
  44275. 0x161427e,0x1f9528e,0x057f04b,0x1d9050a,0x087162d,0x1709fdc,
  44276. 0x0f7f33a,0x1bc2911,0x0332ac1,0x1f3a66d,0x1388bb8,0x194406e,
  44277. 0x10ae069,0x1f50d0f,0x1b01165,0x1e4ef7b,0x08b1159 } },
  44278. /* 78 */
  44279. { { 0x1961d30,0x18d2217,0x123d2bd,0x10f58e4,0x1df968a,0x148366d,
  44280. 0x1e1f2c6,0x04ba65b,0x004abf9,0x0608713,0x0135300,0x0eb373e,
  44281. 0x1ab8711,0x09cb82e,0x1553982,0x0109201,0x033c9f8,0x0fbac3a,
  44282. 0x09e88dd,0x1575bcd,0x17ac2e9,0x1c4a560,0x159db51,0x005b338,
  44283. 0x0525bc2,0x19ea650,0x16afeb9,0x0b71795,0x05991b9,0x169c1a0,
  44284. 0x10c8dc7,0x08b1533,0x169e47a,0x0643315,0x0c60ade,0x18f9581,
  44285. 0x00232c7,0x1553cdf,0x1d165b3,0x066b11e,0x00bd864 },
  44286. { 0x0734189,0x0d45a3f,0x085f7a8,0x119fcbf,0x12c5ac8,0x01bb322,
  44287. 0x1353845,0x0a08894,0x0af9e97,0x1291184,0x11acef0,0x0187a61,
  44288. 0x1778b1d,0x0636fa3,0x16b97c1,0x11bae5d,0x19a2ee8,0x029898e,
  44289. 0x1324f8d,0x0701dd5,0x0e8ec4e,0x16546d8,0x15266c6,0x0ba93af,
  44290. 0x08c167f,0x06bbb9a,0x1c555b3,0x12cc64a,0x11d13dc,0x0746130,
  44291. 0x1319738,0x16b45fb,0x095fe66,0x07d5096,0x00ca196,0x104cd31,
  44292. 0x11c32c9,0x03e8fa1,0x0641f6a,0x131f9b2,0x0466505 } },
  44293. /* 79 */
  44294. { { 0x14a5efa,0x009e635,0x099531b,0x163a0f6,0x0481989,0x0e34e06,
  44295. 0x19b3a2f,0x1a82172,0x02c2531,0x0a67d51,0x028403d,0x101195a,
  44296. 0x09cb5f1,0x172ed22,0x0d494e3,0x107997d,0x085bedd,0x0531200,
  44297. 0x189571e,0x05b59fa,0x058fe79,0x0310310,0x020dc64,0x02cb183,
  44298. 0x15e83ed,0x0a14b30,0x1df4a35,0x16a9364,0x175df34,0x13edc1d,
  44299. 0x10babc4,0x02ff772,0x160df6d,0x1e49827,0x076fdbd,0x1fa10c6,
  44300. 0x0018789,0x01c7cc3,0x0a0305f,0x0957352,0x00c4357 },
  44301. { 0x120cad0,0x199260e,0x0229dba,0x1318c22,0x10decb0,0x0369b6c,
  44302. 0x14e71bc,0x12f4dd3,0x0bc0da1,0x06cbc5d,0x0b1739b,0x0380a0f,
  44303. 0x155948b,0x02a4bf5,0x151c593,0x029c657,0x00f4d59,0x0154e26,
  44304. 0x1d67c0f,0x18a08d4,0x047e772,0x0534d64,0x19f5cca,0x0916661,
  44305. 0x17d0c30,0x167546a,0x0103dee,0x0c0069c,0x1f1790e,0x08c9d42,
  44306. 0x0da08f6,0x0b90b2e,0x0e9b66c,0x1081153,0x11e99e7,0x0845945,
  44307. 0x09023fa,0x13d0ce0,0x156e403,0x1e24e4d,0x0324999 } },
  44308. /* 80 */
  44309. { { 0x0834915,0x1576b3e,0x193599f,0x1578bd6,0x1f77aa6,0x0b1008c,
  44310. 0x0f2d897,0x184e53d,0x0699fd9,0x1771279,0x153db02,0x10e8571,
  44311. 0x16e1eb5,0x0a64bb6,0x049c430,0x1d4cafe,0x135f6d9,0x0489c81,
  44312. 0x1ad4019,0x16e0920,0x0e4f668,0x07043b7,0x1965a68,0x13b26c0,
  44313. 0x1bf3f2f,0x1e77c80,0x06d2678,0x16350ca,0x1bcaaaf,0x09fdf96,
  44314. 0x0da02e5,0x12e760d,0x12cc566,0x1b63218,0x070cebc,0x0a6a69b,
  44315. 0x10ffd81,0x031d290,0x0ae4791,0x097e318,0x057ea2b },
  44316. { 0x0a0f2f2,0x0f0b145,0x12a803d,0x0a1c8d7,0x0c7e75c,0x116216c,
  44317. 0x11e6a92,0x0052f56,0x014baa2,0x0798475,0x0f30bad,0x1a28d28,
  44318. 0x04a901b,0x176ac40,0x0497fbb,0x01ef976,0x0f99d18,0x0328164,
  44319. 0x1603187,0x0a72322,0x1ee3e53,0x1493880,0x1f89e01,0x14e4e2e,
  44320. 0x040a1fa,0x0a9bd05,0x0931d6c,0x05db9c0,0x0f1c223,0x1305a9c,
  44321. 0x0bb688d,0x17c60fa,0x1511e98,0x1705a26,0x19026eb,0x0e484ed,
  44322. 0x1ff1f30,0x061c93b,0x0d7269e,0x08dd4f2,0x060480b } },
  44323. /* 81 */
  44324. { { 0x072ece3,0x03eb31c,0x03e0c42,0x1b2ab6e,0x1f29be7,0x1caddc2,
  44325. 0x13f1e73,0x0436a16,0x1dbffa6,0x171dac6,0x0ae976e,0x0501c04,
  44326. 0x1c0e61d,0x00c0a24,0x0b9445d,0x0a90af1,0x040cf55,0x1058994,
  44327. 0x03382c3,0x1da36d7,0x1e3d800,0x0abc6ae,0x0d77ff7,0x14ad68e,
  44328. 0x0237469,0x173fbf2,0x0636442,0x0bc646d,0x13c7c7d,0x0950318,
  44329. 0x196dbfd,0x1525bd3,0x02fe20d,0x0885dad,0x1f4f448,0x0683668,
  44330. 0x00c16f2,0x082f6da,0x0233316,0x1a7351f,0x00774a0 },
  44331. { 0x1b6c106,0x0c0d5f1,0x02dceb8,0x1f1bc2a,0x0ebe163,0x1aa41b2,
  44332. 0x0e0bdbc,0x02d9eeb,0x13ac7ac,0x1069031,0x1c8abea,0x0cd0522,
  44333. 0x135c680,0x08aa2aa,0x0507984,0x1c7eee7,0x038bf5d,0x10b893f,
  44334. 0x0bed076,0x1fbe063,0x066332c,0x08c3de4,0x11a24f2,0x0593933,
  44335. 0x06744a6,0x0a3ba82,0x1658b06,0x0d0cdc5,0x0cdf4c9,0x046f9bc,
  44336. 0x0c9227b,0x0680ff4,0x060709b,0x148689d,0x0565544,0x07a6fa4,
  44337. 0x1ab9227,0x11e981d,0x0052e58,0x0a84864,0x0081519 } },
  44338. /* 82 */
  44339. { { 0x17b2108,0x1b6c4fd,0x06abe48,0x195aebf,0x1ecc83c,0x10ed089,
  44340. 0x0ac56d3,0x0c5ef8e,0x10315c3,0x0957577,0x0bf8fd5,0x01dbe4e,
  44341. 0x0811e14,0x03c21f7,0x15e6fda,0x164b733,0x0fd1d9b,0x06735aa,
  44342. 0x0c6eb5d,0x161c42b,0x090db20,0x07adc26,0x1528085,0x14d9d92,
  44343. 0x1bf52fc,0x1b7a2cd,0x167937d,0x06c7891,0x0cf17ee,0x1c276b2,
  44344. 0x120c117,0x1ec55b4,0x002a167,0x06500c2,0x0fcda9d,0x1a593c3,
  44345. 0x1691c42,0x07cea0f,0x0e1d3a3,0x0f18589,0x05abf21 },
  44346. { 0x1b3bccd,0x1cb35f9,0x12a91dd,0x017c7c1,0x0047e0f,0x1ea8218,
  44347. 0x00ece31,0x1f99707,0x1946fd5,0x1bf1dd7,0x103a1f9,0x0f0bd3d,
  44348. 0x0579baa,0x0450c69,0x0f155f3,0x1f9fdb0,0x1af25be,0x0cdcb72,
  44349. 0x031c6d8,0x0ba2bd3,0x0da14f0,0x0d3bf31,0x0207e64,0x1547042,
  44350. 0x0c781cb,0x1fd8e37,0x1795366,0x0a45ecb,0x0d14307,0x0ab9a27,
  44351. 0x16bd741,0x12b95fb,0x035b31f,0x07adf98,0x1d0d8de,0x128fccf,
  44352. 0x1270b9d,0x0fbe56a,0x1a9200a,0x10e9b22,0x015ad15 } },
  44353. /* 83 */
  44354. { { 0x0588ae4,0x1176755,0x08c8037,0x1146e34,0x152ebc5,0x1182222,
  44355. 0x0a4d1c4,0x05ba01d,0x1e4b183,0x1dfd33e,0x07a10eb,0x06836d1,
  44356. 0x0829216,0x10fa717,0x05aeef5,0x13b8a3f,0x08404c2,0x0caa103,
  44357. 0x08c5ff4,0x1c704e8,0x1162c7f,0x0331a41,0x18282bb,0x000309f,
  44358. 0x194d107,0x0c2fe15,0x0ff87ef,0x0e4332e,0x0743520,0x1558fd8,
  44359. 0x049922d,0x188dca7,0x1bbdaad,0x12b7f91,0x147c03e,0x0c1b71b,
  44360. 0x066725f,0x040af5c,0x0658c41,0x194a5d0,0x03f9c4c },
  44361. { 0x0ce637e,0x1594b99,0x1377fcd,0x1beba4b,0x01a15f2,0x0156cbc,
  44362. 0x014b62c,0x1d2343a,0x0cfbab3,0x12f9dde,0x1badd4b,0x17aec29,
  44363. 0x1a60d2c,0x06ad3c9,0x124610f,0x04289a8,0x175cdba,0x1112167,
  44364. 0x02e65d9,0x0e0bcf1,0x0132a20,0x00763bf,0x19384b3,0x035360a,
  44365. 0x14df6b6,0x1ad58e0,0x11d2096,0x1fb2fe0,0x0312238,0x04109ed,
  44366. 0x0365581,0x09a618e,0x0486727,0x17734ef,0x1c54704,0x1b79571,
  44367. 0x068d893,0x031c5a3,0x15d2d77,0x1ac447e,0x06479da } },
  44368. /* 84 */
  44369. { { 0x05f2b26,0x02279d8,0x1db15a4,0x150173e,0x135a294,0x087b575,
  44370. 0x1f8a10a,0x0ef1073,0x1026a58,0x10e7d91,0x1fe70dd,0x0d6c5cb,
  44371. 0x1676892,0x0588e2b,0x19b3480,0x07dfd75,0x15672a0,0x16e42bb,
  44372. 0x06eb58e,0x1c0e95c,0x199c0ca,0x10eb84e,0x0ff9246,0x003b382,
  44373. 0x1ded665,0x1fbbb62,0x070cabb,0x1b4dd94,0x1683e81,0x0eaae2b,
  44374. 0x11d4212,0x1bf31b0,0x0392e9c,0x0d2b24f,0x00bd936,0x05f5af3,
  44375. 0x037b98b,0x01dedbd,0x0125fdf,0x129e10c,0x01fe09f },
  44376. { 0x048cc63,0x1f5573b,0x1c51269,0x02cf9f4,0x13ea251,0x1fa2ac8,
  44377. 0x048f194,0x10df917,0x181a16e,0x0abb0cd,0x1919d36,0x0096790,
  44378. 0x1a0c7e8,0x0b0b2cc,0x0204d28,0x04651f9,0x1690a65,0x11b3754,
  44379. 0x0f240a7,0x0652c09,0x0d2b415,0x0a57155,0x1be7866,0x0217deb,
  44380. 0x08c527f,0x0304f15,0x1b19efe,0x07b96b0,0x0cc25d7,0x01fd422,
  44381. 0x14fd869,0x0e9d66c,0x14e7eea,0x007816b,0x1c1b749,0x09e66ac,
  44382. 0x1d83bcb,0x03b4a67,0x149abbb,0x10db6c4,0x04de957 } },
  44383. /* 85 */
  44384. { { 0x1eac2f7,0x1e98a9e,0x0a39219,0x156c3b3,0x0084778,0x1bd96ad,
  44385. 0x1be582a,0x0f3e76e,0x0cfdf4f,0x059802b,0x0e3d2c0,0x1c2a635,
  44386. 0x01d0701,0x0e3bce8,0x1e52356,0x0a6e20f,0x0bc8267,0x03e4ca7,
  44387. 0x02eb530,0x09a9dc9,0x1058110,0x1adfe4e,0x1e63382,0x13f5016,
  44388. 0x0898d30,0x157e3e5,0x16b2ccf,0x0489e44,0x0f31750,0x06fe2d9,
  44389. 0x0d3547a,0x149af7c,0x049ba6b,0x015a19f,0x131ef68,0x142ec1e,
  44390. 0x0435275,0x11b53f2,0x06030df,0x117cc6d,0x01c9441 },
  44391. { 0x1dc1414,0x1098984,0x14dd0e8,0x1887926,0x060765f,0x0fbce70,
  44392. 0x081eb7d,0x194dfe6,0x085d4cf,0x18c58fd,0x0656adb,0x0e5cc7d,
  44393. 0x02f5c42,0x1415980,0x0682792,0x0fe2c24,0x11b9714,0x1415b2e,
  44394. 0x029ff89,0x0784184,0x0726499,0x0c7338b,0x067272e,0x1688141,
  44395. 0x0d673fe,0x1e2ad01,0x04946d2,0x1e7f53c,0x1338ea3,0x023a502,
  44396. 0x12dd76f,0x0f613ed,0x0b4044b,0x1a3049e,0x0862010,0x04cecfb,
  44397. 0x098ceac,0x028a110,0x0d6ea5e,0x1656aa4,0x0611bfb } },
  44398. /* 86 */
  44399. { { 0x00ad2a1,0x152af78,0x035ef6e,0x1c29452,0x09efa85,0x158b4a1,
  44400. 0x11da3a4,0x0607694,0x111ec81,0x1888de6,0x149ec99,0x0e05117,
  44401. 0x060e425,0x0cd01e0,0x033ca8f,0x11095e5,0x12df318,0x05dbe46,
  44402. 0x0eabac8,0x1428c5c,0x1d77e2e,0x0221dc2,0x0cd4d60,0x09dd37a,
  44403. 0x0448255,0x0c7c0f7,0x1b9aa86,0x165ddd3,0x0c5944e,0x1402613,
  44404. 0x1f1e96a,0x105562c,0x0ef2da5,0x110d2d0,0x11d80bf,0x1cb4556,
  44405. 0x1370298,0x0e59dc1,0x0aa345a,0x0881d67,0x086e6c5 },
  44406. { 0x1793d9b,0x0199085,0x1b3bb78,0x023bb6b,0x179fade,0x0985b27,
  44407. 0x16a49a2,0x165ee7f,0x1fe4fd1,0x1556cbe,0x1372201,0x163b254,
  44408. 0x15073a5,0x1e4bb6b,0x1e32f62,0x04d8115,0x1b163ce,0x1305a55,
  44409. 0x12c7ec1,0x060153b,0x13d39c8,0x066d4ad,0x0cd6965,0x0fd590e,
  44410. 0x1d7d4b3,0x1558fcb,0x0883bbe,0x07a5d74,0x0828c8a,0x048379f,
  44411. 0x004c963,0x10b56ef,0x032616f,0x05b0be4,0x064a30a,0x1ae4b2e,
  44412. 0x1233b82,0x18cb5e1,0x049b735,0x17233f4,0x083867e } },
  44413. /* 87 */
  44414. { { 0x0474edb,0x1f39f11,0x06b9dd3,0x083509c,0x0a76639,0x16eb719,
  44415. 0x0a6b671,0x0ba4e06,0x114f8bf,0x062520a,0x19ee400,0x146fa44,
  44416. 0x0e3ce2e,0x08e927d,0x1d4c054,0x036f024,0x054263a,0x13e0a6c,
  44417. 0x0b82c81,0x1080363,0x09fc20c,0x0d840fa,0x1cca804,0x138dbf1,
  44418. 0x123fb95,0x0830f40,0x1200387,0x0651b8f,0x059a9aa,0x11bc121,
  44419. 0x0dd61da,0x16fded8,0x1ada8b5,0x0a64f91,0x0dbaa4f,0x1e047ed,
  44420. 0x1fb6389,0x1aa0a6f,0x0ce7a27,0x145cc51,0x04b26bb },
  44421. { 0x1318454,0x18e5a2e,0x12db4c2,0x1fae86d,0x123b749,0x053a308,
  44422. 0x11c995a,0x03c6221,0x11c84fd,0x02ef091,0x00f5572,0x0dcc108,
  44423. 0x18a5f8d,0x0d8fd5f,0x16db84e,0x1b9c072,0x0c33cfe,0x07f36b4,
  44424. 0x12e4444,0x00703f2,0x0eb71d9,0x0096e63,0x1c2a3aa,0x1219457,
  44425. 0x004137e,0x02d2cf4,0x1f22897,0x1d6bf80,0x04663cb,0x129d2ec,
  44426. 0x1f00270,0x12216d4,0x0b15073,0x07c6a80,0x0931042,0x0b0c0fb,
  44427. 0x0b901e6,0x01ece1e,0x057180b,0x18a592c,0x04d697b } },
  44428. /* 88 */
  44429. { { 0x1a8fb40,0x18f7877,0x0273836,0x16b7473,0x09021c5,0x0e8cef9,
  44430. 0x1ec5602,0x1c351ad,0x14c1219,0x1bc3db9,0x1c1789a,0x02d029d,
  44431. 0x026417e,0x07cbcb7,0x04d0b6e,0x0843689,0x05ebf84,0x117c3c5,
  44432. 0x052914d,0x122dafd,0x1693e71,0x11d708c,0x06062ee,0x0d1009d,
  44433. 0x14be957,0x1c57633,0x13e1093,0x144c0e9,0x0ce6ab0,0x1dcea33,
  44434. 0x02f6f24,0x192400f,0x1f15a98,0x078d1d9,0x1434e1c,0x0f3a21f,
  44435. 0x04e785a,0x0920ecf,0x1360298,0x143cd91,0x076ca87 },
  44436. { 0x02e48b7,0x1fdab70,0x07190d5,0x079813d,0x1bd14b1,0x034e787,
  44437. 0x090d490,0x153b6be,0x02c3b01,0x03c0b2e,0x15b6b7e,0x0f89cd2,
  44438. 0x08e549e,0x1deb05b,0x1fa54e2,0x18ca7e5,0x16b059d,0x1ca97c2,
  44439. 0x0ddffa6,0x0c044b6,0x08c4d3f,0x145ff48,0x1a831cc,0x11ebe5a,
  44440. 0x0a2d3bc,0x0286735,0x0c91094,0x0e42688,0x1b3ce5f,0x13351e9,
  44441. 0x0485f84,0x182ceea,0x1b5e43f,0x1c4a53a,0x0188dfe,0x0a2b24e,
  44442. 0x0be3e37,0x1303a99,0x0def854,0x18cdb47,0x027e7f2 } },
  44443. /* 89 */
  44444. { { 0x0a15883,0x1b2d6f3,0x0ccd8e3,0x18cd5fb,0x14a7e68,0x1896f2e,
  44445. 0x0daaf4f,0x020c40f,0x037b878,0x037fca8,0x13db4c7,0x1964c95,
  44446. 0x02c0d44,0x195f3c6,0x0eb1807,0x1301c2c,0x05a1636,0x18e31e6,
  44447. 0x1724d26,0x059fd12,0x12203e9,0x0c20f63,0x1dce383,0x0bf52c2,
  44448. 0x1d7642d,0x074b0b4,0x070f80a,0x154eed8,0x0d54092,0x0b2358b,
  44449. 0x1664f71,0x0e0dbe9,0x0b27fb5,0x035cbd0,0x05c33a7,0x013d322,
  44450. 0x13c85f4,0x07215f2,0x194a3aa,0x06f0648,0x002e964 },
  44451. { 0x078ea1f,0x0056ed7,0x1a5a455,0x1af6ce1,0x11a1b74,0x0034132,
  44452. 0x19107dc,0x18ff326,0x07d7520,0x1cbeb75,0x184b863,0x1404d39,
  44453. 0x020faa6,0x1c9041a,0x042b2a1,0x0886c4b,0x0637561,0x1bd241c,
  44454. 0x0e05023,0x0c293de,0x140607c,0x026bc29,0x1ccefd6,0x1776dee,
  44455. 0x1b0109a,0x04d43b0,0x1fd4a28,0x09d6493,0x00ae3ce,0x0f6c170,
  44456. 0x1e821e0,0x042f1df,0x04c1b25,0x09d3f43,0x0a8a754,0x1f983cc,
  44457. 0x1919062,0x1c5ca70,0x149f7b6,0x1b49e2c,0x0739f53 } },
  44458. /* 90 */
  44459. { { 0x04adc5f,0x1a54449,0x15b5e97,0x0d5031e,0x15646c1,0x0afcaa4,
  44460. 0x044a5de,0x0001d89,0x1d19c54,0x1a43a9e,0x044ad0a,0x06d640b,
  44461. 0x0616fa2,0x143d24a,0x0f597cf,0x1a0ccd6,0x001045f,0x0538ba5,
  44462. 0x0a97850,0x0a06262,0x0623b63,0x0254b5c,0x09e712d,0x16007ab,
  44463. 0x19d659a,0x18d3d19,0x18e09bc,0x0e5e618,0x1090cdc,0x1c8637b,
  44464. 0x092d39c,0x120dd7c,0x1ac6c36,0x0282d2c,0x01b6ee9,0x14734fe,
  44465. 0x058c413,0x0cc8f0e,0x03a120e,0x1ff441c,0x0020c23 },
  44466. { 0x1c74661,0x1256d57,0x0194483,0x064eff8,0x17bbcf6,0x0e73cc9,
  44467. 0x073dadb,0x1428209,0x17b161b,0x1c6b5a9,0x043ec96,0x086352c,
  44468. 0x0922218,0x0feef3b,0x07b2747,0x00c61bd,0x04d42d8,0x1e995fd,
  44469. 0x09137d2,0x0ae054c,0x0dfb388,0x16a2ac9,0x137b747,0x09c0371,
  44470. 0x1f45bfb,0x0d8070e,0x0a1b885,0x1e97bda,0x137e6a8,0x0a43b54,
  44471. 0x08e024d,0x10261ee,0x15278ba,0x010fc20,0x1a48e2a,0x158db88,
  44472. 0x1d8b4f8,0x03d88cf,0x073bc88,0x0a7f24d,0x076e7bf } },
  44473. /* 91 */
  44474. { { 0x1ebd187,0x1421413,0x16ed7c4,0x176cb55,0x0d3320a,0x12c34ac,
  44475. 0x1d969c8,0x1576084,0x18f0986,0x11f99fc,0x1fd40f6,0x0f4f5d7,
  44476. 0x0541180,0x012fb8d,0x11ddb2a,0x1e4964b,0x1edff7d,0x0606f3d,
  44477. 0x197c7ed,0x161e842,0x1ae3da8,0x1bb98f9,0x17cffdc,0x07c14a4,
  44478. 0x1d7e719,0x1232668,0x0edacee,0x1bf0954,0x1f37828,0x1c4bd50,
  44479. 0x11eea12,0x1cee675,0x07960cc,0x00d10b7,0x1aad426,0x1a9a8da,
  44480. 0x1cbb80e,0x009612b,0x1bc247b,0x04e572d,0x079e7ad },
  44481. { 0x130caae,0x0b86e47,0x1bd0f36,0x0214dd7,0x05cabcf,0x0a30b6c,
  44482. 0x018fb1c,0x130c783,0x1519e3a,0x0286d85,0x0c4f587,0x12c6c99,
  44483. 0x09f39b8,0x112a3db,0x19f607c,0x16199be,0x1b9d67d,0x1b8abd5,
  44484. 0x025246d,0x144b751,0x00dcccc,0x1e3d13f,0x1da2481,0x1a86503,
  44485. 0x08fbe0f,0x0049a57,0x0d5c83b,0x0bb23ee,0x1d7beda,0x0c84e6f,
  44486. 0x0cacbd8,0x094073c,0x0c10232,0x0c7ee0f,0x197b6c3,0x1ba787a,
  44487. 0x0fe5005,0x048b642,0x1aa50cb,0x1589817,0x07f8c37 } },
  44488. /* 92 */
  44489. { { 0x1ac05e5,0x00f2a21,0x0094cfb,0x099b1a7,0x1a4a4da,0x1fcf15e,
  44490. 0x0302e22,0x1b90db1,0x0b53811,0x06b8ee8,0x0eae90d,0x01a5478,
  44491. 0x1e65504,0x1b0b08d,0x1102526,0x09f4057,0x06e279a,0x18e16a1,
  44492. 0x0c196b0,0x14b5447,0x0890535,0x17e2975,0x16aa28c,0x1bb5a45,
  44493. 0x1eca79f,0x137ad2e,0x14aacec,0x023e0bf,0x1cd81e9,0x13edf9b,
  44494. 0x03176b3,0x121a2d7,0x00e44e7,0x0c4a707,0x0bb793d,0x1e2bcd1,
  44495. 0x1c92a74,0x1024ccf,0x1f0bebf,0x1552e1c,0x01d7703 },
  44496. { 0x10062a9,0x0640e9f,0x02eaa29,0x11b2d44,0x031eb2b,0x05e880f,
  44497. 0x0637e19,0x028cdbb,0x04413b6,0x102fac9,0x1557e2e,0x141bd34,
  44498. 0x1151a67,0x1725a96,0x10bc25c,0x1564759,0x0ec7184,0x1d5aed5,
  44499. 0x11fda46,0x11687cf,0x07f4ce0,0x05bb621,0x148394c,0x047d7b8,
  44500. 0x12069e4,0x0673e9a,0x00d37c5,0x16bc73d,0x0305ac6,0x194aa23,
  44501. 0x104f72f,0x1fc699b,0x02cb2e1,0x1ad7db4,0x1744447,0x13a9588,
  44502. 0x07f296f,0x17b1e6a,0x021c717,0x1d92784,0x00a2c40 } },
  44503. /* 93 */
  44504. { { 0x15747db,0x01c27d7,0x01ac26f,0x0d80d57,0x1bad608,0x1e0aa39,
  44505. 0x020ba79,0x17f480d,0x155977a,0x0a99368,0x077ac0b,0x140bb50,
  44506. 0x11063a9,0x0925b08,0x01b929d,0x1d72135,0x07a4ab2,0x10a017c,
  44507. 0x171802e,0x0e43a9a,0x1dbf7d0,0x14f944f,0x068bf66,0x1bcde0e,
  44508. 0x0e66dec,0x139faee,0x1f6ae7e,0x042e24e,0x074bab6,0x024fb62,
  44509. 0x0cdb4b7,0x0eddda0,0x0017e1f,0x012e9ee,0x170136a,0x0772e2e,
  44510. 0x14b05e4,0x14bf1ea,0x121f9b0,0x08cad93,0x02efb45 },
  44511. { 0x121c064,0x0958045,0x0a7a91c,0x0494e0c,0x1186fe4,0x1a7857e,
  44512. 0x0cd026d,0x052c86b,0x17ec9e6,0x0b2d521,0x183421a,0x0ce7898,
  44513. 0x0adda14,0x1f982bd,0x19599c2,0x0dec016,0x0403ce8,0x13f82f4,
  44514. 0x1100685,0x00e7520,0x007ec05,0x1c14a73,0x05ac798,0x19ee08c,
  44515. 0x0325269,0x09d103c,0x0fa339f,0x1282283,0x17053d2,0x0c69bab,
  44516. 0x0374e2b,0x1954cc6,0x1a68fb3,0x021a86d,0x1fc7a54,0x17d97d5,
  44517. 0x1d2d760,0x08b36a8,0x047927d,0x19c8c51,0x0337532 } },
  44518. /* 94 */
  44519. { { 0x000bb9b,0x08c299d,0x1a14fc4,0x1c8becc,0x0d2ffba,0x1771269,
  44520. 0x06a1752,0x0dd35c2,0x1034185,0x05d0f0d,0x04d27c6,0x02f04e6,
  44521. 0x15a9ac8,0x0a2b8ad,0x0f7f529,0x1a5d582,0x03c5daa,0x1d2fba1,
  44522. 0x0d6dda9,0x090772a,0x1e9b30a,0x127fc39,0x04ba6b6,0x07420ab,
  44523. 0x02d8472,0x0700ab3,0x0e3b6b1,0x126a92f,0x18fa70b,0x020d1ce,
  44524. 0x07d86d9,0x081a2b1,0x141d756,0x02f850a,0x08dfc28,0x10c5328,
  44525. 0x0bb2890,0x05801a3,0x0cafff6,0x0bba99a,0x0192a2b },
  44526. { 0x05ced07,0x1b3141b,0x147d8d5,0x160bbc3,0x029f32f,0x0053d50,
  44527. 0x0e6f2fd,0x08eda2f,0x09bb50a,0x18d9504,0x0989e06,0x1776f2b,
  44528. 0x1b9389a,0x19a7e0c,0x13fd83e,0x10e72a5,0x092387d,0x179d5ca,
  44529. 0x0483335,0x00a7ccd,0x14f0a8f,0x05b1d4d,0x0fbcb75,0x1d04252,
  44530. 0x0ede151,0x1d0cd58,0x0c20e2f,0x1f74181,0x1c11bea,0x13d64ff,
  44531. 0x1e0af56,0x12b9810,0x18bfd95,0x1786302,0x028fe30,0x14d0da9,
  44532. 0x1d9b31b,0x1d5d578,0x109a30c,0x1127781,0x0632e22 } },
  44533. /* 95 */
  44534. { { 0x1a1ccca,0x08e900a,0x0f0c721,0x18fca45,0x0efe290,0x155829a,
  44535. 0x0755463,0x02e16e8,0x1bc85e2,0x132b0cb,0x1e2ca6b,0x083c039,
  44536. 0x18ae131,0x134a423,0x0b2d64d,0x1b15c5c,0x10fc31b,0x075abdd,
  44537. 0x09939e2,0x1debad8,0x0d86dec,0x064e5cb,0x1bea15b,0x12307b4,
  44538. 0x1681327,0x0b516d8,0x00e0f5e,0x007e704,0x0c6fedf,0x0b7f8e8,
  44539. 0x06d6291,0x114d57b,0x1589805,0x0b78c92,0x0b160fe,0x0e673ea,
  44540. 0x1a7e9ea,0x16f6c7e,0x135173d,0x182ba39,0x068c3d9 },
  44541. { 0x0b392b7,0x13132f3,0x14259f8,0x1eeebb2,0x0ec1d9b,0x128a7be,
  44542. 0x0f3535d,0x039c2d5,0x00de72e,0x037acd9,0x1ec0cf6,0x079a35b,
  44543. 0x0ca66e4,0x02f22be,0x0d10d00,0x1b545b6,0x1165681,0x0db3d3c,
  44544. 0x00451cc,0x1cf757e,0x0961c32,0x1769d8f,0x019bf85,0x07a4dcc,
  44545. 0x0298ef6,0x0b6c927,0x01506b7,0x17d41bb,0x02f9719,0x006fccc,
  44546. 0x0b3be54,0x18be0ed,0x0876e63,0x09cb5ae,0x0b96c8f,0x14abc25,
  44547. 0x0ec6747,0x17dd9b1,0x01a9427,0x1dc4665,0x08f2055 } },
  44548. /* 96 */
  44549. { { 0x02c1af0,0x15cf1dc,0x0991292,0x0fe595c,0x1c65e9e,0x0c3ea37,
  44550. 0x0b02980,0x0c69fd5,0x1e393b3,0x1e9f99a,0x0eb3389,0x1801033,
  44551. 0x119c9f7,0x1c55330,0x1d062d6,0x15d2a7e,0x157372a,0x0ffd4a2,
  44552. 0x16ce162,0x1af0091,0x1c1c937,0x0fb78fd,0x144321b,0x1e1419d,
  44553. 0x0bd89a2,0x0f5a457,0x08d9d0e,0x1cbabf4,0x17d2d8a,0x15059f8,
  44554. 0x05040e9,0x0823b31,0x033f68a,0x1b3d179,0x02cc862,0x0cffd9d,
  44555. 0x0319bf0,0x112a079,0x0c8b810,0x192681a,0x01292c8 },
  44556. { 0x186463d,0x1aac381,0x05ffd7a,0x0406e3b,0x14bbc2b,0x00ce2d6,
  44557. 0x115c42e,0x082366c,0x0cf04ad,0x05da16b,0x0e7b043,0x18eccd2,
  44558. 0x075d819,0x100c23f,0x116b04e,0x065c90e,0x1021c72,0x027b825,
  44559. 0x12c15e0,0x1cb1415,0x02952c9,0x19dab0f,0x0548ee2,0x1f3746b,
  44560. 0x0df0079,0x11419c2,0x087aaa5,0x10463f8,0x0a2b907,0x02a7c57,
  44561. 0x18e8bab,0x061a384,0x075ed77,0x1c80040,0x1b57ecc,0x1559689,
  44562. 0x1011293,0x0a35617,0x05d9249,0x057d704,0x07c7876 } },
  44563. /* 97 */
  44564. { { 0x07902b6,0x1eb7d83,0x0602e3d,0x07a2e6b,0x12823a4,0x1a0eeed,
  44565. 0x1ec4965,0x0b80c59,0x14033f9,0x11c8d83,0x026e31b,0x0146d0b,
  44566. 0x123831d,0x0911487,0x11d3525,0x03e75c6,0x0d6222e,0x0a6d58a,
  44567. 0x0fc234e,0x01f9bca,0x08f58f0,0x17383f9,0x156645e,0x11cc0f8,
  44568. 0x0a0ba06,0x0120b35,0x1f5f87e,0x004e27c,0x0a328f6,0x0aa026b,
  44569. 0x0a9f095,0x131219a,0x12e3264,0x0590506,0x0513b28,0x19e440f,
  44570. 0x12f4e09,0x0c6e03a,0x1a07572,0x009b09b,0x0694035 },
  44571. { 0x1407206,0x1d9b372,0x0a33e2d,0x1e1b11f,0x1ecf54c,0x1397378,
  44572. 0x19523dc,0x0d0dfdf,0x081ab44,0x12989b9,0x1d10235,0x1e1c9c8,
  44573. 0x1f52cb5,0x124839b,0x109ace9,0x1a0e33c,0x19b4980,0x192bb60,
  44574. 0x1c9cb2b,0x068c501,0x11c991f,0x07a3479,0x1e39829,0x1089b12,
  44575. 0x0a32990,0x015c3bb,0x12e5456,0x14aae01,0x11adbf8,0x19b28a5,
  44576. 0x1beac6b,0x1f7a687,0x0ebff92,0x00f9a11,0x0c06df6,0x0265f3f,
  44577. 0x1a6b30e,0x0287035,0x0551ab6,0x04f78bf,0x06da9e0 } },
  44578. /* 98 */
  44579. { { 0x09490ce,0x172612e,0x0e0487b,0x061bed0,0x096ec4a,0x149b475,
  44580. 0x01f8292,0x1e7cd8c,0x04bc262,0x0582495,0x10d3ff6,0x04208c1,
  44581. 0x0d0846a,0x146f99e,0x1fde990,0x0ec25ef,0x0442182,0x08862a8,
  44582. 0x126f340,0x0bf9d22,0x13dc9d2,0x06e7e30,0x1c95847,0x1ea39ca,
  44583. 0x17e8897,0x05a8acf,0x053a302,0x1f477e6,0x07538f3,0x108abaf,
  44584. 0x083a855,0x1239080,0x1e0a951,0x1568568,0x02eb3c0,0x1e1a44d,
  44585. 0x058b8e5,0x0635620,0x1644a81,0x17366a2,0x0773b40 },
  44586. { 0x031cfd2,0x1966e1b,0x1ef003f,0x0700ee6,0x14c4c2d,0x0529380,
  44587. 0x185a8ce,0x1bdac00,0x1b32cab,0x0719836,0x0c5f2b4,0x11d54e1,
  44588. 0x0e33673,0x1cf9a9f,0x1d2aa35,0x075a7e5,0x0d9576f,0x03897b5,
  44589. 0x06caf38,0x0f30a51,0x0a30e42,0x06ed496,0x01763e5,0x0925bb2,
  44590. 0x1d475d8,0x05ecc48,0x0934579,0x1c0d4b9,0x0eabbd3,0x0a7592a,
  44591. 0x0f11c97,0x181daa2,0x1394ace,0x1573618,0x0166efe,0x0efc1f3,
  44592. 0x033fd13,0x092aa34,0x13dd770,0x10b8ad8,0x012b463 } },
  44593. /* 99 */
  44594. { { 0x12951de,0x0df5ec9,0x1252043,0x04b54d3,0x16959d4,0x197846c,
  44595. 0x07013b2,0x058bf89,0x02250b8,0x03a7866,0x113876b,0x134a75d,
  44596. 0x0d96a43,0x0824cd6,0x0f2ae6a,0x1675f86,0x06654d9,0x197e66f,
  44597. 0x018eba2,0x1e50b87,0x1f88f4a,0x1f237f5,0x08dccdc,0x1356fda,
  44598. 0x1672c3c,0x1063a8e,0x03f8480,0x038a226,0x13e56ec,0x0017a97,
  44599. 0x006b609,0x1494c95,0x089ab7a,0x0b1f91a,0x198767c,0x0e143f6,
  44600. 0x0e55331,0x034df08,0x1505c5f,0x0bcfb11,0x061c193 },
  44601. { 0x092ae43,0x116cd9a,0x0168b9c,0x0a0a71e,0x1ef89d9,0x0555b18,
  44602. 0x1962080,0x02f5cef,0x0eba4b1,0x0396090,0x1872e0a,0x0590748,
  44603. 0x065c243,0x05c9c79,0x16cd0d3,0x0fb8062,0x0c58c4c,0x082df95,
  44604. 0x05acde3,0x0a03bab,0x0c30d2e,0x0fe5c48,0x0a141b2,0x06c3e19,
  44605. 0x0f4617c,0x1d71e85,0x0168d72,0x03ef6e3,0x1c01382,0x1af8f9f,
  44606. 0x17ef440,0x116491d,0x0628af5,0x0e5703a,0x0741232,0x071ac84,
  44607. 0x0ca1877,0x11ed1c9,0x16e51d7,0x1e4e3a7,0x027ad0d } },
  44608. /* 100 */
  44609. { { 0x05b5aed,0x1ed3c98,0x1a9e78e,0x08b331a,0x0c67d4a,0x1f5b801,
  44610. 0x1874c3d,0x08990ab,0x0147d1c,0x0c53f4f,0x1503b70,0x0c31912,
  44611. 0x003ea99,0x1f35fe9,0x0ef8829,0x0886f4a,0x064ecc1,0x164a43f,
  44612. 0x13be171,0x0f240e6,0x0bd5729,0x18eaf0f,0x1e83539,0x091ad6d,
  44613. 0x0b1e64d,0x06a7ed1,0x159b880,0x10543c0,0x1366a17,0x186d2d2,
  44614. 0x0e0a8f1,0x0348e6e,0x03fbd2b,0x010747f,0x1019ff8,0x0bafdf1,
  44615. 0x0acfb66,0x1437ef7,0x150bfb1,0x04edba2,0x05d9b5e },
  44616. { 0x13e472e,0x1e2d2e5,0x0178d8d,0x0e61428,0x0153d92,0x04c2ac1,
  44617. 0x04b96d1,0x0a20133,0x1f39a08,0x0780666,0x1b15806,0x18236b8,
  44618. 0x0e26237,0x09a1aa0,0x03b5020,0x0630883,0x1f07e7f,0x1ff7be5,
  44619. 0x1d215da,0x1246cd7,0x091aecd,0x0d5e4a6,0x06dd6f8,0x02c44ec,
  44620. 0x178de4a,0x05c470b,0x0f171af,0x0a5cafa,0x171858c,0x0163ad5,
  44621. 0x1e5730e,0x07edc73,0x12c2c28,0x19afe70,0x1bcb589,0x0c98fc1,
  44622. 0x035a599,0x18ef58c,0x11d9b81,0x19b9771,0x024f891 } },
  44623. /* 101 */
  44624. { { 0x178c1e2,0x1b05fb3,0x197093b,0x1a01ab7,0x1f49c03,0x00d04ff,
  44625. 0x061b8bc,0x0b1d823,0x0ae096e,0x0d39452,0x1e61316,0x1db6e0e,
  44626. 0x05aabbc,0x038652d,0x11cef4a,0x01c7bf6,0x0614de3,0x1464946,
  44627. 0x1d9eaf2,0x1cff349,0x09cf3fa,0x15f610d,0x00f0acb,0x1b36bbd,
  44628. 0x10d629c,0x06fd7d3,0x07182c6,0x1bd5d4b,0x09b54ca,0x1bdf202,
  44629. 0x18f57fb,0x0dba621,0x0eebc76,0x190e67e,0x1f8e3d8,0x0aee91d,
  44630. 0x18ee8af,0x0e19588,0x1d84bfa,0x19fa85b,0x0863ac3 },
  44631. { 0x05a2fe2,0x17e53dc,0x171828d,0x11dc853,0x13e70d0,0x0e1ca27,
  44632. 0x0882450,0x0151937,0x067272a,0x0354083,0x02f418c,0x0aabf2d,
  44633. 0x1de69a1,0x0a9e301,0x1bdf91c,0x1c9f570,0x14aef56,0x04b8330,
  44634. 0x01e02d3,0x186d713,0x1263c0d,0x111d0e9,0x10d95ff,0x0aa4592,
  44635. 0x17a8643,0x13c80fc,0x1bb7fbd,0x12312fe,0x0a17a0d,0x18ea36d,
  44636. 0x0f7aef8,0x10b599f,0x1179100,0x1e0ef37,0x18ca3e7,0x19c1b4d,
  44637. 0x01e7142,0x0ea9edf,0x1c96872,0x03d170c,0x03e3f1b } },
  44638. /* 102 */
  44639. { { 0x17fbf05,0x10ae03d,0x020adfa,0x0c3e347,0x192f11b,0x0e68de4,
  44640. 0x1656b47,0x11793bb,0x0ad0f7e,0x0fadbfd,0x1eade4c,0x0bd7f94,
  44641. 0x062936e,0x0cd2adf,0x1d05f70,0x1caa861,0x04343cd,0x18fb7a7,
  44642. 0x0bc112f,0x1ebccb0,0x0408971,0x1221446,0x1cf0ee3,0x00feaea,
  44643. 0x0c59fb8,0x07830d5,0x16062d6,0x0c9dc5b,0x03b0d3a,0x05304bd,
  44644. 0x161bde8,0x0072960,0x185ecc8,0x1a8bec5,0x11d2fec,0x0d340b2,
  44645. 0x079c3f0,0x16acbbd,0x0009626,0x1b0e015,0x081208e },
  44646. { 0x0c4ce37,0x1a84c8a,0x0298424,0x0743549,0x134bb84,0x06ac747,
  44647. 0x1c09160,0x1750c00,0x1b375b8,0x0da1624,0x0f7a0db,0x0a49da7,
  44648. 0x16ac365,0x124919d,0x08786d1,0x128deaa,0x1d564dd,0x15e3e62,
  44649. 0x1ed6dab,0x09606b7,0x01a39c1,0x0c00a36,0x1fc8ae8,0x04429ea,
  44650. 0x0fbbc87,0x1b205b1,0x1ed2485,0x159fafe,0x0d6df13,0x06d0e5a,
  44651. 0x0457fc4,0x0c4c015,0x00e2620,0x08b3fb3,0x0a76076,0x12f58fb,
  44652. 0x16e7a19,0x0713065,0x0cf09ba,0x17101bd,0x044383f } },
  44653. /* 103 */
  44654. { { 0x04f9af6,0x1f80ef2,0x0873841,0x1b1963f,0x16381a4,0x1eea499,
  44655. 0x18fb3ed,0x13fccb7,0x026a883,0x05c21ad,0x1e27634,0x122a7d8,
  44656. 0x1fee60f,0x15e62f0,0x17fa940,0x15039c4,0x0c57e44,0x0023be0,
  44657. 0x0c2e96e,0x1d3f064,0x0dd9349,0x17ef0c0,0x1750bcc,0x147a239,
  44658. 0x19eaf64,0x01d4581,0x1afadc2,0x01df109,0x0742cb8,0x1062789,
  44659. 0x188a239,0x0e41404,0x0156cc5,0x1dbbfa2,0x1799c94,0x139aa8f,
  44660. 0x06013a5,0x14d3765,0x0111660,0x11e1aa9,0x08aee70 },
  44661. { 0x0c54409,0x116ce19,0x0b1063c,0x0cebd75,0x09ebfa4,0x1424c0d,
  44662. 0x1a4a218,0x01921c5,0x16b3a8e,0x0100fb7,0x1d907b4,0x02d97ae,
  44663. 0x15c9730,0x180b82b,0x09bcbc1,0x19c03f2,0x08ffec0,0x024c202,
  44664. 0x0c674c1,0x12c423e,0x08c4bf6,0x02648d4,0x1d2d721,0x0061504,
  44665. 0x0fbcee0,0x090a620,0x1793db5,0x1dacea4,0x167d1eb,0x03e614e,
  44666. 0x0dabdf9,0x1843a6a,0x0307db8,0x14a02fd,0x11aaeec,0x1ead6d8,
  44667. 0x033e805,0x0cd3f18,0x09683c1,0x1fcc12d,0x0970f61 } },
  44668. /* 104 */
  44669. { { 0x1ec8e4a,0x09e918d,0x0d306f1,0x086b4c0,0x0809ac1,0x0f2326c,
  44670. 0x0076942,0x06a9dc1,0x18a4882,0x0b570fe,0x0192d92,0x10c664b,
  44671. 0x1fa1ae9,0x1a66834,0x1284fa5,0x14d6975,0x058b1d8,0x01b9c66,
  44672. 0x1dae769,0x0e3eb1c,0x16fb5fa,0x0463f58,0x12466fa,0x09c853b,
  44673. 0x0f13fad,0x0f6fae4,0x049267e,0x0b076ce,0x0d8bd74,0x008ad08,
  44674. 0x1faf388,0x0af2176,0x06d7605,0x1bc6efb,0x1b7920a,0x15262d5,
  44675. 0x15f855f,0x0c7d96b,0x1329f83,0x128b4fb,0x0404b5b },
  44676. { 0x17a15c7,0x1341528,0x080be7b,0x19df100,0x0ae4cfb,0x0351aa5,
  44677. 0x104e544,0x1cf9dc5,0x0170feb,0x0f300c9,0x03152d7,0x13fae7a,
  44678. 0x17589e3,0x0648495,0x171c4d6,0x1fcbe32,0x13f0a7b,0x0e5bf6a,
  44679. 0x187325e,0x124855e,0x17d92bd,0x1629caf,0x034bbc5,0x1665e13,
  44680. 0x0c1ca70,0x0e086a5,0x154b461,0x0b0ea4d,0x0d6195a,0x18254a1,
  44681. 0x0b0a4ca,0x14a0161,0x025a979,0x1e9187f,0x12b958b,0x18bf43e,
  44682. 0x00da253,0x1aad791,0x1800983,0x16b0628,0x07faa11 } },
  44683. /* 105 */
  44684. { { 0x0402149,0x1278637,0x0466c2e,0x1b2c798,0x1584cc1,0x093a3b1,
  44685. 0x1706a99,0x1e4ee81,0x1c95715,0x1bbffba,0x07ec38f,0x095a7f1,
  44686. 0x1fb2f23,0x17cdf1f,0x05640cb,0x0fd04aa,0x01d0423,0x1fe4fd9,
  44687. 0x054fb64,0x1dfe714,0x1d13eb2,0x1008020,0x02754eb,0x037b051,
  44688. 0x0545b7f,0x152e797,0x190e54f,0x1a944f9,0x1e75c8d,0x12ea6c2,
  44689. 0x10c034b,0x04837c3,0x193ed62,0x10196f5,0x097c090,0x023ca7e,
  44690. 0x03a4e70,0x0abb1b6,0x1fafee6,0x0a5db31,0x014b63a },
  44691. { 0x1c43336,0x05aa9b8,0x092dd84,0x0c47490,0x19dfd4a,0x03028d8,
  44692. 0x08b800a,0x1b6f72f,0x08f5f1e,0x155ddce,0x1f6ab61,0x1aef36c,
  44693. 0x1b67a57,0x06affd7,0x13941b7,0x078c715,0x19589ac,0x042ed4f,
  44694. 0x168f454,0x197550e,0x0ed2081,0x07f49a3,0x00cd4f6,0x1f3405a,
  44695. 0x161f1a1,0x038d955,0x1ce9967,0x0196126,0x1df8a1b,0x1185a7a,
  44696. 0x076df83,0x1d6fab4,0x1c4c741,0x12e783b,0x1271ca3,0x191e08d,
  44697. 0x17c171a,0x0e85e3f,0x09954cb,0x0e706da,0x0024858 } },
  44698. /* 106 */
  44699. { { 0x1a4cd8d,0x06e91ba,0x09e3350,0x072f797,0x132ca43,0x06b0fa8,
  44700. 0x1361096,0x0d0618b,0x1da1e8e,0x13f602c,0x1750282,0x02e23ac,
  44701. 0x1607a8f,0x1a1a86b,0x079957b,0x15c850d,0x0f05983,0x05cc673,
  44702. 0x162faf4,0x02723b3,0x1d497b6,0x12d8dd2,0x0e94a78,0x0d659ec,
  44703. 0x132e91f,0x114a37b,0x08fe8ed,0x1acdd8d,0x0f0ed2b,0x087661f,
  44704. 0x1d8e5e5,0x0be1168,0x09008cb,0x1071777,0x1096596,0x0ffad7c,
  44705. 0x1177bc8,0x16a89e0,0x0b6b9e3,0x1bffca2,0x06798ce },
  44706. { 0x197c5c6,0x1fc7e8d,0x0cfd278,0x1cf1876,0x19fbab3,0x1acadd1,
  44707. 0x1104903,0x0ec884e,0x15d7d43,0x1a112dc,0x111ddc5,0x1f98f38,
  44708. 0x05880b3,0x194b592,0x0eb2a0c,0x1c309b8,0x1f71734,0x12ac89e,
  44709. 0x124d11c,0x1647a73,0x0a11a4d,0x19e8a10,0x13aecdc,0x0c117b9,
  44710. 0x00cf9f3,0x09fdce9,0x18c33f8,0x0c3159e,0x10874ca,0x1598af9,
  44711. 0x095d7c1,0x13e000b,0x06efe7f,0x1e4eda8,0x1e3006f,0x03155d4,
  44712. 0x178e7c4,0x0bc92af,0x18e57e4,0x1a4a5d2,0x03ea7ae } },
  44713. /* 107 */
  44714. { { 0x106ae25,0x0bf022d,0x03be618,0x1b96aea,0x1cac148,0x0615d15,
  44715. 0x0bc3981,0x0eb23d4,0x176b789,0x060cfb5,0x1686040,0x0da0ca3,
  44716. 0x1b79b9b,0x04a2b82,0x0896faf,0x0b7e3e6,0x1f35c00,0x0985a1a,
  44717. 0x109361b,0x1689057,0x1777440,0x0b6b1b9,0x0ae3c26,0x08969b8,
  44718. 0x16c561c,0x0ccb2fe,0x18c241a,0x1280bdc,0x0a1ec1e,0x0492045,
  44719. 0x05467fc,0x07a5e51,0x0f3246a,0x033cbf7,0x1d96f1d,0x1c02d86,
  44720. 0x10705f7,0x092b4fe,0x001118b,0x1380a4a,0x06a8ad3 },
  44721. { 0x0be7282,0x18106a3,0x1c4b917,0x1a42701,0x1405afe,0x0d35684,
  44722. 0x096f757,0x03c99b9,0x07f8be6,0x16b78c2,0x0e05e30,0x12a6b2d,
  44723. 0x1420132,0x1d46fca,0x0ec79ed,0x0569b1a,0x1bb3957,0x13abe30,
  44724. 0x0330ed5,0x136af70,0x1fecd74,0x099bd9f,0x05643fe,0x0bb929b,
  44725. 0x1b65314,0x0b99cdd,0x188cd79,0x01838c0,0x03feba7,0x196bfbb,
  44726. 0x0ca70b9,0x198c36e,0x168e424,0x1f96523,0x1e9aa9c,0x1aeefa5,
  44727. 0x05cb58c,0x126dd56,0x186ab7b,0x0f339f5,0x01a1811 } },
  44728. /* 108 */
  44729. { { 0x1575ed0,0x1fb17bb,0x066dbdb,0x12fa3b5,0x18f14fa,0x17ebfb0,
  44730. 0x0bbeda7,0x0665ce5,0x1ddc286,0x02d5a65,0x1160d31,0x1a90b0d,
  44731. 0x18b0e20,0x1cbbaee,0x05c0468,0x08931a7,0x008f413,0x0009864,
  44732. 0x14457b6,0x011d75e,0x1ed92d4,0x0e01306,0x1141a81,0x1957223,
  44733. 0x1736219,0x1434f2d,0x1ba1a4e,0x19ea118,0x1736174,0x122fe63,
  44734. 0x08d39c4,0x12bb139,0x171aa1f,0x1de4c17,0x11a981e,0x049774f,
  44735. 0x012b7fd,0x128af39,0x1d6a3ce,0x0eb2461,0x07d2ddc },
  44736. { 0x0d2cae8,0x0c0b6a7,0x0ddcf41,0x1b73800,0x0cf6bc7,0x15846a2,
  44737. 0x0639991,0x101847d,0x14b9c01,0x0f73630,0x05e707e,0x1427df2,
  44738. 0x0ae11c9,0x076cb44,0x0d851fa,0x0e14f4b,0x048d066,0x0bd7f5b,
  44739. 0x1da149d,0x0066782,0x08f2d67,0x14bafcf,0x0a27765,0x14d15bd,
  44740. 0x1228d37,0x0c35dab,0x191532c,0x0340bab,0x1dd5502,0x0ac7831,
  44741. 0x1cd2040,0x0996d95,0x0dd4f08,0x055f3c9,0x0149e15,0x0ce189b,
  44742. 0x0e729d7,0x0cb4ee3,0x102ea11,0x0f5637e,0x05a52f8 } },
  44743. /* 109 */
  44744. { { 0x1ecacbd,0x0cf4884,0x17abb40,0x1af7137,0x0544023,0x039b8f3,
  44745. 0x07c2d5c,0x02ef98a,0x016c8e2,0x0419582,0x166ad45,0x0d05024,
  44746. 0x14b1aa6,0x11f1b0e,0x0403e48,0x0b854dc,0x0e9e3a9,0x172c9f7,
  44747. 0x1b04389,0x16d77a2,0x013f699,0x19ca39d,0x0b521e1,0x0e930f9,
  44748. 0x14dc5b2,0x174f8e0,0x1495678,0x0fb800e,0x147ad25,0x024ee1e,
  44749. 0x04e1126,0x1baa4ef,0x1df278a,0x0adccc1,0x1b23bbf,0x00ee1c7,
  44750. 0x16bd02a,0x12c2233,0x17ff8ab,0x0c87ce0,0x017f027 },
  44751. { 0x1abea1f,0x0008694,0x1133769,0x0a480f5,0x036b969,0x1990c5b,
  44752. 0x004a410,0x0952d4c,0x1163d53,0x110fe1d,0x081597c,0x0b7d998,
  44753. 0x1705ba1,0x0b142ab,0x0e39536,0x009a624,0x0578788,0x00d8a21,
  44754. 0x026a7f9,0x17e6095,0x02b196f,0x1625f32,0x1229fc1,0x05610bd,
  44755. 0x020e86e,0x08eee8d,0x0bfd296,0x1efe4f8,0x0343b88,0x03a9d25,
  44756. 0x13705ec,0x1762e7a,0x04b1e88,0x03ddf34,0x0910f70,0x0e7599d,
  44757. 0x0c441d7,0x0ae446a,0x055fb6c,0x134a7cb,0x00ef030 } },
  44758. /* 110 */
  44759. { { 0x08e5b60,0x12b90fd,0x0ec93f0,0x1ad2381,0x046938a,0x0511243,
  44760. 0x12dd82c,0x0efc8da,0x07de168,0x11fcd61,0x0718c21,0x0dde4e4,
  44761. 0x02503bb,0x05b3fd8,0x106677c,0x17a73f1,0x172e07a,0x13c60f6,
  44762. 0x0cbc376,0x1bd6f76,0x09f3cf9,0x18361e4,0x0bfdc9b,0x0e444b5,
  44763. 0x08b2d19,0x1ae5b80,0x1d3c517,0x1eb4c22,0x1c4f378,0x17c622b,
  44764. 0x1913839,0x0388a78,0x1bdaa44,0x0964045,0x09b69ba,0x02af7c6,
  44765. 0x1d77356,0x1e1feca,0x0dcaaa6,0x18d766f,0x03d3b6c },
  44766. { 0x122c880,0x189664b,0x0225b9b,0x0e50d6d,0x1a1b6ae,0x17d7f61,
  44767. 0x1026eb4,0x1df7439,0x043bb8b,0x0b256bd,0x0fd30eb,0x14012f8,
  44768. 0x1ba5af6,0x01a9d48,0x1f2c367,0x17ed655,0x0ab69cc,0x06509fe,
  44769. 0x0aaf064,0x142723e,0x07e5699,0x0111d12,0x0b6f555,0x0911b34,
  44770. 0x0180f95,0x01e7103,0x1c49133,0x153cf7f,0x13a365b,0x1d5f43e,
  44771. 0x188a4a5,0x1f4994b,0x054fa38,0x10db620,0x08f59ef,0x096720c,
  44772. 0x18f41a4,0x133e2bb,0x1139c7e,0x0878f6a,0x02e946e } },
  44773. /* 111 */
  44774. { { 0x00934ae,0x07eefe3,0x1b44a60,0x1e2c840,0x0c3e7ef,0x176bad1,
  44775. 0x1fe5905,0x1b9eebc,0x15cd0b2,0x1630679,0x0b61efe,0x1d9c3f5,
  44776. 0x1dddc4b,0x0c24f2e,0x0fea1f2,0x1e35cea,0x0a32c1b,0x1e2ea8b,
  44777. 0x11ccad2,0x1b7d502,0x096b565,0x1d67243,0x001faf8,0x172ed28,
  44778. 0x074d6cd,0x1df2065,0x0197939,0x1eb9a4e,0x0c4ebc3,0x1e009d5,
  44779. 0x085d211,0x087ad87,0x162e034,0x103b533,0x125519e,0x1ad21b1,
  44780. 0x1eda677,0x06bc6b0,0x16309da,0x0aa0303,0x00997ce },
  44781. { 0x05a0b81,0x1ba364b,0x17ea4a5,0x0dcbc25,0x08b58be,0x0fa1bfa,
  44782. 0x0cf11c5,0x0b2aae7,0x1b565c4,0x012f483,0x09e5f39,0x0a242b0,
  44783. 0x0f4f43f,0x0752a3a,0x16be9be,0x00959cb,0x1be13de,0x19575c7,
  44784. 0x0281f20,0x1f2be1d,0x09feed7,0x1733160,0x0f804a9,0x0859e2e,
  44785. 0x0e9b8c7,0x022dfcb,0x0b8a287,0x1d4aeb3,0x14e2f38,0x00da2e7,
  44786. 0x0651d65,0x1f20340,0x1d3c02d,0x0b5973e,0x1ba9c24,0x11cf49b,
  44787. 0x0fa9b98,0x19395a9,0x1ff9942,0x13fa122,0x096f9f0 } },
  44788. /* 112 */
  44789. { { 0x0310a96,0x0556216,0x1cd1e3a,0x07ef454,0x12a9830,0x0b11039,
  44790. 0x0a0f48e,0x10188d9,0x0d95412,0x0898f37,0x0fa446b,0x18bc595,
  44791. 0x085791f,0x020db63,0x12ddfae,0x110f0a1,0x1ea3d3c,0x157fc9e,
  44792. 0x0401ef3,0x083e3be,0x11fd065,0x012ae6f,0x13b9ca7,0x07c72e4,
  44793. 0x1131732,0x060f07b,0x06b5342,0x05bcf48,0x1e22bfa,0x155fd1a,
  44794. 0x096a644,0x1136066,0x050122b,0x0a6a750,0x07d0194,0x17173ca,
  44795. 0x19d3e0a,0x1e3d56b,0x1fa9508,0x04c8171,0x071998e },
  44796. { 0x0b6ed78,0x007e6e7,0x1459005,0x0e30a68,0x053cf37,0x0b06e63,
  44797. 0x0d96ba3,0x1f008a1,0x09dac55,0x1360d3b,0x15a1b33,0x125b5c0,
  44798. 0x028a96a,0x093892b,0x1911d88,0x1284a5f,0x150a4f3,0x13a3de5,
  44799. 0x114c7f0,0x18dfe5f,0x1ff0f0e,0x03887f4,0x125f0d1,0x0f259ff,
  44800. 0x087839c,0x00cfda4,0x0009bec,0x0a58a49,0x04c2905,0x114e6c0,
  44801. 0x1cd0006,0x06b9194,0x02b5ad8,0x0efd03a,0x1c5dbb9,0x0386f03,
  44802. 0x1dfa4ab,0x15c2f81,0x0cab329,0x034161a,0x0838994 } },
  44803. /* 113 */
  44804. { { 0x0067dff,0x031516f,0x058b03c,0x0179700,0x14f3269,0x03d15ee,
  44805. 0x064341c,0x123319b,0x0fae4a3,0x17e31dc,0x0b60516,0x16f7665,
  44806. 0x11684f1,0x18ccefd,0x08b738b,0x0b09161,0x17f48f2,0x1113070,
  44807. 0x0b57a18,0x07b6018,0x1171739,0x0a19c67,0x07a23e1,0x159ea45,
  44808. 0x1942902,0x19e8033,0x01a0d6b,0x122af97,0x02614c1,0x17c95c5,
  44809. 0x1b0bea9,0x0269d88,0x0ff95f5,0x1409a82,0x09bbede,0x099e00c,
  44810. 0x137a470,0x059e82d,0x1b09515,0x0624d29,0x01fbfda },
  44811. { 0x0f69c77,0x1db2be4,0x03ebf7a,0x1747bf1,0x12a8278,0x1dbc5a4,
  44812. 0x155c707,0x0668c76,0x011c71a,0x103350d,0x0562c34,0x0286113,
  44813. 0x0610c88,0x07ceb3d,0x1d71f83,0x0f71f72,0x0087303,0x0ed52e9,
  44814. 0x02fd618,0x0a00ba8,0x09a95ee,0x13bedd3,0x0c039b3,0x0c598e8,
  44815. 0x03cb3c9,0x02ac49e,0x0533e10,0x15930c5,0x1c9d700,0x1b1d112,
  44816. 0x1a029fb,0x1723c8f,0x0184869,0x1c25f7f,0x17ae30b,0x1e373af,
  44817. 0x00e278b,0x1c448ae,0x1c6799d,0x195884d,0x04f9488 } },
  44818. /* 114 */
  44819. { { 0x151b8ce,0x0fe6a6e,0x1a01843,0x106c461,0x0857927,0x0ccab10,
  44820. 0x1fc70d9,0x0efdb8f,0x1e2cae8,0x02f56a5,0x19d8224,0x0bb3cf2,
  44821. 0x0ca1c32,0x1e9c493,0x0e7b776,0x0149c7c,0x0685f6f,0x06d4964,
  44822. 0x11e83e9,0x1f0015e,0x0aabe16,0x0df2fb0,0x142d36d,0x070a7a6,
  44823. 0x1412f98,0x04e1b32,0x026de5e,0x096c44a,0x0e72b26,0x002c270,
  44824. 0x0efa958,0x1caab85,0x1bd4901,0x09708d5,0x069c5ca,0x1e6f083,
  44825. 0x0174218,0x05ad557,0x1ae49b8,0x1091ef2,0x0688e06 },
  44826. { 0x13b8f64,0x17b2098,0x118b37f,0x172858e,0x0ef11b7,0x06c55ed,
  44827. 0x1eddd70,0x1520cf9,0x0af4041,0x04752f8,0x14843d8,0x1b04d26,
  44828. 0x0823d5b,0x13c8bd0,0x0e413f0,0x05a42b5,0x1fe45d2,0x1c2edd8,
  44829. 0x14d8567,0x0bca129,0x18f2c3d,0x070e9cd,0x0baed4a,0x0959de1,
  44830. 0x0a828f4,0x12a6eae,0x1c8315e,0x084135b,0x195f442,0x1a19bc7,
  44831. 0x0dd5d0a,0x15266fa,0x11fa7d9,0x07edbe8,0x1027193,0x19acd41,
  44832. 0x1bb817e,0x12adc7c,0x049955b,0x1c7c988,0x01723c7 } },
  44833. /* 115 */
  44834. { { 0x08b43f3,0x0436c6e,0x19a2699,0x024c813,0x1c3e0e6,0x1a3001f,
  44835. 0x110df66,0x0f63113,0x16284ec,0x142819a,0x16eba8e,0x0b88d53,
  44836. 0x1c5a366,0x14bc499,0x1da5077,0x02920f7,0x1106934,0x08f6ad2,
  44837. 0x12e000b,0x14f6f51,0x0a59664,0x1230768,0x180fddb,0x09d7e4e,
  44838. 0x06ba31f,0x13fe1f0,0x07cb0e2,0x12d9da8,0x1db08a2,0x07bce78,
  44839. 0x0d8ab06,0x19bcf47,0x119e882,0x1458364,0x14a76fd,0x0a2bcef,
  44840. 0x0e947cb,0x0bc5d52,0x064e886,0x056ec61,0x084bf54 },
  44841. { 0x164f21e,0x166d4f1,0x15fb077,0x0a025ca,0x0d6cf34,0x07c8708,
  44842. 0x1a12162,0x1717448,0x1e3b104,0x1b6ed25,0x1bd5ea7,0x068dc75,
  44843. 0x096bf7a,0x14193f5,0x00a67fb,0x1cd8e42,0x087da95,0x0d54cfa,
  44844. 0x0b37d91,0x1f027da,0x14b824f,0x0945ea0,0x1476ecb,0x1f434c3,
  44845. 0x101afca,0x0d20328,0x0a737af,0x1b3e973,0x1039e47,0x19caf20,
  44846. 0x10abd06,0x18a15be,0x1e9e6ba,0x14f24f1,0x0eb8d07,0x069e426,
  44847. 0x0b157f2,0x146079e,0x0054d25,0x0f7b40d,0x0383f82 } },
  44848. /* 116 */
  44849. { { 0x183ff4c,0x03510b2,0x079cbb1,0x1295ae1,0x0e645a2,0x0650952,
  44850. 0x1a73f01,0x1cbb8cd,0x09160a7,0x178947a,0x11d8ba0,0x0f62ad3,
  44851. 0x07bfb22,0x0176dc7,0x031e58f,0x1ed11f0,0x00649a0,0x053ed7f,
  44852. 0x1452e33,0x082ea85,0x00beb7e,0x09c36f2,0x0e83171,0x16f2662,
  44853. 0x052861d,0x18df868,0x07eff81,0x12059cd,0x0e9903b,0x14ab108,
  44854. 0x0e18791,0x1ee07d7,0x0ef874e,0x1bc5b7d,0x11fb757,0x15ecd12,
  44855. 0x1af5ea3,0x1432a3a,0x11895bf,0x02a87f2,0x03b121f },
  44856. { 0x19275e9,0x17423b2,0x19416c9,0x1ada1f9,0x07581cf,0x11f8f7a,
  44857. 0x12ff62a,0x01cabeb,0x1e484e6,0x13df18a,0x1a63907,0x041ffd2,
  44858. 0x04d8f1a,0x1d5823c,0x151b6a5,0x1b67c4b,0x175834c,0x0d2936d,
  44859. 0x1422802,0x0811b31,0x08161fd,0x102dae5,0x1f0012c,0x1c977d1,
  44860. 0x03bb365,0x177ad9f,0x15d66ed,0x0a19824,0x1ac737f,0x140be17,
  44861. 0x06bc17e,0x1a4e72a,0x0e102d2,0x199b3cf,0x102ffb2,0x1e551ca,
  44862. 0x0a6a515,0x1a237d9,0x0320d9c,0x1a26e52,0x05505e1 } },
  44863. /* 117 */
  44864. { { 0x15e68a6,0x00a50e8,0x179430c,0x0cc9ba6,0x0f9f0b2,0x16b3fcb,
  44865. 0x1d0b40e,0x1083186,0x0d2c144,0x040c607,0x068f2dd,0x02d21a8,
  44866. 0x1ec5181,0x024f9f4,0x12320ff,0x1270ccb,0x0612c27,0x04d9306,
  44867. 0x1b413a7,0x10df5d9,0x0758f60,0x15febe2,0x09ecb33,0x052ffb1,
  44868. 0x0313390,0x164259e,0x0025c06,0x1504c9d,0x0b3762c,0x1543a84,
  44869. 0x1fa7e5d,0x130751b,0x1582714,0x0cc74ae,0x19a7675,0x106a1a4,
  44870. 0x0f6fd34,0x05c4e58,0x0c5f217,0x1a94ae8,0x0617d80 },
  44871. { 0x0022b67,0x1933f38,0x052933b,0x0a6ed17,0x00536bb,0x1c22314,
  44872. 0x0959b49,0x03262a7,0x0382439,0x082a6a2,0x1e31292,0x02e4bbe,
  44873. 0x1a8d11e,0x0ad0f1a,0x094a9c7,0x1c63b36,0x0808171,0x103c336,
  44874. 0x0ce2803,0x0a03b63,0x02360a8,0x1c673b8,0x0bb64ca,0x1b5efa0,
  44875. 0x176098e,0x174d16b,0x0ee4c01,0x15dcbb5,0x1eb0363,0x04625df,
  44876. 0x02febff,0x09c4367,0x17b9678,0x0703483,0x167f72a,0x02923f8,
  44877. 0x0e93847,0x1127aa8,0x1e02cfd,0x010f9a2,0x05156f5 } },
  44878. /* 118 */
  44879. { { 0x006e8d0,0x1a71101,0x1cc9608,0x08fe2b5,0x15f6f5d,0x1c4a87f,
  44880. 0x1ca2758,0x1e95f56,0x17d4495,0x1762684,0x0a02a59,0x18bad1b,
  44881. 0x0bad890,0x127c51b,0x0a82481,0x0b8bfc9,0x17e0f4d,0x0bccf12,
  44882. 0x112578c,0x0cef5c4,0x035244c,0x19d2dc7,0x1c80e1e,0x1450f72,
  44883. 0x190f475,0x17bb81b,0x170f07c,0x0912b98,0x07fa415,0x07cda0d,
  44884. 0x02ee1a0,0x1601601,0x0d47458,0x039e5fe,0x00e2e99,0x1429399,
  44885. 0x0c9be19,0x16afbd5,0x196e9e3,0x139666e,0x0525459 },
  44886. { 0x01b54c4,0x1cb3cd1,0x167421c,0x156c92f,0x029ece2,0x0443200,
  44887. 0x06a4b21,0x1b3e29e,0x1e9fa79,0x1246e7f,0x08236eb,0x03848d8,
  44888. 0x1e14b91,0x0d71fb4,0x0c3efcb,0x17070b5,0x07ed1ed,0x18c0564,
  44889. 0x02161ae,0x1fae303,0x0bd0146,0x0a2a33e,0x0843ad9,0x0cf9fdc,
  44890. 0x1940816,0x1305511,0x0adcf46,0x1624b83,0x1c1cbed,0x0980440,
  44891. 0x0cb79a1,0x06f8604,0x034c713,0x0468c7f,0x1c39bcf,0x078d8c0,
  44892. 0x14af4e8,0x11b2dd5,0x0ad141f,0x1dbb9f0,0x022f0a7 } },
  44893. /* 119 */
  44894. { { 0x07f1b7f,0x13c8ff5,0x0753898,0x1bb9fe1,0x1c3d8c5,0x03ee2c4,
  44895. 0x0a70ce7,0x1810d85,0x14276e8,0x0d6a00b,0x1875593,0x1eb3d3f,
  44896. 0x090a918,0x1554086,0x15e59c0,0x19b8971,0x0364aa5,0x175bd44,
  44897. 0x1ebe9cb,0x184777c,0x0908fc4,0x0f25643,0x136ed72,0x018fcde,
  44898. 0x190136a,0x0691bf1,0x0527086,0x0abae00,0x1324a28,0x1e33ca5,
  44899. 0x1c791d6,0x0c50f40,0x18a8dc6,0x0191e64,0x066d7ed,0x1272b45,
  44900. 0x0c0389e,0x0361f70,0x1311b86,0x0de2ce6,0x079f81e },
  44901. { 0x04f3c4e,0x160f99b,0x052e0fc,0x0a26cfc,0x136b2ac,0x19f21ea,
  44902. 0x173f164,0x1fc894d,0x110d961,0x072ca3a,0x1caab8d,0x1d9cfc7,
  44903. 0x0508234,0x1ef53f9,0x04b802a,0x1424997,0x0f0a791,0x10f7dd2,
  44904. 0x064b54e,0x10dfa42,0x0af6c20,0x1e5a8e4,0x1fb0343,0x01e36bf,
  44905. 0x1b2cadc,0x10ca468,0x1e04b6f,0x00f4711,0x1bdd45b,0x1d356f6,
  44906. 0x069021c,0x1ae04b1,0x02a1268,0x13db25e,0x0ea05f8,0x0b77edc,
  44907. 0x0d386e8,0x172b31b,0x10001cf,0x06f3bcf,0x0442ecd } },
  44908. /* 120 */
  44909. { { 0x02f90a6,0x08d7345,0x0332d33,0x1adeb5a,0x1277d41,0x0ea5c77,
  44910. 0x0a31100,0x062d470,0x0d83766,0x00bd09a,0x04492fa,0x0b1bebc,
  44911. 0x04142b7,0x1eb5caf,0x1ef1a77,0x13c7c4b,0x15fd74a,0x151864f,
  44912. 0x02598f3,0x01e2c7b,0x186d5ac,0x1b86731,0x0caa7bb,0x1daaa88,
  44913. 0x10ea5d8,0x13d3d34,0x0262250,0x1bc47fe,0x0ced585,0x1b52f55,
  44914. 0x195d6b4,0x1a7c308,0x114a6c1,0x09c881a,0x0b0dfc2,0x107b22c,
  44915. 0x033d56e,0x0856ecf,0x1a47970,0x0e60d54,0x085176b },
  44916. { 0x0a21e38,0x0887d14,0x14e28c8,0x1aaee7a,0x17b6379,0x0106e24,
  44917. 0x1eefcb4,0x19ba6d2,0x1961833,0x08bbac9,0x0a14596,0x0bf5cbf,
  44918. 0x126d704,0x1c355ae,0x043ca69,0x0b6e067,0x030dc4f,0x15605ed,
  44919. 0x1318571,0x004815b,0x0d91cca,0x01628a3,0x0387c5c,0x059df0f,
  44920. 0x072d0a7,0x1d0e75a,0x002d9a6,0x09080e1,0x01aa0a8,0x07cebf3,
  44921. 0x02de6c2,0x08cd2ac,0x08160be,0x15b8f1c,0x10b6523,0x184726b,
  44922. 0x1431590,0x1ec1e04,0x1a2cf5f,0x176dcae,0x08ab154 } },
  44923. /* 121 */
  44924. { { 0x13c4a96,0x030019a,0x00d4a1a,0x1120b9b,0x0e5c60e,0x137c662,
  44925. 0x04d923d,0x13d7ab2,0x09faccf,0x15c05cc,0x18e796d,0x1f5dc64,
  44926. 0x0bbc1c1,0x13c556f,0x18e5b48,0x0405a5e,0x0d01898,0x08053cb,
  44927. 0x091d20d,0x16a91e7,0x0e3e18a,0x01d98d8,0x0b3415b,0x0c8a25b,
  44928. 0x068dd01,0x1de0add,0x052c0fc,0x00706db,0x1206c52,0x0535ec7,
  44929. 0x0db593b,0x13e2ef3,0x11a361e,0x19a5449,0x03f14aa,0x05b04d2,
  44930. 0x12922e2,0x15dc704,0x00aa4d0,0x109c016,0x01bfcdd },
  44931. { 0x1a365d9,0x1cd21ba,0x0c0cc42,0x1c11b1f,0x14ade15,0x016fc1e,
  44932. 0x14f5f5d,0x085392e,0x0de3187,0x1b984ea,0x02b3833,0x042466c,
  44933. 0x031228e,0x1bb34b2,0x10f48e3,0x0b4a620,0x1edf90f,0x1fe156d,
  44934. 0x0d7e4e5,0x0c996ef,0x101041d,0x0562236,0x14802cc,0x02e41fc,
  44935. 0x0642d23,0x03ae1e4,0x16e6a88,0x1980245,0x1eae47f,0x1d89020,
  44936. 0x09215b8,0x0d190ed,0x1864455,0x10358a2,0x01088cd,0x1e3438f,
  44937. 0x027757b,0x1b368f9,0x153c66d,0x077ef73,0x025b78a } },
  44938. /* 122 */
  44939. { { 0x16707ce,0x1ab8c0a,0x042a420,0x108629f,0x1bdc239,0x12bedec,
  44940. 0x0216a2f,0x17002f9,0x1ad63a4,0x05dd112,0x0b3ff75,0x170c2b5,
  44941. 0x025ce71,0x194aa39,0x09991d5,0x1a7babe,0x1f74f0a,0x1854078,
  44942. 0x10d4bb5,0x0a7147f,0x06ca010,0x02a101e,0x1e29901,0x018e769,
  44943. 0x07a8833,0x00d9596,0x180b72b,0x06867dc,0x0b17c7b,0x0ce7f69,
  44944. 0x11cb812,0x17ac653,0x18681a4,0x16e1bcf,0x0518dbe,0x16712f3,
  44945. 0x12b7895,0x0b28644,0x073c371,0x0e0cb4a,0x070ab95 },
  44946. { 0x1585d93,0x1c7623d,0x193919d,0x014c67f,0x0a6d361,0x10188d6,
  44947. 0x055393a,0x05e43b4,0x1bd6400,0x1910c85,0x12dea6b,0x158fb23,
  44948. 0x179e633,0x17341be,0x04f0c7f,0x1dd15da,0x1d71616,0x16d2503,
  44949. 0x0bf3585,0x144e647,0x1694d78,0x12dd0a6,0x1019a5b,0x1eb0841,
  44950. 0x154d74d,0x1e4b99b,0x189de38,0x10bca09,0x15a5c2e,0x15062ad,
  44951. 0x170c156,0x1147596,0x13df538,0x0476d18,0x12d4a82,0x1cb12d5,
  44952. 0x04c85dd,0x0421504,0x19afbf2,0x0f2a3bb,0x05fec9f } },
  44953. /* 123 */
  44954. { { 0x0519f99,0x0163e7f,0x0d4d7af,0x01ca820,0x0396bd8,0x1cc479f,
  44955. 0x0500a28,0x1435bdb,0x1d601bd,0x001db9a,0x1992b07,0x006c299,
  44956. 0x10fd302,0x0092014,0x0dfafa4,0x012fab0,0x1a3a554,0x0e55750,
  44957. 0x02e204e,0x0e7a4b6,0x10b9dce,0x15f6584,0x0d7b504,0x07b5678,
  44958. 0x09ff7d6,0x038cc81,0x0418b6c,0x0aa86fb,0x04c11d5,0x17ab215,
  44959. 0x0249df4,0x049f922,0x17fa645,0x092a6a3,0x06dc9e6,0x18f625d,
  44960. 0x184c618,0x0957116,0x14655eb,0x0c79d1d,0x00a8d56 },
  44961. { 0x021fde1,0x028b185,0x01250eb,0x0cd207b,0x0fcf5dd,0x0eb140e,
  44962. 0x067b97f,0x068da49,0x077a49a,0x0f6e378,0x1701bd3,0x058050e,
  44963. 0x0646bda,0x1a3dc02,0x18383d8,0x106dfa1,0x09b5e67,0x1082c0b,
  44964. 0x1a2a010,0x032255b,0x1d32c96,0x05549d9,0x17cffa8,0x0aed78b,
  44965. 0x18edb0c,0x123cf89,0x1b634df,0x12e35ad,0x05e7cb7,0x0b9ce67,
  44966. 0x103aae1,0x03a4056,0x0a4b434,0x0fe9344,0x155f8e8,0x02bb084,
  44967. 0x13a86f9,0x17d5ead,0x18a7e1c,0x126d548,0x095b934 } },
  44968. /* 124 */
  44969. { { 0x1f951de,0x05380cc,0x0d16666,0x0de0b1b,0x0fade59,0x081ee9c,
  44970. 0x0707bcf,0x1a69a8f,0x133b141,0x14946ae,0x1a2901b,0x100159f,
  44971. 0x1d9a465,0x00e77d1,0x022b4bf,0x0e4dda2,0x121e013,0x1b25cb4,
  44972. 0x1a0eee7,0x0d4d6d1,0x0544b9b,0x0e09217,0x0a7c79b,0x0cb2cd6,
  44973. 0x0f6762f,0x1a0e9fc,0x1978416,0x069ba12,0x011e1ca,0x09cd0b0,
  44974. 0x06f53a4,0x04a2aa8,0x0a4dc68,0x10b36f7,0x02b3208,0x08df006,
  44975. 0x11d1612,0x03d70e9,0x1e9f6f7,0x0a2c435,0x02e25ef },
  44976. { 0x18e7357,0x1e7c7ee,0x16e094c,0x11d59db,0x133ba21,0x0269561,
  44977. 0x18c741e,0x1c4d1c7,0x0f2804a,0x0493f9b,0x1eb5f87,0x1a44efc,
  44978. 0x0001433,0x0c3fbc5,0x10073c1,0x04f5c16,0x036aa00,0x0cefe78,
  44979. 0x16691ad,0x08d9163,0x0d32c9e,0x030f944,0x0a9b792,0x114087b,
  44980. 0x0da2f1b,0x1ab6eab,0x17cb42e,0x08c461c,0x1efb563,0x1b720ce,
  44981. 0x1d067c2,0x043a590,0x1ec37cd,0x122d9aa,0x0e5edc3,0x047b7e0,
  44982. 0x0c7ce85,0x031546d,0x1cf5bc2,0x14fc283,0x087979e } },
  44983. /* 125 */
  44984. { { 0x11c747f,0x13d9fbf,0x0da66df,0x1b8dcc6,0x151a4c1,0x196dd00,
  44985. 0x1fdc2cd,0x1fc84e7,0x0d3ee54,0x136911a,0x12b83f2,0x1c19a67,
  44986. 0x0c12fc8,0x0eeb788,0x0ca14e1,0x139f24e,0x1bdf01a,0x0e4379f,
  44987. 0x0db2ba4,0x04ceffc,0x0a44532,0x1997f7f,0x0e69c00,0x115e42e,
  44988. 0x0a328ce,0x0fa164e,0x1bda9cc,0x004acee,0x096813c,0x19efb35,
  44989. 0x0a31a1e,0x11b65db,0x14aab12,0x07f5e8c,0x116bbb1,0x05bc61b,
  44990. 0x179241b,0x0911b54,0x1305b01,0x005847a,0x03ec988 },
  44991. { 0x072f74d,0x13b0620,0x01643e7,0x1d56b28,0x078eb0d,0x1804e17,
  44992. 0x1a90326,0x1cbb67b,0x038b59a,0x1f43af8,0x16a8191,0x086c569,
  44993. 0x08f40eb,0x04879bc,0x1a93e48,0x15f1734,0x1afedbf,0x177f5f4,
  44994. 0x019f895,0x1f2d4b3,0x0aebf87,0x11bad5b,0x079bfb4,0x1b62796,
  44995. 0x0782a3f,0x1108bf9,0x19c3e89,0x02058e3,0x0c0dbe5,0x03767ea,
  44996. 0x05d74ac,0x06068e5,0x17cc268,0x1f3c029,0x18acad9,0x051b7eb,
  44997. 0x1a25da3,0x119f9d5,0x12450bd,0x1d1df5d,0x03e9315 } },
  44998. /* 126 */
  44999. { { 0x19a9ea9,0x0e7d291,0x098a495,0x0017c67,0x00f3c69,0x1b215e9,
  45000. 0x1ad2e72,0x030eb3d,0x000bae7,0x18b62a3,0x043e10c,0x0dabe68,
  45001. 0x16874a7,0x087894d,0x0ed40ba,0x03e3824,0x1a81285,0x056e47c,
  45002. 0x0d89023,0x16ec943,0x177bf57,0x0f8d403,0x045bb00,0x01bb8b8,
  45003. 0x0cef21f,0x0d3ba37,0x13969a9,0x1893a8f,0x0955ba3,0x0df3837,
  45004. 0x0c07857,0x168baf3,0x09c0c79,0x08843b1,0x0c21de3,0x0e224f0,
  45005. 0x0c6a22d,0x0c2ee3c,0x09e4489,0x01a14d0,0x02ed02a },
  45006. { 0x1aa2682,0x01a0b26,0x18954c1,0x16026b2,0x0e26d32,0x03384b8,
  45007. 0x00d2af6,0x05c8939,0x1ee77ae,0x0d0ce95,0x1b05a44,0x053475e,
  45008. 0x1439bd5,0x0e6b082,0x1329701,0x01fc26d,0x19bdc6c,0x0b1b852,
  45009. 0x04f544d,0x041a4f7,0x051aca4,0x02aaa62,0x161cc35,0x19bd7e5,
  45010. 0x058c996,0x102f5e9,0x02943e6,0x1963732,0x0f01510,0x04bd3d8,
  45011. 0x185a6a3,0x023a42f,0x0c36d34,0x1baf416,0x0229d4b,0x03e22ed,
  45012. 0x009b2a6,0x1809ca5,0x15f7476,0x08953df,0x0146278 } },
  45013. /* 127 */
  45014. { { 0x12803cf,0x11d7691,0x1cd1af2,0x17352df,0x01e4398,0x15bc45e,
  45015. 0x1d5fdd2,0x09b95ec,0x07e68c0,0x1d29f00,0x1f34830,0x1832b96,
  45016. 0x0a5f969,0x0e0345e,0x02d969b,0x06065e5,0x1d31d86,0x071e500,
  45017. 0x1e02385,0x0677030,0x18be9b7,0x0cf7f30,0x0d75c13,0x03728db,
  45018. 0x13542b0,0x0df93b7,0x1befb77,0x00afc33,0x1275cee,0x1795c81,
  45019. 0x119f460,0x1101ef7,0x0dc5f77,0x1b60a1e,0x14fde11,0x05ade07,
  45020. 0x09ba507,0x0faaabd,0x058a00d,0x16d6805,0x07acb57 },
  45021. { 0x0e6b07c,0x09ab4a2,0x1177490,0x13c38e6,0x051c4cc,0x19dcfda,
  45022. 0x1136389,0x1f880e8,0x1b88e34,0x124b03c,0x09ddb7f,0x099fe2a,
  45023. 0x1c77d18,0x03a114c,0x040cee7,0x0512eda,0x08477bf,0x014d053,
  45024. 0x1a3c108,0x1fbe21d,0x16d659f,0x16225da,0x1385c51,0x135d0aa,
  45025. 0x106c2fb,0x06ac18e,0x0f64f9f,0x059705b,0x16b607b,0x0e231e4,
  45026. 0x0a20ce0,0x0ea93c5,0x0aed251,0x110ea03,0x0471dd2,0x1bdf2f1,
  45027. 0x0675fbd,0x0c03e3c,0x145b2ba,0x172c6c6,0x06a5a05 } },
  45028. /* 128 */
  45029. { { 0x08f4f33,0x18f5335,0x1d2a4b9,0x0c9bd51,0x12fc6fc,0x144230f,
  45030. 0x094b3fb,0x011a6ac,0x008954d,0x0d8541f,0x0add996,0x18468d1,
  45031. 0x045bd68,0x0807c68,0x0a04d5e,0x0cf5c80,0x1c052b8,0x08c0e0c,
  45032. 0x01d9310,0x14a2d23,0x1d24986,0x1709aba,0x12c077e,0x06cef6f,
  45033. 0x09ae559,0x18c8b93,0x151b726,0x0da2e04,0x0097c8f,0x024ce20,
  45034. 0x1ee379a,0x04b3880,0x0df0032,0x14ec5bb,0x0b645f4,0x0c81235,
  45035. 0x0a7ab5f,0x1a3690a,0x192329f,0x168e1d9,0x0688054 },
  45036. { 0x1a5b86c,0x0b45528,0x091fc34,0x112aeee,0x0437e4d,0x1901949,
  45037. 0x101dbc5,0x09d5d08,0x19647a5,0x13d643e,0x1588b02,0x1496080,
  45038. 0x0f1e597,0x1853cf9,0x1bf971b,0x02adbdb,0x0c24d55,0x1579f78,
  45039. 0x1c11f3d,0x1f609dd,0x0137917,0x0faa5b1,0x0de49e6,0x097c170,
  45040. 0x0a32f31,0x18643af,0x0c3119a,0x02af8cb,0x018978e,0x08673f1,
  45041. 0x0bf4a32,0x19bcb0f,0x10fc3ba,0x1bdf6dc,0x1c722e1,0x1bba65a,
  45042. 0x0a8e10c,0x0191006,0x1b94ced,0x033b29e,0x00021f4 } },
  45043. /* 129 */
  45044. { { 0x1519d26,0x0891621,0x0114864,0x1a814a3,0x1dafac1,0x05dc4fd,
  45045. 0x1c7a552,0x1f398de,0x016844b,0x1799bae,0x1a35567,0x1ef22f1,
  45046. 0x05e7789,0x0fc5f0e,0x1d666d8,0x1bc8009,0x19a2cbb,0x0c04464,
  45047. 0x04c81b2,0x1344c11,0x0851893,0x1ffe698,0x086b92f,0x11fd5fd,
  45048. 0x0b3fee0,0x15e3326,0x07fc52a,0x03e7013,0x041ef96,0x0a66154,
  45049. 0x0d8360e,0x02fe03b,0x1fad8ad,0x1dbb9ba,0x15d9b7a,0x04df868,
  45050. 0x0425251,0x18b582d,0x1b67c79,0x10053c3,0x0798558 },
  45051. { 0x1106473,0x19d554a,0x08128b2,0x02b4c3b,0x15fafa4,0x0ab1e04,
  45052. 0x04d894e,0x10ffa79,0x195312b,0x1524048,0x0171dae,0x0b057f1,
  45053. 0x156c7e7,0x11863c6,0x1db6ad8,0x0881ae1,0x11c7747,0x1467182,
  45054. 0x1f6d861,0x1d7a29f,0x00966db,0x1d0c872,0x0c38107,0x1cc5c55,
  45055. 0x0c4666e,0x1eb5d08,0x09d3ccc,0x07aafc5,0x1b9b669,0x16e27f3,
  45056. 0x1f401aa,0x00da506,0x0f72f6c,0x1a0f57d,0x179a441,0x0e63198,
  45057. 0x0569247,0x081304b,0x0c23671,0x1863a1f,0x095d823 } },
  45058. /* 130 */
  45059. { { 0x00528a5,0x15ec30a,0x0f21abb,0x14a72f3,0x1268c2b,0x00a255f,
  45060. 0x06e293b,0x1db6379,0x182a7d7,0x17d5d86,0x0463607,0x01a29c0,
  45061. 0x0ef12c7,0x10e0aac,0x181c5a2,0x1ce7c62,0x0b7e4b7,0x099f214,
  45062. 0x0ebb277,0x0ecc6f0,0x035c631,0x1f70956,0x145cbfe,0x02f6548,
  45063. 0x10bfbbc,0x0951bef,0x01d07e0,0x0425f0e,0x088f9c4,0x05edf14,
  45064. 0x174f73b,0x0ead94a,0x1dc15aa,0x14720d4,0x03b2e40,0x07e6323,
  45065. 0x0aeadb0,0x0f0142b,0x13d51fb,0x1aaf0ca,0x00e2708 },
  45066. { 0x1e20f88,0x06629e6,0x00e489c,0x18beb62,0x1338272,0x058edfc,
  45067. 0x1867977,0x182a085,0x1b72d74,0x19ef10c,0x0aa9552,0x1516555,
  45068. 0x0616c49,0x1dd435d,0x0110f96,0x02d2a01,0x17220cf,0x0f735e6,
  45069. 0x026af44,0x1f58d75,0x039d59f,0x1df88ab,0x0a0c485,0x09974a4,
  45070. 0x08af2f3,0x0837269,0x1c1c9ea,0x04fe07c,0x017766f,0x03cfb48,
  45071. 0x0f9a10b,0x0f50224,0x13469bd,0x0b9dc65,0x0d1a90a,0x1a9181e,
  45072. 0x03990db,0x0bc2531,0x059e3f1,0x077f653,0x00d3dab } },
  45073. /* 131 */
  45074. { { 0x029c3cc,0x1bb7367,0x0f1a3e0,0x19e02d9,0x0b0507e,0x1ca670e,
  45075. 0x1e65978,0x083bd7f,0x173c50d,0x07e2937,0x1b38f49,0x14a85a2,
  45076. 0x014edd5,0x08e098a,0x0def766,0x10c0d76,0x0f2e33a,0x071a217,
  45077. 0x018a76a,0x12066f8,0x13312ae,0x122c955,0x15febb1,0x0570af6,
  45078. 0x18997d8,0x0bb0d49,0x068cdcc,0x1ad9197,0x06751fa,0x0ef1484,
  45079. 0x05a0965,0x03182e3,0x01e97fb,0x0b9abd4,0x084efda,0x13c9e91,
  45080. 0x1cb89f6,0x1c3e172,0x0d09a84,0x1d6b0e9,0x0530b4e },
  45081. { 0x0b7b5ae,0x13ad0dd,0x0fd3a7c,0x1a074af,0x1b69dc4,0x0e282dd,
  45082. 0x1712a91,0x00592e9,0x1416ac4,0x131b4f9,0x061771c,0x1cf15db,
  45083. 0x01735e4,0x06ea235,0x12361e7,0x160540a,0x0699e16,0x1426758,
  45084. 0x026c469,0x1edf48f,0x0784f73,0x0fd9527,0x1aa8310,0x1536d2e,
  45085. 0x1690293,0x15958fb,0x03c0ea2,0x02999c0,0x0d66c18,0x12adc22,
  45086. 0x005932c,0x0612a44,0x194e7d6,0x19138db,0x1390f68,0x13c0a5a,
  45087. 0x08b6a4d,0x1c59738,0x15dfd49,0x0a5018c,0x0909425 } },
  45088. /* 132 */
  45089. { { 0x15b4c2f,0x0d0a686,0x127349a,0x16b914c,0x0b8fc59,0x11bea51,
  45090. 0x12ceac3,0x0fd2b7d,0x0911103,0x0d0d3b4,0x0d4c8bf,0x00b529c,
  45091. 0x1c5810e,0x10bc7d7,0x137304a,0x19cc544,0x1b28e3d,0x02e1631,
  45092. 0x114b111,0x187e2f2,0x1161995,0x01a16a2,0x0d4cc3b,0x1df0252,
  45093. 0x1a60ab4,0x009d012,0x0a2eba7,0x0a9264a,0x03caf88,0x1303717,
  45094. 0x11c9746,0x06c937e,0x04091ab,0x162f8ea,0x1efdc13,0x078fa15,
  45095. 0x1d8b333,0x1e8eb15,0x05bd49e,0x0239fcc,0x0505701 },
  45096. { 0x134356b,0x025677a,0x1ef3402,0x0a96961,0x1df1de0,0x1026e0c,
  45097. 0x1f8173b,0x1c20435,0x0361b78,0x05ef344,0x034e2d9,0x198fdef,
  45098. 0x0ea324f,0x15852f2,0x0cdcb3b,0x0332dfd,0x0b36581,0x177827e,
  45099. 0x1ac2ad3,0x1cbaa0b,0x186e7dc,0x0411c62,0x078a6d6,0x1b0006e,
  45100. 0x03197bc,0x0e7ef2f,0x05201ae,0x17ebc8a,0x0e67ab8,0x0b45e8c,
  45101. 0x0b50cc2,0x1f3ec7f,0x0a7d04e,0x0c5da13,0x048ed70,0x19438fe,
  45102. 0x05dce22,0x0dc2411,0x19e7d21,0x0dfaa81,0x08ff0b3 } },
  45103. /* 133 */
  45104. { { 0x1f42cff,0x1717a1f,0x05f267c,0x1a386a6,0x03c19f9,0x10daa2d,
  45105. 0x04e4aae,0x065b6e9,0x14afa9a,0x0119582,0x1350da1,0x1a8dafb,
  45106. 0x150b855,0x02e7cc8,0x10d7881,0x1443115,0x0c7f001,0x0ebe791,
  45107. 0x15020c1,0x1a6b5dd,0x0fcd057,0x0caa9e6,0x0969294,0x1c57272,
  45108. 0x0579393,0x013af2b,0x00d08bb,0x0406656,0x053958a,0x002f1d6,
  45109. 0x18e6c24,0x0f3d362,0x08051a3,0x10c6b31,0x1027f19,0x1f6941b,
  45110. 0x0748e7a,0x0742bfb,0x158fa78,0x1dd8aef,0x071b28e },
  45111. { 0x1726bf8,0x15866cc,0x1cf1250,0x1238411,0x1290a3b,0x0cc7550,
  45112. 0x0439ec1,0x051fae5,0x1a25a91,0x153bc8f,0x1f5f6b1,0x1649806,
  45113. 0x1b2d33d,0x187141b,0x07bfac1,0x1c54184,0x16ee3da,0x1dfb86c,
  45114. 0x141d809,0x1b03230,0x17e343e,0x1426a56,0x12bac2a,0x18b6e98,
  45115. 0x1101fe8,0x1eede3a,0x1ab49ba,0x17f654d,0x18aa4ed,0x103435b,
  45116. 0x122ea04,0x1c22b30,0x14aa8f2,0x12e2764,0x076cfae,0x141a21b,
  45117. 0x0318295,0x1ff623b,0x0496b39,0x034661b,0x0729471 } },
  45118. /* 134 */
  45119. { { 0x0bbd495,0x02c8219,0x1cfff39,0x037ca92,0x130f4dd,0x0e1fa71,
  45120. 0x1b87576,0x00800d7,0x059ba72,0x077303c,0x0b1da10,0x1a7e858,
  45121. 0x1ec194f,0x14ff445,0x19dac4b,0x0042141,0x1dbec2b,0x18be6ee,
  45122. 0x02047b1,0x1a86d60,0x09e4689,0x1b9425f,0x09a9ae8,0x0fa8229,
  45123. 0x195b200,0x1a255e1,0x0c3c479,0x119bf3e,0x196402f,0x1f64749,
  45124. 0x01717fa,0x1dd68c5,0x0751743,0x0689bc5,0x1e0b1b8,0x07337f0,
  45125. 0x1eb292e,0x12f0b85,0x1f57ce5,0x1b0b003,0x0001c39 },
  45126. { 0x04a0912,0x02e5ced,0x1293d20,0x1488217,0x127cb76,0x18eb2de,
  45127. 0x12e3bb1,0x135de7b,0x1481684,0x007dd95,0x0918d5e,0x004d516,
  45128. 0x08ef6a7,0x0962273,0x1897220,0x0e9502a,0x12c4d7a,0x0312611,
  45129. 0x0c58c79,0x0ee06e9,0x1c2e81a,0x18edc8b,0x01393df,0x0c3db2a,
  45130. 0x065fd1f,0x11e8e82,0x072f79b,0x0209009,0x131fcfb,0x1060eb8,
  45131. 0x0558df3,0x115b48e,0x0e4dbc2,0x0cb9311,0x1172b3a,0x01eea61,
  45132. 0x0e28745,0x0b06e67,0x0bc4e80,0x0e17723,0x09132e6 } },
  45133. /* 135 */
  45134. { { 0x196099d,0x1f7f13c,0x0232015,0x1740dcc,0x172344d,0x0ac2c45,
  45135. 0x01d0342,0x1d3d695,0x079e5ae,0x09ed783,0x08beb79,0x1535211,
  45136. 0x0ac9560,0x083f383,0x12f84c4,0x048d4fe,0x19b2830,0x136af9e,
  45137. 0x1f328f9,0x11d1b44,0x1292a5f,0x1326147,0x1ad4772,0x03bfaf1,
  45138. 0x0310ef3,0x1f2a67d,0x08b281c,0x05c18f8,0x0da6839,0x0b4a520,
  45139. 0x1f040bc,0x0ea1a71,0x0bb07cc,0x1701a8b,0x0f8aeb6,0x1ae07d0,
  45140. 0x14d3c9d,0x09e0335,0x03b47aa,0x1caf328,0x07d0b03 },
  45141. { 0x1d94c63,0x1f51826,0x0ce97f9,0x0ae7161,0x17ef01c,0x0735a5a,
  45142. 0x09e3285,0x0ed2a69,0x0a53532,0x1b1166f,0x0b40181,0x140ef84,
  45143. 0x09af696,0x1ea3590,0x0f06219,0x05694e6,0x0bb626c,0x04b2a66,
  45144. 0x013cf13,0x11a7435,0x0b74a09,0x1696b9a,0x0d65be7,0x0aa3920,
  45145. 0x1021a5d,0x11fefe9,0x1c7b144,0x0574fa5,0x01aa39e,0x1492d96,
  45146. 0x09fe5c9,0x1f1d652,0x0e75d0e,0x09537e9,0x04b8646,0x1df574e,
  45147. 0x1b83e50,0x035a1d4,0x1798298,0x05fb56b,0x031b178 } },
  45148. /* 136 */
  45149. { { 0x034db92,0x0dd22a0,0x11361e3,0x031e69b,0x0397790,0x1aa619d,
  45150. 0x13cbb7d,0x1111a00,0x0cd563a,0x152caa5,0x1feb47a,0x191376b,
  45151. 0x18a29d6,0x186c5ed,0x0b7d956,0x1b68f51,0x02d8cdb,0x1fbfdc2,
  45152. 0x034c816,0x1c74070,0x1ca9b72,0x193e563,0x10cd6c2,0x14a8ebb,
  45153. 0x00bcbd8,0x12fffe3,0x07ae934,0x06deee3,0x10fca67,0x0e1c062,
  45154. 0x000f640,0x1018032,0x1dacf7b,0x0fc268f,0x163d5a0,0x02eb9ec,
  45155. 0x1cefbbc,0x13f31a2,0x1b47d5e,0x1ca7c0f,0x06fc0fb },
  45156. { 0x01b0e5f,0x088b5dc,0x0ee125b,0x0a5590a,0x182dd2a,0x19c3f86,
  45157. 0x08b50c9,0x0b26afc,0x0ba912c,0x1199542,0x177304f,0x0c8693a,
  45158. 0x138b71c,0x01c6c2e,0x060bba5,0x19a9c19,0x13cbf7f,0x1c85caa,
  45159. 0x03fb578,0x0737787,0x09032cb,0x0e2d621,0x08b19f2,0x00fb4ab,
  45160. 0x01217bf,0x07775f9,0x1682e79,0x0b580b5,0x09e0c65,0x0961477,
  45161. 0x0fc42ec,0x09176dc,0x0f3aee5,0x03748ae,0x1a722c1,0x1e95ce4,
  45162. 0x0a0e553,0x1330095,0x03f232c,0x1435299,0x0701935 } },
  45163. /* 137 */
  45164. { { 0x0626dea,0x06a0ed2,0x0e7f796,0x142b720,0x05ef66c,0x12732d9,
  45165. 0x04290c5,0x19f3350,0x1748cfc,0x1f36d56,0x10bea67,0x0d7a5e2,
  45166. 0x167ab9a,0x0ea38bc,0x12e85a1,0x1473749,0x1366bc3,0x1096985,
  45167. 0x0fd141d,0x0d4bb91,0x0c0e1f4,0x148a10d,0x0e1a394,0x1774389,
  45168. 0x0620659,0x1c83d34,0x1b69a62,0x1696aa5,0x0537072,0x0e6a72a,
  45169. 0x17d40e7,0x13d202c,0x0a07a9e,0x02efe21,0x1fcf5f5,0x015071f,
  45170. 0x1b5ceb3,0x0c8f2d1,0x0980106,0x1912d39,0x06c961e },
  45171. { 0x0e7eb46,0x1ee0de2,0x0d21c0e,0x0eb2d8f,0x16bac55,0x17eba6e,
  45172. 0x05f359a,0x1e69f32,0x1656ce6,0x11aa882,0x05c5d55,0x0a18649,
  45173. 0x0d3d1fb,0x11f7fd9,0x099e0f9,0x1457bfb,0x1f3eefa,0x1debcf8,
  45174. 0x1ebe7bd,0x1f7ca82,0x17a4a4e,0x112d2ad,0x1b3bd91,0x0e26608,
  45175. 0x132381a,0x0d188b7,0x1ee5589,0x165454f,0x027e96d,0x121d058,
  45176. 0x0f1a82a,0x0906567,0x18fe5d2,0x1d56022,0x037d6b7,0x14a4683,
  45177. 0x049e7f9,0x0d44e5e,0x12d4f01,0x1b0d3c4,0x0830883 } },
  45178. /* 138 */
  45179. { { 0x0557389,0x18e3101,0x02f2566,0x0f5bdf8,0x1fe5ce9,0x1879c1a,
  45180. 0x0f9fe0c,0x03d1277,0x116cfb8,0x1f06357,0x10a3f49,0x0cb7a08,
  45181. 0x026f64e,0x1bcf30c,0x17a4916,0x02394a7,0x1c1487e,0x1845189,
  45182. 0x116f3a4,0x1d87728,0x149e65c,0x0a6b3f6,0x0cef00c,0x0f046a4,
  45183. 0x16b2430,0x0e934f9,0x1e4eb4c,0x0f1cbb5,0x00890cd,0x15b863c,
  45184. 0x1a7c9a0,0x13c8bdf,0x015c34f,0x1d7f538,0x0e939b2,0x1826ba9,
  45185. 0x1e3fcc6,0x11bc523,0x03e310e,0x0ff2cc7,0x02376f9 },
  45186. { 0x0575b99,0x10f6057,0x037029b,0x1f0372e,0x1e14cb4,0x139ca3b,
  45187. 0x0e0934e,0x13be014,0x1fb235a,0x1a5ce40,0x18a5102,0x02beb7e,
  45188. 0x1a8d151,0x0f0b2eb,0x14d6d0c,0x07c779f,0x0a2b2ee,0x1ae897f,
  45189. 0x1460b9e,0x13094de,0x108e629,0x19e1b2e,0x1390f8b,0x1e6dce4,
  45190. 0x0709130,0x000cc99,0x03f4d15,0x1316940,0x196dce6,0x1e875d7,
  45191. 0x1508f13,0x046ceaa,0x00ba0ae,0x12bc253,0x10b6c0c,0x02a37b5,
  45192. 0x015464a,0x1a0c851,0x00a5a2a,0x0c2d7e2,0x08c4616 } },
  45193. /* 139 */
  45194. { { 0x11f36a5,0x0512c16,0x1cb7bff,0x051298b,0x0eded2b,0x076c278,
  45195. 0x136e10f,0x1366b4b,0x0db0e3b,0x087c4c1,0x068448a,0x15e00e3,
  45196. 0x16cce0e,0x1cd1b16,0x1995f90,0x0fc8fa1,0x15d6269,0x02a8b52,
  45197. 0x198d945,0x1c3eef1,0x09bc269,0x05ea813,0x178f7b7,0x038af8a,
  45198. 0x0230044,0x1c6f676,0x131c155,0x1707e63,0x089eabd,0x1db98f2,
  45199. 0x0d06f7b,0x072bf9b,0x0b678cf,0x0d80090,0x0473fe7,0x112119f,
  45200. 0x15f52cc,0x15e37a2,0x0458b2f,0x045698c,0x0155ea6 },
  45201. { 0x16fa42e,0x1178fc3,0x1b9e52f,0x12ff5bd,0x0b5e874,0x0432d7d,
  45202. 0x1c3d4e3,0x160d25c,0x0df8059,0x174cdc2,0x09eb245,0x00dd16b,
  45203. 0x0b0ceb6,0x16a31e9,0x148cd5c,0x013419d,0x0232a9a,0x1968793,
  45204. 0x0187ef7,0x1333187,0x110b252,0x13e0df1,0x1c46222,0x1155bc6,
  45205. 0x029c50d,0x19ecd89,0x00ec4d4,0x179f36f,0x029708d,0x037c7f8,
  45206. 0x020f29d,0x1b507df,0x1a013a1,0x1422252,0x14612ac,0x151d209,
  45207. 0x1cbd4ab,0x14259ed,0x1630cbf,0x0484b20,0x08f570f } },
  45208. /* 140 */
  45209. { { 0x0a9c508,0x1364516,0x1e037ad,0x04d3ad6,0x0dc5bec,0x156b001,
  45210. 0x0499a23,0x0282dac,0x149d726,0x0c20dcb,0x1cb9bd8,0x1cd99c8,
  45211. 0x1641e40,0x0fd3d43,0x0890990,0x12f415b,0x133cc39,0x022dcfe,
  45212. 0x105773d,0x1d1f52f,0x029db25,0x190974b,0x004933a,0x167b2ac,
  45213. 0x072c67d,0x0221d46,0x0df069e,0x1c5bda5,0x1027ff8,0x04e336e,
  45214. 0x11a52ac,0x0fcf457,0x09a057d,0x063b1fc,0x089b3dc,0x055b17e,
  45215. 0x08a2621,0x193473e,0x1307532,0x10f6588,0x03d171e },
  45216. { 0x0e49820,0x160b746,0x1724e0a,0x0581889,0x04ee45e,0x142c621,
  45217. 0x1e449cf,0x1f21d8c,0x046327c,0x0c6592e,0x16707e4,0x0ed78c2,
  45218. 0x1343e38,0x1baa2e5,0x0db8380,0x068fd6d,0x1ab5d12,0x0b25c1c,
  45219. 0x0c03550,0x0124e94,0x116972e,0x13440e0,0x09aaca3,0x0eb5086,
  45220. 0x00fffeb,0x06fa52c,0x08d6448,0x14b0059,0x09f4a30,0x0168190,
  45221. 0x001ffba,0x11cd527,0x118016b,0x108e55a,0x11c30bb,0x0f7338d,
  45222. 0x0b9d4ec,0x082d78d,0x0401058,0x1f0699b,0x0234e98 } },
  45223. /* 141 */
  45224. { { 0x0db9cda,0x1a9040a,0x1243fd0,0x0f2d5bd,0x19cfdc4,0x02c5b6c,
  45225. 0x0a9bebd,0x0630875,0x1743eaa,0x18fba0a,0x0d7604f,0x125cc2e,
  45226. 0x15915e1,0x0562cae,0x10688b4,0x1791a68,0x167c044,0x13825df,
  45227. 0x188e88d,0x0c08e37,0x15572f9,0x040ae8e,0x130c98e,0x163bb29,
  45228. 0x0230b76,0x133ca08,0x1c30722,0x05ca873,0x1c910df,0x00d6419,
  45229. 0x17d5ac5,0x10cb709,0x07c999f,0x015bda3,0x07e887c,0x003604a,
  45230. 0x1621695,0x0da9304,0x07a4f79,0x1c79c74,0x06a2130 },
  45231. { 0x13ca1a7,0x1b3d025,0x1a03486,0x0601819,0x0f42ed5,0x16783d5,
  45232. 0x14da24c,0x0b44599,0x15c25c3,0x1291d40,0x013418d,0x12b11ba,
  45233. 0x1becdd3,0x197c9d1,0x168d40a,0x16a60e7,0x03cd5e5,0x1a62f06,
  45234. 0x0c9a1dd,0x1ea90c2,0x0292ef9,0x1e0f3a1,0x1b61ffb,0x09cbdbd,
  45235. 0x0c29ea2,0x18d36cd,0x00ce127,0x115793e,0x1239050,0x1149207,
  45236. 0x14ec26c,0x0ff2686,0x191072c,0x15aa833,0x0e079ab,0x002054c,
  45237. 0x16feb87,0x103a04c,0x0a0c0fb,0x155389a,0x034f06f } },
  45238. /* 142 */
  45239. { { 0x148f005,0x0e3cf91,0x02c61a7,0x03be924,0x1b5c5d7,0x1732524,
  45240. 0x15f29b7,0x169fa36,0x0e82a4f,0x0dbfb9a,0x1e0d988,0x106972a,
  45241. 0x16637cb,0x1e943ec,0x0d0406d,0x1d95792,0x0ac0392,0x18ac87c,
  45242. 0x1dd7d38,0x1b86e6f,0x0c62280,0x07b530d,0x02cdbd4,0x0aad1b5,
  45243. 0x18304a6,0x1853a7a,0x0764c21,0x01af255,0x0895cc8,0x18c97e4,
  45244. 0x07db45e,0x0922927,0x18392fa,0x0adcf24,0x09f7507,0x0b5e6c0,
  45245. 0x1caa82b,0x16bcf12,0x1746914,0x163e822,0x0764d47 },
  45246. { 0x0ee8b9c,0x11181d1,0x152177c,0x070bbf9,0x1b9f72d,0x009d1b8,
  45247. 0x0e60c42,0x1ead685,0x13de741,0x146291d,0x0eed6f8,0x04b5e60,
  45248. 0x0f08576,0x164dfcd,0x1bca66a,0x0b66924,0x0080d44,0x110df56,
  45249. 0x1ae8b03,0x047405a,0x08646a5,0x18bfe71,0x18c0a86,0x00183d5,
  45250. 0x0a235e3,0x188a28b,0x09ed2a4,0x0a86e6d,0x0c89f74,0x1cf4606,
  45251. 0x17b4f02,0x081db11,0x081904f,0x1fe3802,0x0d58f2d,0x109e4d3,
  45252. 0x121b973,0x10ea9d1,0x0e04026,0x1864614,0x01c0dd9 } },
  45253. /* 143 */
  45254. { { 0x06a7d9a,0x10fb3e2,0x0733fea,0x097dbf2,0x0474333,0x1217973,
  45255. 0x0e9d11e,0x1528b06,0x1241ffa,0x1cc0028,0x1bf9ad9,0x150866b,
  45256. 0x0370979,0x1845920,0x0184fd7,0x023b8be,0x1cd64f2,0x035d917,
  45257. 0x015cb3f,0x1165474,0x014ae1b,0x00bca85,0x06783ad,0x16d9a98,
  45258. 0x0bb293e,0x0fff31a,0x151c289,0x0340964,0x115a0a3,0x1d64d1e,
  45259. 0x1a6907d,0x17e5fdb,0x1ed85ec,0x0a50077,0x1d7e06e,0x183eb03,
  45260. 0x1ef4a15,0x1ccb584,0x106f2a8,0x07360c0,0x052d8be },
  45261. { 0x1631a2f,0x09b7b7e,0x0372f45,0x0166a35,0x11fae7f,0x0931094,
  45262. 0x0431e6c,0x06ba34b,0x12bd0f4,0x16a43af,0x03a9c14,0x0da7256,
  45263. 0x1e9aedb,0x1c1d5c4,0x142af72,0x0325817,0x06289fe,0x1413d08,
  45264. 0x00a82f6,0x0d52c02,0x0814656,0x1be701b,0x16820c0,0x0c7280b,
  45265. 0x0d79f58,0x0fc985f,0x1b6f2a3,0x0e40336,0x1aa3f59,0x094377e,
  45266. 0x04a2480,0x0a46d71,0x137b996,0x01739d9,0x0e38a3f,0x0623a7c,
  45267. 0x080e8da,0x1c3fa0c,0x09175c1,0x0cfb5c9,0x06cff63 } },
  45268. /* 144 */
  45269. { { 0x09a8bb4,0x08219fc,0x1dc6f4f,0x0727731,0x02144c3,0x038516a,
  45270. 0x05b200d,0x13d056c,0x1e5da08,0x07e63ab,0x17f69a6,0x09def7e,
  45271. 0x0c54235,0x0f5e9a6,0x017094e,0x1ba1a31,0x085bec5,0x1171059,
  45272. 0x00a86f2,0x1777c2f,0x0ef0e71,0x184dc2a,0x05677b4,0x12ff4d5,
  45273. 0x0997989,0x0228b92,0x03607cf,0x019f1f5,0x0111525,0x1a8bb06,
  45274. 0x1aaa68e,0x1d9f08b,0x1b0ef7d,0x1688de4,0x188ee7f,0x0192673,
  45275. 0x0825608,0x1f4e2e1,0x1079f24,0x02ec27d,0x01d2c82 },
  45276. { 0x07cfc93,0x09a3ecc,0x0041ce0,0x17e30ff,0x047603b,0x0865188,
  45277. 0x0f27449,0x1e67f4d,0x0bb055b,0x00048f0,0x0be1f12,0x1e34747,
  45278. 0x0bbdf95,0x0a02a05,0x1a1ddc0,0x008b7c4,0x130d7fe,0x0ccc6fb,
  45279. 0x1c8ef0b,0x1026bf6,0x0c46b39,0x060af5f,0x0b08c3e,0x0aac381,
  45280. 0x018305f,0x03ff047,0x1369829,0x181f7e9,0x0d4bfc7,0x0e1270b,
  45281. 0x0481ba5,0x0e8c2fd,0x0163495,0x061073a,0x01a52b8,0x0c72e33,
  45282. 0x0131e2b,0x1349891,0x1dc8bf8,0x06c14a6,0x025486e } },
  45283. /* 145 */
  45284. { { 0x1572806,0x1cae529,0x0385861,0x12cad2d,0x12c8944,0x1991d75,
  45285. 0x0b25cfe,0x1ac2938,0x0409bc7,0x18aef13,0x0486cfe,0x14e58f2,
  45286. 0x1ba90cd,0x102655d,0x0be8538,0x0824ada,0x0f79160,0x1e5e6d3,
  45287. 0x10d7e51,0x10c4c36,0x0b10250,0x1c61417,0x16da1b0,0x14f2397,
  45288. 0x16d62f1,0x1362880,0x0586889,0x1638fda,0x1d74a66,0x0333138,
  45289. 0x09099e0,0x104850f,0x1ffeda1,0x07879da,0x0ffeef9,0x0997ca0,
  45290. 0x19482a7,0x1bf85f5,0x04fc75f,0x0b01109,0x0751b23 },
  45291. { 0x1c9be68,0x1dceb74,0x11b3565,0x08cfa21,0x1794b5c,0x11597a0,
  45292. 0x170f5dd,0x0235119,0x0a1b44e,0x0ca531d,0x03b2a1b,0x1773555,
  45293. 0x1ffb0bb,0x04b1ec3,0x0c3cb43,0x00ebbe9,0x02c5dc7,0x0dba983,
  45294. 0x064ce62,0x0e4d589,0x0cdefed,0x1c2bfce,0x1769818,0x1f18ecc,
  45295. 0x0392a75,0x165110e,0x157719c,0x1a4c9b2,0x0ecc8dc,0x1f915b3,
  45296. 0x0e9c013,0x03148b1,0x11aa9ae,0x1eb29fd,0x137e2ea,0x19d52c8,
  45297. 0x0ba0de7,0x1bc7401,0x1b1d6a4,0x05b9458,0x0144cc1 } },
  45298. /* 146 */
  45299. { { 0x189aa3a,0x1050e94,0x193564e,0x06b3cdc,0x183f228,0x1739976,
  45300. 0x0c32f4c,0x093d271,0x13c3cb2,0x0623262,0x1a9ab3d,0x0bf1f13,
  45301. 0x129750a,0x1a367e1,0x1f96efc,0x170128c,0x19d37b2,0x0e4dfd5,
  45302. 0x0cce71b,0x16e8a67,0x0deef8e,0x1f1dbb3,0x0ff807e,0x0d5d44e,
  45303. 0x14254ef,0x188598a,0x09ef986,0x0ab87be,0x0184885,0x16c0eec,
  45304. 0x1e5c3ed,0x177ce29,0x01af3a4,0x07b49ed,0x005e746,0x12aebe4,
  45305. 0x0465b83,0x047e359,0x0a54770,0x066d709,0x0874ecf },
  45306. { 0x1b3f6be,0x17c1f5d,0x08f5892,0x1211768,0x1578fbb,0x039a93f,
  45307. 0x0c2eb5e,0x084ac47,0x0a62e04,0x1b2cdec,0x0dbde70,0x02cffc4,
  45308. 0x062903b,0x129f935,0x090c31b,0x0259eab,0x1ae3ad7,0x19112a3,
  45309. 0x1bac9ca,0x1121aee,0x0df9b73,0x059eb14,0x056d3dc,0x1d5c959,
  45310. 0x013b053,0x1a74f87,0x039fc85,0x169ea27,0x1bae175,0x167ccc6,
  45311. 0x001d520,0x088a309,0x169bbde,0x178ae15,0x194b2bf,0x129e4f2,
  45312. 0x16bcaf1,0x11f795d,0x18d3e82,0x1039c98,0x031fb85 } },
  45313. /* 147 */
  45314. { { 0x15cd607,0x18368b0,0x0e98e60,0x1554658,0x080c9fa,0x1c898eb,
  45315. 0x1c16ddd,0x001d0f4,0x036708b,0x018809d,0x14a5fc4,0x01c3288,
  45316. 0x16814fa,0x1353cda,0x11560ea,0x17da8e1,0x0bf4b16,0x18181ce,
  45317. 0x0aabe34,0x0f951b5,0x08a518a,0x13ae6db,0x1ccc567,0x07029f5,
  45318. 0x0e738d2,0x1cfef50,0x02343d3,0x166a4e3,0x1ff032e,0x1304ee6,
  45319. 0x02ec2dd,0x07a9067,0x1ba8ea9,0x0a83d32,0x1609577,0x0830089,
  45320. 0x0a4a50b,0x05111f2,0x0795211,0x00031c3,0x0983230 },
  45321. { 0x1f3d5a6,0x10813ab,0x1734a28,0x10dd195,0x1fce564,0x0a8f9df,
  45322. 0x0e06c09,0x1e32b20,0x1935ebd,0x1366327,0x0ea9bac,0x0523810,
  45323. 0x0160611,0x047267a,0x062299a,0x1636b9b,0x173dd53,0x0ac0e1f,
  45324. 0x1ff1887,0x100952e,0x02fa78c,0x187d6e5,0x0c61d0c,0x0799e04,
  45325. 0x08da4c8,0x183fb80,0x169e691,0x0824543,0x115eb5c,0x069fa54,
  45326. 0x1826a38,0x1a0246c,0x0de157d,0x1695051,0x0ec997a,0x0a8bde8,
  45327. 0x188db28,0x11156f0,0x032ab42,0x13d245c,0x08abbe3 } },
  45328. /* 148 */
  45329. { { 0x02d2f01,0x034829d,0x0172d11,0x06bb8cd,0x127c319,0x1a5013e,
  45330. 0x02efc75,0x03ad521,0x15b50ec,0x0ed1a87,0x10b8980,0x08bc7e7,
  45331. 0x121d3dd,0x1c1b774,0x1b84742,0x12f39ec,0x08f474b,0x03f01c8,
  45332. 0x02e1e0d,0x0f8b733,0x1de919e,0x1f5e9e8,0x09d074f,0x1ec0b37,
  45333. 0x08e8d1e,0x123b1e3,0x04d9d38,0x173ff27,0x1e67f69,0x09f39f3,
  45334. 0x12075f5,0x15dd3c4,0x18dc326,0x0cc2634,0x1b6acef,0x0ea5e47,
  45335. 0x0f8fe8a,0x0f18d83,0x0ea57e5,0x1a187a1,0x00f15b4 },
  45336. { 0x10a8d85,0x1b31abc,0x0bc63cb,0x1dc4b2b,0x11bffba,0x1a8943a,
  45337. 0x1fb1892,0x0bba2b6,0x1323471,0x11cdb55,0x151075d,0x0532578,
  45338. 0x130cdd5,0x1b682c1,0x0003a93,0x1c6c0a9,0x152f6d6,0x190f7eb,
  45339. 0x04a4184,0x0fffca3,0x18cdc0b,0x12f7544,0x0da2960,0x13044cd,
  45340. 0x1ba9222,0x1d97676,0x02ef41a,0x0f15236,0x16b0cb6,0x16e025d,
  45341. 0x062c90d,0x195f1d5,0x17a99e7,0x102dde7,0x19b9c6a,0x03725a1,
  45342. 0x15993eb,0x068238f,0x1776efe,0x0f04070,0x0515db3 } },
  45343. /* 149 */
  45344. { { 0x15bef22,0x1f55537,0x1c4bb90,0x1040690,0x152d269,0x1d7b634,
  45345. 0x12139e8,0x0063c98,0x09a8c94,0x06a1a63,0x0626686,0x0e82a00,
  45346. 0x0c63e5d,0x1f47520,0x0e36ef3,0x10e42a4,0x0d29679,0x0653664,
  45347. 0x12b2f7a,0x16d5dc0,0x13ce73d,0x06dbfcc,0x0fda4ca,0x08bc669,
  45348. 0x19bbfad,0x11851fb,0x0df07c5,0x18a3d92,0x00a6de8,0x192fcd8,
  45349. 0x10d241c,0x025b057,0x1e6acb4,0x0cfe4a4,0x0db43b1,0x16b2036,
  45350. 0x1cf34e3,0x04db884,0x1300b2c,0x0fc357e,0x02de048 },
  45351. { 0x1d9d484,0x19179c6,0x0b3062d,0x06f8ef7,0x0334939,0x0c95c54,
  45352. 0x0e3c64f,0x04ab1b7,0x08e3fac,0x06bc6a8,0x1d29f60,0x1302e8b,
  45353. 0x1df0500,0x03be614,0x1caffb6,0x113f1a0,0x0f2c30a,0x1b3d5fc,
  45354. 0x0820835,0x0acfd53,0x173892c,0x17451d2,0x1096ac4,0x0aaa436,
  45355. 0x0faebf0,0x0f4e0b1,0x1ae53a9,0x1c389e4,0x11e546e,0x04ca1eb,
  45356. 0x0747905,0x087d17c,0x18183b8,0x1570592,0x120bbe7,0x008922f,
  45357. 0x13874a3,0x09d22bb,0x1e1b9a0,0x0e39885,0x06f6ac0 } },
  45358. /* 150 */
  45359. { { 0x1d6e3b1,0x01156a6,0x01a74e2,0x195ac41,0x1c78e1c,0x166f407,
  45360. 0x0e114b2,0x1c7cf08,0x0a8469f,0x10e60a5,0x1a3bc84,0x1b4fccf,
  45361. 0x088e8f3,0x069a3a2,0x00f45b9,0x063e9b7,0x1987986,0x19dd0ee,
  45362. 0x0931305,0x16b2ee1,0x101fdfa,0x031f6e3,0x07c284c,0x1b1fe50,
  45363. 0x1d6016c,0x1e4a324,0x0ef3156,0x04ce461,0x00412a2,0x0e302bb,
  45364. 0x1d80a86,0x0651f5d,0x119d5f1,0x1556ce3,0x1a7bd9f,0x0a4f972,
  45365. 0x119bafb,0x0129873,0x00b2fcd,0x199feb5,0x06e2c24 },
  45366. { 0x1af8793,0x18125d6,0x12398c4,0x0206b92,0x144bccf,0x1a805fc,
  45367. 0x19ade54,0x0cbd340,0x01d1167,0x0c8d4a3,0x04f1e1e,0x165d3fb,
  45368. 0x1595add,0x14972a4,0x14b00df,0x1cb9e0b,0x1189f03,0x1658a2d,
  45369. 0x16a87dc,0x1c91952,0x0e4f81a,0x0109ad3,0x080fc9c,0x1654faa,
  45370. 0x0f5a249,0x15195e7,0x000b5fc,0x0d0f520,0x0745b00,0x1914363,
  45371. 0x014bdf4,0x10ca0e6,0x1a8a875,0x0e2c79e,0x0210ba3,0x0b7c717,
  45372. 0x1bf1118,0x045f9a6,0x03e45ad,0x01b2f81,0x05af7fd } },
  45373. /* 151 */
  45374. { { 0x0a224a5,0x0dca87a,0x1ce957e,0x0998a04,0x0190457,0x1f8feaa,
  45375. 0x04cc190,0x10669f0,0x10e50f7,0x0b400dd,0x005c4a6,0x080712b,
  45376. 0x16866d7,0x12048e9,0x0690176,0x0dfcfb7,0x1df16a4,0x078f1bc,
  45377. 0x0efe45a,0x09527f0,0x0bca8d0,0x1a99590,0x0b9320c,0x0543821,
  45378. 0x134b1f7,0x0da4ce9,0x1f60657,0x1f7932e,0x014b5d8,0x1efffdd,
  45379. 0x1db2bac,0x0edb5e8,0x0fef022,0x1b97a30,0x17fb6d6,0x0497291,
  45380. 0x16dfb06,0x02e492d,0x152b946,0x1032c13,0x027a9c3 },
  45381. { 0x12a93af,0x1b9a378,0x0d35cf0,0x18aa6cc,0x028b707,0x00c9e88,
  45382. 0x1635526,0x13b1df4,0x0ef21b6,0x1c1d2e6,0x0283893,0x01474f1,
  45383. 0x1805cbb,0x12d89e4,0x00c5e05,0x0f09802,0x0582b73,0x17f5107,
  45384. 0x140d87c,0x0e2741c,0x02d9df9,0x07e8661,0x0c51268,0x0bc5c36,
  45385. 0x152e77c,0x0678c1b,0x16d9c11,0x1c89ad7,0x1e177a6,0x0f4ab99,
  45386. 0x08c04b7,0x011dc58,0x0b49669,0x18ca4b4,0x15047d7,0x1fb3760,
  45387. 0x0acd886,0x0c1638b,0x0491254,0x129f7bd,0x01c6906 } },
  45388. /* 152 */
  45389. { { 0x0880026,0x13e8b9d,0x17c976d,0x0024bb2,0x09c4f0a,0x165bd24,
  45390. 0x01544fd,0x14a520a,0x15cbbdc,0x15918e8,0x0f2f4cf,0x19332e5,
  45391. 0x1af8cff,0x16aad01,0x13bd352,0x0f85f96,0x1ca2286,0x0ca26a3,
  45392. 0x1ab46a9,0x110a901,0x104596d,0x1c65e45,0x1da95f3,0x0bcab40,
  45393. 0x1844b00,0x04beff2,0x0474628,0x1d3cfc3,0x123c745,0x1374294,
  45394. 0x0e655e8,0x0febb66,0x0867b79,0x1686468,0x02398ef,0x184aa68,
  45395. 0x089ad23,0x0b72eab,0x10ce456,0x1ad4a09,0x07b8c13 },
  45396. { 0x0fb6901,0x01d56a9,0x14ecbf1,0x122d944,0x1c0313f,0x0d56e30,
  45397. 0x00c2945,0x18428eb,0x07f577d,0x09e8c93,0x0f03772,0x1d1dee4,
  45398. 0x1a26e52,0x1f5cfb6,0x0783ae0,0x06eda5e,0x082f180,0x0ccbcef,
  45399. 0x020d24e,0x051d976,0x18e743e,0x0e51ce1,0x068b547,0x1c7ed6b,
  45400. 0x063a9a8,0x1383730,0x092e6cc,0x19e3b47,0x18915d4,0x0451697,
  45401. 0x049b94d,0x0a0a0f2,0x075e3e0,0x1c1fd2f,0x195c834,0x135dff9,
  45402. 0x0fd2fb2,0x16a9e64,0x1334075,0x1ecd2de,0x00e3c3e } },
  45403. /* 153 */
  45404. { { 0x1ee1d83,0x19be090,0x1e20ef0,0x1af0f6e,0x17e08f6,0x07d2674,
  45405. 0x07f304e,0x0b17ee1,0x1a0348e,0x17bbb23,0x199cb6e,0x15794ab,
  45406. 0x1d04f8b,0x1eaf62e,0x14a4675,0x124301d,0x1ff33e9,0x1c67325,
  45407. 0x12c166b,0x13f8ae4,0x12baac0,0x1cee2f1,0x141a0c7,0x0b5ed52,
  45408. 0x0267746,0x1fc1351,0x1b25fc7,0x18bdfcc,0x0087fd3,0x106b5e3,
  45409. 0x1ac5457,0x1551db8,0x1a39c5e,0x0f694d8,0x1aec39e,0x107bb02,
  45410. 0x1c3788b,0x009bb4d,0x09471b3,0x1c78125,0x0463098 },
  45411. { 0x0bd0fa7,0x00463e4,0x1924e99,0x039cd7b,0x1176431,0x1f7bdf6,
  45412. 0x18420a0,0x071c62b,0x199b5d9,0x109e63b,0x1269ae0,0x0b028b4,
  45413. 0x11af7f1,0x1294f26,0x03f6c3f,0x193ada0,0x177ce66,0x12ae9c7,
  45414. 0x0f52e54,0x0f99803,0x1986b4f,0x04d7b8f,0x0365d6d,0x0c9a015,
  45415. 0x19fcbcd,0x16b895a,0x12968ee,0x10c1ca0,0x1c89f11,0x102215a,
  45416. 0x07db65d,0x0f47c46,0x0d0c659,0x05d497f,0x10cc5e3,0x1cb0229,
  45417. 0x0698e11,0x13a6033,0x0e16b8b,0x1274691,0x07f8fd0 } },
  45418. /* 154 */
  45419. { { 0x19428af,0x0c96560,0x1997c91,0x0274610,0x192a1c8,0x05debf8,
  45420. 0x0604b8c,0x17284b1,0x1836c6b,0x06d8391,0x19261c4,0x03d2b31,
  45421. 0x0b9c7a4,0x1756b7a,0x1fc5e79,0x0588915,0x1b97586,0x1387c7c,
  45422. 0x1c8660f,0x16046ed,0x11526b3,0x0dcc732,0x09760fa,0x0a24314,
  45423. 0x126a8d7,0x0d31d96,0x0a75bc7,0x0a10503,0x081f749,0x0682d2d,
  45424. 0x1c637de,0x1c8d0e8,0x19ee559,0x1ec666b,0x095d9e1,0x0a40c19,
  45425. 0x08476c9,0x1d427fd,0x144c509,0x0a3cc86,0x087b64c },
  45426. { 0x130d3c4,0x037b2a5,0x1c521fd,0x184769d,0x0dec4c5,0x0526b46,
  45427. 0x11d998f,0x0db676e,0x1cf3fb5,0x0f9a134,0x1f51a87,0x13881fa,
  45428. 0x1dd4f13,0x1534d45,0x0df1f1d,0x1afa547,0x0c9cbad,0x0772b5a,
  45429. 0x12508cd,0x1fe6855,0x1da3b28,0x1d3c378,0x0011bf7,0x001905c,
  45430. 0x1149cb7,0x0cbe72e,0x0542599,0x1461df0,0x1f4bddc,0x0304fe7,
  45431. 0x1a11288,0x08924a4,0x12f65e7,0x10f9c07,0x14b3500,0x01cb6ca,
  45432. 0x042dbbd,0x154e150,0x18bd5df,0x0f9b380,0x08c9526 } },
  45433. /* 155 */
  45434. { { 0x1c1abb1,0x081972f,0x1d0d995,0x0825fc8,0x0215af5,0x182f7a9,
  45435. 0x1d580a7,0x1d3faca,0x1dc191b,0x0739992,0x18e6c2c,0x0cbd810,
  45436. 0x137ab3c,0x0e1f333,0x141fd44,0x0aaaace,0x1c3c861,0x0b1c5f7,
  45437. 0x0bc312b,0x03119e8,0x186d5d0,0x0e6c4b0,0x010e8c0,0x18ce83d,
  45438. 0x003f7b2,0x0e8022b,0x13e8f34,0x0ea8b81,0x00672ef,0x17fea52,
  45439. 0x177d84a,0x08b73d1,0x0197c9f,0x116ba2b,0x0df61e4,0x1f68a64,
  45440. 0x0b2d59b,0x09971d2,0x1a85afc,0x0e77094,0x08afa1b },
  45441. { 0x193ac70,0x0cb7573,0x1441acd,0x1dddedb,0x0c94ef8,0x0117202,
  45442. 0x13e89c1,0x0c724d6,0x0e9e5d7,0x0638ee7,0x0aab7f2,0x16e1ea2,
  45443. 0x1f352fc,0x1441cba,0x1ee84e2,0x0762636,0x190058c,0x0abcc89,
  45444. 0x1dd03f4,0x0412552,0x0697969,0x0d8b058,0x066b651,0x106f564,
  45445. 0x1438810,0x1b8de31,0x13c5d2e,0x0ddc238,0x1b80eb7,0x1fe0d58,
  45446. 0x0298446,0x0e1d88b,0x082bac8,0x09992de,0x049cc4b,0x11ddcc0,
  45447. 0x1240adc,0x08c58d5,0x024f2d0,0x12256b4,0x0672111 } },
  45448. /* 156 */
  45449. { { 0x15cf9bf,0x0c9837a,0x1b6647a,0x1148d72,0x1b04530,0x1d32efc,
  45450. 0x0787679,0x1775c78,0x1c731bc,0x09e58a8,0x1629851,0x044f49a,
  45451. 0x0214be5,0x0be3a66,0x16b248a,0x001ac73,0x045822e,0x1a687bd,
  45452. 0x18ac0f7,0x163aa38,0x0b2dafe,0x125d50c,0x0ec770e,0x056e9e1,
  45453. 0x07178df,0x119bf9e,0x1a25ada,0x19a6514,0x0e055ff,0x0a2a0ee,
  45454. 0x01fa57b,0x0d49c57,0x1fbc76b,0x0ee74cb,0x1fc7e96,0x03cbd8c,
  45455. 0x0c0367c,0x11b4566,0x08ff814,0x02ca9c9,0x07c8639 },
  45456. { 0x07388cf,0x0a5af65,0x14e157a,0x018066b,0x17cc0a6,0x17c2dd0,
  45457. 0x0de2d85,0x10136d3,0x1101229,0x02e8177,0x1429e5c,0x1d0039f,
  45458. 0x12565a6,0x1e8f71a,0x1d2a5b5,0x13b5bd6,0x0ed427b,0x1ae4419,
  45459. 0x1b54cc3,0x150a51c,0x0ee896e,0x158c692,0x0c36218,0x1f273ee,
  45460. 0x18ed59f,0x1294e69,0x0804180,0x121f934,0x03b3ff6,0x045c118,
  45461. 0x1a718b6,0x1baa568,0x042d7a4,0x096c9fe,0x1e8a32b,0x100df1b,
  45462. 0x0092043,0x11b0483,0x156b540,0x0b1f9d0,0x0325827 } },
  45463. /* 157 */
  45464. { { 0x19e8c60,0x0722f9a,0x061bac8,0x0a6c994,0x071bb8a,0x1c70886,
  45465. 0x141c77f,0x0f00562,0x14c93e5,0x1a748e9,0x0743601,0x1c01705,
  45466. 0x1ac0326,0x113541f,0x0648961,0x1413c78,0x0d5fb29,0x11c3d32,
  45467. 0x16b1720,0x147a69c,0x1a29caa,0x12d6d16,0x03b5a17,0x052ca1d,
  45468. 0x00267eb,0x179c939,0x05d8e00,0x0e30963,0x0b1aeaf,0x0e876fb,
  45469. 0x1748fd7,0x04bcc24,0x01fa347,0x1950d5f,0x1e74321,0x1fac50f,
  45470. 0x0c57c3a,0x1549e95,0x1d95926,0x0e2b7b4,0x01a4e6a },
  45471. { 0x14d1267,0x1376f2a,0x0d20684,0x0639a05,0x17f9453,0x18fd8e9,
  45472. 0x1c13338,0x025ae15,0x1097dc0,0x1a08585,0x1edb173,0x1a2e6d8,
  45473. 0x05930e1,0x0344884,0x0bfb907,0x0c71f20,0x0a779fb,0x19a4dd2,
  45474. 0x135be37,0x18b0435,0x0acea16,0x009703b,0x1ecee0f,0x003a29b,
  45475. 0x1033be5,0x16d35c6,0x0883cb4,0x0b27a8a,0x1f18800,0x0936cce,
  45476. 0x098dd49,0x13fd667,0x032351c,0x17a2b65,0x0ef07db,0x15b2268,
  45477. 0x15b9dc8,0x042bed9,0x1a0cb1d,0x1270b69,0x0856a7c } },
  45478. /* 158 */
  45479. { { 0x10a5583,0x1e80106,0x162a801,0x1bdb48c,0x0f1301d,0x0c9cdf1,
  45480. 0x1e590d3,0x06d2380,0x0a70c08,0x065b3c0,0x0795028,0x1f2b7d0,
  45481. 0x18c0b4d,0x0ea5645,0x0ef34d1,0x0c472d9,0x0d05475,0x12be297,
  45482. 0x00173ad,0x05b9483,0x0255cac,0x15bc9a2,0x0457b9a,0x193454d,
  45483. 0x1ef3124,0x13a1b36,0x1e304b1,0x1a772c5,0x1b7c3bb,0x078dbed,
  45484. 0x16eaad9,0x1c45772,0x00e4553,0x11dba1e,0x1aeb131,0x024811f,
  45485. 0x0a4da63,0x13b9891,0x16900f2,0x1098c6d,0x0628890 },
  45486. { 0x0b8d208,0x1fea9c6,0x1b52915,0x12a87e0,0x1a8f800,0x17f955b,
  45487. 0x18553cb,0x1cf6cdb,0x1f72517,0x0ed9475,0x0274b3f,0x1ccdf27,
  45488. 0x0e0149f,0x0c2dc46,0x1a1dcff,0x087eef3,0x10b0ba5,0x0229704,
  45489. 0x02c0ff0,0x136b9f6,0x177bdeb,0x05362f6,0x0c44d12,0x1f806e4,
  45490. 0x1f3cf8f,0x0251b04,0x15706d3,0x179388d,0x059be92,0x1df9c7d,
  45491. 0x04799bc,0x19b604d,0x196bf5f,0x1c47c89,0x0750027,0x07e3d8b,
  45492. 0x0ad9dfe,0x081a2b1,0x135630a,0x058b5b4,0x079d812 } },
  45493. /* 159 */
  45494. { { 0x0529507,0x0726755,0x1400535,0x08e8cab,0x056a081,0x07e23a0,
  45495. 0x028e13c,0x11d81a6,0x03443cb,0x14101f5,0x05ca362,0x1f612fe,
  45496. 0x1233c62,0x1a9077a,0x0e373f6,0x13a7d14,0x15d7cac,0x0507c86,
  45497. 0x1cf3a94,0x0f617f0,0x01cb28a,0x1d36362,0x14456b8,0x0702583,
  45498. 0x171daa1,0x03f51a8,0x1589354,0x0ba9774,0x18f42f2,0x0944bf4,
  45499. 0x1c6476b,0x12d4826,0x1d6b1e9,0x12dbbff,0x0496da7,0x0fa8d84,
  45500. 0x00c4f70,0x095a121,0x155eb1f,0x12b0284,0x02ab3af },
  45501. { 0x05372a6,0x103a635,0x0e9e1b2,0x1cac525,0x128fb83,0x1a0e7ab,
  45502. 0x05b71dd,0x13ae8ab,0x1520ef4,0x05a6750,0x1191c9c,0x1c68c3c,
  45503. 0x1d1472f,0x1fdc562,0x15af598,0x180e3e9,0x0c9c10b,0x0a37296,
  45504. 0x1c68d18,0x129dfc6,0x0877287,0x0c13b7f,0x092141c,0x1deb569,
  45505. 0x157739b,0x00af6d6,0x1cfc572,0x0985b3f,0x0395c32,0x0872c7c,
  45506. 0x1546225,0x1016d50,0x0e40996,0x001f0dd,0x08b22a2,0x1c9ea7c,
  45507. 0x039d25e,0x119fb08,0x0272abc,0x06a4a08,0x007db2c } },
  45508. /* 160 */
  45509. { { 0x17d4703,0x1dc6d81,0x02e71fc,0x1f8be91,0x083708d,0x18ea017,
  45510. 0x00c3e11,0x1d23f75,0x05a2faa,0x0af7469,0x13f07a9,0x1e20a80,
  45511. 0x11c2e5b,0x1516ab2,0x1f5409e,0x1ebf2c8,0x00c7eba,0x19bd29e,
  45512. 0x16cc2af,0x1e17652,0x13ba7ad,0x1f6b264,0x1698b87,0x1de94f0,
  45513. 0x018c0e2,0x027bffe,0x0534b34,0x073bb3b,0x00af021,0x1d5baf5,
  45514. 0x13c94fe,0x01fdf35,0x08100ea,0x0ad53be,0x0137218,0x12e98a7,
  45515. 0x1fe5206,0x143416c,0x15d672c,0x11f9efb,0x008b6ca },
  45516. { 0x16c3b5a,0x12df501,0x0d2f813,0x04ff3e5,0x1872610,0x1cbe079,
  45517. 0x095c0a5,0x14753f9,0x182879e,0x12b0c05,0x1c377c5,0x1376c0f,
  45518. 0x0715338,0x13d8704,0x08488f1,0x0ff8f33,0x0ec9d89,0x0868c04,
  45519. 0x05bb7c6,0x00e2352,0x1118947,0x158390b,0x1e3d4bc,0x111116d,
  45520. 0x129ffd1,0x0802ec5,0x15331be,0x1e3c458,0x04877fe,0x10b2f59,
  45521. 0x097100d,0x06a8f2a,0x1a95233,0x0a3457e,0x1085a18,0x11ac454,
  45522. 0x14faba0,0x021d83b,0x09f4974,0x0041a63,0x02c337b } },
  45523. /* 161 */
  45524. { { 0x022fa65,0x182de75,0x18e9ec8,0x09a2b3e,0x1e183ef,0x1ac91fd,
  45525. 0x161f4fc,0x0a668e7,0x0c11d77,0x13fd983,0x1533fec,0x1cd6540,
  45526. 0x19702e7,0x178c2b0,0x1a7e5f2,0x0a38a79,0x0434e7d,0x1c1aa81,
  45527. 0x0d5ab16,0x1c7b05e,0x1131a63,0x156bb22,0x019edf2,0x0e3f93b,
  45528. 0x1e6afa6,0x0bbf742,0x18ac1f3,0x1730bdb,0x1a51933,0x0c587fe,
  45529. 0x0d81f56,0x15285b8,0x10eca39,0x10c54d8,0x13b9418,0x142fe7b,
  45530. 0x06b7d5c,0x0a74688,0x0c724f6,0x069db10,0x0509b26 },
  45531. { 0x0caed54,0x0a0a724,0x1a5ec6e,0x1997ea3,0x17a78c6,0x14d92c3,
  45532. 0x0323537,0x0f148d1,0x091ee3d,0x01209be,0x1b99300,0x0469c61,
  45533. 0x18a68f9,0x040c86b,0x0c956f2,0x0d216ae,0x05fba80,0x020f470,
  45534. 0x10d53d3,0x071b09d,0x0816500,0x0b6fd29,0x0c63c0b,0x16c7fb5,
  45535. 0x19007cc,0x02ae23f,0x0fa62b9,0x13a901f,0x0e319d2,0x0e912e8,
  45536. 0x0652b11,0x004db6e,0x06f3575,0x0c3dce8,0x1880b0d,0x0ee6773,
  45537. 0x0c31772,0x041cc91,0x01d4889,0x14ea977,0x01592d5 } },
  45538. /* 162 */
  45539. { { 0x17453f0,0x06cd167,0x07c15de,0x15db078,0x0ffb899,0x1415d3d,
  45540. 0x01b4f82,0x1035cca,0x0ea3d50,0x164270d,0x0a8e2cc,0x1181021,
  45541. 0x019ad52,0x1e9be82,0x1f6c082,0x1c83f63,0x1e1d06c,0x13c6b65,
  45542. 0x19d2dfd,0x0fe1e05,0x1022d28,0x1ae21dd,0x1d73495,0x034e367,
  45543. 0x0f2f3f8,0x1fa3694,0x1718cf9,0x0cb763e,0x1c580ee,0x1e0e627,
  45544. 0x094cb97,0x176f60f,0x155539f,0x1579d66,0x11c70f2,0x1b6b528,
  45545. 0x0cc22d2,0x0c5efa2,0x1ddf2e5,0x17aef44,0x01614bd },
  45546. { 0x10ab04d,0x1811876,0x0ba9307,0x00dc410,0x0e347b0,0x162dafd,
  45547. 0x0f18f10,0x06b3e21,0x1de0199,0x029cf37,0x142096c,0x09cecbb,
  45548. 0x16d89bd,0x1de76d0,0x0983fbe,0x1946524,0x15ce62a,0x1c5553a,
  45549. 0x1b20b17,0x0c5f52b,0x0768ed7,0x008c328,0x0679930,0x05c6919,
  45550. 0x16245c9,0x0b42bee,0x1cc7a9b,0x1b7114e,0x1447360,0x095583d,
  45551. 0x1fbbc00,0x02e3ae1,0x1356b94,0x048d85c,0x18a00fe,0x05cd160,
  45552. 0x179c20a,0x0a529d5,0x01ca0e9,0x18f6016,0x0489656 } },
  45553. /* 163 */
  45554. { { 0x1353c25,0x124dd38,0x189390d,0x0227ecf,0x117f27a,0x0f5cf1a,
  45555. 0x0cce870,0x1f2217a,0x078e29b,0x070e02e,0x0fc5765,0x1b2e8e8,
  45556. 0x1084fe7,0x086d16f,0x01d2422,0x077c339,0x1a75367,0x0c1201f,
  45557. 0x0eba86c,0x1ebb683,0x0ead7eb,0x1a920c0,0x13f82b8,0x1ea187f,
  45558. 0x1873fc2,0x06c8e8a,0x19c1987,0x0d0a35a,0x1e8c2c1,0x146cd28,
  45559. 0x06600a5,0x1c02c21,0x1d1a9cd,0x1f52b73,0x1226a29,0x10562a7,
  45560. 0x06e3c49,0x00dbc48,0x0772db5,0x1d3aced,0x0082bb2 },
  45561. { 0x0d6615f,0x077a362,0x0a71860,0x0203730,0x1c629dc,0x1932657,
  45562. 0x0bb003e,0x189bc44,0x010ecc2,0x0a2bf03,0x08b1371,0x133e3dd,
  45563. 0x0c95ce5,0x07ce2d9,0x0cfe9ca,0x021f208,0x062cd63,0x1f701aa,
  45564. 0x18b8894,0x0af8779,0x1e4484c,0x0d4b6c3,0x1b23b0c,0x0a58b4e,
  45565. 0x1e393a4,0x11a985f,0x02811ec,0x0b25628,0x18545ec,0x1f0c600,
  45566. 0x119ef62,0x0b82f18,0x14e0107,0x1802dbc,0x0518b88,0x06908e3,
  45567. 0x022a54f,0x12f11bb,0x0410899,0x08d2039,0x036451a } },
  45568. /* 164 */
  45569. { { 0x1893e71,0x0168c0c,0x02085e0,0x16a7344,0x01765d8,0x01767e5,
  45570. 0x1a8048c,0x13bf8d5,0x1365bf5,0x0a67a8d,0x0caa023,0x1ae41a4,
  45571. 0x0787741,0x0c74021,0x0d0facc,0x073d958,0x12fe747,0x12a9f65,
  45572. 0x0a2c1f2,0x14f3503,0x0b3aaec,0x112b7a5,0x0227fcc,0x143a3ee,
  45573. 0x1d7293f,0x10b2f4a,0x1bd8aa6,0x0c0ad35,0x08ddc22,0x1119550,
  45574. 0x12979dd,0x036f76a,0x1fabec3,0x0ab73c9,0x0559d0f,0x1e91441,
  45575. 0x0b0ebef,0x0e6d897,0x1f3c5d2,0x148d371,0x0705307 },
  45576. { 0x088310b,0x1260272,0x15edea3,0x04a64b9,0x12726e3,0x01f7d60,
  45577. 0x162c126,0x026ba1f,0x002ddb9,0x0b72a96,0x05a171e,0x07eeef7,
  45578. 0x030eeca,0x18af925,0x1d9ba26,0x192f336,0x0d648ef,0x03e139b,
  45579. 0x000871b,0x032d0b5,0x11ea3d6,0x1c50597,0x1f8cf89,0x0edad61,
  45580. 0x09879b6,0x05f4ae3,0x046bd38,0x00e8e63,0x04ee55a,0x1af89b6,
  45581. 0x0e68bea,0x0b3cbe7,0x138b8ff,0x17f3734,0x1690e72,0x003c229,
  45582. 0x0a6ad12,0x0caf61b,0x0abb325,0x1a0afcc,0x080f79b } },
  45583. /* 165 */
  45584. { { 0x0af09b3,0x1a153b0,0x1850f3b,0x1b267bf,0x1c016eb,0x02f5541,
  45585. 0x1c783b6,0x192e419,0x1ceaa3b,0x07af4cf,0x01be5f5,0x13a56e2,
  45586. 0x127216b,0x04b3456,0x1cd30db,0x0ca3ecb,0x0bc5b0c,0x1547dc1,
  45587. 0x0bf6937,0x085e39e,0x059e20f,0x16690fb,0x1acc6ac,0x07a2c31,
  45588. 0x176c7a1,0x1f2dbd3,0x08e198a,0x1888204,0x108e0be,0x0d38656,
  45589. 0x0032097,0x0045803,0x1299079,0x1cffecc,0x1680abb,0x00ec477,
  45590. 0x15c58b5,0x027a79f,0x1fc677a,0x149b049,0x05f5a5d },
  45591. { 0x08311dc,0x192bf3f,0x04d95cd,0x028cd9e,0x1ef94f5,0x0e510d6,
  45592. 0x05916c1,0x06f4e7c,0x002e4ab,0x0754d9e,0x04596ce,0x15930af,
  45593. 0x047760e,0x012580d,0x1f7411f,0x0ab09bf,0x1d13fb9,0x10c46a7,
  45594. 0x15522f6,0x1871704,0x1cacfaa,0x182cf4e,0x069e69b,0x144e01e,
  45595. 0x1720f09,0x1244c1f,0x13ee29f,0x19774aa,0x01fad58,0x0cb423d,
  45596. 0x178e286,0x0b57ad6,0x1856547,0x0b76108,0x14c7cdc,0x16ea227,
  45597. 0x0212907,0x08f3c0a,0x162244e,0x0021b82,0x05319c8 } },
  45598. /* 166 */
  45599. { { 0x161c3af,0x009b735,0x0da08c8,0x1c0f697,0x1d40f2d,0x064bf80,
  45600. 0x1b9fce0,0x074ca3b,0x06a8c31,0x0bc5d38,0x072842a,0x0fac402,
  45601. 0x1b22c58,0x158fa22,0x0ee8862,0x089cc91,0x107e504,0x0c62f57,
  45602. 0x10bf33e,0x13e0548,0x093d554,0x179ec02,0x09591d1,0x1808b22,
  45603. 0x04f6179,0x043a169,0x02af722,0x0c01f43,0x138f8f1,0x10056f6,
  45604. 0x11972e1,0x12475d6,0x0bf9b90,0x02bc552,0x18d4787,0x09ac7fd,
  45605. 0x0bb9ea1,0x04e2d67,0x13fc3cf,0x09be234,0x03d1331 },
  45606. { 0x0513d1e,0x03316da,0x0af7973,0x0baab2a,0x1e78a8c,0x1c36856,
  45607. 0x1e8ff9f,0x18bd146,0x07a04f0,0x1168952,0x1741b32,0x0dc85c4,
  45608. 0x114c669,0x1909b03,0x1851a62,0x1c396a4,0x01b89f6,0x17a6938,
  45609. 0x03bf657,0x1ac2ef0,0x0907aaf,0x0262ddb,0x19b5ceb,0x01b66b5,
  45610. 0x074ac42,0x1d024f4,0x13c9d47,0x02c63bc,0x1a2edd1,0x199b50f,
  45611. 0x136ca7d,0x16ffaf2,0x0406864,0x1c95326,0x074f88b,0x0ce7964,
  45612. 0x0043cc7,0x1482731,0x11ab7ab,0x13f6645,0x067f28a } },
  45613. /* 167 */
  45614. { { 0x0148ab5,0x1d92c65,0x0145f05,0x1f678c0,0x19a1976,0x1946fcd,
  45615. 0x01a6323,0x02fd44c,0x0e8d450,0x1d9663a,0x02908a1,0x06520af,
  45616. 0x1237257,0x0bdf639,0x157b894,0x1778903,0x1cf1d48,0x16ba08f,
  45617. 0x01fd73f,0x02fcd69,0x0e1b462,0x02a0f5c,0x12c01eb,0x0b40191,
  45618. 0x057a6e0,0x14ce20e,0x0f4be7e,0x1f2a9a5,0x141cad1,0x0aeda04,
  45619. 0x074dc2f,0x07052a1,0x087879c,0x052f772,0x154973b,0x1c9826e,
  45620. 0x1d3efb9,0x17bfd27,0x0f6cba3,0x0e837a3,0x05ff091 },
  45621. { 0x19c6632,0x089522b,0x0055e46,0x1f71441,0x1b19a44,0x0b1ce9d,
  45622. 0x1ee114d,0x19de9f2,0x1bc3c9b,0x0bf15e5,0x1990439,0x1e57e33,
  45623. 0x0d122b3,0x09abecd,0x0062768,0x1fecc3e,0x1bb79e5,0x033aab9,
  45624. 0x1cbcf13,0x1cb931d,0x0731444,0x1002688,0x15bd878,0x0ebac6b,
  45625. 0x0366fac,0x19186fd,0x18b2153,0x1f88f90,0x10850b9,0x121f056,
  45626. 0x0cb012b,0x05ee418,0x0e94f64,0x1de4eae,0x19969d4,0x06cfdf5,
  45627. 0x10373a6,0x1e9869d,0x0591b09,0x07452e4,0x0668101 } },
  45628. /* 168 */
  45629. { { 0x04509df,0x0ec89f4,0x0dd84e1,0x1b9e672,0x0978bed,0x11d0a47,
  45630. 0x0974cd0,0x0f25be8,0x1ee8cb5,0x1fd0571,0x1154f10,0x0d3a638,
  45631. 0x08f0153,0x0fdf8ea,0x13c22ef,0x048940b,0x1e69444,0x1d6ffa5,
  45632. 0x0d7768c,0x06bf034,0x0b7c016,0x04f3b7d,0x0217225,0x0e6ef06,
  45633. 0x1fcde16,0x06925eb,0x128953e,0x1b196a5,0x1ec985f,0x0533209,
  45634. 0x131885a,0x0f5204d,0x0db9741,0x0f0dbf9,0x1959438,0x1c72c5d,
  45635. 0x13beffd,0x1051a36,0x0ac7efb,0x05e17bf,0x03b35b7 },
  45636. { 0x15c3749,0x06f4fa9,0x1122ffe,0x1f15bb3,0x03c1f20,0x1c7b319,
  45637. 0x0cdef23,0x09352eb,0x1e8f3ae,0x094f23a,0x1898a09,0x01aa3ab,
  45638. 0x1dc32f1,0x13c3178,0x1034a5d,0x17c6cb5,0x138854c,0x109e3c9,
  45639. 0x0d9f918,0x0009de9,0x0ee148f,0x0872e88,0x1e8de85,0x1051141,
  45640. 0x0778dd2,0x1a6a4ba,0x1b3edcf,0x0d0614c,0x0049529,0x000983c,
  45641. 0x0527d11,0x12ec16d,0x033c709,0x1ae4cc1,0x129496d,0x1906819,
  45642. 0x0771f99,0x117205e,0x11a14fd,0x1d79b2b,0x047d0a1 } },
  45643. /* 169 */
  45644. { { 0x12811f1,0x1a7ffb2,0x000899b,0x06c5de6,0x0aacaa9,0x05d0657,
  45645. 0x1e95543,0x0ced870,0x0007f54,0x1a80a15,0x1c99ce8,0x0054405,
  45646. 0x05c7fd1,0x19ee373,0x0bb95c0,0x0c7b2bb,0x0c3064a,0x1303417,
  45647. 0x18ac947,0x1e17608,0x16e746c,0x12aed49,0x0380c32,0x084cb6a,
  45648. 0x060f243,0x07ae43d,0x0da6d3a,0x0c6f657,0x17770a9,0x1ac63d6,
  45649. 0x099807e,0x1da742b,0x12147f6,0x0f4b08f,0x1578a65,0x0c0b68f,
  45650. 0x03213a1,0x0654d9c,0x0a1732c,0x094932b,0x08f4b61 },
  45651. { 0x14eb3c1,0x0760ca5,0x09c16aa,0x0840647,0x0c549ac,0x1663554,
  45652. 0x04c893d,0x14601a9,0x145f9a5,0x129dcdd,0x1eaeec3,0x0220112,
  45653. 0x10e46ef,0x0bd66be,0x01cf95f,0x16b11fd,0x1e50f7c,0x0be7e67,
  45654. 0x01555f4,0x0a7acb9,0x12e20ea,0x0239447,0x1f767ad,0x1d6d151,
  45655. 0x1edfac0,0x1065596,0x002180e,0x104428e,0x1eb06c5,0x0344807,
  45656. 0x0b1a519,0x04bcb95,0x04cf5bf,0x08d74c0,0x01627f2,0x1db0ab3,
  45657. 0x13c45ea,0x09bc58b,0x06007b6,0x004a499,0x08f942d } },
  45658. /* 170 */
  45659. { { 0x0845808,0x1618147,0x1f147c7,0x156ef57,0x0302bff,0x0cbee3e,
  45660. 0x152e7e3,0x0964d5f,0x03aac59,0x09d41e2,0x165370f,0x17a2ce9,
  45661. 0x1ce3b74,0x0552c88,0x192dcdf,0x059a488,0x173871c,0x131492b,
  45662. 0x0d1103f,0x1e490a7,0x0d7d419,0x19f0295,0x1769a83,0x0d90d81,
  45663. 0x080d684,0x1a13229,0x0be0c93,0x04ad13f,0x0f117aa,0x08f403e,
  45664. 0x0df1d2b,0x11bb93b,0x026dea0,0x1e42eab,0x0dce59b,0x06a4c40,
  45665. 0x13b1eb5,0x16abe1f,0x06b2f82,0x0a52938,0x0383002 },
  45666. { 0x0744723,0x1ad202f,0x120683b,0x0a35c10,0x1b5bcf7,0x00fbb7e,
  45667. 0x16333fb,0x18d57f5,0x1fab37f,0x1d2ec18,0x1b6de3e,0x049191f,
  45668. 0x10be39e,0x16c9f98,0x13eb57e,0x0b8494b,0x11e913d,0x0ba3fed,
  45669. 0x1462dfd,0x148f928,0x0327052,0x163e7da,0x0788235,0x1ca717d,
  45670. 0x1cb9c70,0x08b589a,0x056ec5e,0x0c6a4eb,0x1106c73,0x1c402d9,
  45671. 0x01a8b01,0x1841376,0x0d42a06,0x08256e9,0x11c74f1,0x096a4b6,
  45672. 0x022ce03,0x1a59b44,0x0169727,0x12dd683,0x015f187 } },
  45673. /* 171 */
  45674. { { 0x0ee4684,0x0f50305,0x0f20253,0x0cf9b7b,0x02b21f0,0x09898ca,
  45675. 0x18526c6,0x14d4873,0x181a7db,0x125eea0,0x0ba03fa,0x0e0c785,
  45676. 0x02c6213,0x09411ee,0x02c259c,0x023636b,0x1158326,0x03a21ea,
  45677. 0x0f080e1,0x0df0622,0x12d22e1,0x0b15ecc,0x0338813,0x0327116,
  45678. 0x1bcd6f4,0x063a4ce,0x1474dde,0x125bda3,0x1dae734,0x0ba7e2e,
  45679. 0x166756f,0x13296c4,0x0813d52,0x165346a,0x13d83a1,0x18323b3,
  45680. 0x13e9c2a,0x10bcf57,0x048e158,0x1e73fdc,0x06146f1 },
  45681. { 0x18e2aa6,0x1699f03,0x0996f41,0x0f3bdd2,0x093af7f,0x1207423,
  45682. 0x03e076a,0x0fdaadc,0x09b9a40,0x0fdddc4,0x0654641,0x15b9dbd,
  45683. 0x19dcf44,0x0496dd1,0x1c7e34c,0x0ee96fe,0x1a54231,0x1b3adae,
  45684. 0x17d817a,0x0d44a34,0x1a9e745,0x17c3d1c,0x040c752,0x168e97b,
  45685. 0x1000605,0x148eda1,0x0ad996a,0x1b4bb7e,0x11eeb4b,0x1efab31,
  45686. 0x1617468,0x0c46ef8,0x08149ef,0x085ff81,0x13a5a17,0x1c5c35e,
  45687. 0x02a465d,0x15043ac,0x0014383,0x13c0d7a,0x095543f } },
  45688. /* 172 */
  45689. { { 0x1d7c6ef,0x1e37a42,0x1093df2,0x1ac7637,0x0ad8084,0x065d316,
  45690. 0x13a22fe,0x125bf21,0x0b455c1,0x0725b43,0x1f1bb66,0x11aaee9,
  45691. 0x176146b,0x1d71003,0x188e279,0x04a52e1,0x07961c2,0x0a920e2,
  45692. 0x021397d,0x042a207,0x02737d2,0x110bf14,0x15b4833,0x04ce9f1,
  45693. 0x19f514f,0x0edf188,0x15c3004,0x0a8b20a,0x1b760e8,0x1aecfe7,
  45694. 0x0677ead,0x13d1854,0x146362a,0x0a593ca,0x1e2929f,0x1896da7,
  45695. 0x0e5d698,0x0438827,0x05bfe97,0x0f05745,0x06db434 },
  45696. { 0x03f0d95,0x03249ae,0x0254192,0x049ce91,0x0917db8,0x179f224,
  45697. 0x17d89ac,0x097ee7f,0x02b7f57,0x1076e2a,0x0c9c8f1,0x13455ee,
  45698. 0x0cbe1c0,0x1e5688a,0x0d19a75,0x15ff2fa,0x00a321a,0x04b2330,
  45699. 0x1433587,0x1c5775d,0x150eb94,0x00ef623,0x019b869,0x1513eb1,
  45700. 0x0990db1,0x149d0df,0x13c9d65,0x073c9ad,0x00dddfc,0x1bc0607,
  45701. 0x104473e,0x1b33914,0x0afcd7f,0x0182878,0x0b6db87,0x099d7ff,
  45702. 0x16d2c6e,0x1cc0d84,0x1ea513c,0x1ce55c4,0x007a791 } },
  45703. /* 173 */
  45704. { { 0x09f0300,0x148238f,0x04139c3,0x13799bf,0x00253ad,0x02983c7,
  45705. 0x0a277fc,0x0c4a380,0x0ae8934,0x0f78497,0x11a117c,0x1235490,
  45706. 0x142c90a,0x18ed6a5,0x11bb683,0x0cf6432,0x0f333df,0x0783b28,
  45707. 0x0c56805,0x1311b61,0x10f9c6e,0x175aa17,0x1cb8319,0x1806f1e,
  45708. 0x16311e0,0x086aea5,0x0aba1a5,0x09175b5,0x1f1c8f5,0x11c6d9a,
  45709. 0x151a005,0x1289a35,0x09e3216,0x18e9909,0x0b21011,0x1d32a37,
  45710. 0x05e94dd,0x0614f9c,0x1b2b00f,0x05c8a87,0x06d6acc },
  45711. { 0x1b2d299,0x0cf4aab,0x0737ae6,0x17c7ae4,0x1a2bcd9,0x065a221,
  45712. 0x0e13eed,0x1545cc0,0x1dc060f,0x10bbb84,0x01f37ab,0x0da7193,
  45713. 0x0d74f0e,0x083b7df,0x08df3e0,0x1f7ff34,0x1137983,0x034d78a,
  45714. 0x08fe561,0x1ef43a6,0x03986c3,0x07b6db2,0x0f8872b,0x0e07b24,
  45715. 0x0134f96,0x1bb3e6c,0x1ee0e4f,0x0eab131,0x0252220,0x145e174,
  45716. 0x1f06d6c,0x0f24954,0x18799c1,0x13d455b,0x03ca050,0x043b66f,
  45717. 0x1f28949,0x1228d8f,0x11bbb56,0x0247a78,0x079d182 } },
  45718. /* 174 */
  45719. { { 0x09d5589,0x16ffc88,0x126468f,0x0805368,0x1ed52eb,0x1aa56fe,
  45720. 0x074c2d2,0x0ce27d7,0x1a27bff,0x1c90a60,0x03d1813,0x1dcecfe,
  45721. 0x084c817,0x01d2871,0x17e360f,0x0c46f75,0x1c99402,0x0e2ee01,
  45722. 0x19991f0,0x12b0372,0x07f35f2,0x04c5034,0x042da82,0x0c68a2e,
  45723. 0x07cec31,0x0c4573c,0x158b9d4,0x0003b74,0x02c3fb2,0x10d3a2f,
  45724. 0x0555753,0x16cfa67,0x1cacdeb,0x021775f,0x1e72f1a,0x1743415,
  45725. 0x1e88580,0x0c85159,0x1372141,0x1234f09,0x0731044 },
  45726. { 0x048d676,0x1166f93,0x0ac5132,0x0a9e362,0x1a85eca,0x0070f5c,
  45727. 0x0b250a6,0x112373b,0x11ac8aa,0x1869b84,0x078657c,0x156f8e3,
  45728. 0x1773072,0x17b81bc,0x1463208,0x0cfed74,0x014ac00,0x1d60487,
  45729. 0x1734a49,0x19f8e11,0x1a630e6,0x1110f3e,0x13d6227,0x0e38f8c,
  45730. 0x0a40b83,0x064da55,0x0a3de1e,0x1f3b57c,0x0caf3f1,0x16b5ec2,
  45731. 0x04bde2b,0x13c1c3b,0x039dd07,0x0126e1e,0x17ec489,0x12d017c,
  45732. 0x0bdc009,0x0d90a68,0x1153fd0,0x192a301,0x06a8f8f } },
  45733. /* 175 */
  45734. { { 0x1235132,0x0f6b1a9,0x022d8a8,0x02b3b75,0x1db233f,0x0f7eec0,
  45735. 0x15148a4,0x15d0ac4,0x1b25111,0x1a8294b,0x006f631,0x15f23ae,
  45736. 0x1db5921,0x0bba7a2,0x14175ca,0x0e7ff69,0x05ef18e,0x0371ea6,
  45737. 0x066cc0e,0x1b30bf1,0x1558897,0x1de44d8,0x02a70c3,0x0263039,
  45738. 0x0d1a34d,0x1071e49,0x08888cc,0x125d0d7,0x0eed022,0x0a6100e,
  45739. 0x07f3c91,0x0b07e61,0x1a45f74,0x1e8d193,0x00b2b43,0x10eb4c2,
  45740. 0x0b9c753,0x07a2e96,0x0ff5f6d,0x183b650,0x04752d8 },
  45741. { 0x1dff4d5,0x0b6756a,0x1fd1453,0x168b504,0x14cd5fd,0x0389af3,
  45742. 0x098313f,0x11c20e1,0x01be577,0x1605dbc,0x11ac237,0x059ab1b,
  45743. 0x16271e1,0x0a5e124,0x194226d,0x131596e,0x0636190,0x136ef96,
  45744. 0x1d4a20c,0x1d758cc,0x0af1fd6,0x12e1284,0x1aa8b40,0x19f83e1,
  45745. 0x0cda84d,0x1f009e1,0x0115442,0x18f06d5,0x0868011,0x14468d4,
  45746. 0x114e411,0x15f5e4a,0x03132aa,0x05446b2,0x15dca0c,0x0092d0a,
  45747. 0x0744b47,0x0a48e54,0x015495a,0x1e6ebf7,0x03a6518 } },
  45748. /* 176 */
  45749. { { 0x04042a0,0x076a811,0x079aaaa,0x0048a5e,0x0cb4e3b,0x0108ec3,
  45750. 0x17d31da,0x07fdb94,0x1ef4d5d,0x107f1fc,0x151b953,0x0548a45,
  45751. 0x1533a8e,0x18a233b,0x063887f,0x1a036b3,0x10ef592,0x08a4b62,
  45752. 0x0e99dce,0x00985f0,0x1f00691,0x05a395d,0x0a19c2f,0x062ef7a,
  45753. 0x083b250,0x1514754,0x15f49c4,0x0bb1780,0x19c994c,0x098bda1,
  45754. 0x1fd07be,0x1b9b435,0x001d3a8,0x07b7dcc,0x1ad5c0e,0x01ad0dd,
  45755. 0x1bfbf82,0x062e687,0x1605fa0,0x0c7db84,0x0540ac3 },
  45756. { 0x07f43df,0x0b4d4ff,0x19329c6,0x1058373,0x0665380,0x0e148bf,
  45757. 0x1df6216,0x0095b2c,0x196aa44,0x1654aa2,0x0a5f6ae,0x0abffe2,
  45758. 0x1e0e9d8,0x115753e,0x18625ec,0x07f1c3e,0x0fd36f1,0x1cb76e6,
  45759. 0x1b88037,0x1a60e02,0x08a4627,0x1b64c4c,0x1ca7c1c,0x1e463a4,
  45760. 0x05e6097,0x1a94af1,0x0fd8121,0x1efe443,0x19b299a,0x1304a00,
  45761. 0x16759a0,0x04d6963,0x199de09,0x0ebd18e,0x1d986b3,0x13d88f9,
  45762. 0x0ebe15e,0x14f959b,0x05d3d37,0x1d9f42d,0x017db32 } },
  45763. /* 177 */
  45764. { { 0x0f40599,0x1b48cb6,0x03a9d7b,0x1601804,0x1ea10df,0x157b3cb,
  45765. 0x0b9eff2,0x0f07b4b,0x188ddd6,0x0b31e51,0x0f3f343,0x11fc4ab,
  45766. 0x1e5a21f,0x11a25e3,0x10fd4e3,0x00c65d3,0x11d548e,0x09afb15,
  45767. 0x0f1b993,0x1e484a8,0x1627654,0x13134c9,0x11d569e,0x1e82649,
  45768. 0x1c5f7b0,0x079d1db,0x04e8860,0x0ad2fef,0x01675b0,0x0fd88f4,
  45769. 0x1d5b3e1,0x1ca6851,0x13cdb35,0x1458136,0x16454b4,0x11c7542,
  45770. 0x17a3fb7,0x03812af,0x11176a1,0x0374328,0x0460bd0 },
  45771. { 0x04d8077,0x06e11e1,0x14b2f0d,0x0098e41,0x02f4b58,0x0e8fff4,
  45772. 0x0a445bd,0x1c5453b,0x092783c,0x1c57a90,0x012bcd5,0x03576b2,
  45773. 0x10e29f5,0x1bd508c,0x115c35f,0x1bbe08d,0x1ba571b,0x0a52917,
  45774. 0x1a26ed4,0x1c540d5,0x044dbf4,0x062cf9a,0x1e66cd7,0x1984aae,
  45775. 0x0836726,0x0bbe181,0x16bf3b0,0x0949d30,0x16cbd09,0x1ee5be1,
  45776. 0x1deb6bd,0x0eba720,0x131b787,0x1125e76,0x013cb4f,0x16a5ad2,
  45777. 0x1f95421,0x0513348,0x01e3717,0x0782e69,0x07d342c } },
  45778. /* 178 */
  45779. { { 0x1fd127f,0x1960508,0x117b973,0x10233c9,0x06d36bb,0x1ab561b,
  45780. 0x0c949bb,0x0eac435,0x0e54306,0x067f577,0x1a5864c,0x0fa5587,
  45781. 0x112ede2,0x1c7e733,0x04d44eb,0x0987ac8,0x01b075f,0x030ace3,
  45782. 0x041a766,0x0fdfd2b,0x0ea9d44,0x14753b5,0x0be35bd,0x0b7a2c9,
  45783. 0x1c61b0f,0x1cc562e,0x187a22e,0x175688d,0x092320d,0x058b0dd,
  45784. 0x195862e,0x0f13130,0x0eafb3c,0x1bf4150,0x130b022,0x1618f57,
  45785. 0x00d160b,0x184db71,0x18e9c43,0x14d1c98,0x05be0af },
  45786. { 0x1bbf49c,0x1b69c0d,0x0ffa0aa,0x13180e0,0x1e09ce4,0x07a1319,
  45787. 0x02d7784,0x065d94b,0x1da5a45,0x0e632c0,0x03dedf6,0x10edec3,
  45788. 0x0707e18,0x1287bff,0x066978c,0x10d7c08,0x090de6b,0x0dd8d4f,
  45789. 0x1cd645a,0x14fbd66,0x1b2c584,0x04a8a4e,0x0e3acd2,0x1d75770,
  45790. 0x06a33b0,0x1490a2a,0x030be22,0x00cfe16,0x0db0190,0x0ff3851,
  45791. 0x0faf783,0x18c7cde,0x051b06c,0x037d6dd,0x1ee7a48,0x1543224,
  45792. 0x1e80dc0,0x15af43f,0x0c2bb93,0x1eba9bc,0x01e6fcc } },
  45793. /* 179 */
  45794. { { 0x08ac924,0x0ffb355,0x0fa2d5f,0x0385316,0x06e9ad3,0x1d84060,
  45795. 0x18ca597,0x07fa281,0x11d95c9,0x0d5908e,0x0032a9f,0x1085143,
  45796. 0x096d68d,0x1106f6b,0x04a5022,0x08c3e35,0x15338df,0x1540a8b,
  45797. 0x03aba4c,0x0c095cc,0x0c0bff5,0x04bed72,0x0406e79,0x04c5d13,
  45798. 0x1a97fde,0x0c1a2b9,0x13c4212,0x1ad3b34,0x124f1de,0x0117b23,
  45799. 0x17e3fe8,0x1d50b42,0x1f1c2e4,0x09bca6a,0x13a4051,0x1a98c4d,
  45800. 0x1f0907d,0x02066b5,0x0a0de01,0x0c2bbb5,0x04522d4 },
  45801. { 0x1fbe7c5,0x0f83cf5,0x111a225,0x1b09de6,0x10ea1de,0x10d5cb1,
  45802. 0x07adb52,0x0d0e2d5,0x050a30c,0x1252e91,0x0eeea86,0x0638008,
  45803. 0x155a166,0x080872f,0x041d409,0x00aad7a,0x09d3d8c,0x0dfff1f,
  45804. 0x1ddc906,0x0616300,0x029731b,0x18425c1,0x043fdfb,0x0343187,
  45805. 0x17d75f2,0x07c0061,0x15596ee,0x11a14c6,0x03bceb1,0x0d1522f,
  45806. 0x036eb07,0x047e161,0x038e90c,0x02d628e,0x0a897ef,0x0de3743,
  45807. 0x1da71fc,0x0a92b5e,0x102e827,0x152dafc,0x0346501 } },
  45808. /* 180 */
  45809. { { 0x02b0f1d,0x1224666,0x1c0e1af,0x1358986,0x03eb45c,0x04b5dff,
  45810. 0x1d9767f,0x1b4a70f,0x15ae27f,0x179e274,0x0602273,0x0eec378,
  45811. 0x01a008f,0x11650c5,0x1d28210,0x066e3e6,0x04253b7,0x0774414,
  45812. 0x13024d5,0x1f8db0f,0x0d6bcb6,0x0db0a4b,0x01227b0,0x1c64b89,
  45813. 0x029b949,0x0b35496,0x09ef7b0,0x0b8d94a,0x0a28131,0x07776e7,
  45814. 0x13e5511,0x074422a,0x0683eb3,0x030e79a,0x1e634e4,0x171f64d,
  45815. 0x06c940b,0x1845540,0x125b70e,0x19fcaa9,0x07c1d42 },
  45816. { 0x0110aa7,0x1381fee,0x0de1d9b,0x0fe6c5c,0x0b7b79d,0x16e51e5,
  45817. 0x11d756a,0x0e7a4b3,0x160be33,0x137653c,0x13a3fca,0x14960d8,
  45818. 0x1ff4744,0x19db82d,0x010b33b,0x096a765,0x1aaae30,0x00d1d7a,
  45819. 0x0cb4c6e,0x1f44023,0x08d97bb,0x1d25f74,0x112e9ba,0x0b97073,
  45820. 0x165ce56,0x074169a,0x1b6bdfb,0x09010d2,0x1597452,0x0673f34,
  45821. 0x0dcb1f3,0x1d29f30,0x1d6eb3c,0x0d19377,0x133ce04,0x0c14676,
  45822. 0x1ffa93a,0x101fa1f,0x0764050,0x050e786,0x0031e98 } },
  45823. /* 181 */
  45824. { { 0x05a17ff,0x1f67e3b,0x09953fb,0x11a2521,0x009f388,0x06d01c5,
  45825. 0x1711a4e,0x08d7e4c,0x1a169ad,0x1db0a2e,0x18bfa12,0x0428474,
  45826. 0x0533cf8,0x15e4305,0x0b7d5c6,0x07188ac,0x0fa815c,0x0df9548,
  45827. 0x1fb6a1d,0x143adc2,0x05e145b,0x0d4a37d,0x1e67620,0x01eb476,
  45828. 0x1e784b9,0x095360d,0x12c43fd,0x122146f,0x14fd360,0x0ff2527,
  45829. 0x0830e30,0x11c5a77,0x1180fc5,0x130c3e1,0x0142c5e,0x047c5fe,
  45830. 0x143a35c,0x0002cdc,0x11470e8,0x08b4519,0x0494d36 },
  45831. { 0x1a021f8,0x0135b25,0x0db0e61,0x06f2dbd,0x114c908,0x1b63b16,
  45832. 0x14e55f8,0x02cda5c,0x0751cf2,0x1aab765,0x0928663,0x1c00336,
  45833. 0x0edaca1,0x0590615,0x021f691,0x14e668f,0x0cdff41,0x1c9f6a6,
  45834. 0x11f0335,0x02f888b,0x10098d7,0x0548dfb,0x131218d,0x0b3775f,
  45835. 0x146f93b,0x18ad0f8,0x0795893,0x1a71767,0x1f8443d,0x0d56981,
  45836. 0x1f25b50,0x097e209,0x1670f03,0x032c135,0x07b4a5c,0x0a0a07f,
  45837. 0x134200f,0x070fa3d,0x11bcdda,0x0bd77a9,0x03cfdcc } },
  45838. /* 182 */
  45839. { { 0x123e13d,0x015435a,0x02814db,0x105241a,0x1014a45,0x0b894b0,
  45840. 0x0d1e39d,0x1d47aa5,0x07eb51b,0x0ba3033,0x03a4641,0x10c30f6,
  45841. 0x08709f7,0x1434447,0x02bb621,0x1f9a805,0x1d7d94a,0x1bcd404,
  45842. 0x084a6bc,0x0c065fc,0x008250c,0x194c1e2,0x1d792f9,0x1677d1c,
  45843. 0x11bbb7a,0x1944c19,0x12d8631,0x0634065,0x19c4a4d,0x02d09fa,
  45844. 0x188db76,0x1da9ec3,0x1ece345,0x18b8aed,0x1334795,0x0f74f55,
  45845. 0x04a1ebd,0x062c6d3,0x1ba844e,0x01e7a35,0x089296d },
  45846. { 0x0a82c97,0x09447e6,0x0372c59,0x1a284fd,0x06c6c12,0x1f6ed49,
  45847. 0x13c1d30,0x17ccd52,0x0eaa01e,0x030070f,0x17a1b65,0x1cf861e,
  45848. 0x1114abc,0x05a2b51,0x075c083,0x08584e8,0x013279f,0x05582d5,
  45849. 0x108e11a,0x0c1f5fa,0x19e670b,0x0098c69,0x0863bfb,0x0416631,
  45850. 0x1f1ac89,0x101f583,0x0360e67,0x03c7975,0x01a3010,0x09971e4,
  45851. 0x16197e2,0x1998ccf,0x08bca7d,0x0303e57,0x19e689a,0x199dc35,
  45852. 0x0ac0a12,0x0173266,0x13150c6,0x1ee5634,0x09233a2 } },
  45853. /* 183 */
  45854. { { 0x0cbee17,0x146fb05,0x1371c5f,0x04b849f,0x0f0959c,0x07fe580,
  45855. 0x0621f95,0x0d68de1,0x0d28511,0x0c9ef65,0x07e946e,0x09f1774,
  45856. 0x1e0bfaa,0x08790c1,0x04927bf,0x0eef339,0x1589684,0x0fc9e59,
  45857. 0x0c8b508,0x17f6fe4,0x1009284,0x0d6a157,0x10331c2,0x163ac2a,
  45858. 0x122749b,0x035634f,0x09c5f0f,0x0dea167,0x1c5eeb7,0x14c2ddc,
  45859. 0x17e2c87,0x148f076,0x0fb19ae,0x0e1f3ac,0x0e6d4b8,0x100990d,
  45860. 0x12971ac,0x12c8497,0x00a46b2,0x0d243db,0x02bb26a },
  45861. { 0x1f81416,0x1a21a8a,0x0ed2628,0x0f55feb,0x086e72e,0x0b930e0,
  45862. 0x193780c,0x1fc7a3e,0x05c0a1c,0x0e03c36,0x00d004c,0x09b166d,
  45863. 0x0d542ea,0x0d1cda6,0x1dc9ce8,0x04fe25e,0x0e1cbef,0x00a7f3f,
  45864. 0x1aec9f7,0x1f813c2,0x1dc7ee7,0x0ba0872,0x1037330,0x08767bb,
  45865. 0x0674219,0x0dbd1a3,0x00fcc70,0x052696c,0x0c10709,0x0f6ce11,
  45866. 0x1ac061b,0x0f33f2c,0x17ee8ba,0x18449d1,0x12d0926,0x1c1e77f,
  45867. 0x0e92d4d,0x130a239,0x1ac22eb,0x1f1c32d,0x0937cb3 } },
  45868. /* 184 */
  45869. { { 0x0fbfdce,0x073be0b,0x13015f0,0x13931a9,0x0a034cc,0x0b96907,
  45870. 0x1b5c909,0x079cec0,0x00019a8,0x030daae,0x05c58a6,0x1007e2b,
  45871. 0x1b80ba2,0x02d07eb,0x1050774,0x155441e,0x13b4b0d,0x04432c8,
  45872. 0x08e123b,0x10ae8d5,0x05d2e66,0x0d1f024,0x05b4569,0x0d20bba,
  45873. 0x0c7743b,0x15d40e0,0x16062bc,0x1d8636f,0x174b78c,0x18ca695,
  45874. 0x0a20363,0x0a87c5e,0x0659db2,0x03e0e65,0x09f67ec,0x0063707,
  45875. 0x1f1048c,0x09bfee0,0x1a84619,0x00ef0b0,0x04d57bb },
  45876. { 0x1b396b6,0x1bb4529,0x16b2f12,0x09276a3,0x1c8b24c,0x0570d9d,
  45877. 0x047ae8c,0x18a67ca,0x1945147,0x09ddeca,0x1f8f3a2,0x00622f3,
  45878. 0x146cc86,0x1fc905e,0x0c2859c,0x0c2c069,0x0eb6b25,0x1d99489,
  45879. 0x145a360,0x1345493,0x1128bc6,0x1d7786e,0x0d25279,0x04d33c3,
  45880. 0x1419a87,0x1b59309,0x1efc84d,0x0d8b08e,0x1971470,0x0c84d27,
  45881. 0x17f956c,0x0f736e8,0x1d6eb75,0x19e42b1,0x0ca4237,0x076a6cb,
  45882. 0x15fcfae,0x12bf21a,0x0aaa038,0x0312f3e,0x01067c1 } },
  45883. /* 185 */
  45884. { { 0x0bf8883,0x0a84219,0x199f211,0x14dfa0c,0x0755286,0x0119aea,
  45885. 0x03e3ddf,0x129ae16,0x02f4a2c,0x1c7306d,0x02b3d59,0x1159a23,
  45886. 0x19a468d,0x1fadc86,0x04e0c2e,0x122099d,0x074ed4e,0x075258e,
  45887. 0x1dddba9,0x0e62da4,0x0b12ac6,0x0e1b0dd,0x0e62b5d,0x02448a3,
  45888. 0x1d48299,0x1d76191,0x014c290,0x0c88044,0x12d5a52,0x0997194,
  45889. 0x0f0e911,0x0bfd9e3,0x148694b,0x1dc5c6d,0x05bb199,0x1dc9c0a,
  45890. 0x04306ad,0x152cafd,0x05c96ce,0x123e69d,0x07e4f70 },
  45891. { 0x1f70919,0x00b74db,0x0fd4fce,0x1a2d600,0x165216e,0x064cf2b,
  45892. 0x13fd1de,0x0208d8d,0x030a518,0x152d5f4,0x1ca36f9,0x13cc8bc,
  45893. 0x16ef6f4,0x056677e,0x175cfab,0x1e7eedf,0x06f8c37,0x1f61ca7,
  45894. 0x1901ff0,0x0410056,0x1cbd733,0x1d4b312,0x0623a3d,0x157f601,
  45895. 0x123637c,0x0cd4194,0x1d01fcd,0x0b1753b,0x1fae502,0x1772e65,
  45896. 0x04ffc06,0x1fc4a30,0x1eaeace,0x0e5d0fd,0x05860fc,0x0b38d3e,
  45897. 0x1eadcdb,0x162c56c,0x1a2f544,0x1a8d999,0x02ae49c } },
  45898. /* 186 */
  45899. { { 0x00849f2,0x0d871e2,0x063048e,0x1b48821,0x1136a4c,0x03fb24a,
  45900. 0x16a6795,0x18cc2a6,0x07a9bba,0x1725ee2,0x11ebda4,0x0c8ca6a,
  45901. 0x0a195a1,0x05a3d3a,0x1b2cc66,0x145650b,0x1fc9de6,0x093c2a9,
  45902. 0x18ae94b,0x1807141,0x1a93471,0x041ade5,0x04ae86e,0x063d944,
  45903. 0x150da6f,0x1636a5f,0x1a00acc,0x028dc7e,0x04c8c4d,0x00989e3,
  45904. 0x05c3270,0x1dda425,0x130f12d,0x02987d6,0x1fee71a,0x0336eb7,
  45905. 0x0918de5,0x00569f4,0x1c6dc8f,0x0a54e6e,0x0180e9d },
  45906. { 0x1ab77b0,0x12a1794,0x18a30c5,0x19ef5dc,0x1d411d9,0x1e17a06,
  45907. 0x01a14d4,0x19e0898,0x04b0ae4,0x1c6e3f2,0x1099bd8,0x030b2bf,
  45908. 0x1da0924,0x1e97f5b,0x07699c7,0x12f30c7,0x0d55ea3,0x12b42c7,
  45909. 0x03ce0ca,0x129e62b,0x18317a6,0x03698b6,0x0a508cf,0x146b4f7,
  45910. 0x0cb2630,0x09d97e5,0x17c7fdc,0x1df1efb,0x0ee2f3f,0x0292acf,
  45911. 0x12a2e6d,0x02ada0c,0x1b4f91b,0x07e7e68,0x1b08bd7,0x022ef0c,
  45912. 0x1777eb4,0x1e12b31,0x016d04a,0x079b157,0x021ca6f } },
  45913. /* 187 */
  45914. { { 0x1e66635,0x11589d1,0x1abc385,0x16553ee,0x1ef20a2,0x0d99ab0,
  45915. 0x0e8c11b,0x11b568e,0x17802bb,0x0205ebb,0x06d1302,0x1ebd4d3,
  45916. 0x115b6ba,0x0d9103f,0x1846400,0x0020b8d,0x0a9790b,0x072ef0b,
  45917. 0x0d9fc01,0x025e2bb,0x1d2522b,0x02c5012,0x0617eb5,0x0142284,
  45918. 0x16953df,0x0605e67,0x0fd140d,0x1884253,0x077bff4,0x02000e1,
  45919. 0x0603dd0,0x050153c,0x0440b4c,0x1515a37,0x03d610a,0x1eecfbd,
  45920. 0x05e8d94,0x11055c0,0x1d8d4f7,0x0b24044,0x05aff58 },
  45921. { 0x0458e40,0x1669054,0x0af6016,0x10292e6,0x1a5557d,0x0e5396a,
  45922. 0x104c57c,0x0478e0e,0x0952b53,0x197134e,0x13eb7df,0x0aacc92,
  45923. 0x065c592,0x0d3e933,0x0edeb34,0x050ca2a,0x03d86fe,0x1d36f83,
  45924. 0x1f54eda,0x03b626a,0x0d011e9,0x04f49f5,0x04656ee,0x0c77fcd,
  45925. 0x1e1af29,0x0431eb8,0x0a209e2,0x1565738,0x059b6ff,0x13491dc,
  45926. 0x145de0d,0x1ee053b,0x0695174,0x022b0b7,0x01d9ee6,0x138f30f,
  45927. 0x1907d84,0x1da78ea,0x0a5dd93,0x03911b1,0x03eab7e } },
  45928. /* 188 */
  45929. { { 0x0e5718b,0x14a5b29,0x07a71ce,0x09e99dc,0x03aefa5,0x1f76f57,
  45930. 0x0798d54,0x034ca9d,0x15f3aca,0x12a0f0d,0x00cc5bc,0x09121a1,
  45931. 0x0ed7129,0x1dbfca8,0x196bd8f,0x07c94f2,0x00dc74e,0x06c7e4f,
  45932. 0x0bde7af,0x1c91a5d,0x07e6b4e,0x1545bbc,0x09162a1,0x199d5e1,
  45933. 0x1621ff7,0x006ec63,0x1f7d9e6,0x0451ddf,0x1067278,0x03a17c8,
  45934. 0x0a48435,0x160fc6c,0x1f63501,0x0f14ec8,0x0719e5c,0x0a882ec,
  45935. 0x03a3b8a,0x06632f8,0x0551303,0x09e71c1,0x03491da },
  45936. { 0x1062eae,0x1682365,0x1db59c1,0x0aba10e,0x0e7db73,0x118ae97,
  45937. 0x00148a4,0x1b701bd,0x0c402bb,0x03c2b31,0x14ccdd0,0x04b84dd,
  45938. 0x135f935,0x1eab476,0x1a85359,0x1163cd9,0x1896688,0x0c8b508,
  45939. 0x171c59d,0x1aa40ab,0x1df20fb,0x1bf22ba,0x00cf441,0x012466b,
  45940. 0x1100aec,0x1c4a749,0x05b3614,0x1f3c3a0,0x0263682,0x1b92a19,
  45941. 0x15fbaf4,0x037499f,0x01d172b,0x02c1c20,0x0e755d3,0x1c6efb5,
  45942. 0x00d517d,0x1534ac4,0x16862ba,0x1fad5a2,0x00c843d } },
  45943. /* 189 */
  45944. { { 0x1373300,0x008ffe4,0x0c01156,0x1533fb8,0x1c39332,0x1e5b2a8,
  45945. 0x0e070d4,0x04fc337,0x096a83d,0x1a5c925,0x18fc69d,0x1f9765d,
  45946. 0x07cbfc8,0x0086ab6,0x09e3b10,0x15ef35e,0x02fe0ab,0x1b7ef34,
  45947. 0x0ce6baf,0x0da0e4e,0x1db6756,0x0eb8902,0x0f4d6b5,0x0a393a1,
  45948. 0x1e69470,0x13e5add,0x034e8c1,0x0efb690,0x0d75305,0x1faa2b9,
  45949. 0x0f4b1c3,0x1c0db0a,0x0615aec,0x1fdaef4,0x132c16a,0x0ee3333,
  45950. 0x0a0a8ed,0x17e4b5f,0x17da7bb,0x13a6bed,0x02dcc46 },
  45951. { 0x05f0e77,0x1668363,0x052b329,0x017ae36,0x1dcc798,0x09e6006,
  45952. 0x07e2cf2,0x0af6c44,0x1ae8cbf,0x0fe6ad9,0x0398ff7,0x0e7eedf,
  45953. 0x17bc929,0x0370995,0x01228d0,0x193c5d3,0x003d51e,0x12662cd,
  45954. 0x08cc206,0x1a65767,0x066b9c9,0x0940742,0x0004841,0x17ce52a,
  45955. 0x0032a1b,0x0246158,0x08924e1,0x17f8cae,0x1ba0ffd,0x10675b5,
  45956. 0x00ba5ca,0x1815290,0x00c0a4f,0x0c5e3fb,0x0731667,0x11ec588,
  45957. 0x112da0b,0x064b771,0x1e7f208,0x1b79b7b,0x05a1a65 } },
  45958. /* 190 */
  45959. { { 0x0485684,0x1348d21,0x0326fee,0x125388e,0x013116b,0x15028cb,
  45960. 0x065c798,0x1b56960,0x05ff499,0x1922d53,0x0e3bffc,0x0fe94a4,
  45961. 0x15c2ef8,0x064eaa8,0x1b71aeb,0x1595982,0x07e2dbd,0x1ad3f91,
  45962. 0x06eebb2,0x1b55895,0x18858de,0x16973e4,0x1fcc229,0x112ab27,
  45963. 0x12fc2e6,0x108a637,0x145df81,0x0cabe50,0x0b1bee3,0x0683180,
  45964. 0x15298fa,0x02782f6,0x0d0ce79,0x1a1315f,0x18d7125,0x0f94957,
  45965. 0x1c4e403,0x1a250bd,0x1ef67d2,0x133dfcb,0x05ae950 },
  45966. { 0x04f7455,0x12f73c0,0x1a0848b,0x0e440cc,0x141a499,0x0af1999,
  45967. 0x130c5de,0x1db2fa4,0x0e48efc,0x17a091e,0x0f08704,0x1b2433f,
  45968. 0x0ee8738,0x0331d1d,0x0ef7184,0x14db776,0x0c28593,0x09b01ec,
  45969. 0x0f06b1d,0x044fe5c,0x0519926,0x002f557,0x1faa4ab,0x0d02559,
  45970. 0x16f0bfd,0x16e2dac,0x13f0aa0,0x19cfd08,0x122b273,0x040d31a,
  45971. 0x054e101,0x0a50cf1,0x16088b1,0x0434441,0x1f30996,0x1843ff6,
  45972. 0x0f4a7ca,0x1198b09,0x14a6032,0x0fd47db,0x0411066 } },
  45973. /* 191 */
  45974. { { 0x0d04b63,0x181abe1,0x0862060,0x1be9253,0x1fc5a34,0x08caef9,
  45975. 0x1db688b,0x0e78e77,0x1cb4324,0x06f97c4,0x1fc4e05,0x1cb9d32,
  45976. 0x14345af,0x05cb027,0x18fd7e6,0x015cbb1,0x0e950c1,0x1d6bca1,
  45977. 0x1b497fc,0x1aa88fd,0x00cccef,0x0f0739e,0x0fda394,0x0a9f499,
  45978. 0x0d591ab,0x0462d8d,0x144ad87,0x1778220,0x0bf7608,0x1489dad,
  45979. 0x126ee4c,0x003cf2c,0x11231be,0x065f3ed,0x1a44103,0x13a1507,
  45980. 0x10a96db,0x0f2137c,0x047a8f7,0x08a69be,0x01cceb6 },
  45981. { 0x06d0f55,0x0862786,0x1274b48,0x1738ce7,0x0cadf61,0x071fddb,
  45982. 0x06466a7,0x1c9baff,0x093b063,0x1afa4a6,0x0a4ef84,0x167828b,
  45983. 0x1c580bd,0x07a977b,0x01c8cc8,0x176d49b,0x0e88814,0x13a6c3b,
  45984. 0x1ea5f7b,0x1ee4758,0x18334f6,0x181f1e6,0x1f78ae3,0x0e404e0,
  45985. 0x0f082ae,0x03730b1,0x1377e92,0x111d85a,0x1a17c6e,0x042cc69,
  45986. 0x06b6597,0x073002e,0x0e59e54,0x1b59131,0x0176efb,0x06156c5,
  45987. 0x0d48b20,0x1a28caa,0x17a8cf3,0x0669d44,0x01f1752 } },
  45988. /* 192 */
  45989. { { 0x067ea91,0x13b2d9a,0x1116022,0x1dfa5b3,0x1f4632e,0x195e379,
  45990. 0x171b673,0x15cf6eb,0x0359813,0x1e46920,0x12f637b,0x0413c89,
  45991. 0x0223ecb,0x10a92b1,0x0e8438c,0x1c334b3,0x1343f1e,0x1fd0a6c,
  45992. 0x0c3123d,0x0f8437f,0x1437df9,0x0875186,0x11398a2,0x028eb85,
  45993. 0x0e2a465,0x152d943,0x104999c,0x123e03c,0x0ab3b82,0x0d2e18d,
  45994. 0x1b271bf,0x1c2fa45,0x1277a5a,0x185d6db,0x160e453,0x037b11d,
  45995. 0x0a2392e,0x182e8db,0x0f0af42,0x120cb12,0x04cb8af },
  45996. { 0x14b1953,0x0102bdd,0x1bba8ac,0x09eb2fe,0x0ce08b4,0x1209642,
  45997. 0x1766d79,0x0330a9e,0x1b3cd49,0x0899316,0x0aed746,0x05c8dc8,
  45998. 0x0090276,0x0bc73fb,0x157239b,0x182d906,0x02438b6,0x0477d54,
  45999. 0x1543d86,0x0e6f21c,0x178ed01,0x1172beb,0x0462bd1,0x0b68e28,
  46000. 0x0d5e871,0x07cd0b5,0x0d077a9,0x000b2d8,0x0ca6109,0x1e19140,
  46001. 0x084aa55,0x06e98cb,0x1aee800,0x0020a17,0x049d402,0x03b620a,
  46002. 0x1f080fa,0x0edc98f,0x1e3f230,0x04baf30,0x0486a5c } },
  46003. /* 193 */
  46004. { { 0x01b4f36,0x0f109ca,0x13e4148,0x09f0076,0x1aacfb1,0x12a5d45,
  46005. 0x188b94a,0x0d9fbe3,0x08fe479,0x07d5ddd,0x0eb2dab,0x11b6b1b,
  46006. 0x11ae078,0x00cefd2,0x0635cdb,0x02dddbf,0x06a35a7,0x18aae14,
  46007. 0x1219186,0x1a8ced3,0x0a5ebe7,0x07b1d32,0x142d8e0,0x0c124c4,
  46008. 0x019149f,0x0d98a5a,0x028b7f1,0x12334fa,0x1466ac0,0x0d2ae77,
  46009. 0x1b31153,0x0d30d55,0x1fa4a24,0x04e76c9,0x05c5c69,0x1aa1216,
  46010. 0x01fa75a,0x178eb66,0x1015180,0x112f1c9,0x05d269f },
  46011. { 0x0920419,0x001860a,0x1ce4e9d,0x11212d0,0x0845d86,0x1b87d30,
  46012. 0x05313ba,0x1970373,0x1d9fc5b,0x1e55036,0x1e3cb6a,0x084feb1,
  46013. 0x0a06539,0x18ee295,0x1217d9e,0x037546b,0x1722c91,0x02d3ec6,
  46014. 0x1b0b60d,0x0200b95,0x1347404,0x023d472,0x0d61a29,0x1ca2587,
  46015. 0x0180b8d,0x0758277,0x148445a,0x1b54cdc,0x17cd8a4,0x0ed5918,
  46016. 0x1db02f5,0x0c22c9b,0x1d4185d,0x16be4d0,0x089876e,0x0759db9,
  46017. 0x09b0268,0x125ad60,0x1543c3f,0x0b44db2,0x08ac999 } },
  46018. /* 194 */
  46019. { { 0x040a39d,0x06e4d93,0x07e6cb2,0x11dbc19,0x01ff0b3,0x165d051,
  46020. 0x1a6f687,0x02ee9e8,0x1080d04,0x1481666,0x0518122,0x1465e93,
  46021. 0x15e956f,0x0bbb558,0x03e173e,0x1e92469,0x0ee0066,0x1e10fe3,
  46022. 0x1bbbcd9,0x03d7fdf,0x05ed35b,0x0e2309f,0x1e01160,0x0d740e2,
  46023. 0x1e8e6ea,0x1f6e5ef,0x0a5435c,0x1bf9546,0x048889d,0x1c9b0ed,
  46024. 0x14725d1,0x1b75ff7,0x0867c8c,0x17573e7,0x0c7c72e,0x11a4ce8,
  46025. 0x097912c,0x12a822c,0x07935a0,0x1b9afd4,0x00c7c1d },
  46026. { 0x0e963a7,0x118660e,0x0b794ea,0x19898bf,0x1352f64,0x1457dfb,
  46027. 0x08be0a0,0x00e5735,0x0ca2121,0x0139e2b,0x15db719,0x0ca90b4,
  46028. 0x1caadd7,0x085ae3b,0x05ab0fa,0x1e736c3,0x09fd1aa,0x0106a1f,
  46029. 0x14172f1,0x1240c59,0x12fdfc3,0x192607f,0x05058e1,0x1d043cc,
  46030. 0x0b8d82a,0x1f86799,0x0cfe9e8,0x1eb1f28,0x04ca925,0x0e96fb2,
  46031. 0x17ebafc,0x032314e,0x0061563,0x1b08c06,0x17b5ae1,0x02f3136,
  46032. 0x0d41244,0x1a1222d,0x0ceaefc,0x15c3bec,0x024ffc9 } },
  46033. /* 195 */
  46034. { { 0x1c7cb2b,0x06e02c9,0x0fee27f,0x0ab200a,0x01243b9,0x011a1e6,
  46035. 0x1af3d86,0x0c6c03b,0x166c18a,0x122a377,0x04ca1cd,0x0e03d92,
  46036. 0x11a5290,0x1cbc461,0x16e009b,0x1efaf86,0x02a92d1,0x04295c3,
  46037. 0x0a9e5ca,0x13960a1,0x0005180,0x1e51e59,0x025f519,0x1eb728d,
  46038. 0x077c09e,0x0c27906,0x0bc8906,0x066e588,0x1bb206c,0x1f06f9a,
  46039. 0x0d76814,0x1538281,0x026c6d0,0x17d99de,0x10332d5,0x10c39f9,
  46040. 0x099b396,0x1e7cf79,0x06e9070,0x1a280c4,0x089e4d3 },
  46041. { 0x05a9be3,0x14073d2,0x1ef74d7,0x100e6ad,0x04daa57,0x13de17e,
  46042. 0x158bae5,0x1c6030d,0x047cd16,0x18133cf,0x033a6e9,0x1804be6,
  46043. 0x10ca2f1,0x0fc327a,0x0816d18,0x03acde2,0x1978506,0x13feb6b,
  46044. 0x0822027,0x1b89ed1,0x1ae247e,0x04cd269,0x176b011,0x03f3b50,
  46045. 0x0664a6d,0x138fc22,0x135ea0e,0x1e619d0,0x0c33f19,0x15d6755,
  46046. 0x0afa4e0,0x1290c45,0x1033831,0x00f590f,0x12ebdda,0x0f606f4,
  46047. 0x19a1b5c,0x0b54844,0x143ef45,0x0dfcde3,0x0675d3e } },
  46048. /* 196 */
  46049. { { 0x07193e5,0x13ffeb8,0x039765d,0x030206b,0x0478aa9,0x06c77bf,
  46050. 0x1e7fcca,0x14eac69,0x06dbbd9,0x09d0774,0x055a1a4,0x12d0fc4,
  46051. 0x18379b2,0x04eced1,0x0fd042a,0x069a520,0x1b91b13,0x0ecfc6b,
  46052. 0x160bbed,0x0e84537,0x07789fe,0x111c01e,0x16d5a2d,0x1a4a689,
  46053. 0x1a350d3,0x1f449f4,0x01c9125,0x0b386b6,0x09e23b5,0x0a1b50b,
  46054. 0x1a711cb,0x198b698,0x1864632,0x1fa9884,0x16760f1,0x113edae,
  46055. 0x1e49788,0x0e78ed8,0x0692ea4,0x1fcc15e,0x05f7f92 },
  46056. { 0x145167e,0x10e6302,0x0383c62,0x055ff51,0x15ee2e0,0x153de7a,
  46057. 0x1fd450c,0x0cc499b,0x0a75108,0x1c16d21,0x046bddc,0x023e80a,
  46058. 0x03e894c,0x15578a1,0x13938c4,0x1a55d54,0x0f0f63d,0x0c61e9b,
  46059. 0x1d9818d,0x192aa1a,0x1eabfc5,0x189bf53,0x00494dc,0x172a1ec,
  46060. 0x0d59839,0x021152e,0x050398d,0x0b41ec0,0x0c70459,0x11c7795,
  46061. 0x1ce4178,0x088d61e,0x0bacc0e,0x02bc522,0x01bb112,0x0699a84,
  46062. 0x05bd780,0x1d8d555,0x11634d9,0x1b21456,0x025bece } },
  46063. /* 197 */
  46064. { { 0x033a8fb,0x139c106,0x10741e6,0x021e4bb,0x0fbf6cd,0x0a415b6,
  46065. 0x1cfe31b,0x0949ff8,0x007bf84,0x128f8c6,0x058bc0f,0x046cb32,
  46066. 0x11a7651,0x0a009c0,0x1669d38,0x0314158,0x065e550,0x0cabd34,
  46067. 0x0f2826c,0x18a37bc,0x053fe1e,0x19d4b01,0x0f031fa,0x1c07f09,
  46068. 0x1fd147d,0x184f41d,0x054bef6,0x00a81da,0x015ec1c,0x176ee75,
  46069. 0x01dae94,0x0964c26,0x1d30ed5,0x0b90379,0x0ba3a0e,0x1537af7,
  46070. 0x096373a,0x06c3490,0x0fd8fc8,0x0978761,0x00a616a },
  46071. { 0x01339c9,0x0f9f6b7,0x029881d,0x057f160,0x1afaa07,0x06cda3b,
  46072. 0x1b20af3,0x18fbf5f,0x100ca54,0x1898ac7,0x10c6b91,0x05e2717,
  46073. 0x0a44910,0x1886fe4,0x063c560,0x0a9a95f,0x07559e9,0x064f790,
  46074. 0x149e831,0x0435f38,0x0023e80,0x1bbd0c9,0x1ba0049,0x16046ee,
  46075. 0x1538c7f,0x0a8b1af,0x1fa327a,0x1be32e9,0x0c90975,0x1d768ae,
  46076. 0x1700a1f,0x1ef4a22,0x00728f0,0x0311efd,0x0f983eb,0x1321b7f,
  46077. 0x0311ba0,0x0a07ea0,0x11932a3,0x09c0f8c,0x0876d15 } },
  46078. /* 198 */
  46079. { { 0x0d3ea8a,0x06b6961,0x003b4e9,0x175084c,0x16be681,0x0383391,
  46080. 0x0403790,0x0f78a7e,0x06a7d7a,0x1f2db7f,0x186a0f8,0x09f2bab,
  46081. 0x0a6e699,0x1b04be1,0x12b3489,0x020220f,0x1baa679,0x0096cc6,
  46082. 0x00b8389,0x1888c22,0x072addf,0x016a499,0x120576f,0x086cd2c,
  46083. 0x0e64ba9,0x1c83f1c,0x08cacaf,0x12c1d63,0x08e28b4,0x1a92ec9,
  46084. 0x07b6915,0x0540ef9,0x0f75b39,0x10e8039,0x12edff5,0x0c4eec1,
  46085. 0x0f4b145,0x11ae8d8,0x05c02bc,0x077ceda,0x03040c2 },
  46086. { 0x0fa9a70,0x0e2ada7,0x1842c43,0x1ea7d0c,0x14de414,0x1c513fe,
  46087. 0x1044c27,0x0787b2b,0x106661d,0x02884d2,0x0d44f94,0x1294c1d,
  46088. 0x0bcaa29,0x0f3e99c,0x19054dc,0x1ce3e7d,0x1fc4651,0x027e8a2,
  46089. 0x0f0c4ed,0x17f0719,0x015051b,0x1c0f5c9,0x0c0e781,0x17eb58f,
  46090. 0x16b4414,0x0467434,0x022f835,0x1acce31,0x0f2b6f2,0x197aeec,
  46091. 0x02afa4e,0x1d714ff,0x1dfd1e7,0x1a8e2e0,0x176643d,0x1d0c567,
  46092. 0x032a74b,0x18d6ac5,0x126887a,0x1343d77,0x05486d7 } },
  46093. /* 199 */
  46094. { { 0x1359e13,0x11a7fd0,0x01472cb,0x1e5032c,0x002d8db,0x0b25af1,
  46095. 0x008f48d,0x025d2bc,0x042f6ac,0x189a05b,0x0dc977e,0x10a56ca,
  46096. 0x0d543ba,0x0692335,0x0bb735a,0x0e51703,0x024547c,0x0dfbc01,
  46097. 0x15a7ed9,0x1f14232,0x0ec9559,0x116fd91,0x1416de9,0x1dabca4,
  46098. 0x075409e,0x1888388,0x00a67db,0x1913251,0x16f8c79,0x09309ed,
  46099. 0x0a69f5a,0x16794f3,0x0eb7fb3,0x0b05818,0x0ee3ec8,0x1595733,
  46100. 0x128b409,0x0092b46,0x17e2f48,0x01eb588,0x0380f1b },
  46101. { 0x0a0068f,0x0cf35f3,0x1d4f02e,0x15914e6,0x0b67cf2,0x1d75be2,
  46102. 0x09522cb,0x1874d93,0x1340260,0x1a0bfcc,0x1dce79f,0x10ab981,
  46103. 0x1a8ee56,0x1c04a4e,0x02d443d,0x0ddffe1,0x1c28d5c,0x1d8bb87,
  46104. 0x165a9ee,0x0b57ddf,0x1a2ab4f,0x1b79332,0x081ec44,0x003b9f3,
  46105. 0x180a4b6,0x06317d9,0x1058afb,0x19006c2,0x0b83b3c,0x1dcb773,
  46106. 0x1acd263,0x15182fd,0x09b0fd6,0x1f7e175,0x16ea85d,0x1cb0696,
  46107. 0x1b110b3,0x08227aa,0x0a17a4a,0x1dbd7ae,0x04abedd } },
  46108. /* 200 */
  46109. { { 0x00ef376,0x0f0dcb8,0x0ffccd5,0x14cd9b5,0x156e5d9,0x143b236,
  46110. 0x095d51f,0x0d367b8,0x000f793,0x07a25c5,0x14b8a4a,0x163d418,
  46111. 0x1208c32,0x1b94d9c,0x1e37848,0x0473ab4,0x19ab26d,0x1a0c228,
  46112. 0x033929a,0x0d696fc,0x09f923f,0x0556595,0x08d7dbe,0x00c94b2,
  46113. 0x1c454e2,0x1175dc5,0x106fcc1,0x0fdfa06,0x1ff6f93,0x141dca6,
  46114. 0x019aeb1,0x1154ff4,0x1364b1e,0x19ba2e1,0x1cab382,0x1e0c2ce,
  46115. 0x11e3fb0,0x1846846,0x0cb4d1b,0x16631c2,0x06a20ab },
  46116. { 0x085cbc7,0x1880b35,0x0a9faa0,0x0d269f3,0x1099094,0x1c78d9e,
  46117. 0x042239d,0x1338442,0x12247b7,0x1527fc7,0x121339f,0x1ae28a8,
  46118. 0x04b3171,0x07cc61b,0x100e525,0x028b052,0x1f397df,0x12ed488,
  46119. 0x050e445,0x0b01261,0x18bca6b,0x0d0ba11,0x1d7e542,0x012eb1a,
  46120. 0x1182182,0x0e87f5a,0x0691e49,0x1c18c04,0x0a315ea,0x134a57c,
  46121. 0x0dc3a51,0x0d75a09,0x07af8a3,0x1223ed7,0x19ffc1c,0x1c8982b,
  46122. 0x05456ff,0x0233455,0x0e5dd46,0x14f7e6d,0x045e353 } },
  46123. /* 201 */
  46124. { { 0x1092f71,0x0b3b249,0x15c5d81,0x05eb725,0x0b66b6c,0x045b62f,
  46125. 0x0526f8b,0x07d3b66,0x020c036,0x117ac1d,0x15c25fd,0x1a66079,
  46126. 0x0c688ac,0x15dc8b5,0x14303e3,0x1361d0b,0x02c84c1,0x08dfba3,
  46127. 0x1129ab4,0x1dabf2f,0x1369c76,0x1d688cf,0x1b22e22,0x1ca1707,
  46128. 0x0371beb,0x1532cdc,0x02199c1,0x198d2a1,0x173d2c0,0x1ad1fc1,
  46129. 0x1ed4c71,0x054b405,0x01cd3a3,0x0d0e827,0x1de368e,0x1dd04e8,
  46130. 0x15da333,0x1e2dddb,0x0f4dbb7,0x04994f3,0x015941f },
  46131. { 0x17dd512,0x0607c53,0x17d90ba,0x0e3b86c,0x091b59a,0x1a9c315,
  46132. 0x0533421,0x195d01a,0x1d272fa,0x1121186,0x1f2d685,0x182c804,
  46133. 0x03eea3e,0x00f7cf8,0x1c02d67,0x0291b82,0x1270da3,0x0ea08e0,
  46134. 0x10606bc,0x1dc8918,0x100b801,0x0ccf1d4,0x1b7ca15,0x0135ffb,
  46135. 0x1b0bd0d,0x0122eb3,0x1a2cdc0,0x1073bf2,0x1836b8d,0x03f0737,
  46136. 0x124ed8c,0x17a6403,0x182e588,0x0815da9,0x09ade87,0x12c6db1,
  46137. 0x168641e,0x1bedbb4,0x0b40dc2,0x094231f,0x06d17c3 } },
  46138. /* 202 */
  46139. { { 0x181c99b,0x04420e0,0x12bf3d8,0x0390f7b,0x165dc90,0x106d5f5,
  46140. 0x0d11cdc,0x0b768c1,0x0537751,0x03ce1cb,0x1b09dd3,0x045c152,
  46141. 0x00d447f,0x15607a2,0x05484c0,0x1075a1b,0x06bc905,0x0419859,
  46142. 0x0a24128,0x1d2ef52,0x0b18e25,0x0cc2e28,0x077abff,0x15abed4,
  46143. 0x1bcb7a5,0x16ae7a6,0x07228df,0x179a003,0x1850b6c,0x0ec80f4,
  46144. 0x015e11b,0x16171cc,0x0c8194a,0x197c80d,0x15c4d04,0x1772e50,
  46145. 0x156ee28,0x14f8a4f,0x0753933,0x1487d3c,0x01ab9b5 },
  46146. { 0x14fa7a3,0x0d5c918,0x058c81b,0x008f1ff,0x0c4af0f,0x06cfede,
  46147. 0x05c4e41,0x1fc999c,0x112c045,0x0105175,0x1db5f6b,0x08f1fb1,
  46148. 0x1a44fc5,0x053db7f,0x1b9cb17,0x1eeb110,0x09b6fd6,0x0bfd229,
  46149. 0x0aa0835,0x03a3632,0x11494df,0x0f93c4f,0x0f604be,0x176a7a4,
  46150. 0x0f083aa,0x1994c21,0x0ca80ea,0x0c90a73,0x1125022,0x104858a,
  46151. 0x1558c73,0x0e63ed7,0x1294d15,0x1731a70,0x187650d,0x1f64526,
  46152. 0x1ca966a,0x0140e21,0x0cfb631,0x0ad8435,0x024b349 } },
  46153. /* 203 */
  46154. { { 0x19824e2,0x0e5c332,0x1d3126f,0x109c27c,0x0dc4ce4,0x1f0f753,
  46155. 0x06899ae,0x0af4980,0x11e3ec4,0x1d95c73,0x0a392d1,0x0bc05eb,
  46156. 0x0d7e8b1,0x1199a98,0x07adb9b,0x0a405d0,0x09e17a4,0x1d65d1b,
  46157. 0x1c39327,0x082863a,0x1eb8812,0x059f095,0x10642bd,0x1e90dfb,
  46158. 0x1052311,0x1e72993,0x04a7eca,0x1ed883c,0x0f6c089,0x03f5db8,
  46159. 0x1def98a,0x07fd688,0x079850a,0x18c5d8a,0x0c466f3,0x01f9fbf,
  46160. 0x1a80d04,0x0e1497e,0x16fe649,0x1cafc78,0x0212d65 },
  46161. { 0x015cf08,0x0d9c365,0x0bac8eb,0x0903c2e,0x0dfa4ac,0x0168602,
  46162. 0x0fe4d35,0x18f3a3b,0x174404d,0x0e7b039,0x0aff376,0x0883d26,
  46163. 0x1860508,0x0e34154,0x1a44328,0x0398135,0x01841ac,0x04a947e,
  46164. 0x0efb58c,0x02415db,0x1250e6a,0x1618667,0x0538387,0x1177e5f,
  46165. 0x0ba54e5,0x00aff42,0x1e7ea91,0x0cda169,0x0e7ce5c,0x18f3f67,
  46166. 0x0e83163,0x0df4d0e,0x01d43eb,0x189a43d,0x1680e67,0x0f2d8d8,
  46167. 0x06727ab,0x17cd557,0x0911f9b,0x0a934b8,0x066afa5 } },
  46168. /* 204 */
  46169. { { 0x180e91d,0x155d464,0x1beb696,0x12d5931,0x093cf50,0x1193315,
  46170. 0x0382a36,0x07d6132,0x0008145,0x0e90a98,0x077a100,0x067c7ae,
  46171. 0x122bb0d,0x1f0cd00,0x17db600,0x071ce8c,0x14c78a8,0x02c817f,
  46172. 0x04c4d23,0x055f6e3,0x057b74e,0x0bce7d8,0x0924c9d,0x1a07f1f,
  46173. 0x0a6423a,0x0053b0f,0x1563fe9,0x0fa9848,0x087e30b,0x006cbbd,
  46174. 0x09ad7a7,0x193909a,0x1c5edba,0x0b1d068,0x0e68f46,0x1bd9510,
  46175. 0x0bf6bf0,0x17979af,0x0af7ef1,0x0621ab1,0x001ef06 },
  46176. { 0x0cdcbb0,0x0818b1f,0x0554afe,0x104f839,0x19e2d72,0x1ae4980,
  46177. 0x1c0c255,0x0613ca4,0x1969839,0x0e0e2d4,0x020b7c3,0x01fef9a,
  46178. 0x11ef9f8,0x0fcbf02,0x04541d7,0x036ab9b,0x1fe9cc6,0x079437f,
  46179. 0x03c9331,0x1b671f0,0x1ae3352,0x161b291,0x1b66e67,0x1620953,
  46180. 0x08ca810,0x1d6884d,0x1cc1480,0x04e01fc,0x1400f5c,0x11273b4,
  46181. 0x0b0a8bb,0x1dc188a,0x195d399,0x01520ea,0x15abdfc,0x0e156eb,
  46182. 0x0db730b,0x08404c8,0x04808d0,0x1fabd1a,0x00e4f5f } },
  46183. /* 205 */
  46184. { { 0x1f14c38,0x0322207,0x07caf47,0x155d9c2,0x1a5b59f,0x17b1984,
  46185. 0x0169c8a,0x1dd548c,0x082af24,0x0e4fb2d,0x0845677,0x17fdd73,
  46186. 0x0ff4ee4,0x1a74275,0x18f41d9,0x1559c48,0x1e00e0b,0x1c465f0,
  46187. 0x17eaf72,0x0ad1d5a,0x199d7ca,0x1262bf5,0x0f60354,0x17d30e7,
  46188. 0x0572ce9,0x02f4e23,0x15cc02e,0x03143b9,0x1541769,0x0989207,
  46189. 0x0d92488,0x16b6284,0x1e324ff,0x078b57b,0x140490d,0x1881bb4,
  46190. 0x0133d97,0x019a10d,0x1c08022,0x0c210ed,0x033d411 },
  46191. { 0x078e5ec,0x0d1b5cc,0x08c9d4c,0x028d230,0x1de3e32,0x1182322,
  46192. 0x068cf42,0x0b3a2bf,0x1aa1736,0x1a60dc3,0x1753f9c,0x0945f24,
  46193. 0x14ac209,0x0131587,0x1259687,0x0b97887,0x03e447d,0x03ace48,
  46194. 0x148e4c0,0x1e42bc0,0x1f3492a,0x0f8fac9,0x1ffedb5,0x19bb6bf,
  46195. 0x03b4bc3,0x00432ca,0x12ff755,0x1a07453,0x0d76c09,0x0d358cc,
  46196. 0x1663df3,0x181e4f6,0x0790a22,0x0c667e0,0x0a1232d,0x1974aaf,
  46197. 0x16c54fd,0x110296b,0x0d19964,0x1548f6d,0x02d3de7 } },
  46198. /* 206 */
  46199. { { 0x1add3b7,0x13a3132,0x10aaab7,0x0b57e49,0x05888f3,0x12bec9f,
  46200. 0x1272b86,0x17fa82a,0x02c76f7,0x11170c7,0x080acc3,0x11d57c6,
  46201. 0x0a67f28,0x0e8e878,0x0699ae8,0x15a316f,0x1492881,0x087055b,
  46202. 0x1eb6c3a,0x04810d8,0x132f7d4,0x0294210,0x01c30cb,0x1f3413d,
  46203. 0x077f158,0x0c4c2c2,0x0bb0095,0x045526e,0x0987774,0x062e528,
  46204. 0x162f90a,0x0aecc00,0x1b79564,0x19be7a2,0x18c655f,0x12d8ff8,
  46205. 0x1631628,0x1811eee,0x04a9a2d,0x16cb638,0x047003b },
  46206. { 0x11c1c96,0x000e0e4,0x05c3665,0x124f425,0x0a5dcdf,0x014883d,
  46207. 0x0b85f0f,0x0207572,0x1a3fe47,0x17e747b,0x0663b89,0x1abc9dd,
  46208. 0x18b0d09,0x071d20f,0x0988812,0x14a0d5f,0x0a5a26c,0x158e009,
  46209. 0x06d5c94,0x1ee6993,0x1fe12c6,0x0fa897b,0x0424f5e,0x1dc334c,
  46210. 0x0906eac,0x1531798,0x0415b47,0x17ff070,0x135f216,0x0c2b77f,
  46211. 0x091871d,0x1835a44,0x007e978,0x07ef437,0x1285ac8,0x165994d,
  46212. 0x033fe81,0x06b696b,0x0b39aad,0x00960d4,0x073dff5 } },
  46213. /* 207 */
  46214. { { 0x0e20fb8,0x0ac02ec,0x0fc22d8,0x09056a6,0x1c6873e,0x142a653,
  46215. 0x1c0055a,0x022a40b,0x0cb3692,0x1ff6356,0x024ade1,0x01d98fe,
  46216. 0x0c1fa3c,0x1422ff2,0x0d991fb,0x1e224b6,0x085f8b1,0x1ea3c0f,
  46217. 0x0c3c69b,0x04d0731,0x0b92c65,0x166e5c7,0x13bae31,0x0bedaa5,
  46218. 0x10ead8e,0x06e099f,0x0f2364d,0x03107c4,0x0ac45a3,0x0adea14,
  46219. 0x014853b,0x1b77f95,0x17ca492,0x0d709fb,0x0ff81f9,0x17be822,
  46220. 0x12ab05f,0x1250693,0x1d4d58f,0x16ee291,0x07544d0 },
  46221. { 0x0797ace,0x0689a40,0x05f93fa,0x015f0db,0x016d6aa,0x0d347e1,
  46222. 0x09a23bd,0x109b7e1,0x19f9b26,0x05937a2,0x074bf06,0x19f5133,
  46223. 0x1552fef,0x11211ca,0x0be3609,0x06f01ab,0x069f63a,0x1c7891a,
  46224. 0x1353fab,0x068a9fb,0x1d09293,0x1bd39da,0x0ea0062,0x0aa5831,
  46225. 0x1f276e5,0x18e4d78,0x17fc9ae,0x0ba8ee7,0x1d4f44c,0x0a08036,
  46226. 0x1267bd2,0x0be7374,0x18f12f9,0x0527956,0x1b73d9b,0x14aecfe,
  46227. 0x1922f59,0x03b9f8b,0x0b526ea,0x1d583c8,0x0220081 } },
  46228. /* 208 */
  46229. { { 0x037a0ba,0x1eab9dd,0x17d8c10,0x19ba2ed,0x05a431b,0x10387b8,
  46230. 0x0b3f310,0x0120664,0x067c2d1,0x055e987,0x02f3e97,0x0bbd97f,
  46231. 0x0b362c9,0x1bc3d88,0x19f49dd,0x0bcc9ae,0x15e6ec0,0x1309648,
  46232. 0x19a70c3,0x0d2c639,0x06359e6,0x07b4171,0x09f2776,0x1ff9870,
  46233. 0x01f1295,0x0513c81,0x0628ab7,0x0d51dcf,0x1d500a0,0x13c225a,
  46234. 0x1163803,0x11b01ad,0x1746fc7,0x1886643,0x0efa457,0x1048c0a,
  46235. 0x019f6fd,0x0719459,0x0dcce11,0x158237a,0x0620541 },
  46236. { 0x09e5a29,0x1e9c128,0x0c783df,0x016864a,0x0748d7d,0x1c41dcc,
  46237. 0x04d5334,0x0f51ee9,0x08bfbb1,0x15c563a,0x0b4b171,0x14cc0be,
  46238. 0x03a4616,0x0de58dc,0x1659894,0x04cb567,0x1042fee,0x067ba98,
  46239. 0x0c89416,0x1ae7f7b,0x1556c70,0x1a78616,0x0484750,0x164b366,
  46240. 0x061d854,0x1bec310,0x1710acf,0x1fc8c0d,0x0a4949f,0x02c2f43,
  46241. 0x0b13172,0x02c1ddb,0x0ddcc8b,0x1121002,0x199d5a3,0x0c30099,
  46242. 0x0214165,0x19c2ad2,0x0fa5e47,0x131f265,0x07f3781 } },
  46243. /* 209 */
  46244. { { 0x1a6639a,0x1a5ed6f,0x0e4668d,0x080556e,0x0cbd48d,0x018f168,
  46245. 0x1c8d91c,0x03eb8bd,0x0d0599d,0x04f715e,0x0e110ed,0x16c1c1a,
  46246. 0x08d285e,0x1349c97,0x0faa4bc,0x0a71fb7,0x1bfb8bc,0x048a2af,
  46247. 0x11a6dda,0x0b3fe3c,0x1682ae2,0x0fa0ef2,0x1073b2c,0x0a5a35d,
  46248. 0x0f07199,0x023643b,0x079efdd,0x19c4a30,0x0ad2f11,0x16c3141,
  46249. 0x19f2e4e,0x0d749de,0x1a3cd31,0x1d51f47,0x0813941,0x11f9cd1,
  46250. 0x061bb60,0x0ba0b85,0x043433b,0x167ed58,0x06de716 },
  46251. { 0x12d6dc5,0x0c6820b,0x1973539,0x0cc72f8,0x1ed2cde,0x0f5a745,
  46252. 0x1f86032,0x1b6f5ce,0x075fa2e,0x113aa34,0x199ce15,0x049d523,
  46253. 0x0e4b303,0x11ae459,0x08ea158,0x0510ec0,0x0c2a8f9,0x0cefb6b,
  46254. 0x1bd7a2d,0x1830bfe,0x148aec2,0x159d6ab,0x1e24b84,0x095df78,
  46255. 0x1b4f2d5,0x010bd75,0x03ba1a2,0x0922a89,0x19bd5b1,0x0fb8d8e,
  46256. 0x1de89b1,0x05fe01b,0x1ccd166,0x18ef772,0x1c5ee56,0x09d7933,
  46257. 0x1fe1f77,0x0c1b0b1,0x096c242,0x061767a,0x051f908 } },
  46258. /* 210 */
  46259. { { 0x0922461,0x1b7d0f9,0x034524d,0x062ca1a,0x1bb1b1c,0x0c3046e,
  46260. 0x070cc37,0x00d2572,0x136b899,0x1309625,0x180148f,0x1617bea,
  46261. 0x05e1977,0x11b512a,0x0bffdc1,0x07b1df1,0x0781172,0x166d3e9,
  46262. 0x06f79ee,0x1789770,0x178e0b0,0x1976952,0x0f2c202,0x0365c04,
  46263. 0x00d0d17,0x0d72ded,0x1e506ee,0x0dbe719,0x0a65c5f,0x00ede0a,
  46264. 0x03a1776,0x1833bb3,0x198c82d,0x037c9bf,0x11fd488,0x118c26e,
  46265. 0x1f5bbe7,0x09d1612,0x12f9e78,0x11c1546,0x05eed21 },
  46266. { 0x1d4dc0b,0x12baa00,0x0c1f855,0x0feacd7,0x01ae5f2,0x1112ead,
  46267. 0x1afaee0,0x0d7d30b,0x01189ec,0x19d690e,0x1936757,0x0319d99,
  46268. 0x1917da5,0x0b5b2da,0x128b4fb,0x0ee3990,0x1758ffa,0x13fcc40,
  46269. 0x0b1a69e,0x0d5c245,0x046d50d,0x18e3734,0x12dfcc2,0x1a17627,
  46270. 0x03a605b,0x003c601,0x175cfc9,0x1421fd9,0x10a9969,0x0c6672f,
  46271. 0x01a3145,0x17b1eb0,0x06bf615,0x12370e9,0x0a1e456,0x115e65d,
  46272. 0x0287d30,0x1ba7408,0x10953ab,0x00d4c4c,0x08c14ba } },
  46273. /* 211 */
  46274. { { 0x17ee201,0x1bc4ad8,0x09dc321,0x0311caf,0x005aa47,0x01122b6,
  46275. 0x19d8e5e,0x03a3387,0x0c9c3ba,0x1f37c60,0x027af82,0x09ff687,
  46276. 0x16fe85f,0x0673fdd,0x02f3338,0x0d8c8a7,0x12a6526,0x143b755,
  46277. 0x1e68e10,0x158d219,0x19815c9,0x18e6647,0x07d73ce,0x1ed0fbd,
  46278. 0x1be6a9c,0x00afd0b,0x120e0d7,0x19f821f,0x0ef2ebf,0x07ed8a8,
  46279. 0x19821ac,0x11094a5,0x197ecd9,0x08f5c4f,0x1e8ac33,0x1482dcd,
  46280. 0x1ecc03b,0x1e8acc9,0x0597b8a,0x0bbd576,0x0645c0a },
  46281. { 0x0aa7e31,0x02102a8,0x1697653,0x185f0a3,0x0ec8df0,0x1937355,
  46282. 0x1a424f1,0x13532c8,0x02619bf,0x16dee1b,0x0fef55c,0x01c1c4a,
  46283. 0x061b426,0x06384f0,0x10967ee,0x1d8b72f,0x0bbcdda,0x0fd5fbe,
  46284. 0x12dc0fa,0x0bd163c,0x0fddb4d,0x17039a7,0x06c1b95,0x0abf14a,
  46285. 0x0a4f91f,0x046816a,0x08fd597,0x1f0c117,0x0d1d947,0x03e940b,
  46286. 0x0da08bd,0x0b9cf62,0x0c36156,0x0212106,0x17bcc74,0x0dc8ddc,
  46287. 0x083567f,0x132fb83,0x1b246ca,0x081a5f4,0x027e9ff } },
  46288. /* 212 */
  46289. { { 0x1e952e7,0x08c49eb,0x1c61d49,0x078e6b7,0x15b3058,0x1f02488,
  46290. 0x1664a5b,0x194e656,0x0806d2f,0x1a28c2c,0x017b649,0x0d40371,
  46291. 0x0c71ab7,0x16cfaaf,0x13a765d,0x175397b,0x12048f2,0x19ed305,
  46292. 0x04ac4ca,0x0f810cb,0x11d7697,0x0584c82,0x0db72a7,0x1115c4b,
  46293. 0x0ab23d1,0x19eece1,0x1f882ab,0x1e8d3e7,0x0d74d09,0x1be7ad5,
  46294. 0x0ef6f47,0x04553d6,0x15efe5c,0x008621e,0x1e884dc,0x0118bdb,
  46295. 0x1787026,0x1110bda,0x05ddab6,0x0ce7b59,0x04feee5 },
  46296. { 0x1d3d780,0x0c6a95a,0x1d10c38,0x060e2cc,0x0dadb5d,0x1a10ab2,
  46297. 0x0e1b969,0x10c641a,0x08d6bbb,0x0c61487,0x18f7457,0x06465a4,
  46298. 0x16981a4,0x0c4c231,0x1439f2a,0x1596267,0x04da519,0x1a89c3c,
  46299. 0x177207f,0x1c7f57b,0x043a832,0x0a18ccd,0x1f09e16,0x0e862c7,
  46300. 0x0abcf32,0x1d3ada6,0x15d3e53,0x1f40217,0x14a6279,0x1a1eab4,
  46301. 0x0930a29,0x196caf4,0x1d2a888,0x112f560,0x140fa1a,0x1efdde4,
  46302. 0x04c561f,0x08d2e98,0x1783bb4,0x1cf393d,0x04fe818 } },
  46303. /* 213 */
  46304. { { 0x1c1c7ff,0x0964ebf,0x0b44009,0x1b3f513,0x09bd419,0x1274e65,
  46305. 0x0492901,0x1999274,0x043942e,0x0265e5c,0x05a56ce,0x03fb0e9,
  46306. 0x1f004c2,0x0108b2d,0x120767d,0x02204d3,0x028dde0,0x0f1192b,
  46307. 0x0a6c013,0x06e8aeb,0x1c21ec9,0x1ffb6e7,0x1eccd1a,0x06e58fb,
  46308. 0x1a64b4d,0x0715626,0x0fc8125,0x1d96f5a,0x07c150c,0x00daf43,
  46309. 0x16158b1,0x1856e47,0x19395ce,0x0991894,0x1f15fb9,0x0f9235b,
  46310. 0x110b659,0x1788b0f,0x0fff381,0x0536e9a,0x0819155 },
  46311. { 0x0d9d4ee,0x09218b7,0x1c063b0,0x08d135f,0x1dffa15,0x04d1fa1,
  46312. 0x0d27caa,0x1649574,0x0d467ef,0x0d8f471,0x040b88b,0x06a8072,
  46313. 0x0b18dea,0x1297841,0x0aae14f,0x1ba8e84,0x0c1ed36,0x1389851,
  46314. 0x0a5747b,0x01d0da0,0x1ad3ca6,0x043e3fa,0x19ab1a0,0x10c8cb1,
  46315. 0x1cecfde,0x13287c1,0x0518744,0x05ccd84,0x1850997,0x00a85e9,
  46316. 0x027fbbd,0x14cc645,0x1183f3a,0x0e3ca87,0x12f9e4b,0x044ea8a,
  46317. 0x1136770,0x02608d8,0x1bbcc9d,0x18fd1d4,0x07d06bc } },
  46318. /* 214 */
  46319. { { 0x090212f,0x02ca138,0x011224a,0x18aa43d,0x091b7d4,0x16ddc93,
  46320. 0x0108af8,0x1009807,0x1bd81f8,0x0bb90f6,0x06f0d8c,0x17dd591,
  46321. 0x0dc136c,0x1dc7802,0x1c6d82d,0x115709e,0x0d04e21,0x0934899,
  46322. 0x1b32053,0x0492ddc,0x1c15b0e,0x0bbafd6,0x02cb38c,0x1a4478a,
  46323. 0x1c08466,0x1c5c171,0x193184b,0x0e43954,0x1653559,0x08f5d25,
  46324. 0x145669d,0x18fa7b3,0x033aad5,0x0a1231a,0x074ba03,0x143cc37,
  46325. 0x1c673ca,0x0fb2aff,0x12e4852,0x133a1f3,0x048b52b },
  46326. { 0x1dc05be,0x0a9ccf7,0x17a68e4,0x1027c12,0x1e70db1,0x0d9fed6,
  46327. 0x18ba737,0x0a288f0,0x01a0094,0x15818b1,0x083a8e8,0x1018472,
  46328. 0x0b4b279,0x111dc7f,0x14e53c6,0x02da958,0x0563e56,0x10b1fb9,
  46329. 0x1c50866,0x1ff27f6,0x0474aa0,0x0949eb1,0x149be5b,0x19fc4ed,
  46330. 0x12ea87d,0x08aee90,0x1d1c0e3,0x164f7e5,0x18168ea,0x0192fa0,
  46331. 0x06b9632,0x1665531,0x1704222,0x0f89df1,0x0e42ff2,0x1b46d28,
  46332. 0x0d0684a,0x1713030,0x1dbb3c5,0x10f3b18,0x017c0de } },
  46333. /* 215 */
  46334. { { 0x0c01958,0x0fa29ee,0x0e4ef29,0x0839d10,0x1d94595,0x0fadb6b,
  46335. 0x1428558,0x178bcc6,0x07e2d36,0x08e1e43,0x10e9b0a,0x1b094b5,
  46336. 0x0df6c7e,0x0cc0036,0x04f102f,0x1d876f2,0x0875671,0x0fbc5d8,
  46337. 0x10fa26a,0x051edd6,0x01ed1c9,0x19d70f5,0x1f7ca37,0x049656b,
  46338. 0x1a5b1b9,0x102b15d,0x146845b,0x123a4e0,0x1ed3e34,0x015b8b3,
  46339. 0x11823b0,0x0b78160,0x091cf7b,0x0bfacf1,0x05a6317,0x0e61ca0,
  46340. 0x15c799b,0x1e1a86f,0x1875c31,0x1c4158d,0x06862b9 },
  46341. { 0x1fa1f64,0x17a73cf,0x0d255b1,0x1543c48,0x1ed6a91,0x1ba9197,
  46342. 0x1b83336,0x00fd341,0x10322d6,0x1e4859b,0x1fbe1ef,0x15a48c5,
  46343. 0x1429480,0x015fe79,0x08525a7,0x1c71ff8,0x1e0a539,0x0372908,
  46344. 0x0a94527,0x13d84c2,0x15322a5,0x096b835,0x0657f88,0x1390852,
  46345. 0x1b108e9,0x0417bbf,0x0d77201,0x099d5d4,0x12d2987,0x0185dec,
  46346. 0x1ba9698,0x155d42b,0x142dca5,0x1884e56,0x0f1d261,0x13ad587,
  46347. 0x090af64,0x070e201,0x179b319,0x05aa3f1,0x05093fa } },
  46348. /* 216 */
  46349. { { 0x02d553b,0x1994026,0x10a7133,0x04772cd,0x1c1abe2,0x0b48a56,
  46350. 0x152708a,0x192aad4,0x1999976,0x064fc5a,0x1a0fcf6,0x0f7aeed,
  46351. 0x17c22c5,0x1e42f62,0x0a50aad,0x0c3ea9e,0x1e56e2c,0x0779a03,
  46352. 0x084f6d2,0x0bd195e,0x18c7f00,0x1ef9934,0x11c3214,0x1814a96,
  46353. 0x088d7ca,0x00f737a,0x1582dd4,0x0d7ad7d,0x0a4bd9b,0x188338a,
  46354. 0x053c040,0x0dc1311,0x085bc3b,0x0950029,0x106bd7e,0x15d80ce,
  46355. 0x0f7ef24,0x18b2137,0x090e0cb,0x09ad8ef,0x012f9c4 },
  46356. { 0x1313a1c,0x0f4b241,0x0cdc654,0x14678b1,0x18edd3d,0x1620224,
  46357. 0x0fd4b1e,0x1d09db7,0x10dcb5e,0x136537b,0x108be21,0x11eadba,
  46358. 0x0eec0ae,0x0330f61,0x1def150,0x0a47820,0x13ad422,0x1369cc8,
  46359. 0x039f2cf,0x0bc3d0b,0x1b45d10,0x1fe4bcd,0x11f24e5,0x12f6b24,
  46360. 0x1d4a909,0x1f39910,0x0fa254b,0x1dec514,0x1462410,0x0c13a74,
  46361. 0x1034235,0x0b2f01e,0x0cbed0f,0x0887632,0x089c238,0x0627af8,
  46362. 0x1679b1a,0x036c333,0x0746346,0x09c4d5c,0x002f75e } },
  46363. /* 217 */
  46364. { { 0x1f307d7,0x1bf5fa3,0x11dc6d8,0x15a0282,0x0b644a6,0x02d4063,
  46365. 0x0f594b8,0x0630546,0x1fed07b,0x078d079,0x1b965f2,0x0ff26d2,
  46366. 0x1ec09ee,0x03ffe00,0x0a9fb0f,0x0e7739b,0x0fef8f3,0x0aa4fc4,
  46367. 0x0eee262,0x1a32c38,0x07b7c88,0x14efe55,0x164a93f,0x1c95641,
  46368. 0x19ee23a,0x0d2897f,0x07d7b2c,0x0b5d4c8,0x0fb47df,0x11bff19,
  46369. 0x1039da4,0x04ba10b,0x0a5c420,0x1aad14b,0x15609b1,0x07b9224,
  46370. 0x1bce972,0x05cc2fc,0x0650560,0x0ccc72c,0x072b1b5 },
  46371. { 0x10e5558,0x045043c,0x1e0275c,0x020d135,0x1853604,0x189dafc,
  46372. 0x1ee2908,0x035d0bc,0x055a49d,0x15d0949,0x1c6c2f9,0x0961586,
  46373. 0x195e76c,0x09c7370,0x1413ce6,0x13442b0,0x02260ae,0x146ea0a,
  46374. 0x1a12173,0x009d372,0x1e43d8b,0x12c43f7,0x1e5312e,0x038bce7,
  46375. 0x08e67f1,0x0e20893,0x033dae6,0x04c47c5,0x0a96629,0x15543d0,
  46376. 0x14fcb42,0x099405d,0x066772a,0x1daa8d9,0x1938b58,0x0ad1dd1,
  46377. 0x0e78b5b,0x15d94c9,0x096b737,0x02dc2e4,0x05df192 } },
  46378. /* 218 */
  46379. { { 0x1f2e7e3,0x13f0f46,0x1f78800,0x11b1b40,0x1183cc6,0x05734a5,
  46380. 0x0e9a52d,0x1119c6b,0x13ca62e,0x0b6cbef,0x1fb4b22,0x0276a5d,
  46381. 0x0f3de47,0x135e842,0x01b1038,0x12477a0,0x1bbfc81,0x00f4db8,
  46382. 0x0ab31ac,0x038f6c3,0x0840999,0x1247b2b,0x194324d,0x1e8ea48,
  46383. 0x161d187,0x05109c2,0x06fff4f,0x021e562,0x1914186,0x0fd7fd0,
  46384. 0x0265a45,0x12abca6,0x11236de,0x196bcc7,0x1baa861,0x16c2797,
  46385. 0x06a2a48,0x1da2753,0x070c9fd,0x185c151,0x0452265 },
  46386. { 0x1430010,0x0f63c92,0x03012b5,0x1fd7a12,0x0ac786f,0x14e9fae,
  46387. 0x1d3fc82,0x0bf4bf3,0x0a3edc6,0x05fa089,0x0fac47f,0x073819e,
  46388. 0x0088248,0x0552db8,0x175b53a,0x1157171,0x1fdb756,0x171138e,
  46389. 0x1d11583,0x1d86e76,0x1296e43,0x130e7ba,0x1e3abe4,0x152db36,
  46390. 0x1ae0e3f,0x1ea8c04,0x1770977,0x16625a5,0x0b77110,0x1c5a35d,
  46391. 0x191ae3d,0x16bd9e3,0x09efc8d,0x1f65503,0x0eb9827,0x03832a5,
  46392. 0x1f4dbde,0x118176a,0x015550f,0x1f23c0f,0x014b02b } },
  46393. /* 219 */
  46394. { { 0x07e5b57,0x0e3b45c,0x155cb1c,0x0fea634,0x0bcc78f,0x0cbee40,
  46395. 0x0fe2fdd,0x0be9ff2,0x1139e17,0x1470136,0x1329b2c,0x0e4f972,
  46396. 0x1c6b83b,0x003cfbf,0x0bf8ec8,0x1a2e05d,0x0decf3b,0x015652a,
  46397. 0x0bc371b,0x082678d,0x035e17c,0x12e67af,0x0fa8799,0x0aa0b8d,
  46398. 0x11a4834,0x1c4d334,0x0398402,0x0c6757a,0x1d03882,0x138360b,
  46399. 0x03259b1,0x03419f2,0x0efffbe,0x0eb263d,0x0f9f42b,0x0c9b08f,
  46400. 0x0ea2aa4,0x0de6fdd,0x1429752,0x0e8598f,0x085e07e },
  46401. { 0x1c25bca,0x1705305,0x13b08ea,0x03c89ec,0x0e8e55f,0x03dbb9b,
  46402. 0x05b62d8,0x013c3cd,0x0d30059,0x14853a3,0x112642a,0x199a597,
  46403. 0x1d072b1,0x034717a,0x03f9b1b,0x11d921a,0x1f053e2,0x0c90762,
  46404. 0x0010330,0x043f69e,0x02c779b,0x09fe625,0x09cdd6f,0x1758fbb,
  46405. 0x1def9e1,0x069fafa,0x04d703e,0x1862baf,0x0cd318d,0x00b8165,
  46406. 0x071c45f,0x1d24dee,0x12823c4,0x179cd37,0x02efb40,0x0671b6b,
  46407. 0x1db6932,0x1a4918b,0x1d0c396,0x13f1a93,0x0096403 } },
  46408. /* 220 */
  46409. { { 0x0999eba,0x1a78b2b,0x0c1485d,0x0f63bcc,0x1d8ee28,0x0593349,
  46410. 0x1dc9b78,0x143b035,0x13f8942,0x1a2349c,0x0f84f0d,0x0c2bd40,
  46411. 0x0fbcf6b,0x0a7139e,0x03030d6,0x0b8ada6,0x056c672,0x127e99d,
  46412. 0x02fa5e8,0x0a695b5,0x0251a57,0x133e115,0x1e6490a,0x018b892,
  46413. 0x1bdb59d,0x1b42728,0x131a909,0x0f9aed9,0x06bf59d,0x0bd66a1,
  46414. 0x0ca4502,0x0cdd37d,0x1404a2c,0x171f4ac,0x1a61725,0x008e71f,
  46415. 0x0ad666d,0x1d9f075,0x1795af2,0x1a4c778,0x0626b0f },
  46416. { 0x1a1ec42,0x0bedd70,0x11411c8,0x1756b59,0x0a6ae7d,0x0998e8d,
  46417. 0x0ac7a19,0x0df6fc3,0x03d3012,0x0229838,0x186146e,0x13c1bdc,
  46418. 0x0428064,0x15344aa,0x01bd28f,0x1ec6510,0x1adcb56,0x1a5df21,
  46419. 0x12bfe53,0x1737b57,0x17be036,0x12de831,0x0365079,0x0de7576,
  46420. 0x19d4468,0x1eb410b,0x12ab5ab,0x090d225,0x1e15341,0x048f7fb,
  46421. 0x05a68ee,0x1d70dfb,0x0c426ce,0x09461c4,0x0a0445e,0x016adcd,
  46422. 0x16399e0,0x1f389ac,0x1ab064c,0x1b342f6,0x009bbdd } },
  46423. /* 221 */
  46424. { { 0x0fd3673,0x1ce0ef2,0x181dd78,0x034cb91,0x1880d9d,0x04e3ff7,
  46425. 0x10771ca,0x0008e4b,0x03529d2,0x1b39af7,0x11ebcd6,0x05da78e,
  46426. 0x15c1f8f,0x08977ef,0x1ce663e,0x13872b9,0x0184985,0x0f6b913,
  46427. 0x19a5e57,0x12745e1,0x12a7237,0x0b4358e,0x029aae3,0x15105c9,
  46428. 0x015de22,0x0bf0064,0x13e76e3,0x1cefadf,0x067547b,0x1d99011,
  46429. 0x170221b,0x093821d,0x02687d4,0x1f6a65b,0x185df20,0x153e387,
  46430. 0x1af366e,0x0aebf82,0x0b4939b,0x171a3df,0x02eaa01 },
  46431. { 0x1357c74,0x1fdb80f,0x1e51791,0x1553c76,0x13085c4,0x02d482c,
  46432. 0x01ccdba,0x1929e13,0x1be0244,0x09c047f,0x159837d,0x1f27476,
  46433. 0x1691ddd,0x19dcaf6,0x1d8ddef,0x041a916,0x1b7bb39,0x1c8dc88,
  46434. 0x1a84f3c,0x1e117f0,0x0e587cc,0x0bf500c,0x14fb63e,0x18aa328,
  46435. 0x0434378,0x0d358f5,0x07834b5,0x1cd5bbd,0x16259a8,0x1247cdc,
  46436. 0x177f0ac,0x1dde2fb,0x0ebceae,0x1ce42cb,0x110d55f,0x11ed296,
  46437. 0x07d5bba,0x068a878,0x061ad23,0x1d36983,0x002d31d } },
  46438. /* 222 */
  46439. { { 0x079499d,0x1cf0f6f,0x0ab69ae,0x11fa1f8,0x16ca8ff,0x1ec9ab7,
  46440. 0x1e3a069,0x04f7d81,0x1e8f063,0x01e8e4f,0x002faef,0x042e766,
  46441. 0x1b805c7,0x009e0c0,0x1082821,0x13a0200,0x07ef0ca,0x14f4d0b,
  46442. 0x0bbb775,0x19213a3,0x0a72076,0x1fc71d4,0x1928665,0x0f6853c,
  46443. 0x1f7a7a7,0x1f49e73,0x1172534,0x1581f7e,0x148407a,0x0a53f36,
  46444. 0x19fcdda,0x1523243,0x16679e2,0x0ddeb7a,0x03cfb87,0x13e47fc,
  46445. 0x0bf9fa9,0x08bab36,0x15d971e,0x1e5c1e9,0x0965860 },
  46446. { 0x1a5f79c,0x03815bf,0x09b79cd,0x0cb5e5a,0x130bd42,0x19f0674,
  46447. 0x02e61b1,0x05a8b7b,0x14ee44a,0x0df3df6,0x122869f,0x00492ad,
  46448. 0x0ec129e,0x1be6fc0,0x17016b1,0x14b36df,0x02b589c,0x1b8535d,
  46449. 0x066096b,0x1080433,0x10b6fc4,0x0a3d11f,0x074a12d,0x141515e,
  46450. 0x010a428,0x16c58ed,0x04acabd,0x03d6366,0x135ee3b,0x021d19c,
  46451. 0x1b3c145,0x11dff4d,0x007eb26,0x132a63d,0x021b598,0x182ddc8,
  46452. 0x0549ee4,0x1de280a,0x02949e9,0x0643f53,0x0650810 } },
  46453. /* 223 */
  46454. { { 0x07ed9b2,0x072305b,0x0f4927c,0x0186db2,0x0cda0fd,0x03af0e0,
  46455. 0x18fa623,0x19376b2,0x1614bc0,0x0bddf49,0x1a1815d,0x100334e,
  46456. 0x049a9b8,0x0476e2a,0x0df8abd,0x0b30b51,0x19eb51a,0x04f3bf6,
  46457. 0x0efc093,0x04a4e9d,0x0636dd0,0x040aa2e,0x1662d8a,0x001b740,
  46458. 0x1aed048,0x11d1cde,0x06078a8,0x1f84027,0x0cb4f27,0x1eae2a8,
  46459. 0x11f719b,0x16a40d1,0x127032f,0x0fd0ad6,0x12ba05a,0x0593417,
  46460. 0x1a7ca8a,0x1037909,0x194bd81,0x08d30c4,0x0982950 },
  46461. { 0x011c128,0x1a30017,0x09f8f8d,0x1a1cdb9,0x00dfae5,0x0a91324,
  46462. 0x05b8b65,0x087c880,0x0880b71,0x12fc479,0x0e2073d,0x11a8a4d,
  46463. 0x1eca3d2,0x0fdc357,0x1167747,0x1f2b1f3,0x0c24c74,0x1aa4430,
  46464. 0x12da7d3,0x1d48793,0x0cecd06,0x17399a7,0x14d0f26,0x0652e26,
  46465. 0x0ccd635,0x0062e61,0x0d7ce9b,0x12bfe80,0x12653ba,0x10e659b,
  46466. 0x0f4b806,0x144a0a4,0x1510fdf,0x13f5918,0x038a988,0x01ddca7,
  46467. 0x0a23cd1,0x0fe4506,0x1d52fab,0x0367cf1,0x04b7e6e } },
  46468. /* 224 */
  46469. { { 0x15f928b,0x083b7ed,0x13b1e72,0x0d6e68f,0x06250bb,0x007620f,
  46470. 0x1de62b0,0x18ea96c,0x09d9619,0x006905d,0x10d0fe4,0x01a0b3c,
  46471. 0x17ed42c,0x028c9ae,0x1ce7a15,0x0039c7b,0x18264f7,0x0131c88,
  46472. 0x07e1eab,0x1e4aa9c,0x1aaace8,0x04b2fc8,0x1f7759e,0x048a73f,
  46473. 0x1163fa3,0x0cacb66,0x112eb3a,0x1902be5,0x0f9ea55,0x061554a,
  46474. 0x1575e32,0x1de49c8,0x0b2aff4,0x0e1353d,0x1024737,0x05e1dac,
  46475. 0x00ca282,0x0521058,0x1d96255,0x18ba652,0x00611c4 },
  46476. { 0x1e81829,0x1000e54,0x0b33c64,0x0011450,0x1ed3332,0x0ef6cde,
  46477. 0x1f7863e,0x00617fa,0x1b78890,0x1c9d606,0x1e97759,0x123a6ae,
  46478. 0x0bbb00d,0x00169e1,0x1e88e9e,0x12029c2,0x08cfb54,0x1ffcafc,
  46479. 0x1c6db81,0x037e978,0x0c8b7cd,0x1011ac4,0x0b8ec92,0x02240ec,
  46480. 0x135b8a4,0x0984da9,0x1b1015b,0x090380b,0x16a1b52,0x0086748,
  46481. 0x1d1571d,0x10a02f3,0x1e03271,0x089045d,0x05decf3,0x002bcd8,
  46482. 0x10cbfe5,0x0d12604,0x0159942,0x0523821,0x0820795 } },
  46483. /* 225 */
  46484. { { 0x07d353e,0x09e7f8e,0x18ed74b,0x1afbc19,0x15e7ecc,0x143b1ae,
  46485. 0x01d7db2,0x07d6962,0x025f9ad,0x1420270,0x12d6bb6,0x1d1240b,
  46486. 0x016b963,0x04f910d,0x17b8360,0x159493c,0x1d9ea41,0x06b2642,
  46487. 0x1110a8d,0x0d89d26,0x15a46a4,0x1f1e7b2,0x0b1bfe5,0x082faf9,
  46488. 0x05c1ee5,0x0263b2b,0x07bafe7,0x1020135,0x1a63886,0x0e9cc46,
  46489. 0x11a56d8,0x1ed68e5,0x002b46a,0x188b8b2,0x05942df,0x063fbca,
  46490. 0x1e0c05e,0x1c7939d,0x1129e53,0x06d5106,0x07487b0 },
  46491. { 0x03e2370,0x072bace,0x1c66a18,0x07f0090,0x19d5819,0x117cd50,
  46492. 0x0fcf29b,0x136741b,0x1614471,0x163f4ac,0x1fb086d,0x18e9bdf,
  46493. 0x1fa9049,0x1fa8675,0x08192c8,0x1bc2b17,0x0c049a1,0x1589411,
  46494. 0x07549fc,0x096fb36,0x0430b65,0x0e87fe8,0x111c216,0x00a88d7,
  46495. 0x14a674f,0x0ca9be3,0x0e8eb76,0x0aa64a3,0x1533b5e,0x0b65f19,
  46496. 0x13928fb,0x04fc833,0x12f44d0,0x0dcbc97,0x1a0a974,0x1e5b09d,
  46497. 0x1b6fa69,0x1b5891e,0x0ef7731,0x18a43f4,0x0834f85 } },
  46498. /* 226 */
  46499. { { 0x0e9b31a,0x1a3e096,0x0edcca4,0x15fc7f6,0x1d88522,0x1fc87e8,
  46500. 0x1ed354b,0x03a979d,0x02b1a08,0x1d8b9c3,0x047c214,0x0374548,
  46501. 0x1a538c1,0x0a0db01,0x056e4f0,0x1ae82f1,0x1aab10b,0x114c9dc,
  46502. 0x0644a61,0x17a08c1,0x0ba5ccb,0x1877505,0x19a7ebe,0x0cc312e,
  46503. 0x0462235,0x12a6a42,0x10d9ffe,0x14c7713,0x1478da4,0x0e8e8e1,
  46504. 0x1df2eb5,0x154c069,0x1339227,0x189c8e2,0x017f986,0x0a1cdae,
  46505. 0x174ff51,0x0a5b307,0x0d53374,0x014a665,0x0639d8b },
  46506. { 0x02217cd,0x118b10b,0x039be90,0x1502385,0x0e0e4a2,0x1b36e01,
  46507. 0x1386085,0x1ded1b3,0x1046a06,0x0931b9c,0x0484054,0x0463bbd,
  46508. 0x1344eea,0x08a14c6,0x01f23c8,0x0afd20c,0x0ba63d9,0x093f939,
  46509. 0x17a32b8,0x1d01994,0x063fe7c,0x11127bd,0x1605baf,0x0ce7c68,
  46510. 0x0e5a789,0x1ea26f6,0x094daea,0x06ead44,0x1f77af1,0x10d771d,
  46511. 0x0f19135,0x0579f31,0x0b2bf6e,0x14b1630,0x07cca7e,0x067616b,
  46512. 0x0bb5002,0x1b4d0d5,0x100b2c1,0x06c18ea,0x0409031 } },
  46513. /* 227 */
  46514. { { 0x070433f,0x1439d0b,0x17f2134,0x0c4a927,0x09394df,0x1e7c4f6,
  46515. 0x0866a03,0x02dd60b,0x0db2976,0x1cf2188,0x18c11b8,0x1b93b3c,
  46516. 0x1e50742,0x0ef4e54,0x06b6320,0x03a1be6,0x194fb7b,0x0c3555f,
  46517. 0x0cf20b4,0x1b44f43,0x0d8436c,0x1a1cb81,0x1ec68bb,0x0102533,
  46518. 0x1fddc46,0x11c1405,0x1748e58,0x0965691,0x1c9353e,0x0179bd9,
  46519. 0x1a4b6cb,0x025f714,0x1b5b317,0x0023a6a,0x08ec206,0x11f370f,
  46520. 0x1e95257,0x0c84c30,0x0af2361,0x1dbe6f4,0x080668e },
  46521. { 0x19a0249,0x0e69ad9,0x1abb8bb,0x0965f15,0x0f230cd,0x11ef82d,
  46522. 0x05791c8,0x1e852b6,0x0e0e937,0x1b34c15,0x12458ae,0x16e5197,
  46523. 0x01019d2,0x07a4ee5,0x144aba7,0x00f68b8,0x1a7630f,0x088da48,
  46524. 0x00e1d3a,0x09e6994,0x143348d,0x132265b,0x107f43a,0x0b66187,
  46525. 0x19ae1f9,0x05609fb,0x17b62d8,0x006c5a9,0x0ad81c4,0x0a7fb0f,
  46526. 0x0a27a0c,0x093187a,0x1600dd4,0x10b8176,0x1067094,0x06bf963,
  46527. 0x1a9c1f3,0x1194fe1,0x1b3a564,0x09037bc,0x0046775 } },
  46528. /* 228 */
  46529. { { 0x1233c96,0x0f2b71c,0x1abfb8f,0x1900e6f,0x068c409,0x0d5e344,
  46530. 0x046f480,0x00b595c,0x12b4862,0x196754d,0x0415b03,0x0fc2de3,
  46531. 0x01e3238,0x12ee152,0x1d4d96a,0x17d0dd4,0x0cc12b4,0x0bb614d,
  46532. 0x158ca53,0x1f956f1,0x1f24a01,0x058655c,0x0076fa2,0x02980a9,
  46533. 0x06e5bf4,0x1d53b32,0x0f2e5ad,0x1c22312,0x04e097f,0x1ad8bb3,
  46534. 0x0a6d927,0x0a7f9eb,0x196422e,0x1fb1a50,0x06f42df,0x0ab2f19,
  46535. 0x1c22989,0x1f59c71,0x1115ad7,0x1f61067,0x0038a49 },
  46536. { 0x1e93257,0x1c0c609,0x106cd78,0x1b4c24e,0x14cebc9,0x1560358,
  46537. 0x04925f2,0x02c9edd,0x13daa11,0x113c719,0x080d2a0,0x0cbc9bc,
  46538. 0x10e7cc5,0x050dd31,0x1f7257c,0x0df7b76,0x1236695,0x140eecf,
  46539. 0x0c4cb75,0x1cc6337,0x1337c63,0x117e120,0x1b88ac0,0x117d638,
  46540. 0x081937e,0x05611c2,0x176324e,0x0763329,0x1b56448,0x1d65535,
  46541. 0x01ed533,0x00df230,0x07cd44e,0x06cf98d,0x06eea3e,0x0c3ba87,
  46542. 0x1f74a8e,0x06153c3,0x1598198,0x0442436,0x04bb76e } },
  46543. /* 229 */
  46544. { { 0x0354817,0x08f4573,0x10e1e85,0x15e0716,0x13d494e,0x0ac4c31,
  46545. 0x11a2216,0x024990d,0x11dcbac,0x10a9c13,0x16b419c,0x1f1981d,
  46546. 0x16f487a,0x128072e,0x0cc147f,0x0feab5a,0x11bd6e4,0x085388d,
  46547. 0x11d1ab5,0x0e134f1,0x135ea68,0x1132017,0x09fc5c9,0x0618260,
  46548. 0x08efafb,0x04be368,0x0701b1d,0x1de3808,0x03e2da9,0x07676e6,
  46549. 0x1cf431d,0x0125c20,0x0c5f96e,0x095ba18,0x0f3caa8,0x041e272,
  46550. 0x0107eb0,0x0c200b1,0x1e62c91,0x0bef6ed,0x08843d2 },
  46551. { 0x1b2a83e,0x080ee76,0x1c91385,0x005771a,0x1cfe8fb,0x12efb15,
  46552. 0x0196764,0x1861204,0x142ab6f,0x038aee7,0x0277f4f,0x00ab41e,
  46553. 0x0a73c05,0x11ac857,0x19d1763,0x0e93c24,0x0d876ff,0x1a9c17a,
  46554. 0x0483198,0x13fddf5,0x11cafc6,0x08cfeb8,0x1785808,0x0eb89ab,
  46555. 0x1c3bd90,0x1f9210c,0x04f7b5a,0x100197a,0x03a1163,0x1075b13,
  46556. 0x0de31fa,0x0fa4c98,0x1bd7958,0x0e4c61a,0x1915c56,0x0aadc45,
  46557. 0x1a7373b,0x1f9516f,0x12525c6,0x073126b,0x00503f9 } },
  46558. /* 230 */
  46559. { { 0x1dad4f6,0x0ee3338,0x086d96b,0x120497d,0x038e488,0x02e9ee9,
  46560. 0x1238bd8,0x113f6ed,0x0b0d96b,0x1eafaef,0x06cb2c4,0x146acc0,
  46561. 0x14e0b5b,0x01f1e92,0x1f52476,0x11d4fc6,0x023240c,0x1744302,
  46562. 0x047266e,0x0305e7d,0x1919374,0x1cd43d6,0x09b0b2b,0x0e9e52a,
  46563. 0x1040af5,0x051a589,0x0651000,0x17379da,0x1f42e75,0x0bdf036,
  46564. 0x0753331,0x097a211,0x0e8ec50,0x1da8011,0x1deb776,0x1618a62,
  46565. 0x1ecfead,0x0698e94,0x1a3e5a4,0x1fc2ecc,0x0735778 },
  46566. { 0x03c1137,0x1771f42,0x0f343e1,0x147e16e,0x1c1c42f,0x19071d1,
  46567. 0x19e762a,0x15c1cea,0x016242f,0x1caf8fa,0x024b91b,0x0238736,
  46568. 0x007b88e,0x0611b56,0x0a500f9,0x005cc2c,0x1412dac,0x133082f,
  46569. 0x18b818c,0x18514f0,0x1c8d74d,0x1979d91,0x08463fe,0x08bff7e,
  46570. 0x0417c07,0x08f08c1,0x113015c,0x136ab40,0x1be4de4,0x0dba677,
  46571. 0x01cb199,0x12f7ee2,0x0c4c01d,0x1833b0e,0x1b6b153,0x1165940,
  46572. 0x1450d0f,0x0cced53,0x00a87f1,0x14c3463,0x052e637 } },
  46573. /* 231 */
  46574. { { 0x1ebc6db,0x18078b5,0x1649205,0x17f2a07,0x0a6b45d,0x0a9c8ca,
  46575. 0x134f174,0x1798e2b,0x1e5ad2a,0x0150e02,0x0d19be5,0x086756f,
  46576. 0x0b36a82,0x1d09c8c,0x104efb6,0x1cd9d74,0x02490f4,0x134c52b,
  46577. 0x0fc7cf2,0x041b4de,0x1ab3bb7,0x0eb1a38,0x0845b50,0x07a6c12,
  46578. 0x1222730,0x14f7006,0x0118ee9,0x1fa9980,0x045fd17,0x0f26b14,
  46579. 0x11eb182,0x1015b93,0x1603b2c,0x17de531,0x126917e,0x177e2df,
  46580. 0x04bc94a,0x003fbfe,0x05a6104,0x09f4e96,0x07c916b },
  46581. { 0x0bac2d4,0x137c8bc,0x01d7040,0x104c035,0x0a2e809,0x19eb204,
  46582. 0x09db801,0x1115a5e,0x0fcc1fb,0x01b0862,0x0ca47d1,0x104594d,
  46583. 0x1c5727b,0x0476307,0x1154cb2,0x1a9160c,0x099ed9a,0x1a8f244,
  46584. 0x150fc40,0x16916be,0x0eeb841,0x1f6ac8e,0x09b32c6,0x19eb517,
  46585. 0x0df0f9d,0x0da7e25,0x02cd1f7,0x14f9404,0x04c5213,0x066165a,
  46586. 0x112a86b,0x00a4f81,0x13b6828,0x1e7a83b,0x1041c08,0x0d546e9,
  46587. 0x0b74c92,0x1e88003,0x141f1cc,0x0deef51,0x01ff391 } },
  46588. /* 232 */
  46589. { { 0x197939d,0x0c7f27c,0x0ecea88,0x16f22b0,0x1d4dfbb,0x1bab059,
  46590. 0x0d76a1f,0x131674f,0x15da92c,0x0e01400,0x19bd2aa,0x155a8cc,
  46591. 0x17e1eb4,0x0a674ee,0x0c5e944,0x060ec5d,0x0a4ef8f,0x17a3533,
  46592. 0x043951b,0x168b8d0,0x04dd900,0x0c25d78,0x1debc89,0x109a85f,
  46593. 0x1c8725c,0x1ef1e60,0x1639320,0x0127e44,0x0d88b23,0x0f208b8,
  46594. 0x1118beb,0x1580edc,0x19612e4,0x08a0df0,0x0d18cb7,0x15e91ae,
  46595. 0x125e34d,0x18fbacc,0x0432706,0x0ac0e57,0x019ed1a },
  46596. { 0x0735473,0x1fe6f36,0x10fa73d,0x0ec0077,0x0ab88e6,0x0ccddc5,
  46597. 0x1f2f3ec,0x17a2430,0x19acccc,0x1b98220,0x195166e,0x1e7961e,
  46598. 0x02214af,0x17c9314,0x1b2068d,0x04170d5,0x1329f9d,0x0554165,
  46599. 0x1dcf324,0x07f21ea,0x17e182f,0x15fb112,0x12bd839,0x08ec5be,
  46600. 0x144bfbd,0x1a9f8c5,0x076e5c1,0x1291625,0x02c18e3,0x1074be1,
  46601. 0x0b71ba4,0x0af7d2f,0x13d6208,0x11bfc9c,0x00b11ad,0x0bd1ae7,
  46602. 0x11fed1d,0x112e65f,0x05667d9,0x1f2d0d0,0x06f31e0 } },
  46603. /* 233 */
  46604. { { 0x0b8f204,0x17f2ac1,0x152b116,0x0da6b16,0x0c0441b,0x0afaf6d,
  46605. 0x19efeb3,0x126e427,0x1139bcd,0x08a6385,0x0f2ec06,0x0b032db,
  46606. 0x01714b4,0x0f69ae9,0x0a5f4d4,0x03e41d2,0x0376a3e,0x0c7b204,
  46607. 0x1cf35c1,0x15153a5,0x1f6d150,0x00ee6ec,0x1ecdba0,0x1eadb05,
  46608. 0x0eb655c,0x110ad2a,0x124aa96,0x0c20a01,0x089f037,0x05711d8,
  46609. 0x1a34434,0x18856cd,0x11b2079,0x146a424,0x18f43bb,0x0a95e35,
  46610. 0x01556f4,0x1f26142,0x09f984d,0x010c7b1,0x0875e33 },
  46611. { 0x16c0acc,0x07eee57,0x1023720,0x0d763cf,0x15ad1e6,0x02c2d6e,
  46612. 0x1eb860a,0x14db8e2,0x0275c7d,0x0e2a1a0,0x0e7856f,0x10a5a4d,
  46613. 0x10f4b4c,0x1502fd2,0x0287efd,0x19664be,0x047817b,0x0e37c0f,
  46614. 0x03fcb87,0x1a8650e,0x17fc2cb,0x0b33e3f,0x0289240,0x10b4d89,
  46615. 0x1acb7b5,0x02be822,0x11199b0,0x1d2e55a,0x17d63d2,0x03e7f36,
  46616. 0x1131d36,0x01c4e82,0x1067d87,0x0c2577b,0x15ea2c9,0x1765942,
  46617. 0x15f0fde,0x0e2dfdb,0x1802525,0x103e70d,0x05abb05 } },
  46618. /* 234 */
  46619. { { 0x0c97f57,0x11695f8,0x031e2f9,0x032c5e5,0x0fe0487,0x1a855d8,
  46620. 0x0919d1e,0x1db8a91,0x144fa09,0x1593701,0x16a5bbd,0x0dc7560,
  46621. 0x02fd44c,0x1873574,0x0c00cb1,0x1133bdb,0x02bd7e4,0x1145ea0,
  46622. 0x0df0470,0x05d2c73,0x171643f,0x0767489,0x03b0ff0,0x1fa1f18,
  46623. 0x18bc902,0x1d63b4d,0x09f2af0,0x1b39675,0x124cc99,0x0449034,
  46624. 0x053a22a,0x084c120,0x11461aa,0x13cf052,0x0a2e58b,0x018fe95,
  46625. 0x0b1b3e8,0x1810854,0x192f13b,0x10037fd,0x0705446 },
  46626. { 0x01901c1,0x1eb8989,0x12abeac,0x0ffd5aa,0x090a262,0x045d11f,
  46627. 0x14a16f0,0x0fcc9ed,0x136ec22,0x0cc980a,0x0646ae3,0x15720d8,
  46628. 0x0c99a16,0x1b24e71,0x0c73d6f,0x075010d,0x15966be,0x02c9033,
  46629. 0x12e8b3c,0x06c4f39,0x1486188,0x03f7fa9,0x0b055ee,0x04475e4,
  46630. 0x098964b,0x12bdfd6,0x002ab9e,0x1a1fa9e,0x018a80c,0x1ca0319,
  46631. 0x13b6b76,0x1bf11e2,0x044bb79,0x16cfe9c,0x0f52dc7,0x0d8367c,
  46632. 0x1620503,0x11a509e,0x029adb1,0x19f70d0,0x06f56ae } },
  46633. /* 235 */
  46634. { { 0x1205c5d,0x0e401ec,0x04a6c07,0x1ace247,0x08955f7,0x0db2b2b,
  46635. 0x0fff676,0x1fc7bd7,0x0d3b1ac,0x0221caf,0x13bbfee,0x1642c12,
  46636. 0x0b04328,0x114c8ff,0x0c7fea0,0x1a0eacc,0x0e6190d,0x086ef33,
  46637. 0x015df01,0x0078abd,0x040775b,0x0fc8b91,0x1b24739,0x176747e,
  46638. 0x08a408e,0x1cb4d14,0x0816284,0x1a6edf1,0x0e06761,0x0a2bcd3,
  46639. 0x023ce96,0x0f6e3a5,0x03029c5,0x0186008,0x10a2d13,0x181087e,
  46640. 0x130e0b9,0x1357fc3,0x112b763,0x0229dac,0x07b6be8 },
  46641. { 0x13aa54e,0x1c7251e,0x0268fb0,0x07b07aa,0x1023394,0x1caaf10,
  46642. 0x0988490,0x089f095,0x1f51d3d,0x088238b,0x0938dca,0x0858fd9,
  46643. 0x1e62d24,0x02fd2ae,0x16948f6,0x1436b18,0x0da851d,0x0637ae6,
  46644. 0x000051a,0x1795504,0x02e0044,0x14700b8,0x1dd4079,0x14159d9,
  46645. 0x19359e6,0x0597840,0x16b03bc,0x07bb4d5,0x164f013,0x16e47ec,
  46646. 0x1625ebb,0x0a61721,0x0dacd0e,0x09175a4,0x15bee10,0x1c98bf5,
  46647. 0x1700a1d,0x02760f6,0x151d08a,0x06bb794,0x086f9a8 } },
  46648. /* 236 */
  46649. { { 0x10cc69f,0x0c82aa2,0x063c387,0x1993dbf,0x10eb14b,0x1f5d00a,
  46650. 0x139dfb9,0x0a63772,0x1998f8e,0x1bd339b,0x1bbbc17,0x09c6362,
  46651. 0x1558838,0x0c2e2f0,0x04a1c8f,0x0a55577,0x145cbd9,0x07f28f1,
  46652. 0x189059d,0x01dc50f,0x02f0c5d,0x178800c,0x1f7051b,0x1eb7c59,
  46653. 0x19e92e7,0x09f07b9,0x1ed95af,0x0035675,0x08e2895,0x16ef28b,
  46654. 0x12ac554,0x171dc20,0x00dfe31,0x0223aca,0x180f10c,0x0685246,
  46655. 0x0460a91,0x03788a6,0x07e1a4c,0x15e076a,0x05bfa9f },
  46656. { 0x07b258e,0x1fa9608,0x0770a88,0x17acc68,0x189e82b,0x1e7f8d4,
  46657. 0x13b6208,0x03ea947,0x0719b49,0x02dbbca,0x0f7ee3d,0x0430486,
  46658. 0x0e898c2,0x0249287,0x0776473,0x0ecaa1f,0x0ae4fa1,0x0a86151,
  46659. 0x10c9fd1,0x1439c85,0x1e41f7a,0x0b2c1d8,0x04e856b,0x17f5b3c,
  46660. 0x0d5a5a1,0x0e6cd50,0x02387ef,0x1639545,0x1f7f879,0x01db48a,
  46661. 0x07abe4a,0x10fd034,0x10e4e0c,0x0694b60,0x0958420,0x1009fb9,
  46662. 0x12755bd,0x064b0b0,0x1bb69ab,0x155051f,0x01b1266 } },
  46663. /* 237 */
  46664. { { 0x14ee49c,0x005003b,0x1f5d3af,0x0596c46,0x176f685,0x1c9c51b,
  46665. 0x112b177,0x17bf80a,0x0b6fbfb,0x19c4764,0x1cbabb0,0x179ae8b,
  46666. 0x1784ac8,0x18f6749,0x1159826,0x1f42753,0x0ac7de8,0x0b2b7db,
  46667. 0x14cae1c,0x1bdae94,0x1f095f8,0x05d5444,0x0ac350a,0x16f5d85,
  46668. 0x07f2810,0x1a621d9,0x1bfbb2c,0x0c84dc3,0x09c2db2,0x0db5cf4,
  46669. 0x041110c,0x0724221,0x0c4bc5d,0x0082c55,0x0da13f6,0x1d24dee,
  46670. 0x071ef60,0x17d348a,0x1e88d14,0x1b6431a,0x033517f },
  46671. { 0x13c4a36,0x19fa32c,0x07baa70,0x106d635,0x0c69d71,0x1bdf765,
  46672. 0x0307509,0x138ab44,0x07e4f17,0x1465127,0x162288f,0x06d3a8d,
  46673. 0x1857373,0x1983817,0x13ac731,0x1aae8e3,0x19735ee,0x1458c26,
  46674. 0x1c133b0,0x0a2f440,0x0a537f4,0x0c6b831,0x1fc4a74,0x1aefc38,
  46675. 0x0571bb1,0x05903d2,0x060d436,0x0e95861,0x1ab8ef7,0x08cfb0f,
  46676. 0x06c9eca,0x16bbb00,0x1c4cc13,0x02c8fd3,0x156c50d,0x07cfcc4,
  46677. 0x1a3592b,0x0c9bdc2,0x1d524d2,0x07a618e,0x031fac6 } },
  46678. /* 238 */
  46679. { { 0x0913fb6,0x0678d82,0x1accbba,0x002ed34,0x1e40135,0x1f30f83,
  46680. 0x0edc5e0,0x1fcf21d,0x1e27f2f,0x12883fc,0x1e26fc7,0x0cffdb5,
  46681. 0x0d124ba,0x12c6f34,0x0480387,0x157dc31,0x0a36df5,0x14b1399,
  46682. 0x12fad2a,0x186f9f5,0x1a7672c,0x0b749e2,0x0c317ea,0x0c67277,
  46683. 0x0317cde,0x0b62615,0x1e0c2cb,0x0fecbcc,0x05b96a9,0x1a820df,
  46684. 0x1b52bf0,0x0e619cc,0x1f40a60,0x06c2785,0x09e64d0,0x112d437,
  46685. 0x07626b0,0x10c12a0,0x12fd4fb,0x1b6f561,0x001db35 },
  46686. { 0x00efee2,0x1de16d6,0x0d15b83,0x1bae3b7,0x0406ebc,0x1b4d5f4,
  46687. 0x178f866,0x045ce57,0x137e018,0x0e5bf30,0x162d312,0x0038228,
  46688. 0x03cbb8c,0x143e2eb,0x02d211d,0x0ceec84,0x1a1454c,0x00c23ef,
  46689. 0x060e746,0x1d223ba,0x1046bed,0x0493c6f,0x06e7727,0x03466d8,
  46690. 0x1d62b88,0x16e14a5,0x064f9de,0x1e12d0f,0x0e3ba77,0x0332a1e,
  46691. 0x1f1eb24,0x0eec9dd,0x08695fd,0x032e78a,0x1c2e6b1,0x03c1841,
  46692. 0x06e2cdb,0x1746945,0x0d0758d,0x119aeaa,0x07b6ba9 } },
  46693. /* 239 */
  46694. { { 0x1881ab4,0x0cf01e0,0x12232c7,0x0b662d1,0x19c25d5,0x11b2670,
  46695. 0x0f51ca0,0x049505a,0x0f161aa,0x0cca1c8,0x0ecb265,0x1801c3d,
  46696. 0x157838b,0x1ef63d3,0x1577f32,0x044151f,0x1c24ff7,0x026e901,
  46697. 0x1bfbfd2,0x02e7661,0x0b355ec,0x198b214,0x067c74a,0x0dd027f,
  46698. 0x1d9e505,0x0f8e035,0x0b02cc6,0x0522e57,0x023b159,0x11c27e9,
  46699. 0x1b5ab83,0x131a123,0x101059e,0x032475e,0x0392995,0x10d662d,
  46700. 0x1375e79,0x08a23f9,0x1142088,0x032e3d6,0x047e810 },
  46701. { 0x08c290d,0x0ea2d5e,0x0ce9c11,0x0b021f6,0x033d135,0x1ddf97d,
  46702. 0x002491b,0x1b2575e,0x1385c7c,0x07f9f8d,0x066172b,0x01d9c2c,
  46703. 0x08c5b15,0x154443a,0x1b829fc,0x1b9918d,0x08e5e88,0x1cec446,
  46704. 0x12e1910,0x0e6be59,0x16f24dd,0x1b9e207,0x130784e,0x1fdad23,
  46705. 0x025fff3,0x0e3fe1d,0x1c95fb9,0x1968762,0x0db1354,0x07c9f99,
  46706. 0x14ea995,0x005bfe5,0x0f58d0a,0x131ca22,0x0622a32,0x0ef1c7e,
  46707. 0x13e8669,0x1236677,0x1a1ece5,0x005c1b9,0x0785b19 } },
  46708. /* 240 */
  46709. { { 0x12f9a20,0x111b0d4,0x103bf33,0x0f3ac8a,0x17bdca8,0x006be2d,
  46710. 0x06a1474,0x04da8e7,0x02e97c9,0x13d646e,0x09aa2c1,0x1ffcf1b,
  46711. 0x092aea3,0x11e28db,0x0a2fd51,0x02834d0,0x0797155,0x03b78e2,
  46712. 0x05df604,0x197dec7,0x0e7af4b,0x04aa0de,0x1d6f125,0x0e0834a,
  46713. 0x14066d1,0x157f00f,0x161dd57,0x0505ab7,0x07ae80d,0x03eeacf,
  46714. 0x1bdb884,0x0705566,0x056e166,0x0eb1a55,0x1bdae74,0x08cbdd1,
  46715. 0x0e4ed84,0x110b056,0x0b09e66,0x0cf6ee2,0x06557c3 },
  46716. { 0x15b6e52,0x181346b,0x1a25586,0x00231a1,0x1081364,0x1758d75,
  46717. 0x0ccc1a8,0x1299fea,0x06d0908,0x1231113,0x1075213,0x044f6bf,
  46718. 0x0dbb351,0x0bd1831,0x197a81d,0x05b8b26,0x17bd66e,0x1a65651,
  46719. 0x0425621,0x1afa477,0x13bf220,0x09c6223,0x0703f4e,0x10fb49f,
  46720. 0x1370a67,0x05c56ff,0x13415fd,0x1e15d79,0x13f33ae,0x1a2608b,
  46721. 0x0d08179,0x124b44d,0x0d1f0a5,0x1ddfedc,0x1d25c8b,0x09526c9,
  46722. 0x0227d28,0x08d73bc,0x02ad322,0x00941c1,0x015c40d } },
  46723. /* 241 */
  46724. { { 0x00e18d1,0x18b4d15,0x1f0a6eb,0x0e98064,0x1971c01,0x0131674,
  46725. 0x0c8fdef,0x0f3b034,0x1818ff3,0x04cedc6,0x0f0cc08,0x0c7a99a,
  46726. 0x13663f6,0x008d02a,0x14c970c,0x148e1de,0x1dcf980,0x04e6b85,
  46727. 0x127b41c,0x08a5a23,0x0e13e64,0x1a5633b,0x0befd0f,0x10b854b,
  46728. 0x0c0a6ae,0x0624bdf,0x011c124,0x1f55caa,0x1e6ba92,0x1d43a48,
  46729. 0x0502ae5,0x155f532,0x055f537,0x132aba0,0x16ecd9c,0x1ff92b5,
  46730. 0x1119d6b,0x11a1dce,0x078dd91,0x1413a68,0x0788e94 },
  46731. { 0x053461a,0x137f2ce,0x1bb414e,0x1c11c76,0x15ec897,0x146c9cb,
  46732. 0x14bcc1d,0x09f51eb,0x0cc213d,0x1eb5ffb,0x0051f26,0x16820b6,
  46733. 0x09590c7,0x1e3dc0b,0x08d8a2d,0x0f1d241,0x06e5bce,0x1e33504,
  46734. 0x17b0763,0x09a5049,0x0ce93dd,0x0260cee,0x0242b3d,0x086b4fd,
  46735. 0x0d875d8,0x0d93319,0x07a98e0,0x1202cf8,0x1cc1285,0x0bcbf86,
  46736. 0x18ec896,0x08df1a8,0x1a612b4,0x17d1cc8,0x15e3057,0x108430b,
  46737. 0x119f678,0x0af61b8,0x1aa4f7d,0x18cf01b,0x091b19c } },
  46738. /* 242 */
  46739. { { 0x15d8b80,0x1384ee5,0x183bafc,0x05f86ac,0x03b9618,0x0f7cb48,
  46740. 0x1664415,0x08570e7,0x1e47c43,0x0f525a6,0x1e219f4,0x0489aa9,
  46741. 0x0fcc4b9,0x1ec6bbf,0x0c68b2b,0x1eac727,0x0e7e8c1,0x1034692,
  46742. 0x065cc15,0x1f576c9,0x174f5f5,0x0802a11,0x00c9231,0x071d227,
  46743. 0x1e2b53f,0x05f61b6,0x0deeda0,0x1a0fd1d,0x1313b5e,0x09ebec7,
  46744. 0x04a5920,0x15fa5a7,0x1b6a069,0x0518d3d,0x1238212,0x0b80db0,
  46745. 0x04f0c32,0x13fd97f,0x10ebda1,0x0680ce6,0x03c2ba8 },
  46746. { 0x13ad63b,0x16bbace,0x0c7ead8,0x0eb3c1d,0x1f9cab9,0x02f08b9,
  46747. 0x0a98ce2,0x13ce066,0x0e20b2f,0x11657e7,0x12a51fc,0x14fc93d,
  46748. 0x0db529b,0x11146c4,0x0550859,0x12ac249,0x1ec3923,0x0407511,
  46749. 0x10dc191,0x120fcfa,0x0e441b8,0x0aab1f2,0x12dfe91,0x14961f4,
  46750. 0x1829eb2,0x1c96654,0x1120181,0x014e414,0x0991ced,0x0d06123,
  46751. 0x1ae3337,0x0691a10,0x1a2325b,0x177099b,0x1427d82,0x1eacdda,
  46752. 0x147f253,0x1870488,0x0ef60f4,0x14b820e,0x01fa627 } },
  46753. /* 243 */
  46754. { { 0x0478fd4,0x1115121,0x0002844,0x02ce164,0x0cf4c6f,0x0ce36f5,
  46755. 0x0c13e0d,0x179ee37,0x17b93cd,0x0c71414,0x16d82d8,0x15c6461,
  46756. 0x0996e1b,0x0b2d9d9,0x1ff4ed2,0x0abbbe2,0x1c6bc70,0x1d2c31c,
  46757. 0x0e05f5f,0x1525da9,0x08a4c3e,0x13691d8,0x0420aca,0x02e021d,
  46758. 0x1228adc,0x0cbc238,0x1883a27,0x0a773c8,0x1f77c97,0x07cb81f,
  46759. 0x1973df9,0x0577cc1,0x03f8245,0x100beb6,0x12f2e03,0x173c865,
  46760. 0x00a45ed,0x052d66e,0x1d0f854,0x00a8f30,0x067b8bd },
  46761. { 0x0797cf7,0x03cda7a,0x180b998,0x15a07fb,0x031c998,0x055778f,
  46762. 0x1d8e953,0x022b546,0x0f76497,0x06cd0ff,0x06c69d9,0x18e75e5,
  46763. 0x137ce0d,0x1db3654,0x186c20f,0x0d4f0cc,0x0fe32fb,0x0dfa6ba,
  46764. 0x1c02958,0x0dde13b,0x115925f,0x1fc18e8,0x0af10e0,0x0d7bc6e,
  46765. 0x0c10c53,0x12db6ae,0x1e20b31,0x0928bf3,0x1a99b8d,0x0789a28,
  46766. 0x09207d2,0x0d75823,0x00161cd,0x125050a,0x13b7c62,0x093b29a,
  46767. 0x0467a82,0x1b18b2d,0x0bb7d94,0x1534993,0x074297a } },
  46768. /* 244 */
  46769. { { 0x01124ba,0x1ac5271,0x0f4b125,0x1150fff,0x19bd819,0x131c544,
  46770. 0x13744f5,0x0ec8bf7,0x015f7bf,0x0322ffc,0x1b55fa5,0x06df89c,
  46771. 0x195fa67,0x09730ed,0x0b991d6,0x128943d,0x00ccbdf,0x03cabae,
  46772. 0x16cc75d,0x02608e4,0x1ae6a3d,0x112655a,0x1e2077c,0x0510fe4,
  46773. 0x1d2991a,0x02cc6df,0x0289ab1,0x07a0eb2,0x061d4a2,0x0c296c3,
  46774. 0x1dcb962,0x1140281,0x1b5c13b,0x1bc151b,0x0678fec,0x001f283,
  46775. 0x1bc14e9,0x15502c8,0x0ec49c8,0x175aab7,0x089aab7 },
  46776. { 0x056bdc7,0x02d4b6b,0x14ee2cd,0x1fc2ed9,0x03bdc8a,0x0b2621a,
  46777. 0x062d8cb,0x083ad2a,0x179b82b,0x079b253,0x033e0bf,0x089dff6,
  46778. 0x1b907b3,0x0880943,0x14320f1,0x121dfe7,0x05934cd,0x074f935,
  46779. 0x1c20ad7,0x0b55e40,0x0165e5f,0x1af673e,0x13adcb1,0x130d9ac,
  46780. 0x10a81be,0x15574ac,0x1ffc54d,0x1dde931,0x063d5ef,0x0121d41,
  46781. 0x0ac1158,0x0a95d0e,0x00be14f,0x03b434a,0x13278c8,0x157dcf7,
  46782. 0x01bc4d7,0x0b513ee,0x0ad1b52,0x12eb281,0x0002dc2 } },
  46783. /* 245 */
  46784. { { 0x09d60c3,0x19c9bdb,0x1d57b94,0x05fd2e4,0x060be55,0x0392d31,
  46785. 0x0de3703,0x185623f,0x0cab2e7,0x0c1613f,0x0c8b2da,0x1bb3dc4,
  46786. 0x174bcee,0x0913827,0x0ac67b4,0x0c2cb2a,0x085854a,0x096fa61,
  46787. 0x0c64921,0x016b7ef,0x152aba4,0x08008cf,0x1f2f2a5,0x15bb0df,
  46788. 0x1d1cbe5,0x160ba33,0x0f6743c,0x17ea6df,0x14ebc99,0x171a5c6,
  46789. 0x05cf0a5,0x00b5026,0x095f8f4,0x1afbb02,0x0359ccc,0x0518b3d,
  46790. 0x0054212,0x09e9927,0x169cc2d,0x06a7877,0x04d5645 },
  46791. { 0x05c0877,0x17c003f,0x1d91cc8,0x0c19534,0x081b43e,0x00938b2,
  46792. 0x13d2e8b,0x184463e,0x1ed3136,0x0acb42b,0x0cc3782,0x064471b,
  46793. 0x1cae826,0x0cc8475,0x0beb502,0x0463cca,0x014af0d,0x085c68c,
  46794. 0x072f0d2,0x018a961,0x1f8e268,0x19a5f9d,0x1f5158b,0x056b2bf,
  46795. 0x1090b09,0x01a14c2,0x117857f,0x0de7394,0x178168e,0x08c8de1,
  46796. 0x01dc05d,0x108b495,0x06944b3,0x0aa0d48,0x1d2a0a8,0x09598da,
  46797. 0x1155c8b,0x04dd59d,0x1b18ab7,0x19cee60,0x01f2f89 } },
  46798. /* 246 */
  46799. { { 0x0ffefdf,0x1f7a0cd,0x15ae094,0x0a99f24,0x05d7ece,0x0272418,
  46800. 0x00bcad1,0x03e6ee0,0x1cba547,0x0c4baaf,0x0f8056c,0x0797ab9,
  46801. 0x09c8848,0x1505c21,0x13df1a5,0x1ec3a4a,0x1d461f3,0x18c4285,
  46802. 0x0891c55,0x0421121,0x0b0d7ba,0x176c977,0x0d6aef0,0x0bbd912,
  46803. 0x0cabe96,0x0257dab,0x12f155a,0x1b446e4,0x1a74929,0x1cb7b53,
  46804. 0x11b62e8,0x05de974,0x0b90db7,0x0d93d7e,0x1f82642,0x1dba469,
  46805. 0x16f4366,0x19e0b23,0x0351ef7,0x0fe2fca,0x009c809 },
  46806. { 0x0050c07,0x058a030,0x0df9a81,0x108751c,0x029e831,0x0af20fe,
  46807. 0x0a6caed,0x0759728,0x02ce60e,0x097f52d,0x160bd3b,0x1fe7b73,
  46808. 0x1adc7b1,0x143e9bf,0x1afb30d,0x0ea7291,0x032ecb0,0x13c8a9f,
  46809. 0x1c1d5a4,0x000a9ea,0x19ba6a6,0x064003a,0x0e1c734,0x1245be2,
  46810. 0x1386f30,0x1be0bd3,0x1a0cd5e,0x1d3f8b3,0x0151864,0x19d49ca,
  46811. 0x024749a,0x1a69b71,0x12a0222,0x06db8c8,0x13d167f,0x0ccce5f,
  46812. 0x04ff303,0x1f9346a,0x185b168,0x1a6d223,0x06f113e } },
  46813. /* 247 */
  46814. { { 0x036f1c9,0x0efac8c,0x01f54aa,0x0a84646,0x1a6519f,0x16942d7,
  46815. 0x11c0577,0x0eb080d,0x0af627f,0x10aa2e5,0x0105f42,0x03dd59c,
  46816. 0x03ae111,0x13089a2,0x0a2f7da,0x19797f6,0x0ab52db,0x06f4f78,
  46817. 0x004f996,0x183036f,0x1225e9d,0x0dcc893,0x02c76af,0x10298b2,
  46818. 0x198e322,0x13f2f82,0x1b64d3b,0x18772cd,0x1ba4bf5,0x076d5cc,
  46819. 0x19d3ae1,0x07836ab,0x0919a34,0x14307d9,0x0d2652a,0x0d535bb,
  46820. 0x16811ff,0x19106ff,0x00f886d,0x077a343,0x06636a2 },
  46821. { 0x0587283,0x0ad1690,0x11777d7,0x13de0ff,0x0b3822c,0x1b6f1c0,
  46822. 0x0f5543b,0x03a2f0d,0x125d167,0x11e7c83,0x0c77bc5,0x0e3e39b,
  46823. 0x0a74bf9,0x04217e2,0x127a0c0,0x0a9eeae,0x1c727f8,0x187176d,
  46824. 0x13892b2,0x0f77b57,0x108dbb2,0x1602df6,0x106c673,0x1920979,
  46825. 0x0123ef7,0x16dd56d,0x0f62660,0x04853e3,0x16e6320,0x10b732f,
  46826. 0x0c9274d,0x1dcb3fa,0x1789fa8,0x194fad1,0x0eebfa7,0x002c174,
  46827. 0x0f5378a,0x169db0d,0x09be03c,0x0ece785,0x07aeecc } },
  46828. /* 248 */
  46829. { { 0x043b0db,0x03abe6e,0x12b7ce9,0x0b30233,0x1d8a4e8,0x0b60ab1,
  46830. 0x16fd918,0x12ff012,0x04f533e,0x11503de,0x1f16b4f,0x06ce739,
  46831. 0x0ca9824,0x06b4029,0x09ae8eb,0x1d8cc31,0x1908a1c,0x0deb072,
  46832. 0x0ac6da5,0x10834a0,0x195bae3,0x090c850,0x061b7fc,0x063fb37,
  46833. 0x0beacad,0x1bd96f9,0x1331ca3,0x1b12644,0x10a9927,0x139c067,
  46834. 0x1ab0e3a,0x0b0d489,0x0439a80,0x0f81e54,0x1fc0585,0x0bdbcfe,
  46835. 0x07a1f88,0x124c841,0x1d91520,0x00d6f14,0x028ec40 },
  46836. { 0x0fe0009,0x1061751,0x13a7860,0x05e270e,0x011ba5d,0x126da97,
  46837. 0x0915314,0x0532ea4,0x07fede5,0x0a3ba13,0x1403513,0x0335364,
  46838. 0x0b01d34,0x0c34922,0x0229248,0x1c3739c,0x023dd1b,0x05d0b48,
  46839. 0x0a8c078,0x187ca86,0x0788242,0x1d38483,0x06d5bde,0x0951989,
  46840. 0x12a09c7,0x01cf856,0x075dbe5,0x139a308,0x1fb60e9,0x1f05b10,
  46841. 0x0d3b76b,0x17872ec,0x16bee54,0x1854202,0x0183fdf,0x1e8ca7f,
  46842. 0x0011c0a,0x0a43b79,0x0970daf,0x18e192a,0x0134f4c } },
  46843. /* 249 */
  46844. { { 0x138dff4,0x0d1f674,0x068e588,0x1690d4f,0x1d101a7,0x0a829bb,
  46845. 0x1be5f7a,0x1b7e589,0x1e65d87,0x18c204c,0x0e33ebc,0x1ff66e7,
  46846. 0x0eb89c7,0x142148b,0x0ea9417,0x14ec8d1,0x1094ebe,0x1d3c87e,
  46847. 0x164a24a,0x1beda9c,0x1741679,0x0e7e7f6,0x0808ccc,0x101fe42,
  46848. 0x0efd298,0x08085fa,0x1740d11,0x194f1bb,0x0858c87,0x0f659a1,
  46849. 0x1e8b2c2,0x04aea90,0x05eb6dc,0x18248cf,0x0857af2,0x02a0ceb,
  46850. 0x1381d47,0x0973a7b,0x15bd027,0x05307a7,0x06ea378 },
  46851. { 0x05cc40a,0x004a5a7,0x17ef197,0x1435e6f,0x1a2e3f6,0x0137223,
  46852. 0x1fa77e4,0x0a7dece,0x193880f,0x1c3c64a,0x112aa6d,0x160efec,
  46853. 0x1c4aa30,0x1790461,0x1145a0c,0x0cc7741,0x1ae658d,0x03e013b,
  46854. 0x187644c,0x1678715,0x1ea4ef0,0x13b4ae1,0x0c0bcde,0x018bc1a,
  46855. 0x0c1c56a,0x1cff002,0x10832f3,0x1fa92b8,0x0a0e7c9,0x0dceab4,
  46856. 0x151c1b5,0x0b250c8,0x1225dff,0x1384e45,0x1196366,0x10a4fa8,
  46857. 0x07c08d6,0x02ac6d4,0x1c1f51f,0x1cd769d,0x0606ee6 } },
  46858. /* 250 */
  46859. { { 0x1c621f6,0x0cfe3ab,0x15200b6,0x02ffd07,0x092e40c,0x18ccd81,
  46860. 0x11e867b,0x0cc37bf,0x0e62c76,0x0502081,0x0e1d4de,0x06e1cce,
  46861. 0x0f16cda,0x0f1d32d,0x0065d34,0x1c41379,0x048f78f,0x10cba10,
  46862. 0x1d66071,0x140b157,0x102dc83,0x1a4e44b,0x1c9ac90,0x034cf15,
  46863. 0x12f1e9d,0x114cc45,0x03fca6b,0x0e57f36,0x1cf5ec4,0x11cc0eb,
  46864. 0x162850f,0x164d1bb,0x09d7e45,0x07fbb4e,0x09557f1,0x062cd9b,
  46865. 0x04aa767,0x0266f85,0x01c1d81,0x1efd229,0x049dba6 },
  46866. { 0x158e37a,0x03fd953,0x1d98839,0x0e5b1d5,0x0f6b31d,0x0e11085,
  46867. 0x157e5be,0x0566a55,0x190efc3,0x049fb93,0x12c9900,0x13b883c,
  46868. 0x15435c9,0x02d8abc,0x0a1e380,0x06aeb7f,0x0a40e67,0x0cce290,
  46869. 0x1fba9d6,0x104b290,0x148bca6,0x00f8951,0x00a7dee,0x1459c6a,
  46870. 0x1cc182a,0x162d2a3,0x0fab578,0x023b0e9,0x082cdfa,0x1a4daab,
  46871. 0x19a6bc0,0x1177d1c,0x06ebfea,0x1ca55fc,0x1e0bd54,0x1e7b570,
  46872. 0x0bc8eb8,0x05fbcbf,0x19e3116,0x14936fb,0x04890a7 } },
  46873. /* 251 */
  46874. { { 0x1a995f6,0x0cb44c6,0x1bbf5ca,0x0fd8c2a,0x139eaae,0x15416ae,
  46875. 0x01030d5,0x1fcd2b2,0x1c135bc,0x1023590,0x0571e2c,0x16c81eb,
  46876. 0x00ea720,0x13e2fda,0x0093beb,0x077f805,0x14c0edb,0x14bec7e,
  46877. 0x07c93af,0x00520af,0x06b912f,0x078c3f5,0x05bf11f,0x13ab846,
  46878. 0x1fd2778,0x166610c,0x122498f,0x0674d6d,0x0d30a62,0x1a5945b,
  46879. 0x00208d8,0x193666d,0x0352e25,0x1ba2b65,0x1b29031,0x172711a,
  46880. 0x1c92065,0x12ad859,0x069dbe3,0x0960487,0x05c1747 },
  46881. { 0x0accab5,0x073e145,0x016f622,0x0d559da,0x1802783,0x1607b28,
  46882. 0x01df733,0x10430b7,0x0125c28,0x1e56e0e,0x1715324,0x0814cff,
  46883. 0x1345df5,0x013c451,0x0f21b8b,0x1f4589e,0x069e3a0,0x19f43a2,
  46884. 0x1ce60f3,0x1b548e4,0x18a5c59,0x05a54b6,0x0c18f12,0x1cb122a,
  46885. 0x12bcfc2,0x061e1c6,0x1e1390a,0x01cf170,0x04fd539,0x1496786,
  46886. 0x0164028,0x1283cc0,0x1f92db7,0x09d0e5b,0x0905b29,0x0f2acf2,
  46887. 0x11ab0fa,0x1b798ed,0x10230d7,0x168f6b0,0x05d675e } },
  46888. /* 252 */
  46889. { { 0x10c6025,0x10d3bc3,0x1f2abbb,0x0f2345b,0x1c4a23b,0x15b2627,
  46890. 0x18310e1,0x162f61c,0x1e5ae72,0x0ead8be,0x1e884b5,0x11593dd,
  46891. 0x166dfc8,0x0a01c5c,0x1abbefb,0x05d989f,0x1568e2d,0x184cd61,
  46892. 0x04abc81,0x1d4c240,0x1218548,0x0dc4e18,0x13ffb67,0x1cce662,
  46893. 0x091c4e0,0x0700e0f,0x1ebe0c0,0x01376c9,0x13c3be0,0x080e33b,
  46894. 0x1ea1e01,0x1810433,0x0cd6ede,0x1837ff0,0x181fe06,0x1ef80ab,
  46895. 0x0080b36,0x1b1fce7,0x1b28e0a,0x15e153f,0x002fccb },
  46896. { 0x07cac61,0x0ea68da,0x04b2664,0x0f570dc,0x0e9d168,0x0a78211,
  46897. 0x157b0ae,0x1cb18d0,0x148e648,0x120028c,0x06b15f2,0x1f65df1,
  46898. 0x0d9ba91,0x0df3c96,0x1064818,0x03c2a9e,0x1cbbd0f,0x0c16910,
  46899. 0x1111006,0x1d6277f,0x0fdc062,0x194cbc8,0x1cea5f0,0x0cf4c97,
  46900. 0x16d9460,0x1ad273c,0x01b48dd,0x08dba60,0x1f0f23c,0x026af6b,
  46901. 0x15e19cb,0x0769ec7,0x01851dc,0x139f941,0x1833498,0x1ea1475,
  46902. 0x0ac60f6,0x072c7e7,0x1551600,0x0ac2708,0x056f1e4 } },
  46903. /* 253 */
  46904. { { 0x0c24f3b,0x059fb19,0x1f98073,0x1e0db02,0x19eb1c7,0x1133bb4,
  46905. 0x102edaa,0x1c11b8c,0x00845d5,0x01c57ff,0x09e6a1e,0x1963f03,
  46906. 0x10f34fe,0x1f340cd,0x0b8a0b4,0x14970d4,0x1ce8237,0x0e25cbb,
  46907. 0x1d8d90e,0x0d67b70,0x04970f4,0x004bcb8,0x09197d5,0x1237c87,
  46908. 0x0876287,0x1636bf0,0x10d0663,0x004416d,0x1d94bb0,0x031b849,
  46909. 0x0c95ece,0x053ad21,0x0012e16,0x168d242,0x16d482a,0x0605d93,
  46910. 0x05dc34e,0x1717e34,0x033e2bf,0x06c4aa0,0x0911d19 },
  46911. { 0x1e5af5b,0x0deac7a,0x0a9c4ec,0x16f6d44,0x07ca263,0x17956e5,
  46912. 0x1b137ce,0x17b56d7,0x1a04420,0x1328f2c,0x0db0445,0x1676974,
  46913. 0x103b448,0x1fa1218,0x18aff37,0x0d97678,0x0a5f1a9,0x06f0ae2,
  46914. 0x1347e60,0x15b143c,0x1a3abe0,0x071b339,0x004af45,0x02559bb,
  46915. 0x03af692,0x0e72018,0x115d825,0x1edb573,0x1f5ca58,0x0415083,
  46916. 0x0c1f7c6,0x1112d47,0x103e63c,0x1d9f85c,0x1513618,0x1dea090,
  46917. 0x009887d,0x080cdce,0x0e19579,0x1fd41ea,0x02be744 } },
  46918. /* 254 */
  46919. { { 0x150f324,0x0682fad,0x1e88153,0x083d478,0x19b1eb2,0x1c735bd,
  46920. 0x02971ff,0x104950b,0x0ec0408,0x01c817f,0x0ea6f76,0x0929a19,
  46921. 0x1e72b26,0x194e4f0,0x05dbe42,0x1b703a0,0x102ceba,0x002ea75,
  46922. 0x1cae2ff,0x080b626,0x1190874,0x00bcf56,0x17104a2,0x056919a,
  46923. 0x03dd3ec,0x019ea25,0x1cfd354,0x089334e,0x0c3a098,0x1c66ab2,
  46924. 0x0eecdec,0x1e85d00,0x0e99497,0x08c5940,0x1e82e3d,0x0980f68,
  46925. 0x1568fde,0x0871e29,0x039eb1c,0x05f9d5a,0x0735f54 },
  46926. { 0x0380039,0x0d0b89c,0x07232aa,0x0fee9a3,0x0dfafe1,0x1e0d45d,
  46927. 0x0e4fb32,0x00b25a8,0x1fe0297,0x02edf9c,0x1a6cd8f,0x0b57261,
  46928. 0x0a4552b,0x157ea4a,0x198c0c8,0x15886fd,0x0d73f02,0x041354d,
  46929. 0x04d58a6,0x0a6ac53,0x1b3998c,0x03b9a15,0x0321a7e,0x1f36f34,
  46930. 0x10020e4,0x0d4eba8,0x134d1e2,0x06c3a34,0x0856376,0x0add67d,
  46931. 0x193c37b,0x111580f,0x07ee73f,0x18e5ea0,0x00fc27b,0x1bf58fa,
  46932. 0x0d475ba,0x0b4be5a,0x0e67897,0x13a297a,0x01e984c } },
  46933. /* 255 */
  46934. { { 0x050c817,0x082b0a4,0x04b71db,0x1269130,0x108a5b1,0x0c65df5,
  46935. 0x1455179,0x0b4e4e7,0x04be61e,0x0805afd,0x1ae3862,0x0d23af5,
  46936. 0x0baa088,0x09ad1ea,0x1999abf,0x0fa7bcc,0x19957ec,0x01c5160,
  46937. 0x1a35bd7,0x091d1ec,0x1746a06,0x163d6e0,0x07e7f24,0x060cb86,
  46938. 0x116c084,0x13491d0,0x01879ab,0x0c6e144,0x047e733,0x1b9b155,
  46939. 0x01189b0,0x1bdfedb,0x00c25f2,0x1696a2a,0x093336f,0x0530090,
  46940. 0x039a949,0x0dfe700,0x0b8052d,0x0aced28,0x06c474a },
  46941. { 0x188e3a1,0x1cd20be,0x10a8eba,0x118908e,0x105d3c8,0x1308988,
  46942. 0x1a344ff,0x117cb3b,0x11a869e,0x047adb5,0x1764285,0x18b354e,
  46943. 0x137a8ab,0x110a300,0x0326f1d,0x099b25e,0x147c382,0x121fd53,
  46944. 0x09742e4,0x0c7430d,0x0ebc817,0x1e4de5d,0x0ef0d06,0x08ba3bb,
  46945. 0x13160f7,0x0fa70c0,0x16dd739,0x0a79ca5,0x0de4c2a,0x13366a8,
  46946. 0x1b457ab,0x0ebaeca,0x0d8996c,0x12a952f,0x1c47132,0x09c9fea,
  46947. 0x1c5305b,0x0f4c2d1,0x08b3885,0x0a9f437,0x06b2589 } },
  46948. };
  46949. /* Multiply the base point of P1024 by the scalar and return the result.
  46950. * If map is true then convert result to affine coordinates.
  46951. *
  46952. * Stripe implementation.
  46953. * Pre-generated: 2^0, 2^128, ...
  46954. * Pre-generated: products of all combinations of above.
  46955. * 8 doubles and adds (with qz=1)
  46956. *
  46957. * r Resulting point.
  46958. * k Scalar to multiply by.
  46959. * map Indicates whether to convert result to affine.
  46960. * ct Constant time required.
  46961. * heap Heap to use for allocation.
  46962. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  46963. */
  46964. static int sp_1024_ecc_mulmod_base_42(sp_point_1024* r, const sp_digit* k,
  46965. int map, int ct, void* heap)
  46966. {
  46967. return sp_1024_ecc_mulmod_stripe_42(r, &p1024_base, p1024_table,
  46968. k, map, ct, heap);
  46969. }
  46970. #endif
  46971. /* Multiply the base point of P1024 by the scalar and return the result.
  46972. * If map is true then convert result to affine coordinates.
  46973. *
  46974. * km Scalar to multiply by.
  46975. * r Resulting point.
  46976. * map Indicates whether to convert result to affine.
  46977. * heap Heap to use for allocation.
  46978. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  46979. */
  46980. int sp_ecc_mulmod_base_1024(const mp_int* km, ecc_point* r, int map, void* heap)
  46981. {
  46982. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  46983. sp_point_1024* point = NULL;
  46984. sp_digit* k = NULL;
  46985. #else
  46986. sp_point_1024 point[1];
  46987. sp_digit k[42];
  46988. #endif
  46989. int err = MP_OKAY;
  46990. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  46991. point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap,
  46992. DYNAMIC_TYPE_ECC);
  46993. if (point == NULL)
  46994. err = MEMORY_E;
  46995. if (err == MP_OKAY) {
  46996. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 42, heap,
  46997. DYNAMIC_TYPE_ECC);
  46998. if (k == NULL)
  46999. err = MEMORY_E;
  47000. }
  47001. #endif
  47002. if (err == MP_OKAY) {
  47003. sp_1024_from_mp(k, 42, km);
  47004. err = sp_1024_ecc_mulmod_base_42(point, k, map, 1, heap);
  47005. }
  47006. if (err == MP_OKAY) {
  47007. err = sp_1024_point_to_ecc_point_42(point, r);
  47008. }
  47009. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  47010. if (k != NULL)
  47011. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  47012. if (point != NULL)
  47013. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  47014. #endif
  47015. return err;
  47016. }
  47017. /* Multiply the base point of P1024 by the scalar, add point a and return
  47018. * the result. If map is true then convert result to affine coordinates.
  47019. *
  47020. * km Scalar to multiply by.
  47021. * am Point to add to scalar mulitply result.
  47022. * inMont Point to add is in montgomery form.
  47023. * r Resulting point.
  47024. * map Indicates whether to convert result to affine.
  47025. * heap Heap to use for allocation.
  47026. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  47027. */
  47028. int sp_ecc_mulmod_base_add_1024(const mp_int* km, const ecc_point* am,
  47029. int inMont, ecc_point* r, int map, void* heap)
  47030. {
  47031. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  47032. sp_point_1024* point = NULL;
  47033. sp_digit* k = NULL;
  47034. #else
  47035. sp_point_1024 point[2];
  47036. sp_digit k[42 + 42 * 2 * 6];
  47037. #endif
  47038. sp_point_1024* addP = NULL;
  47039. sp_digit* tmp = NULL;
  47040. int err = MP_OKAY;
  47041. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  47042. point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap,
  47043. DYNAMIC_TYPE_ECC);
  47044. if (point == NULL)
  47045. err = MEMORY_E;
  47046. if (err == MP_OKAY) {
  47047. k = (sp_digit*)XMALLOC(
  47048. sizeof(sp_digit) * (42 + 42 * 2 * 6),
  47049. heap, DYNAMIC_TYPE_ECC);
  47050. if (k == NULL)
  47051. err = MEMORY_E;
  47052. }
  47053. #endif
  47054. if (err == MP_OKAY) {
  47055. addP = point + 1;
  47056. tmp = k + 42;
  47057. sp_1024_from_mp(k, 42, km);
  47058. sp_1024_point_from_ecc_point_42(addP, am);
  47059. }
  47060. if ((err == MP_OKAY) && (!inMont)) {
  47061. err = sp_1024_mod_mul_norm_42(addP->x, addP->x, p1024_mod);
  47062. }
  47063. if ((err == MP_OKAY) && (!inMont)) {
  47064. err = sp_1024_mod_mul_norm_42(addP->y, addP->y, p1024_mod);
  47065. }
  47066. if ((err == MP_OKAY) && (!inMont)) {
  47067. err = sp_1024_mod_mul_norm_42(addP->z, addP->z, p1024_mod);
  47068. }
  47069. if (err == MP_OKAY) {
  47070. err = sp_1024_ecc_mulmod_base_42(point, k, 0, 0, heap);
  47071. }
  47072. if (err == MP_OKAY) {
  47073. sp_1024_proj_point_add_42(point, point, addP, tmp);
  47074. if (map) {
  47075. sp_1024_map_42(point, point, tmp);
  47076. }
  47077. err = sp_1024_point_to_ecc_point_42(point, r);
  47078. }
  47079. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  47080. if (k != NULL)
  47081. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  47082. if (point)
  47083. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  47084. #endif
  47085. return err;
  47086. }
  47087. #ifndef WOLFSSL_SP_SMALL
  47088. /* Generate a pre-computation table for the point.
  47089. *
  47090. * gm Point to generate table for.
  47091. * table Buffer to hold pre-computed points table.
  47092. * len Length of table.
  47093. * heap Heap to use for allocation.
  47094. * returns BAD_FUNC_ARG when gm or len is NULL, LENGTH_ONLY_E when table is
  47095. * NULL and length is returned, BUFFER_E if length is too small and 0 otherwise.
  47096. */
  47097. int sp_ecc_gen_table_1024(const ecc_point* gm, byte* table, word32* len,
  47098. void* heap)
  47099. {
  47100. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  47101. sp_point_1024* point = NULL;
  47102. sp_digit* t = NULL;
  47103. #else
  47104. sp_point_1024 point[1];
  47105. sp_digit t[6 * 2 * 42];
  47106. #endif
  47107. int err = MP_OKAY;
  47108. if ((gm == NULL) || (len == NULL)) {
  47109. err = BAD_FUNC_ARG;
  47110. }
  47111. if ((err == MP_OKAY) && (table == NULL)) {
  47112. *len = sizeof(sp_table_entry_1024) * 256;
  47113. err = LENGTH_ONLY_E;
  47114. }
  47115. if ((err == MP_OKAY) && (*len < (int)(sizeof(sp_table_entry_1024) * 256))) {
  47116. err = BUFFER_E;
  47117. }
  47118. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  47119. if (err == MP_OKAY) {
  47120. point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap,
  47121. DYNAMIC_TYPE_ECC);
  47122. if (point == NULL)
  47123. err = MEMORY_E;
  47124. }
  47125. if (err == MP_OKAY) {
  47126. t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 2 * 42, heap,
  47127. DYNAMIC_TYPE_ECC);
  47128. if (t == NULL)
  47129. err = MEMORY_E;
  47130. }
  47131. #endif
  47132. if (err == MP_OKAY) {
  47133. sp_1024_point_from_ecc_point_42(point, gm);
  47134. err = sp_1024_gen_stripe_table_42(point,
  47135. (sp_table_entry_1024*)table, t, heap);
  47136. }
  47137. if (err == 0) {
  47138. *len = sizeof(sp_table_entry_1024) * 256;
  47139. }
  47140. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  47141. if (t != NULL)
  47142. XFREE(t, heap, DYNAMIC_TYPE_ECC);
  47143. if (point != NULL)
  47144. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  47145. #endif
  47146. return err;
  47147. }
  47148. #else
  47149. /* Generate a pre-computation table for the point.
  47150. *
  47151. * gm Point to generate table for.
  47152. * table Buffer to hold pre-computed points table.
  47153. * len Length of table.
  47154. * heap Heap to use for allocation.
  47155. * returns BAD_FUNC_ARG when gm or len is NULL, LENGTH_ONLY_E when table is
  47156. * NULL and length is returned, BUFFER_E if length is too small and 0 otherwise.
  47157. */
  47158. int sp_ecc_gen_table_1024(const ecc_point* gm, byte* table, word32* len,
  47159. void* heap)
  47160. {
  47161. int err = 0;
  47162. if ((gm == NULL) || (len == NULL)) {
  47163. err = BAD_FUNC_ARG;
  47164. }
  47165. if ((err == 0) && (table == NULL)) {
  47166. *len = 0;
  47167. err = LENGTH_ONLY_E;
  47168. }
  47169. if ((err == 0) && (*len != 0)) {
  47170. err = BUFFER_E;
  47171. }
  47172. if (err == 0) {
  47173. *len = 0;
  47174. }
  47175. (void)heap;
  47176. return err;
  47177. }
  47178. #endif
  47179. /* Multiply the point by the scalar and return the result.
  47180. * If map is true then convert result to affine coordinates.
  47181. *
  47182. * km Scalar to multiply by.
  47183. * gm Point to multiply.
  47184. * table Pre-computed points.
  47185. * r Resulting point.
  47186. * map Indicates whether to convert result to affine.
  47187. * heap Heap to use for allocation.
  47188. * returns MEMORY_E when memory allocation fails and MP_OKAY on success.
  47189. */
  47190. int sp_ecc_mulmod_table_1024(const mp_int* km, const ecc_point* gm, byte* table,
  47191. ecc_point* r, int map, void* heap)
  47192. {
  47193. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  47194. sp_point_1024* point = NULL;
  47195. sp_digit* k = NULL;
  47196. #else
  47197. sp_point_1024 point[1];
  47198. sp_digit k[42];
  47199. #endif
  47200. int err = MP_OKAY;
  47201. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  47202. point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap,
  47203. DYNAMIC_TYPE_ECC);
  47204. if (point == NULL) {
  47205. err = MEMORY_E;
  47206. }
  47207. if (err == MP_OKAY) {
  47208. k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 42, heap, DYNAMIC_TYPE_ECC);
  47209. if (k == NULL)
  47210. err = MEMORY_E;
  47211. }
  47212. #endif
  47213. if (err == MP_OKAY) {
  47214. sp_1024_from_mp(k, 42, km);
  47215. sp_1024_point_from_ecc_point_42(point, gm);
  47216. #ifndef WOLFSSL_SP_SMALL
  47217. err = sp_1024_ecc_mulmod_stripe_42(point, point,
  47218. (const sp_table_entry_1024*)table, k, map, 0, heap);
  47219. #else
  47220. (void)table;
  47221. err = sp_1024_ecc_mulmod_42(point, point, k, map, 0, heap);
  47222. #endif
  47223. }
  47224. if (err == MP_OKAY) {
  47225. err = sp_1024_point_to_ecc_point_42(point, r);
  47226. }
  47227. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  47228. if (k != NULL)
  47229. XFREE(k, heap, DYNAMIC_TYPE_ECC);
  47230. if (point != NULL)
  47231. XFREE(point, heap, DYNAMIC_TYPE_ECC);
  47232. #endif
  47233. return err;
  47234. }
  47235. /* Multiply p* in projective co-ordinates by q*.
  47236. *
  47237. * r.x = p.x - (p.y * q.y)
  47238. * r.y = (p.x * q.y) + p.y
  47239. *
  47240. * px [in,out] A single precision integer - X ordinate of number to multiply.
  47241. * py [in,out] A single precision integer - Y ordinate of number to multiply.
  47242. * q [in] A single precision integer - multiplier.
  47243. * t [in] Two single precision integers - temps.
  47244. */
  47245. static void sp_1024_proj_mul_qx1_42(sp_digit* px, sp_digit* py,
  47246. const sp_digit* q, sp_digit* t)
  47247. {
  47248. sp_digit* t1 = t;
  47249. sp_digit* t2 = t + 2 * 42;
  47250. /* t1 = p.x * q.y */
  47251. sp_1024_mont_mul_42(t1, px, q, p1024_mod, p1024_mp_mod);
  47252. /* t2 = p.y * q.y */
  47253. sp_1024_mont_mul_42(t2, py, q, p1024_mod, p1024_mp_mod);
  47254. /* r.x = p.x - (p.y * q.y) */
  47255. sp_1024_mont_sub_42(px, px, t2, p1024_mod);
  47256. /* r.y = (p.x * q.y) + p.y */
  47257. sp_1024_mont_add_42(py, t1, py, p1024_mod);
  47258. }
  47259. /* Square p* in projective co-ordinates.
  47260. *
  47261. * px' = (p.x + p.y) * (p.x - p.y) = p.x^2 - p.y^2
  47262. * py' = 2 * p.x * p.y
  47263. *
  47264. * px [in,out] A single precision integer - X ordinate of number to square.
  47265. * py [in,out] A single precision integer - Y ordinate of number to square.
  47266. * t [in] Two single precision integers - temps.
  47267. */
  47268. static void sp_1024_proj_sqr_42(sp_digit* px, sp_digit* py, sp_digit* t)
  47269. {
  47270. sp_digit* t1 = t;
  47271. sp_digit* t2 = t + 2 * 42;
  47272. /* t1 = p.x + p.y */
  47273. sp_1024_mont_add_42(t1, px, py, p1024_mod);
  47274. /* t2 = p.x - p.y */
  47275. sp_1024_mont_sub_42(t2, px, py, p1024_mod);
  47276. /* r.y = p.x * p.y */
  47277. sp_1024_mont_mul_42(py, px, py, p1024_mod, p1024_mp_mod);
  47278. /* r.x = (p.x + p.y) * (p.x - p.y) */
  47279. sp_1024_mont_mul_42(px, t1, t2, p1024_mod, p1024_mp_mod);
  47280. /* r.y = (p.x * p.y) * 2 */
  47281. sp_1024_mont_dbl_42(py, py, p1024_mod);
  47282. }
  47283. #ifdef WOLFSSL_SP_SMALL
  47284. /* Perform the modular exponentiation in Fp* for SAKKE.
  47285. *
  47286. * Simple square and multiply when expontent bit is one algorithm.
  47287. * Square and multiply performed in Fp*.
  47288. *
  47289. * base [in] Base. MP integer.
  47290. * exp [in] Exponent. MP integer.
  47291. * res [out] Result. MP integer.
  47292. * returns 0 on success and MEMORY_E if memory allocation fails.
  47293. */
  47294. int sp_ModExp_Fp_star_1024(const mp_int* base, mp_int* exp, mp_int* res)
  47295. {
  47296. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  47297. !defined(WOLFSSL_SP_NO_MALLOC)
  47298. sp_digit* td;
  47299. sp_digit* t;
  47300. sp_digit* tx;
  47301. sp_digit* ty;
  47302. sp_digit* b;
  47303. sp_digit* e;
  47304. #else
  47305. sp_digit t[4 * 2 * 42];
  47306. sp_digit tx[2 * 42];
  47307. sp_digit ty[2 * 42];
  47308. sp_digit b[2 * 42];
  47309. sp_digit e[2 * 42];
  47310. #endif
  47311. sp_digit* r;
  47312. int err = MP_OKAY;
  47313. int bits;
  47314. int i;
  47315. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  47316. !defined(WOLFSSL_SP_NO_MALLOC)
  47317. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 42 * 2, NULL,
  47318. DYNAMIC_TYPE_TMP_BUFFER);
  47319. if (td == NULL) {
  47320. err = MEMORY_E;
  47321. }
  47322. #endif
  47323. if (err == MP_OKAY) {
  47324. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  47325. !defined(WOLFSSL_SP_NO_MALLOC)
  47326. t = td;
  47327. tx = td + 4 * 42 * 2;
  47328. ty = td + 5 * 42 * 2;
  47329. b = td + 6 * 42 * 2;
  47330. e = td + 7 * 42 * 2;
  47331. #endif
  47332. r = ty;
  47333. bits = mp_count_bits(exp);
  47334. sp_1024_from_mp(b, 42, base);
  47335. sp_1024_from_mp(e, 42, exp);
  47336. XMEMCPY(tx, p1024_norm_mod, sizeof(sp_digit) * 42);
  47337. sp_1024_mul_42(b, b, p1024_norm_mod);
  47338. err = sp_1024_mod_42(b, b, p1024_mod);
  47339. }
  47340. if (err == MP_OKAY) {
  47341. XMEMCPY(ty, b, sizeof(sp_digit) * 42);
  47342. for (i = bits - 2; i >= 0; i--) {
  47343. sp_1024_proj_sqr_42(tx, ty, t);
  47344. if ((e[i / 25] >> (i % 25)) & 1) {
  47345. sp_1024_proj_mul_qx1_42(tx, ty, b, t);
  47346. }
  47347. }
  47348. }
  47349. if (err == MP_OKAY) {
  47350. sp_1024_mont_inv_42(tx, tx, t);
  47351. XMEMSET(tx + 42, 0, sizeof(sp_digit) * 42);
  47352. sp_1024_mont_reduce_42(tx, p1024_mod, p1024_mp_mod);
  47353. XMEMSET(ty + 42, 0, sizeof(sp_digit) * 42);
  47354. sp_1024_mont_reduce_42(ty, p1024_mod, p1024_mp_mod);
  47355. sp_1024_mul_42(r, tx, ty);
  47356. err = sp_1024_mod_42(r, r, p1024_mod);
  47357. }
  47358. if (err == MP_OKAY) {
  47359. err = sp_1024_to_mp(r, res);
  47360. }
  47361. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  47362. !defined(WOLFSSL_SP_NO_MALLOC)
  47363. if (td != NULL) {
  47364. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  47365. }
  47366. #endif
  47367. return err;
  47368. }
  47369. #else
  47370. /* Pre-computed table for exponentiating g.
  47371. * Striping: 8 points at a distance of (128 combined for
  47372. * a total of 256 points.
  47373. */
  47374. static const sp_digit sp_1024_g_table[256][42] = {
  47375. { 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000,
  47376. 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000,
  47377. 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000,
  47378. 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000,
  47379. 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000,
  47380. 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000,
  47381. 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000 },
  47382. { 0x15c1685, 0x1236919, 0x09605c2, 0x03c200f, 0x0ac9e97, 0x052539f,
  47383. 0x1cf7d0f, 0x0ea81d1, 0x1826424, 0x1237c0a, 0x15db449, 0x176966c,
  47384. 0x1b3af49, 0x195f8d7, 0x078b451, 0x0a3cdb1, 0x02c2fd1, 0x013df44,
  47385. 0x1e21c5f, 0x1db90b1, 0x0c6fadd, 0x1f8b563, 0x15b6166, 0x11d5cb1,
  47386. 0x01a1b2d, 0x186873a, 0x018707c, 0x1f5ef40, 0x07e0966, 0x084d4db,
  47387. 0x1f59b6f, 0x0fa769e, 0x1f11c06, 0x1e4c710, 0x080b1c9, 0x02c2a57,
  47388. 0x086cb22, 0x0ac448f, 0x0ebd2bf, 0x0d4d7a7, 0x059e93c },
  47389. { 0x1dd4594, 0x0e9b7b8, 0x079b953, 0x1e015de, 0x1bc9cc9, 0x0fb2985,
  47390. 0x0913a86, 0x0513d4b, 0x13f5209, 0x0c4554c, 0x1050621, 0x12991eb,
  47391. 0x1a97537, 0x0089ccf, 0x02f5e4b, 0x0d56a23, 0x0fdf5cb, 0x15cde9d,
  47392. 0x1b2e594, 0x1a39645, 0x1813813, 0x13a01c4, 0x1f51589, 0x1908639,
  47393. 0x1119b4a, 0x15b28fb, 0x0428603, 0x1b3ed52, 0x1bfa2ed, 0x168bcfb,
  47394. 0x1644e51, 0x0a153a1, 0x0f18631, 0x1b9e98b, 0x0835be0, 0x12be338,
  47395. 0x1b6a52b, 0x02d6354, 0x0b80efa, 0x0f6e9ec, 0x063ef18 },
  47396. { 0x16f45e7, 0x1b5bf80, 0x0be1f0d, 0x0e57d90, 0x1c1bdb5, 0x014db00,
  47397. 0x1dd0739, 0x03ae725, 0x0c7afd8, 0x1edf851, 0x04262db, 0x163ee48,
  47398. 0x0fbda41, 0x1db07c6, 0x101d1d2, 0x1789ab6, 0x141b330, 0x1499f06,
  47399. 0x0cfe8ef, 0x105060e, 0x0cd1ae1, 0x0d87ae3, 0x083b4a6, 0x130c191,
  47400. 0x1354e3f, 0x020bff9, 0x1855567, 0x026c130, 0x1f85cbb, 0x1b1e094,
  47401. 0x0faac32, 0x08ed0bf, 0x02ecc49, 0x0cb19b4, 0x1b0bac6, 0x14a0bd1,
  47402. 0x1dac2cd, 0x0e63ca6, 0x1688e43, 0x039e325, 0x04fe679 },
  47403. { 0x1e8733c, 0x011ea82, 0x1f06529, 0x0a3aae2, 0x0c845e6, 0x10d9916,
  47404. 0x1fa23a5, 0x19846f8, 0x0db4181, 0x02238e3, 0x0f5c843, 0x0bc4e27,
  47405. 0x0900c87, 0x1960bd8, 0x1f7a7b6, 0x1d5ed3b, 0x1e5e88c, 0x1218536,
  47406. 0x0e073a9, 0x0f4c34f, 0x18d5aaa, 0x13119fc, 0x1a94b40, 0x0d13535,
  47407. 0x0fdd060, 0x155daaf, 0x1972b12, 0x019f4f9, 0x1507613, 0x188a474,
  47408. 0x14be936, 0x09d343c, 0x09570c4, 0x000b818, 0x1d84681, 0x0431843,
  47409. 0x1e78d9d, 0x0e8fff5, 0x0ca5d55, 0x030ac3b, 0x004482a },
  47410. { 0x1d486d8, 0x0c56139, 0x079f9dd, 0x0cc39b8, 0x0169f94, 0x0455a7c,
  47411. 0x067f086, 0x060e479, 0x0f33736, 0x072a781, 0x1089828, 0x1c4b7b1,
  47412. 0x00560be, 0x0298de3, 0x1f0c1f1, 0x1fd6a51, 0x11a7e44, 0x1eb790f,
  47413. 0x1c4a34d, 0x089338a, 0x0a45c8e, 0x1f6bd97, 0x058ec14, 0x147a445,
  47414. 0x07a0432, 0x1342061, 0x14d5165, 0x16a30a9, 0x1557e95, 0x124feb9,
  47415. 0x1e99b86, 0x10d240e, 0x1267fd9, 0x0138106, 0x034f9cd, 0x09f426a,
  47416. 0x08ccdb4, 0x0e1f92b, 0x1e27c6a, 0x1f1bdb7, 0x0833a0f },
  47417. { 0x1376b76, 0x00ce3d5, 0x0332a31, 0x064fa1e, 0x1b7294f, 0x0628a69,
  47418. 0x0e78aa4, 0x14dcad7, 0x0a62575, 0x18dd28f, 0x102a224, 0x00f6131,
  47419. 0x0a56fee, 0x1a60b51, 0x0f96bba, 0x04c1609, 0x10be6eb, 0x072899a,
  47420. 0x075709c, 0x1db5ad4, 0x0dd1339, 0x0cf4edd, 0x1cd9bb5, 0x1a0dd81,
  47421. 0x1be882d, 0x1eda109, 0x032c461, 0x05ac739, 0x01058a2, 0x0af0ec5,
  47422. 0x1c47fb2, 0x1456e89, 0x1f73ea6, 0x02e0601, 0x146bd3c, 0x00e83fa,
  47423. 0x05f811a, 0x16fcad4, 0x0597cb8, 0x1c7d649, 0x0692b3c },
  47424. { 0x0a127b4, 0x165b969, 0x05bc339, 0x0b1f250, 0x06a46ea, 0x11bb0b3,
  47425. 0x1d18d1e, 0x1dc87d9, 0x1e0ab96, 0x11ecd00, 0x16fa305, 0x18db65d,
  47426. 0x05c8145, 0x06f2733, 0x109b2b9, 0x0a5f25e, 0x14074e2, 0x08ba685,
  47427. 0x14abe0c, 0x0481aef, 0x093654c, 0x0b9eb29, 0x1607e8e, 0x13a8d2a,
  47428. 0x1491ca0, 0x01e02dc, 0x0d51499, 0x189d0a6, 0x1283278, 0x0198ea0,
  47429. 0x094cb59, 0x0e06c3e, 0x0479038, 0x184f932, 0x06c627b, 0x00ee832,
  47430. 0x01de5fe, 0x078557c, 0x10b5b03, 0x015e800, 0x0333e43 },
  47431. { 0x126d3b7, 0x026f267, 0x06f977c, 0x0d6a7ef, 0x17a7730, 0x045b322,
  47432. 0x0f17c60, 0x0c14802, 0x0850373, 0x1948f52, 0x1840dfb, 0x1afa160,
  47433. 0x1b1ffc9, 0x12e489d, 0x1413765, 0x10b0fb3, 0x1aff13b, 0x0ca451b,
  47434. 0x18fb9d5, 0x086907f, 0x1386b54, 0x1a02318, 0x0ff0879, 0x1bd6b18,
  47435. 0x104e5cd, 0x0a959d0, 0x0995cb3, 0x09fc30c, 0x0aa4089, 0x18d08ad,
  47436. 0x18bae69, 0x08b3d48, 0x0dc6fe5, 0x18151c5, 0x05d52ba, 0x037631a,
  47437. 0x0f7791d, 0x093b1b1, 0x15c22b8, 0x03bad77, 0x010e8b3 },
  47438. { 0x0d9f1af, 0x181f29f, 0x059ae1f, 0x0eaccec, 0x03ad247, 0x070adc0,
  47439. 0x158c1d3, 0x0b671b9, 0x026b1e8, 0x03bf158, 0x0670546, 0x1a2e35f,
  47440. 0x1ab1654, 0x09c12a3, 0x00ba792, 0x0bdeb2f, 0x07c26d5, 0x036e3fe,
  47441. 0x1efad53, 0x11f2ba5, 0x0357903, 0x1f01b60, 0x1f96437, 0x1b87eff,
  47442. 0x16eae4f, 0x14467e5, 0x13cd786, 0x163f78a, 0x0a5568c, 0x0ed96d0,
  47443. 0x15cf238, 0x0b6deaa, 0x087393f, 0x005034d, 0x0ccb9eb, 0x1670c8d,
  47444. 0x0a8495a, 0x130e419, 0x112f3f4, 0x09819b9, 0x0648552 },
  47445. { 0x0a6ff2a, 0x1d9f162, 0x0a286af, 0x146b4c8, 0x0aa03fb, 0x17fba11,
  47446. 0x09fc226, 0x1271084, 0x0ba5dbd, 0x19bc41d, 0x060b2c8, 0x15d3a54,
  47447. 0x0538186, 0x04d00f8, 0x1c1d935, 0x03cf573, 0x1eb917b, 0x1c9208f,
  47448. 0x1c32ed6, 0x163206a, 0x1e7c700, 0x0adc8a5, 0x1754607, 0x102305a,
  47449. 0x0443719, 0x0cb89ae, 0x115d2e6, 0x04eb1a4, 0x0d28b23, 0x147ab19,
  47450. 0x0269942, 0x1f4707e, 0x0078bac, 0x19ec012, 0x1830028, 0x12ca8d4,
  47451. 0x0df8b44, 0x030e3d1, 0x158f290, 0x1e5e468, 0x01f76f3 },
  47452. { 0x0c436b0, 0x160a1a2, 0x01ea6a8, 0x0c3ed39, 0x1907055, 0x16d96fb,
  47453. 0x045ed7d, 0x1046be6, 0x1ed56ba, 0x0bb0fa0, 0x0be9221, 0x0c9efa1,
  47454. 0x1ef8314, 0x1d6e738, 0x07ca454, 0x0e91153, 0x093116b, 0x1593dfb,
  47455. 0x0ee510e, 0x14b5193, 0x1de8a98, 0x131772f, 0x1fe1e00, 0x025596e,
  47456. 0x193dd18, 0x0491d37, 0x137212f, 0x1f25499, 0x14995aa, 0x1157f8e,
  47457. 0x074f095, 0x009db13, 0x19fc33c, 0x1529c7e, 0x0a513b4, 0x0d80519,
  47458. 0x049ea72, 0x19b3dd8, 0x0381743, 0x1f67a21, 0x004924f },
  47459. { 0x073562f, 0x0471ee3, 0x1230195, 0x0bc5d5c, 0x13b3302, 0x0e34bbe,
  47460. 0x14cad78, 0x0f7cc3f, 0x06ebe55, 0x1271032, 0x1b86390, 0x038083a,
  47461. 0x1b76739, 0x0a6bf4a, 0x03aee38, 0x0371897, 0x1d42099, 0x1a5745b,
  47462. 0x004a434, 0x01becdc, 0x1f4ef8a, 0x11c92f2, 0x125f892, 0x0104e55,
  47463. 0x1b2cb15, 0x130bcd3, 0x18941c9, 0x08160e5, 0x02fa49b, 0x10c1483,
  47464. 0x13b6b67, 0x1e78a77, 0x180a784, 0x013ccc3, 0x0dda7c5, 0x0cb1505,
  47465. 0x0146842, 0x06c24e6, 0x0b8d423, 0x0138701, 0x04dfce8 },
  47466. { 0x127b780, 0x14e596a, 0x0375141, 0x0b2ef26, 0x152da01, 0x1e8131e,
  47467. 0x1802f89, 0x0562198, 0x0bb2d1b, 0x0081613, 0x0b7cf0d, 0x0c46aa9,
  47468. 0x074c652, 0x02f87fa, 0x0244e09, 0x0dcf9ad, 0x0c5ca91, 0x141fd46,
  47469. 0x0572362, 0x01e273a, 0x16b31e1, 0x1740ee2, 0x1c5cf70, 0x09db375,
  47470. 0x0cb045c, 0x1143fe7, 0x011f404, 0x00ffafb, 0x1a532f3, 0x18a9cf9,
  47471. 0x0889295, 0x1c42a78, 0x1e9e81d, 0x052042c, 0x057790a, 0x078ac4b,
  47472. 0x1339bd2, 0x1ed7fc4, 0x1a00b71, 0x0117140, 0x00d0759 },
  47473. { 0x0085f2a, 0x17953ef, 0x0b961c2, 0x1f7d336, 0x08fcd24, 0x05209dc,
  47474. 0x1498567, 0x0a31181, 0x08559f8, 0x1815172, 0x0b68347, 0x0043ec4,
  47475. 0x1583b96, 0x16e51b0, 0x0170bd5, 0x18d04b8, 0x11c7910, 0x100a467,
  47476. 0x1c9a56f, 0x1e512c4, 0x0ef6392, 0x1ad46b2, 0x020f42e, 0x1f978a5,
  47477. 0x122441c, 0x1f2f786, 0x1149845, 0x0bb5f9d, 0x0928e9f, 0x095cf82,
  47478. 0x0aada18, 0x0727e5c, 0x03f744d, 0x008a894, 0x1fb5c03, 0x1df7dda,
  47479. 0x04360df, 0x06f10ad, 0x14d6bcb, 0x0385e10, 0x024fa96 },
  47480. { 0x16df7f6, 0x1ed9fb0, 0x0c981d9, 0x11f7b20, 0x043057d, 0x016aa23,
  47481. 0x0aa41ba, 0x1b62e9b, 0x1689643, 0x14279a2, 0x0681808, 0x03bf991,
  47482. 0x1218b19, 0x0b613e8, 0x0d1abd3, 0x0a28b75, 0x086c989, 0x12d2bfa,
  47483. 0x1250be7, 0x0429d39, 0x0158c03, 0x07a0ca8, 0x09cf872, 0x15a8756,
  47484. 0x1759f39, 0x0b9c675, 0x1f943b8, 0x1c3716f, 0x0d7d4e5, 0x18fe47a,
  47485. 0x1cfd8d6, 0x0eaac07, 0x0ff77e3, 0x17d3047, 0x0745dd4, 0x02403ec,
  47486. 0x0a6fb6e, 0x0bd01ea, 0x0045253, 0x07bf89e, 0x0371cc2 },
  47487. { 0x090c351, 0x188aeed, 0x1018a26, 0x1e6c9b3, 0x0d196eb, 0x08598db,
  47488. 0x0480bd9, 0x05eef51, 0x06f5764, 0x01460b2, 0x00049f3, 0x1c6c102,
  47489. 0x1bdc4f7, 0x0e26403, 0x0db3423, 0x081e510, 0x156e002, 0x1894078,
  47490. 0x072ce54, 0x14daf13, 0x00383f9, 0x099d401, 0x1029253, 0x0fa68e8,
  47491. 0x17e91e8, 0x12522b4, 0x1c9b778, 0x01b2fa0, 0x00c30e7, 0x12c6bb2,
  47492. 0x1181bda, 0x0b74dcd, 0x1c2c0e8, 0x009f401, 0x09ebc6f, 0x1e661ed,
  47493. 0x09f4d78, 0x101727e, 0x1edfcf9, 0x1401901, 0x092b6bc },
  47494. { 0x100822e, 0x0ae41af, 0x1c48b8f, 0x057162d, 0x0e82571, 0x1851980,
  47495. 0x0a7124a, 0x0a90386, 0x1a7cc19, 0x1a71956, 0x0504fda, 0x19dc376,
  47496. 0x070bee9, 0x0549651, 0x1edeea9, 0x122a7db, 0x0faea3b, 0x0e6a395,
  47497. 0x03c303e, 0x013cfc0, 0x1b70e8f, 0x192e6f5, 0x0938761, 0x136c76d,
  47498. 0x1ae084a, 0x1b2ff15, 0x00ff563, 0x0802837, 0x162759f, 0x0f6d51d,
  47499. 0x0235fb1, 0x0f21c61, 0x0af6e67, 0x1bf18cd, 0x00c07c9, 0x1842b5b,
  47500. 0x0f33871, 0x0da5cc6, 0x1e2779f, 0x1929e05, 0x071ff62 },
  47501. { 0x04a84d9, 0x0388115, 0x079aa93, 0x1abd78e, 0x02ee4ac, 0x06b2bc7,
  47502. 0x0a297c7, 0x14a7623, 0x1fff120, 0x1faf7cf, 0x1940ce0, 0x11c213c,
  47503. 0x00a4c59, 0x050220c, 0x1a7e643, 0x05183c3, 0x146f598, 0x1c5c196,
  47504. 0x0ebd4da, 0x1e51406, 0x168a753, 0x18db6a7, 0x04bb712, 0x199a3e1,
  47505. 0x0692a72, 0x01976ef, 0x1748899, 0x07541ef, 0x12661cd, 0x1b1f51e,
  47506. 0x168e36e, 0x1fb86fb, 0x1e19fc6, 0x1b5a678, 0x0d4213b, 0x12d8316,
  47507. 0x1f1bba6, 0x141ff4e, 0x009cf9a, 0x1cebf2b, 0x040fd47 },
  47508. { 0x07140a4, 0x05ba313, 0x0bed6e2, 0x1dd56de, 0x0dbbfc1, 0x0312a43,
  47509. 0x12239a6, 0x185bb3d, 0x12eb6ef, 0x0df75d0, 0x03fe21a, 0x0295159,
  47510. 0x10cfc22, 0x1ad10ca, 0x15725ba, 0x1f6d32b, 0x0054171, 0x1c99c4e,
  47511. 0x0d1a0cd, 0x0ba8a43, 0x025c2d8, 0x042089a, 0x0535a28, 0x0d842e8,
  47512. 0x00139ec, 0x026f296, 0x1fdcc02, 0x019e172, 0x178aa32, 0x15130fa,
  47513. 0x10c6b05, 0x1f36d5c, 0x0b9fab3, 0x0534a8c, 0x0447615, 0x0cd1b04,
  47514. 0x1ffbe28, 0x19a6cc6, 0x0ce302c, 0x0afcc72, 0x05b1c11 },
  47515. { 0x0b6bb8f, 0x0d558b9, 0x0b0a43b, 0x0405f92, 0x0dc64ed, 0x14a639c,
  47516. 0x08f17f9, 0x1c9e857, 0x1cb54dc, 0x0b6e32f, 0x108370c, 0x0d46c64,
  47517. 0x14cb2d6, 0x02b6e7c, 0x19c1b9c, 0x0593a2d, 0x164a4f3, 0x01404e3,
  47518. 0x09bb72a, 0x11b061d, 0x1f57ab1, 0x1340e32, 0x13f46b3, 0x1425820,
  47519. 0x1651c7d, 0x1240fc8, 0x1b1de46, 0x15877ac, 0x1e67a30, 0x0e7a3c2,
  47520. 0x046dab4, 0x1b41fab, 0x0d3fc44, 0x031a272, 0x0005b87, 0x079c2c9,
  47521. 0x13e50ab, 0x0f4e5c1, 0x1bbd213, 0x0754ead, 0x0963ab8 },
  47522. { 0x14ea5a3, 0x1a3ec6f, 0x17fa512, 0x0ab9fc8, 0x1656881, 0x1e1ab24,
  47523. 0x1f56228, 0x02ba2dc, 0x0e7c99e, 0x072ad9f, 0x01c6f21, 0x009beaa,
  47524. 0x0e3fee2, 0x0202bee, 0x001bca4, 0x0aae0e2, 0x10dbba7, 0x07f461c,
  47525. 0x0c66b6b, 0x0b796c6, 0x1fd8364, 0x183e105, 0x00627a2, 0x0fb2af1,
  47526. 0x109697d, 0x11dc72a, 0x06e67d3, 0x06fa264, 0x0cfb6a0, 0x1290d30,
  47527. 0x168046c, 0x106e705, 0x0594aaa, 0x0ee03b3, 0x07f60f0, 0x0991372,
  47528. 0x076b988, 0x015c4c8, 0x11561ae, 0x1f97c8b, 0x0443480 },
  47529. { 0x114221a, 0x1ffda48, 0x09ebe3f, 0x1c7d0af, 0x0aec4f2, 0x12a3c3a,
  47530. 0x143903e, 0x0a485c5, 0x1d6f961, 0x19f3598, 0x1a6ddfb, 0x0a6ff7f,
  47531. 0x0ab2296, 0x1da1d43, 0x0a743cb, 0x0558d85, 0x0ed2457, 0x1920942,
  47532. 0x1c86e9e, 0x0d122fc, 0x078da38, 0x00608bd, 0x16fbdf0, 0x02c0b59,
  47533. 0x09071d3, 0x1749c0a, 0x18196a3, 0x05b5b53, 0x02be82c, 0x1c6c622,
  47534. 0x16356c4, 0x1edae56, 0x16c224b, 0x01f36cd, 0x173e3ac, 0x0373a6a,
  47535. 0x0170037, 0x168f585, 0x09faead, 0x1119ff5, 0x097118a },
  47536. { 0x1ecb5d8, 0x02cd166, 0x019afe7, 0x175274d, 0x0083c81, 0x1ba7dfc,
  47537. 0x1760411, 0x16849c1, 0x0a02070, 0x1bcd1e5, 0x1ede079, 0x1f761f7,
  47538. 0x049d352, 0x1f7950e, 0x0c36080, 0x1ca0351, 0x17b14b3, 0x15c2c31,
  47539. 0x0a20bfc, 0x0e14931, 0x0fa55ba, 0x019d837, 0x089cc02, 0x05fdc55,
  47540. 0x002f410, 0x1d2d216, 0x0628088, 0x09cec53, 0x03fc72e, 0x1d1342e,
  47541. 0x19f6e8a, 0x1fca5d5, 0x14fe763, 0x1a2fb2a, 0x01689c3, 0x18616a8,
  47542. 0x0573387, 0x150bbd5, 0x1ea0b55, 0x11a96e3, 0x017c077 },
  47543. { 0x135e37b, 0x0ff8e93, 0x15c839b, 0x0ccadd8, 0x09884e5, 0x1dd4bc6,
  47544. 0x0b2767a, 0x18945eb, 0x0ba09f3, 0x07d228c, 0x010ddd0, 0x02efeb6,
  47545. 0x0a8c3fa, 0x0b3d176, 0x0877b36, 0x17a8143, 0x0700528, 0x13b45e5,
  47546. 0x01a4712, 0x092a563, 0x1fd5f22, 0x02f436a, 0x05b84b1, 0x10b34d4,
  47547. 0x1915737, 0x1073d06, 0x0683ff3, 0x047e861, 0x0cc9a37, 0x1bcdd4b,
  47548. 0x0e16a36, 0x035a474, 0x1d12ae0, 0x1aec236, 0x0e878af, 0x0d3ffd8,
  47549. 0x0452ed6, 0x074270d, 0x1931b5b, 0x190ae3f, 0x01219d5 },
  47550. { 0x02969eb, 0x1533f93, 0x1dcd0fa, 0x1a5e07c, 0x1a3ab39, 0x1d84849,
  47551. 0x1f9455e, 0x0e9cc24, 0x18d1502, 0x1c15876, 0x02f6f43, 0x15b1cb0,
  47552. 0x0bffffc, 0x14ba1f3, 0x14f41d6, 0x023aca3, 0x1b18bac, 0x00a425e,
  47553. 0x0c930e2, 0x1b3321d, 0x07c695c, 0x083fd63, 0x085a987, 0x09cd70e,
  47554. 0x0f762a0, 0x0642184, 0x072e95f, 0x10cbbac, 0x14a07a2, 0x1586e91,
  47555. 0x1e4f0a5, 0x0740f27, 0x0f92839, 0x14f673b, 0x187c2f8, 0x04e16af,
  47556. 0x1e626f4, 0x0a5417b, 0x1c8c04c, 0x165acaf, 0x02c8d7a },
  47557. { 0x025e4d6, 0x1ac4904, 0x0d119f3, 0x0addf07, 0x1f51eaa, 0x080846e,
  47558. 0x197604c, 0x07ec7cc, 0x18dd096, 0x14fc4fa, 0x190da88, 0x09bb3be,
  47559. 0x078c4b1, 0x0a2f5dd, 0x16b91a7, 0x1e70333, 0x1775a4d, 0x188c555,
  47560. 0x078dffa, 0x12f17a5, 0x17efda8, 0x1556516, 0x1a73b56, 0x0fad514,
  47561. 0x0d05dc6, 0x11a364c, 0x15dfe12, 0x08e97e1, 0x0cd59a7, 0x059776c,
  47562. 0x1ef510a, 0x1a3a731, 0x0fd1cd5, 0x10588d8, 0x0f6e528, 0x08b2c02,
  47563. 0x1b404c4, 0x15b82d0, 0x165625b, 0x0ee9613, 0x02299d2 },
  47564. { 0x04397e6, 0x06ac6e3, 0x0c796e7, 0x1d7edba, 0x0c198f1, 0x0f8ed95,
  47565. 0x16384fa, 0x118b0cd, 0x18fcdc6, 0x02d7143, 0x1007f50, 0x019bca7,
  47566. 0x16a4b28, 0x008edaf, 0x058fcb5, 0x1f141b9, 0x189bec4, 0x1f6aea8,
  47567. 0x05bba62, 0x1fa27b2, 0x148e336, 0x198216f, 0x1a496c6, 0x1c00e9c,
  47568. 0x16291ac, 0x14a867a, 0x0094c5f, 0x11a7169, 0x1c446be, 0x0e95c10,
  47569. 0x0d31eb4, 0x1e16cb2, 0x1c44135, 0x106a838, 0x0dbd4b2, 0x0d2e36e,
  47570. 0x07b46c2, 0x0ffd2b9, 0x1863abe, 0x0f2326c, 0x021ac67 },
  47571. { 0x17fbcd2, 0x1071f96, 0x1062ad0, 0x072f7bf, 0x1272247, 0x1aea5a0,
  47572. 0x0cfe137, 0x1a69240, 0x03807b7, 0x1e6a11b, 0x10d895b, 0x1613667,
  47573. 0x14dfc19, 0x1079140, 0x15bcdd6, 0x0337027, 0x059037c, 0x0384bc5,
  47574. 0x1fc9ee7, 0x13132e1, 0x03894f3, 0x02b0ad2, 0x1f03869, 0x0c05ee9,
  47575. 0x1496a3e, 0x10e7fd1, 0x06c9872, 0x07e3886, 0x0164cdc, 0x08edf70,
  47576. 0x07d8488, 0x1cfef7d, 0x0463ee4, 0x170dd98, 0x19e24b0, 0x0c02bef,
  47577. 0x04483a5, 0x1ec46b1, 0x1676198, 0x1ce1cc5, 0x00e8ec1 },
  47578. { 0x00878dd, 0x06614c5, 0x1c6aa23, 0x1acc800, 0x19ac175, 0x0b9b0bc,
  47579. 0x1208294, 0x02b2068, 0x0dd58a3, 0x0b6811f, 0x088684c, 0x17a911a,
  47580. 0x0330785, 0x0ace247, 0x12cf79e, 0x14ee36e, 0x1824c67, 0x1a17701,
  47581. 0x02e4514, 0x1ed9bbc, 0x1e9159e, 0x144d91b, 0x1e0c2b8, 0x0bb064a,
  47582. 0x07a4c49, 0x13370c2, 0x1b41dcd, 0x0f6242f, 0x14a3256, 0x1643514,
  47583. 0x0996064, 0x10c9b06, 0x0aa0f56, 0x09f2dbb, 0x144bd2c, 0x1bc5457,
  47584. 0x1b6b73f, 0x0860e00, 0x0d8d761, 0x0beba20, 0x0653a79 },
  47585. { 0x0dcb199, 0x144c2a8, 0x0d833f8, 0x1cff405, 0x135b8e5, 0x1b01e85,
  47586. 0x15f0f25, 0x16b794f, 0x127f131, 0x0729446, 0x04b54ac, 0x09bdc56,
  47587. 0x073aa70, 0x0edb92e, 0x01ac760, 0x16227c4, 0x19ac5d1, 0x1858941,
  47588. 0x0d175d8, 0x12e197b, 0x1e8e14f, 0x1f59092, 0x1265fe4, 0x0fb544d,
  47589. 0x1739cee, 0x074deba, 0x1c7fbc8, 0x0dd97a7, 0x0a42b14, 0x108a3e3,
  47590. 0x147e652, 0x04ff61f, 0x089eb4f, 0x06d25e9, 0x14c6690, 0x0c2230d,
  47591. 0x1b9d797, 0x1fb2d2f, 0x19d7820, 0x0f7a888, 0x030dfc4 },
  47592. { 0x0aadfe8, 0x02d714f, 0x004af3f, 0x0969a9d, 0x05027e5, 0x099ab09,
  47593. 0x00b7e2d, 0x029560e, 0x056a6a2, 0x15ce102, 0x041a3a8, 0x1ef460b,
  47594. 0x0fb1a3d, 0x0c41888, 0x1452c86, 0x11c3946, 0x136c4b7, 0x05bdf11,
  47595. 0x18bda61, 0x0e79cc7, 0x1ac6170, 0x1316efb, 0x01b8452, 0x1af8791,
  47596. 0x192bf07, 0x14493b0, 0x0fac6b8, 0x1b4d3c1, 0x1849395, 0x18ba928,
  47597. 0x08260eb, 0x080f475, 0x0c52a4d, 0x1f10c4d, 0x1f6ab83, 0x022a6b8,
  47598. 0x197f250, 0x17f4391, 0x04b3f85, 0x03ea984, 0x0572a59 },
  47599. { 0x1a5553a, 0x1420c84, 0x0ef1259, 0x1064ee6, 0x1f05431, 0x17eb481,
  47600. 0x0d2c8fb, 0x1a9f39d, 0x1f22126, 0x09e5fcd, 0x1655e2f, 0x03805fd,
  47601. 0x186d967, 0x0501836, 0x0965f3b, 0x09fcb77, 0x1613d67, 0x15b82f6,
  47602. 0x1fccfdd, 0x06c456c, 0x0c31f1d, 0x0308e5c, 0x056f3cf, 0x07a3552,
  47603. 0x067dce5, 0x1a1d1c2, 0x07e422a, 0x005fd25, 0x15767a9, 0x04cec68,
  47604. 0x1edb8f9, 0x1215fa0, 0x142db5c, 0x18c8740, 0x1ef1b22, 0x1c2418d,
  47605. 0x04919a4, 0x0432a99, 0x0b0f203, 0x1c3b190, 0x065c2cb },
  47606. { 0x060bb63, 0x06d1053, 0x0915a13, 0x150dd0c, 0x07dc3b0, 0x10776b9,
  47607. 0x0b3d9ae, 0x0b0ec8e, 0x1679dd1, 0x0e0b172, 0x14b511e, 0x04ee108,
  47608. 0x1eb6884, 0x009fabc, 0x06f1acd, 0x02ee105, 0x1ec9501, 0x1c9750a,
  47609. 0x1dce060, 0x09c6008, 0x12f15e3, 0x04b9f0e, 0x030f28d, 0x137a7bd,
  47610. 0x0f1dc22, 0x169d2e2, 0x0e53bdf, 0x107dfe3, 0x0e7a1a7, 0x19c6efd,
  47611. 0x1491b6d, 0x0341330, 0x153d72e, 0x07a55a1, 0x1562837, 0x124a675,
  47612. 0x0e7888b, 0x02a80b0, 0x1fd9b60, 0x1aa774e, 0x0831440 },
  47613. { 0x011b2da, 0x117197b, 0x1ab3d0f, 0x13a1f48, 0x1d066e2, 0x059e06a,
  47614. 0x1cfa208, 0x1e1d12f, 0x01d3e44, 0x02e1473, 0x09e99b1, 0x1ecdbfa,
  47615. 0x17929d7, 0x080f428, 0x16e1828, 0x0f1bae6, 0x0983de0, 0x1751fe7,
  47616. 0x0e33846, 0x0efb6ac, 0x0b3bc99, 0x17a429b, 0x01220e0, 0x195bf8c,
  47617. 0x07a3c64, 0x1b8bf06, 0x1e0851e, 0x19a2fef, 0x011e3e3, 0x11e60da,
  47618. 0x1b7a559, 0x130bf68, 0x139ac8f, 0x08ce52b, 0x0736f3c, 0x0a70a73,
  47619. 0x015a281, 0x0c2d387, 0x115992a, 0x114dabe, 0x0504c3a },
  47620. { 0x0fa53c7, 0x0a941dc, 0x138c02d, 0x10a128e, 0x185cff3, 0x1e712fc,
  47621. 0x090710d, 0x1da469a, 0x0e5a129, 0x0c19218, 0x1319d0a, 0x12ad557,
  47622. 0x016ad38, 0x1f740f7, 0x1700075, 0x04e0545, 0x0b6670b, 0x1a611e3,
  47623. 0x1ba28ee, 0x1cacfd4, 0x13eab35, 0x07534b3, 0x0f1c2cf, 0x1c51d59,
  47624. 0x1a9c3e6, 0x1ed42d3, 0x1954ded, 0x15cd09b, 0x0937dc2, 0x01f2b6f,
  47625. 0x0897b2b, 0x1f08608, 0x12ea6c9, 0x0e2905f, 0x1f41dff, 0x1a7195e,
  47626. 0x09f56ad, 0x1d7858b, 0x0874b09, 0x1338e3a, 0x0496e46 },
  47627. { 0x1a93467, 0x07e414f, 0x1852e85, 0x081d654, 0x02e3768, 0x19f04de,
  47628. 0x13ebd20, 0x198cb37, 0x03686bd, 0x042cba9, 0x0c85aaf, 0x010103e,
  47629. 0x1840bfd, 0x0be040d, 0x18ef698, 0x0f27788, 0x086bb04, 0x0de80fd,
  47630. 0x1359031, 0x03d9cc5, 0x15c45a2, 0x0a1101e, 0x05efda9, 0x022cf6f,
  47631. 0x00edc95, 0x134675a, 0x1dd96e8, 0x0cf5595, 0x0b51f9d, 0x0cf4d75,
  47632. 0x0ea2e83, 0x161ad0c, 0x14b215e, 0x034a960, 0x136f97c, 0x0a6a99b,
  47633. 0x0b3744b, 0x15ae67e, 0x1ffa13c, 0x0e62606, 0x0133891 },
  47634. { 0x1003cd1, 0x0032022, 0x0b1bb9a, 0x18895c5, 0x1dac17b, 0x07298a7,
  47635. 0x1067f7a, 0x0b8979a, 0x1c7cea9, 0x0f1a75c, 0x0df8060, 0x0c5a71e,
  47636. 0x08bb577, 0x1304c86, 0x1133ec0, 0x094f7d9, 0x1f950a3, 0x185e249,
  47637. 0x10cc13b, 0x0e82e4a, 0x0a2a680, 0x1935e45, 0x0bb03f2, 0x08bfd4b,
  47638. 0x09b463b, 0x1d64f3d, 0x1957ef6, 0x17652a5, 0x05dff44, 0x0053024,
  47639. 0x05943c3, 0x09bd48f, 0x0c5104d, 0x11d0101, 0x0825a57, 0x0ba59df,
  47640. 0x0da1f34, 0x00815a3, 0x0fef532, 0x0e7e706, 0x0422eb5 },
  47641. { 0x0ad3f47, 0x0975b53, 0x083ab16, 0x1b2e297, 0x10861f6, 0x140a2cd,
  47642. 0x1a4641c, 0x006af83, 0x064ea58, 0x1be4a71, 0x049c8f3, 0x0d58a96,
  47643. 0x0a72537, 0x0d7db9b, 0x09ae907, 0x079b9e5, 0x120cba0, 0x0e44f44,
  47644. 0x0c3f4eb, 0x041968b, 0x19fef2e, 0x0a6b302, 0x09ba969, 0x13bf178,
  47645. 0x1fa8b88, 0x15ff731, 0x059a8fc, 0x01e38fc, 0x1312e14, 0x1e4e3a3,
  47646. 0x1fc27fa, 0x0e4f333, 0x119b9c2, 0x09582be, 0x0d32dff, 0x0d53f77,
  47647. 0x00da2dc, 0x1d13ebd, 0x0960b3e, 0x19e584a, 0x0368541 },
  47648. { 0x0799d37, 0x09e4f11, 0x0ce9443, 0x0b59f46, 0x1b677de, 0x07bcad8,
  47649. 0x1863c20, 0x1849cd5, 0x0afc8df, 0x0da9e15, 0x10b709a, 0x036c1d0,
  47650. 0x0879754, 0x16033ff, 0x09bcabe, 0x1b0efab, 0x003bd07, 0x1681045,
  47651. 0x152f8bc, 0x08e7e0c, 0x023e34b, 0x157a8af, 0x199f040, 0x1835e91,
  47652. 0x1bf9d2a, 0x0805806, 0x06da84f, 0x04c9f48, 0x094c11e, 0x1c354bf,
  47653. 0x1d059a5, 0x10d4b0d, 0x1d8cf2d, 0x093f484, 0x01a71fe, 0x0c0e77f,
  47654. 0x0241a56, 0x0bbc401, 0x04cd2e2, 0x0b2444c, 0x059a5bf },
  47655. { 0x1347191, 0x0e48f40, 0x05cba74, 0x19d72d3, 0x186c1ab, 0x0a353f8,
  47656. 0x01d9ea7, 0x12e0f11, 0x0daa7d3, 0x149e7e6, 0x0e6a836, 0x13e3b23,
  47657. 0x0c08bee, 0x1c6e9e3, 0x19ff5e3, 0x1020104, 0x0d09422, 0x1fc9c30,
  47658. 0x0b6d1fe, 0x14e355b, 0x0f8a6a6, 0x1bd30ab, 0x072a81a, 0x1091793,
  47659. 0x105e039, 0x09ad50d, 0x1caaaa4, 0x0dbb846, 0x1f3bd13, 0x103cd89,
  47660. 0x135df9f, 0x09598be, 0x10b5cbe, 0x07e9b46, 0x17e2613, 0x1009b48,
  47661. 0x13d3e0f, 0x077b0c6, 0x1e673c5, 0x18287d6, 0x0467564 },
  47662. { 0x0fff5d7, 0x12c825b, 0x1d4a35c, 0x1f25b88, 0x037f33a, 0x105c550,
  47663. 0x155d5b4, 0x073212b, 0x143baec, 0x111afe0, 0x0ae6c0c, 0x095ed14,
  47664. 0x01a2feb, 0x0a69ae3, 0x1140c62, 0x0e90cc3, 0x0a2ea87, 0x1d6495b,
  47665. 0x046f1bc, 0x09162a0, 0x1cb28eb, 0x1463cf6, 0x08a3f84, 0x1a5400d,
  47666. 0x1bc0ca5, 0x0284fb8, 0x08bc56e, 0x062cee6, 0x036218f, 0x19463d0,
  47667. 0x07bfa35, 0x09f03c1, 0x08f39cb, 0x0286c83, 0x0059edf, 0x062ee7e,
  47668. 0x0d6a1e0, 0x07bd6df, 0x0135434, 0x02c9dd3, 0x08a0dee },
  47669. { 0x1366e6f, 0x0c8dfa3, 0x0015412, 0x1fd0d86, 0x18084d9, 0x06671b5,
  47670. 0x11d4690, 0x1c42989, 0x03f1961, 0x1da3553, 0x11790ee, 0x0bf2808,
  47671. 0x1f56a78, 0x048f10a, 0x0346d5f, 0x1011bb7, 0x13ec7ee, 0x0354722,
  47672. 0x0ea87a3, 0x0cfdf17, 0x0109c03, 0x18f1f0c, 0x0c43647, 0x0414586,
  47673. 0x0fd0e7e, 0x13bfcbe, 0x1155330, 0x03d0190, 0x028403f, 0x1e0ebdb,
  47674. 0x1f3a26e, 0x07fc142, 0x178a966, 0x00039bb, 0x067f07c, 0x053d3b6,
  47675. 0x16f6bed, 0x13ff3ed, 0x1388cb3, 0x1a5dd2f, 0x07b04b5 },
  47676. { 0x0c5faf8, 0x035e3c1, 0x025d6d5, 0x1d1d702, 0x1a734c5, 0x1c28f00,
  47677. 0x1a1879d, 0x03e7aac, 0x1e956d5, 0x19d0809, 0x0f0df20, 0x0e63878,
  47678. 0x0cc7351, 0x1060a47, 0x1dce3ef, 0x1de82c0, 0x0bbe1bb, 0x1976378,
  47679. 0x1e94615, 0x0558dd9, 0x0df00aa, 0x0bb371d, 0x01ca40b, 0x045adc6,
  47680. 0x15089c6, 0x017e6a6, 0x0e9b760, 0x15c4364, 0x0863723, 0x0d2a99c,
  47681. 0x08b9519, 0x151b030, 0x05119a0, 0x14bbd6c, 0x00c8de1, 0x189e29a,
  47682. 0x1c7b272, 0x0d840e4, 0x18c7145, 0x1499337, 0x01c6a95 },
  47683. { 0x0821363, 0x0a56ae1, 0x18729ac, 0x069a2fb, 0x029c182, 0x16f4244,
  47684. 0x14b1332, 0x04f5deb, 0x182489e, 0x009559c, 0x07649fd, 0x0131e10,
  47685. 0x1f92c9c, 0x1ae5d68, 0x01ef7d1, 0x13f62df, 0x0b81a1d, 0x17a556d,
  47686. 0x1d7cedd, 0x14f2476, 0x08fe475, 0x0b6dddd, 0x067742b, 0x0e1568b,
  47687. 0x161644b, 0x178c1b7, 0x04d2f66, 0x148c910, 0x1abda32, 0x11375d4,
  47688. 0x1ed7244, 0x1ccac4b, 0x0ec8709, 0x0725f26, 0x0678206, 0x19a9672,
  47689. 0x14f6879, 0x004e420, 0x1932697, 0x0046150, 0x072708a },
  47690. { 0x14a466c, 0x1e058f9, 0x16e93cc, 0x18ff3a8, 0x01bae09, 0x143c2e5,
  47691. 0x03fb838, 0x103ae1e, 0x0908808, 0x12638a3, 0x10f68e0, 0x1855760,
  47692. 0x12e2416, 0x07637a1, 0x0f69c4f, 0x07c38e6, 0x049c979, 0x095ac83,
  47693. 0x0d724d9, 0x05ab616, 0x1b2adb6, 0x111f2e0, 0x0d57adb, 0x02d6a2a,
  47694. 0x0b5cebb, 0x08e67f4, 0x07dc25a, 0x1c1030d, 0x085bd59, 0x1cfdb0d,
  47695. 0x1df2197, 0x1f5c207, 0x169d3cc, 0x13f4ef8, 0x11cdcd1, 0x072a4b8,
  47696. 0x0369511, 0x1aae05a, 0x17485f6, 0x098e64c, 0x07491c7 },
  47697. { 0x0d2b94d, 0x16adfc0, 0x182cc4b, 0x0774964, 0x1b8ac63, 0x110cd08,
  47698. 0x1163358, 0x11d590d, 0x1aeb82c, 0x0be67b5, 0x1e73b4c, 0x13dcb3d,
  47699. 0x1a2dfb2, 0x1215e6a, 0x09f6263, 0x16403b5, 0x1c85974, 0x049f14a,
  47700. 0x07f16b7, 0x0eaf09b, 0x03ba69e, 0x0f80955, 0x15b11c2, 0x0ba7973,
  47701. 0x09f37c8, 0x15e8fed, 0x174f752, 0x0a90fc4, 0x1ba22ee, 0x0580859,
  47702. 0x0ec03f5, 0x18dd1b9, 0x1591493, 0x1433265, 0x1eaef39, 0x0d6e653,
  47703. 0x08906b7, 0x14e8e13, 0x1a105a0, 0x1cae82e, 0x08bcfd3 },
  47704. { 0x1c8c314, 0x0139a69, 0x00cc1a2, 0x02230e1, 0x15f0b2f, 0x145d0b4,
  47705. 0x1df0f01, 0x10f726f, 0x0779247, 0x1b2f06c, 0x04889d4, 0x1cbc3f3,
  47706. 0x0f15527, 0x13effea, 0x01a5920, 0x0c71214, 0x1f22f58, 0x0eac59e,
  47707. 0x0bc83ab, 0x08d712d, 0x0257834, 0x05a83a3, 0x0275e5c, 0x0454d22,
  47708. 0x0d20640, 0x1bcecf4, 0x1d9c7b0, 0x03cbf15, 0x1fe91ed, 0x128482b,
  47709. 0x061bd50, 0x0a51208, 0x14dda81, 0x09956f8, 0x043876e, 0x117af00,
  47710. 0x105a937, 0x0c68f24, 0x0ad24f8, 0x1ef7a6f, 0x053cadc },
  47711. { 0x053d0ff, 0x0f6fbaf, 0x1d9c6ed, 0x1911157, 0x1886606, 0x10368ae,
  47712. 0x0c3e048, 0x066c923, 0x1e22b6a, 0x180c1a2, 0x0ecc5ec, 0x129762e,
  47713. 0x15aba67, 0x1ee4f2c, 0x079619d, 0x049a318, 0x0822396, 0x1a70832,
  47714. 0x0957754, 0x0a5cb3b, 0x079c617, 0x15cf214, 0x0062d3a, 0x03e57da,
  47715. 0x0784b49, 0x14f657b, 0x0879e50, 0x1b9b73a, 0x1262243, 0x0a42887,
  47716. 0x170da50, 0x14ca1d8, 0x06f190a, 0x14bb008, 0x16bada6, 0x0cea854,
  47717. 0x032d104, 0x1ebaf4e, 0x18ac5a6, 0x0c97f18, 0x0908499 },
  47718. { 0x093c661, 0x0867b2d, 0x015ac4e, 0x093b6be, 0x1848626, 0x0d0bc40,
  47719. 0x0ea7694, 0x1352552, 0x16772de, 0x1865dc7, 0x0521f06, 0x1d7af8e,
  47720. 0x1e6e67f, 0x0731211, 0x0d0e0b5, 0x085f1f3, 0x10ebb5a, 0x14b7ed2,
  47721. 0x022693c, 0x03666ec, 0x0516c92, 0x1dc3af6, 0x1274cb5, 0x0202496,
  47722. 0x0d2cac4, 0x1bd5ec3, 0x071087e, 0x0d0c441, 0x17de33f, 0x04d5fb5,
  47723. 0x1a0f865, 0x1d27924, 0x1ee18f0, 0x0266066, 0x1578237, 0x05a9db7,
  47724. 0x13580d2, 0x1badf23, 0x15fa30a, 0x1f48d19, 0x03d7f6f },
  47725. { 0x1fbd5d1, 0x194866f, 0x037fa9e, 0x0d2e067, 0x1d759da, 0x1f76e4c,
  47726. 0x02c2243, 0x11cacd0, 0x142dce6, 0x034857a, 0x19360af, 0x1e57655,
  47727. 0x008519d, 0x1f8cadb, 0x04919fd, 0x043e8ac, 0x02cd83c, 0x1b2cd1a,
  47728. 0x159458c, 0x0e37eaa, 0x0562557, 0x1aaa45d, 0x17f1a24, 0x125e474,
  47729. 0x1920394, 0x00bdaa0, 0x0e72718, 0x0cea51c, 0x1e60195, 0x076a288,
  47730. 0x154fc19, 0x03a2d4a, 0x03f9eb9, 0x055f718, 0x13f4895, 0x187c318,
  47731. 0x1d434e7, 0x0ca6b7f, 0x1d39902, 0x07edbbc, 0x08fb12d },
  47732. { 0x13cb7a4, 0x1c0d114, 0x1935b18, 0x0170f6f, 0x053e09f, 0x0561f7a,
  47733. 0x0a08c1e, 0x1229e42, 0x0578cae, 0x04ffd68, 0x0e9377a, 0x12d4e2d,
  47734. 0x004a2b6, 0x1b7ac05, 0x1a06853, 0x0260e28, 0x17b4c2f, 0x089ac7c,
  47735. 0x04cbee2, 0x12d32c5, 0x1af7878, 0x0513452, 0x0a77614, 0x0473f06,
  47736. 0x11f6dfe, 0x0ced7bb, 0x193d1d2, 0x1e41fa5, 0x1ca0e95, 0x1f3bc33,
  47737. 0x1b26d90, 0x06eb303, 0x1858ecd, 0x18e4bf3, 0x096466a, 0x077d28d,
  47738. 0x06ff345, 0x0981d10, 0x0dec53e, 0x062eba4, 0x03fcc67 },
  47739. { 0x121f920, 0x0f5eaef, 0x0e41427, 0x1f82803, 0x1af70e1, 0x132557f,
  47740. 0x12ff656, 0x0444853, 0x12c37a1, 0x109042a, 0x0e49afc, 0x07e8fbd,
  47741. 0x1c1d4c9, 0x0fd9f8e, 0x1cf9302, 0x1788c25, 0x0595b51, 0x12b042d,
  47742. 0x043f6f4, 0x1ebac5e, 0x13c22a2, 0x07ef865, 0x183758b, 0x01e4a96,
  47743. 0x024a36b, 0x15b8aa2, 0x1559184, 0x074b40b, 0x15249cc, 0x1867d0f,
  47744. 0x022faf8, 0x0fcc543, 0x0ec6903, 0x14c9c92, 0x0eb2bd0, 0x0aebe1f,
  47745. 0x13fa868, 0x09a2ee5, 0x070d350, 0x1fb8e2a, 0x0645146 },
  47746. { 0x01924f9, 0x0319d5d, 0x1b87b3b, 0x0c00c64, 0x1ba6f13, 0x087e0bd,
  47747. 0x15eb1f9, 0x000406e, 0x1ef3d8e, 0x1298c8c, 0x1169d32, 0x0d54a3b,
  47748. 0x189545a, 0x098a095, 0x087563f, 0x1a000dc, 0x0057bb1, 0x180de18,
  47749. 0x1b46a70, 0x1138d2d, 0x1a48f17, 0x0fcc2c7, 0x1ebcb4d, 0x12f7d0a,
  47750. 0x109b981, 0x12ea1a6, 0x14a6a89, 0x1b80eea, 0x18fa801, 0x1df3e02,
  47751. 0x13b2b40, 0x0a97429, 0x0d70a9f, 0x0853a49, 0x1415b01, 0x14db8f0,
  47752. 0x0d005dd, 0x1e5254a, 0x07cb8a9, 0x0e557f7, 0x0448d3d },
  47753. { 0x1b33989, 0x178a294, 0x056b715, 0x19535d0, 0x068351b, 0x03a20a4,
  47754. 0x1584d2c, 0x07767e8, 0x03cd9f3, 0x0ae7215, 0x1b928e5, 0x09d8bfe,
  47755. 0x1113ade, 0x1287554, 0x0ab1c56, 0x1dfbfa7, 0x0995666, 0x10630f6,
  47756. 0x1a911c2, 0x145171e, 0x04c9108, 0x0272a42, 0x100bbd6, 0x1c5e66e,
  47757. 0x1b162d0, 0x05e5c12, 0x1ed1bdf, 0x1b9a263, 0x12fd893, 0x1c764b7,
  47758. 0x1e08205, 0x04b2518, 0x18c5d67, 0x1e22ca6, 0x0f7e658, 0x1e50b46,
  47759. 0x192a309, 0x04b8bae, 0x06695c9, 0x0f396e0, 0x0768814 },
  47760. { 0x1767eed, 0x1d08a48, 0x176ee90, 0x1b257ec, 0x1e11b9a, 0x12f10d2,
  47761. 0x0b3800e, 0x02bd144, 0x12a3354, 0x1b02210, 0x1ab5898, 0x0768953,
  47762. 0x05c2c56, 0x1059577, 0x1018992, 0x1c3ae97, 0x1758bf2, 0x0badc6a,
  47763. 0x0228997, 0x1e1dcfa, 0x12a71cf, 0x0ed85b8, 0x05e4538, 0x030d25a,
  47764. 0x125d04b, 0x00ae1ac, 0x115b33a, 0x1c4a7e9, 0x1f0e3ad, 0x120e4ff,
  47765. 0x06691e4, 0x1bb57da, 0x0b9d06e, 0x1728328, 0x098167e, 0x00ce26a,
  47766. 0x132ce18, 0x1b007da, 0x0189bcd, 0x038bcb5, 0x0670eb0 },
  47767. { 0x1cdbb43, 0x1e057b9, 0x06b77dc, 0x0afe486, 0x0f08ecc, 0x0d1c22e,
  47768. 0x01504a8, 0x1e322f0, 0x09224dd, 0x0d08279, 0x11fbfda, 0x071b7d5,
  47769. 0x024352f, 0x1e16899, 0x0eced39, 0x168edf8, 0x030b5e4, 0x0534f4a,
  47770. 0x1d691bc, 0x0646812, 0x0ece7d9, 0x0f2eb27, 0x0024e26, 0x0468bd3,
  47771. 0x01250db, 0x0b5bdc1, 0x09fd2de, 0x06aa526, 0x190b1f2, 0x060aa5d,
  47772. 0x158bba7, 0x12225ef, 0x1a9c8f5, 0x157190f, 0x1e6072e, 0x145a1e5,
  47773. 0x0075166, 0x1f81b30, 0x1fc9edd, 0x1cec6bb, 0x0504852 },
  47774. { 0x0f392fa, 0x19e72d1, 0x01e0bc3, 0x15d8d92, 0x126c076, 0x1d557b1,
  47775. 0x17a4a12, 0x1275a03, 0x1cbe8e9, 0x00d8b69, 0x142422c, 0x18485b2,
  47776. 0x1871305, 0x1c29d79, 0x1bf585c, 0x053418c, 0x00ed3c4, 0x1bb9a8a,
  47777. 0x1eafc09, 0x0362543, 0x11778a3, 0x0102c59, 0x0814c00, 0x18fbd73,
  47778. 0x1d9fca9, 0x09855ff, 0x0fa199f, 0x00bded3, 0x09e13fd, 0x198474d,
  47779. 0x070bce9, 0x1723d5d, 0x14c9a19, 0x073621f, 0x1b9d863, 0x00a1a19,
  47780. 0x1240f8b, 0x126e202, 0x03313ec, 0x0a3efd2, 0x0992fe1 },
  47781. { 0x0f197aa, 0x06d989c, 0x1e61115, 0x1b0f0e5, 0x04ded69, 0x1854145,
  47782. 0x09ec113, 0x18d2f68, 0x0a31e48, 0x010f0d7, 0x03bfb26, 0x013fbb3,
  47783. 0x0ee38cb, 0x040659d, 0x0e13ea1, 0x0aae641, 0x0a84747, 0x1dd2dda,
  47784. 0x1543a5a, 0x1c10159, 0x1550a9b, 0x0e77881, 0x111147a, 0x08264b9,
  47785. 0x0e75fc4, 0x19eb137, 0x00e2978, 0x1dd4bd3, 0x10abd26, 0x1f5cd15,
  47786. 0x0a5cc86, 0x136c105, 0x092e484, 0x1e61565, 0x1a2a64a, 0x163b902,
  47787. 0x1c8eb9f, 0x0767a5c, 0x1c7804d, 0x15098b6, 0x05a68bf },
  47788. { 0x10a2bfb, 0x19da2ff, 0x02c2d3f, 0x12aa05f, 0x1105fff, 0x0e06136,
  47789. 0x162156c, 0x00829bc, 0x10d3b9d, 0x08b432d, 0x14e45fb, 0x08a604d,
  47790. 0x0e2f5a2, 0x1a6d9e0, 0x08bd24f, 0x11e5cd4, 0x08ae241, 0x0a438aa,
  47791. 0x026fbd8, 0x06c750a, 0x1bec6ab, 0x1d5c65d, 0x0472878, 0x023472d,
  47792. 0x0dc9840, 0x0bbb8f0, 0x0835729, 0x1f305c1, 0x097bc1f, 0x1822c0c,
  47793. 0x19fad02, 0x010b5ab, 0x1c24a46, 0x1bdbe25, 0x1e8298c, 0x1fa2b91,
  47794. 0x1ef1628, 0x07377bd, 0x1d0e55b, 0x1f33ebd, 0x078acfd },
  47795. { 0x0520189, 0x1bf8afc, 0x071116f, 0x018efec, 0x154202a, 0x11170dc,
  47796. 0x11ae77e, 0x10e73db, 0x11f4a34, 0x16b0133, 0x13314b4, 0x1252902,
  47797. 0x03cd933, 0x02f4f89, 0x1da8490, 0x16defbc, 0x0a0ae36, 0x0711837,
  47798. 0x00e9638, 0x02a4317, 0x031a538, 0x1b50209, 0x0618aed, 0x0637ce3,
  47799. 0x0253cbf, 0x10ff46d, 0x08df7a1, 0x1bf8a66, 0x0e48902, 0x09fb485,
  47800. 0x14bc972, 0x11754dd, 0x0bcb8f0, 0x1a514b3, 0x183e422, 0x12de215,
  47801. 0x1061c94, 0x1a5a465, 0x08d9a32, 0x0e7a0eb, 0x00ad92d },
  47802. { 0x0ca548a, 0x0aff6e1, 0x06aefee, 0x01019b1, 0x0778c62, 0x1361402,
  47803. 0x0552cd1, 0x0057d32, 0x1d4be89, 0x11df049, 0x1a07b7a, 0x132a27c,
  47804. 0x01847b7, 0x017a00b, 0x0aa3d2c, 0x0ffd1e4, 0x14d4aeb, 0x11f7965,
  47805. 0x0ebb57d, 0x18a2a36, 0x11639ad, 0x08cc618, 0x1b0733f, 0x1afb11f,
  47806. 0x0c17ba3, 0x04bee15, 0x0d19084, 0x11f4c9a, 0x190bcf0, 0x005bca5,
  47807. 0x1ad7afe, 0x016a153, 0x178b4ba, 0x153358d, 0x04d09e6, 0x1a349fd,
  47808. 0x075b3ce, 0x1a6e578, 0x1a6ba3b, 0x140e14d, 0x095bbd8 },
  47809. { 0x014bbd0, 0x0924af3, 0x0d8d67e, 0x0f7047c, 0x1567a88, 0x0deb53b,
  47810. 0x127b3f0, 0x085c48f, 0x18e835c, 0x1fd57a3, 0x1819a8a, 0x09c155b,
  47811. 0x16314ef, 0x0e0b699, 0x0aea98d, 0x1c7120e, 0x071e2f0, 0x1fd214e,
  47812. 0x141f643, 0x03cba17, 0x1c04cac, 0x1528a7a, 0x1a7fcd7, 0x0aa9d82,
  47813. 0x053fcc0, 0x03fc498, 0x1ca8d65, 0x163b0d6, 0x0be487a, 0x1830157,
  47814. 0x0878a7e, 0x1bf739e, 0x0a10d6d, 0x0fe7ad0, 0x0167c83, 0x155a28e,
  47815. 0x18867a2, 0x06e337d, 0x0a46520, 0x09f824b, 0x0375a88 },
  47816. { 0x017f7ea, 0x05f1709, 0x16ac5e3, 0x150eb8d, 0x1a161e2, 0x0d8d2a0,
  47817. 0x1fb006f, 0x195eee0, 0x0e4fd73, 0x1c43250, 0x0836199, 0x0cc9a27,
  47818. 0x08baebc, 0x0469833, 0x0c97e67, 0x0b2a080, 0x1c92f1c, 0x1dc9f6c,
  47819. 0x1078199, 0x06cec6a, 0x0763fdf, 0x185c8d3, 0x1f65fee, 0x0f39341,
  47820. 0x069ea60, 0x0239355, 0x007aaa3, 0x0e60790, 0x063c55c, 0x0e40d7d,
  47821. 0x16f7b1d, 0x09fa255, 0x1cdcde2, 0x041c500, 0x169c65a, 0x133fc1b,
  47822. 0x1841537, 0x1d849d9, 0x013b19a, 0x1161197, 0x0268d81 },
  47823. { 0x1580555, 0x171ac20, 0x00edcf6, 0x0e8e7a2, 0x0fc32e6, 0x0660d5a,
  47824. 0x0404efb, 0x1bc4818, 0x0b24ee9, 0x1204cf9, 0x03819b6, 0x16b73f5,
  47825. 0x0e37b0c, 0x121c6bf, 0x0b81391, 0x002816b, 0x1642b72, 0x03fbe98,
  47826. 0x0e7929e, 0x1e9db66, 0x037586e, 0x169d3ec, 0x0979dfb, 0x0e0f85d,
  47827. 0x1ad37bd, 0x0c4c41f, 0x083e5e4, 0x02d6c67, 0x1a208e8, 0x0145173,
  47828. 0x1ab8930, 0x0886aa2, 0x171fe3c, 0x195fa88, 0x0ccd3d7, 0x0c7d727,
  47829. 0x01b53a5, 0x0cf6a58, 0x0912e10, 0x0b80ad9, 0x08b0273 },
  47830. { 0x1019195, 0x1da3270, 0x0306e26, 0x0de7f85, 0x1de4c02, 0x1e1d908,
  47831. 0x039b8af, 0x05f5824, 0x091bdf9, 0x038de2d, 0x056f27b, 0x15681b3,
  47832. 0x1e485d7, 0x13248ff, 0x119da3b, 0x1c4cb2f, 0x119afbc, 0x16caa96,
  47833. 0x186ddb0, 0x0d8ffd1, 0x0d1bbae, 0x00ebf1d, 0x059f60a, 0x1312e68,
  47834. 0x09af95e, 0x0c11f0a, 0x1228320, 0x03e0049, 0x006c0dd, 0x1fede18,
  47835. 0x133d5c7, 0x0b0ee7a, 0x12ecf7e, 0x0a06c59, 0x1e0bf4d, 0x04b0454,
  47836. 0x0436504, 0x1a2e1f8, 0x017f96a, 0x140969b, 0x0400e3a },
  47837. { 0x046e4a2, 0x10b24af, 0x01d11cc, 0x084826c, 0x17a2ed6, 0x0763be9,
  47838. 0x08ec718, 0x05ccb24, 0x1e5e0ac, 0x109d561, 0x01eadd7, 0x08378a2,
  47839. 0x1bda17c, 0x19e129e, 0x0c8bb25, 0x0452ccb, 0x1b8a501, 0x1ff9c33,
  47840. 0x1886a66, 0x0cc1aa0, 0x03f5fed, 0x03644fe, 0x08f0a14, 0x0c8a34f,
  47841. 0x150b9f1, 0x0379f69, 0x099f2d6, 0x0f87c06, 0x1185b12, 0x03bccb3,
  47842. 0x06f201f, 0x0942601, 0x1c157d4, 0x18fa684, 0x191eb6b, 0x106c5ee,
  47843. 0x13a6a19, 0x015cd67, 0x180e529, 0x1451b4d, 0x0131c3d },
  47844. { 0x1da83ba, 0x02ff8d3, 0x10d929e, 0x0ba09e8, 0x1415b42, 0x01fc097,
  47845. 0x066f7b0, 0x144f811, 0x080f5f4, 0x0c6a08d, 0x0946e71, 0x0c21fb4,
  47846. 0x123d32d, 0x069d979, 0x0ed1413, 0x0107933, 0x04bf4c2, 0x08cc622,
  47847. 0x0c3a0ff, 0x04c35ee, 0x1b9060c, 0x0fe5816, 0x0183293, 0x1e3cf90,
  47848. 0x1838b9d, 0x06487fb, 0x1f131a4, 0x16f39f2, 0x15f1546, 0x0a6baeb,
  47849. 0x1fc4c54, 0x03961d1, 0x1c074f1, 0x0bb0ad3, 0x0b06cb0, 0x0172415,
  47850. 0x04aa0ff, 0x004c56a, 0x173a77a, 0x0d468a8, 0x071d1a4 },
  47851. { 0x01b382e, 0x1c7bb7d, 0x0835d85, 0x06ee5bb, 0x00d8ecc, 0x0a68985,
  47852. 0x0acab17, 0x05954b5, 0x08d7262, 0x1e9c5d2, 0x0fb4189, 0x1b6d947,
  47853. 0x0fc5410, 0x1c9e766, 0x0de9621, 0x1c7afec, 0x0fd6e65, 0x08fb2ed,
  47854. 0x0291590, 0x08950ac, 0x140bc3b, 0x1427bc2, 0x03d1ece, 0x09ac1ec,
  47855. 0x1dadd5e, 0x16ac127, 0x105f4ed, 0x1199f21, 0x1fc13ad, 0x15ef992,
  47856. 0x0e4023a, 0x06c91f5, 0x090d716, 0x096a59f, 0x1ce8931, 0x1672c9f,
  47857. 0x133d0ac, 0x0e620b2, 0x1d486e5, 0x13e22cf, 0x06cd269 },
  47858. { 0x0f4f3ac, 0x0059d89, 0x17ecb63, 0x0533a37, 0x103dcfe, 0x19b9935,
  47859. 0x0d3e0c3, 0x104a800, 0x17c5a8c, 0x16eb449, 0x1c51088, 0x07a19b1,
  47860. 0x12eb709, 0x0c2ba17, 0x09e569d, 0x1b5bb12, 0x02c087a, 0x170af94,
  47861. 0x1aaded7, 0x1b8e922, 0x0bb47bb, 0x05d2c56, 0x14c3f90, 0x1758737,
  47862. 0x017ebe2, 0x05e06f2, 0x1b18681, 0x1696334, 0x1355694, 0x01a6f93,
  47863. 0x1be4ce3, 0x0615632, 0x0f03742, 0x064b2f4, 0x12e1b22, 0x0df45df,
  47864. 0x07eeb82, 0x17713a6, 0x1770867, 0x07fb468, 0x0327c06 },
  47865. { 0x147cd53, 0x0cf7fad, 0x1bfaace, 0x1a32875, 0x1be9869, 0x0154335,
  47866. 0x131ec50, 0x02dcc9d, 0x0b1c25a, 0x1f3e155, 0x1789c70, 0x16f2045,
  47867. 0x1fc4216, 0x1b36b52, 0x037f320, 0x0666dcb, 0x09eda81, 0x068aca8,
  47868. 0x0c2fedf, 0x0801e42, 0x0780370, 0x0cc9da4, 0x06f9381, 0x1e79a44,
  47869. 0x1a1fe39, 0x1c38311, 0x0bbb2d3, 0x0554456, 0x07b83b7, 0x024b361,
  47870. 0x0fc6bd3, 0x1b4bf4b, 0x042a94b, 0x00d793d, 0x008922c, 0x1935f75,
  47871. 0x1670112, 0x15ce951, 0x1a15bad, 0x1a381be, 0x0020f19 },
  47872. { 0x0dbba20, 0x08d4352, 0x1714dc1, 0x0db63bc, 0x1618ebc, 0x092c205,
  47873. 0x0286799, 0x09b34f0, 0x1d2bccc, 0x0201816, 0x0168925, 0x047a205,
  47874. 0x08e9ff0, 0x1d24313, 0x04dfb8c, 0x0228e77, 0x0f24cd6, 0x1f1bf71,
  47875. 0x0f415f3, 0x177fa74, 0x0fce79f, 0x09e66ef, 0x17ee85b, 0x0462e4e,
  47876. 0x058ec5b, 0x16dc8b0, 0x19c830e, 0x0ed33d7, 0x0f6bba4, 0x01c345a,
  47877. 0x1c0989d, 0x1e3140e, 0x0b0092a, 0x108b02a, 0x03aeb32, 0x0133a12,
  47878. 0x0c888f6, 0x0bf0ff8, 0x01513dd, 0x041600a, 0x079e727 },
  47879. { 0x020a239, 0x1679294, 0x0c418ca, 0x1d55cd6, 0x11a3974, 0x0050efd,
  47880. 0x15ae923, 0x155ac3f, 0x15a3ee7, 0x1229e1c, 0x0111b74, 0x0b41730,
  47881. 0x0f54845, 0x0f0b33b, 0x0a765ef, 0x0eb433e, 0x00c7893, 0x0f92965,
  47882. 0x1d0ea61, 0x035e7ce, 0x1d8de96, 0x0b3366d, 0x1c31e71, 0x18a71f2,
  47883. 0x1854ecb, 0x08e0a51, 0x0a849a1, 0x11b54e7, 0x1f558c5, 0x1da2954,
  47884. 0x017a6d6, 0x1f7a2bc, 0x1af7f83, 0x0c9ce9b, 0x049ce28, 0x0d4890f,
  47885. 0x1511a05, 0x14595ac, 0x011b790, 0x1c6e02b, 0x0001d3c },
  47886. { 0x145b1d7, 0x11b5cf0, 0x19935af, 0x140138a, 0x13e3938, 0x007b6df,
  47887. 0x0b9f79f, 0x0725cac, 0x0c343f5, 0x0882273, 0x025ec65, 0x0571b21,
  47888. 0x1ca5ab6, 0x0897bcb, 0x087dc2d, 0x051c963, 0x154750f, 0x0c8e6eb,
  47889. 0x1ee0597, 0x101c5ff, 0x02b3b4c, 0x03aca68, 0x197b4e7, 0x1067db8,
  47890. 0x0a49d56, 0x10c6609, 0x13cda4e, 0x0e6d297, 0x12c404e, 0x09a57e6,
  47891. 0x050d330, 0x023a803, 0x11bd5fc, 0x02f2303, 0x011ff16, 0x080aeb2,
  47892. 0x190b7a0, 0x1401b03, 0x11a12cc, 0x1f8815f, 0x04bb8c6 },
  47893. { 0x10f8796, 0x0716efe, 0x0778c48, 0x1b62679, 0x0968a40, 0x1b4e373,
  47894. 0x19b02a4, 0x077fd46, 0x0600727, 0x1f2db6b, 0x0050e4d, 0x19e1197,
  47895. 0x0539e4e, 0x0ff5e00, 0x1ffa736, 0x16a7890, 0x0440199, 0x1f5c57a,
  47896. 0x04d467a, 0x049c765, 0x1c162f1, 0x0564164, 0x0183086, 0x13b8b21,
  47897. 0x1d6f270, 0x094d668, 0x14db541, 0x0d2daa8, 0x120bfc5, 0x0efcac8,
  47898. 0x04300fd, 0x021ff4d, 0x1a3e88d, 0x19413cc, 0x1e95b10, 0x13a9f39,
  47899. 0x1a135d8, 0x07f54f4, 0x1f9e0ba, 0x1036d4e, 0x03699a8 },
  47900. { 0x0b1c64d, 0x119b90f, 0x05516f2, 0x1be3a50, 0x09cf3a2, 0x1b8837f,
  47901. 0x1a6cd94, 0x09b6fc5, 0x14f7cbf, 0x160b8a8, 0x02cdfc1, 0x02dc40b,
  47902. 0x05cbde4, 0x041a74e, 0x114e9fa, 0x074eb05, 0x1e2e9ac, 0x14a6def,
  47903. 0x1799f00, 0x1d8d978, 0x080d795, 0x0f8a135, 0x0308f09, 0x11a9f3f,
  47904. 0x0d20d6a, 0x11af716, 0x134edf0, 0x071b54a, 0x1a4d528, 0x07601eb,
  47905. 0x1cee782, 0x0f03968, 0x09475e9, 0x18e5565, 0x0e797b0, 0x0ee4e3e,
  47906. 0x0253518, 0x18474fc, 0x1fe2c77, 0x0064115, 0x04f3a4b },
  47907. { 0x0d095f8, 0x1c0838f, 0x15383de, 0x0db444d, 0x03e37fa, 0x19b68e9,
  47908. 0x0614abe, 0x023161f, 0x007d8e3, 0x08a31a7, 0x03c5bac, 0x152fc7c,
  47909. 0x17b9634, 0x010f761, 0x152ee71, 0x0438248, 0x1dbd72b, 0x05a766a,
  47910. 0x17c835f, 0x0070d0d, 0x00a2f96, 0x1eefc37, 0x07d4d67, 0x1891155,
  47911. 0x154fa5a, 0x0fa621e, 0x0f44127, 0x0dae295, 0x00607a5, 0x159f581,
  47912. 0x1784c54, 0x0f40464, 0x1be1c18, 0x1426da4, 0x1d294ab, 0x0089e49,
  47913. 0x0b5a7b8, 0x092e018, 0x1e7f679, 0x08d4da2, 0x06d8744 },
  47914. { 0x09a42f5, 0x083d55f, 0x13234a7, 0x186f039, 0x1fd5316, 0x034f508,
  47915. 0x169b677, 0x034e34e, 0x188fee9, 0x10cf06f, 0x113c493, 0x09b9f1a,
  47916. 0x0499c2b, 0x18d74a7, 0x1db7e48, 0x199840b, 0x076cf28, 0x193fdd4,
  47917. 0x15fdf3a, 0x141e03e, 0x1b746e1, 0x1a79fe9, 0x180fc7c, 0x183a427,
  47918. 0x1c4a742, 0x0c05076, 0x01f7ae1, 0x195584e, 0x0848bc5, 0x1c8fd78,
  47919. 0x0743d75, 0x00f58eb, 0x1f514ad, 0x1e2988b, 0x1cd2413, 0x1b2b472,
  47920. 0x1bb70f3, 0x125654b, 0x1582656, 0x193ff38, 0x03cf384 },
  47921. { 0x01fc9e3, 0x0835d67, 0x0e65c01, 0x04ced60, 0x0972174, 0x15fbd9a,
  47922. 0x06e379c, 0x1ee5694, 0x079b209, 0x1430154, 0x1aa3872, 0x17219c4,
  47923. 0x1a90580, 0x1f1279c, 0x1cce6df, 0x0c5c23d, 0x1916293, 0x05b62ec,
  47924. 0x1dec93d, 0x0e9c34a, 0x11e9511, 0x1a82f22, 0x1ce03f2, 0x106437b,
  47925. 0x17afb14, 0x0957a6c, 0x0dd1f97, 0x13300d7, 0x19a6080, 0x0eb2df4,
  47926. 0x0821549, 0x1a8abd0, 0x04828d9, 0x1053293, 0x1017615, 0x011918a,
  47927. 0x1103077, 0x13f39e3, 0x17c98f1, 0x0a1dce7, 0x02b2488 },
  47928. { 0x141159f, 0x1e6f342, 0x02c885c, 0x109f682, 0x18224c1, 0x1650e3b,
  47929. 0x018647c, 0x0800f45, 0x0a8b23e, 0x16103eb, 0x08d1294, 0x04214d6,
  47930. 0x05071a0, 0x1af694a, 0x03961f2, 0x198d9b6, 0x0ef810f, 0x0b62b5c,
  47931. 0x0b610ee, 0x118b1ec, 0x0975124, 0x1eba633, 0x12e40d8, 0x0d8cdec,
  47932. 0x0f7f2e6, 0x05f31a4, 0x07049af, 0x05f3a88, 0x0e49e8b, 0x1951b9e,
  47933. 0x1c2b01f, 0x1d0361b, 0x0486758, 0x110e8a9, 0x1534751, 0x1942116,
  47934. 0x14414a1, 0x130f673, 0x108545c, 0x198d475, 0x0938b3b },
  47935. { 0x0ded340, 0x050b5f2, 0x00daa79, 0x1501d10, 0x0e65fb2, 0x0b9d65c,
  47936. 0x0581b73, 0x1532e11, 0x0aaa657, 0x01d021a, 0x006c187, 0x18b0922,
  47937. 0x0cf304f, 0x0d05db2, 0x03ed86b, 0x05bebcc, 0x0ecf554, 0x1c0c615,
  47938. 0x1bddb57, 0x040aeca, 0x1d97740, 0x0849299, 0x0d59ade, 0x1add6bf,
  47939. 0x055e574, 0x05bd723, 0x16956d1, 0x01ef436, 0x147ea56, 0x0bcdc9b,
  47940. 0x159e5c0, 0x1e5b59c, 0x0e7e0e8, 0x01e0345, 0x181e13a, 0x03308e8,
  47941. 0x1530734, 0x1464f68, 0x075ac93, 0x14bb3d1, 0x06cff58 },
  47942. { 0x1e51f68, 0x000d801, 0x1f59423, 0x0a3a5fc, 0x01d1f22, 0x1ec402f,
  47943. 0x0342c26, 0x16fef33, 0x003e415, 0x0af483d, 0x165e609, 0x0cfac0f,
  47944. 0x16d1484, 0x0da29c4, 0x170ec7a, 0x0a1e80a, 0x013809f, 0x01a8008,
  47945. 0x008cff7, 0x165f4da, 0x00b8fbb, 0x057f8c1, 0x02da02c, 0x1a62fc0,
  47946. 0x004dc38, 0x1efd8ea, 0x1333231, 0x067aa88, 0x013f841, 0x03f3376,
  47947. 0x121fea1, 0x008dc5c, 0x13f83d8, 0x1d9d661, 0x1f15218, 0x0e78c4f,
  47948. 0x0b936af, 0x13fc557, 0x04c9d7d, 0x11e636f, 0x05fe4ac },
  47949. { 0x16f401e, 0x1525fc5, 0x1b51606, 0x075ab8f, 0x05db12a, 0x183da50,
  47950. 0x01c99be, 0x1a8f603, 0x09c22bc, 0x0e88f82, 0x1c7257f, 0x0fa8d26,
  47951. 0x0f5454a, 0x0cd2375, 0x1b157ee, 0x12da00c, 0x07c7fef, 0x00c31be,
  47952. 0x0e0fa57, 0x183a68d, 0x02dcbaf, 0x09805da, 0x1570e16, 0x1cfce24,
  47953. 0x1ec2b34, 0x1746ec6, 0x02c6133, 0x13939f6, 0x0278646, 0x062124d,
  47954. 0x19e3730, 0x04021e5, 0x10d95f2, 0x1d21014, 0x1325a5d, 0x1b0dc4a,
  47955. 0x0b2abda, 0x098e44f, 0x0152082, 0x0c82438, 0x0813771 },
  47956. { 0x05a8edf, 0x1592f4e, 0x1eb5899, 0x0420f14, 0x0e1388c, 0x1b776fb,
  47957. 0x1cdf521, 0x02ebe04, 0x1627446, 0x017d3fc, 0x14e0a89, 0x17b3670,
  47958. 0x0f3e2cf, 0x017b8df, 0x16b5ec4, 0x0152575, 0x0fa677d, 0x02b155e,
  47959. 0x07f7fcd, 0x1d7a2ea, 0x0c78573, 0x093e128, 0x15fd961, 0x0f9512d,
  47960. 0x116eec4, 0x04f7067, 0x019d88b, 0x199af36, 0x12c0758, 0x0c417c7,
  47961. 0x054c7f1, 0x14c010a, 0x032b37e, 0x062dd49, 0x0d860ba, 0x1c9af76,
  47962. 0x12f146f, 0x1239ae6, 0x16e62fc, 0x1dd39a5, 0x079c280 },
  47963. { 0x0b48122, 0x04101f9, 0x123af73, 0x0d60958, 0x08c0491, 0x02442f5,
  47964. 0x193727f, 0x03959e0, 0x182c100, 0x1c1c4cb, 0x178942a, 0x0e42ced,
  47965. 0x007339e, 0x070d5c1, 0x0a96baa, 0x0965c2f, 0x0a06bc1, 0x0126946,
  47966. 0x05ad88c, 0x18b76f0, 0x1606570, 0x0e67735, 0x1b1448d, 0x07d5c84,
  47967. 0x1f89f18, 0x1a58d95, 0x1a71989, 0x1c75e78, 0x1e38bc3, 0x02135a8,
  47968. 0x0ef82c1, 0x0e7c81c, 0x0dbc58e, 0x12df213, 0x15e2d6f, 0x107f3ba,
  47969. 0x12c8f40, 0x0cfbc8a, 0x1fd3e7f, 0x14953c7, 0x0758073 },
  47970. { 0x091ca22, 0x1d82bc3, 0x06d9f49, 0x0c27454, 0x1206bfd, 0x1caa09f,
  47971. 0x14e16b1, 0x00fd097, 0x0755366, 0x0e8c515, 0x0389331, 0x1bcf914,
  47972. 0x1d2e166, 0x1e23a6d, 0x155d430, 0x10874ad, 0x0c11366, 0x16f7a22,
  47973. 0x1d2e10c, 0x08dca79, 0x1783146, 0x1854fec, 0x12f0340, 0x0fdc406,
  47974. 0x0c82429, 0x163ded2, 0x1ff5ef9, 0x1a16217, 0x07f3ff3, 0x123b046,
  47975. 0x114b485, 0x169fa98, 0x0e52599, 0x0f08203, 0x1e8527a, 0x1bf7573,
  47976. 0x0661d32, 0x0153fd4, 0x1aaa24d, 0x0b1f5ec, 0x03f3e34 },
  47977. { 0x11597aa, 0x01ad7ca, 0x13ad47b, 0x1893bec, 0x1677d4a, 0x1a77fad,
  47978. 0x136726f, 0x06a04ed, 0x1515a29, 0x11f6524, 0x0ee70d0, 0x0aa7fb3,
  47979. 0x1c8a696, 0x16f0f84, 0x07ba77f, 0x0bf31f3, 0x156199e, 0x15c7d14,
  47980. 0x14a4b0c, 0x070eb06, 0x081bb76, 0x0e7e207, 0x01cd3b7, 0x08afb2b,
  47981. 0x15e9f65, 0x095ec16, 0x18c31e3, 0x11dc647, 0x033d67c, 0x172660a,
  47982. 0x0bb9dec, 0x0790629, 0x0d9f807, 0x117b1ab, 0x1788a83, 0x1c883dd,
  47983. 0x0c48295, 0x0f0bf6b, 0x053bc7a, 0x1886985, 0x0640d20 },
  47984. { 0x084d513, 0x105c719, 0x14e93a6, 0x0be62a0, 0x074c354, 0x166a950,
  47985. 0x1d01d16, 0x16f66dc, 0x01de50d, 0x005ee7e, 0x07f11b6, 0x0fb84a9,
  47986. 0x088d9d4, 0x181f83d, 0x0dbbc4c, 0x1a98453, 0x0ca6d4a, 0x1a7230d,
  47987. 0x127c6dc, 0x1c6a3bf, 0x0e65ca8, 0x06aba30, 0x02f1025, 0x065a6cf,
  47988. 0x02b330f, 0x1745b18, 0x18a15d0, 0x1340e96, 0x0c29c36, 0x1588c3b,
  47989. 0x1eb7f94, 0x12257a2, 0x19e4609, 0x1531cf9, 0x1598d26, 0x031dc81,
  47990. 0x072e05c, 0x1448156, 0x0a05ae5, 0x15181b2, 0x00f9c1c },
  47991. { 0x1433df3, 0x1d559b3, 0x0a307ae, 0x0e2ba6c, 0x16aa534, 0x1862e65,
  47992. 0x083625f, 0x1f22746, 0x165e408, 0x1648c65, 0x1cd145c, 0x10a9aa6,
  47993. 0x094b638, 0x05a6e50, 0x04e668c, 0x0264ce6, 0x1300a3b, 0x06792b3,
  47994. 0x1822ce2, 0x0c1bf4c, 0x0dfd5ea, 0x183d948, 0x162b5d2, 0x0d29f36,
  47995. 0x02789d7, 0x1d8c190, 0x02d98c3, 0x10b27b7, 0x1e3eaf4, 0x1fb8632,
  47996. 0x1e0f6d1, 0x07ce4c7, 0x1949c91, 0x17f99b1, 0x1b1b9b9, 0x0137359,
  47997. 0x098a824, 0x1ecdd38, 0x1bb14d2, 0x05e8ba6, 0x07e31c1 },
  47998. { 0x1fd2dd7, 0x00eb406, 0x0762f8a, 0x004956c, 0x1efacb0, 0x018fcb8,
  47999. 0x0017e51, 0x1797386, 0x0959cb3, 0x10646fd, 0x0ed0199, 0x18619ff,
  48000. 0x0dfdd5f, 0x1cb4d08, 0x118c6f9, 0x1fa36f4, 0x09ede13, 0x119b718,
  48001. 0x1251c1d, 0x077f5bf, 0x022376b, 0x0eee639, 0x1ea4649, 0x0d89dc3,
  48002. 0x10d7315, 0x1a3ba0f, 0x0438acd, 0x1ec9dc8, 0x04d93c4, 0x0969f7e,
  48003. 0x0ba1afa, 0x1f89f76, 0x13b7e03, 0x050dde2, 0x13d4cdf, 0x015832d,
  48004. 0x1e23ba6, 0x120d183, 0x14d5d37, 0x08a64da, 0x01a219c },
  48005. { 0x04db0bc, 0x1bf7c55, 0x058ff73, 0x0cf6d93, 0x0e23180, 0x050c979,
  48006. 0x0419cf6, 0x0e384c7, 0x0ffdc77, 0x0676171, 0x103b6f0, 0x1c6b45f,
  48007. 0x03997c8, 0x0166302, 0x1843b06, 0x10240f1, 0x0cb2b0c, 0x17e86f1,
  48008. 0x0795fe3, 0x188afed, 0x11c34d6, 0x192da9f, 0x054f9a6, 0x1f13971,
  48009. 0x0330ac4, 0x1f32115, 0x065559a, 0x05fe465, 0x1442d19, 0x0816a1b,
  48010. 0x00dcf35, 0x17d4d28, 0x04ce590, 0x1833178, 0x0dfbe00, 0x06d582a,
  48011. 0x16d0bf9, 0x15e7bbd, 0x064bf80, 0x1337920, 0x017aaa9 },
  48012. { 0x055db2e, 0x0ab21c7, 0x014434f, 0x067728d, 0x035dee4, 0x042317c,
  48013. 0x103956e, 0x0f83428, 0x1ea17e2, 0x17f9d9a, 0x17dea69, 0x186dbb2,
  48014. 0x0f23f99, 0x1eeb396, 0x05ff766, 0x08b80e4, 0x01edd20, 0x0fa0056,
  48015. 0x1fc1ac9, 0x0ab90e9, 0x09be94b, 0x1287252, 0x0291283, 0x076d026,
  48016. 0x05e91b4, 0x162f449, 0x04853e5, 0x117dbbc, 0x17fa977, 0x152607c,
  48017. 0x19c3d15, 0x14b7fa4, 0x08fd86b, 0x10477d1, 0x163ef9d, 0x1876965,
  48018. 0x026474b, 0x0affc61, 0x0c92bef, 0x1e14be7, 0x06b282a },
  48019. { 0x141a595, 0x0012fb1, 0x0a31e3f, 0x0d488bc, 0x191c38d, 0x0234212,
  48020. 0x1b8f7ad, 0x066e57a, 0x1755478, 0x1ca3369, 0x185b10f, 0x09a6107,
  48021. 0x1491141, 0x0ad3d65, 0x176519a, 0x1f6c828, 0x1098fd2, 0x08816ef,
  48022. 0x0ff61ec, 0x165a5a1, 0x10882a2, 0x0e2ca2a, 0x1a7a6f9, 0x0048bbc,
  48023. 0x18bf4a8, 0x187771b, 0x02c8c1a, 0x01617ad, 0x1e9f3d8, 0x02e3615,
  48024. 0x115da95, 0x0900584, 0x09d167b, 0x096fda1, 0x109cad0, 0x0427cc8,
  48025. 0x0e8d976, 0x127a94f, 0x1bafed9, 0x046a8e0, 0x06d4f5d },
  48026. { 0x0ba9f88, 0x0795b00, 0x02fcd72, 0x00f76da, 0x1dc807e, 0x1c0f2df,
  48027. 0x1b50ace, 0x03c1424, 0x0a7ac78, 0x1ae7367, 0x172e98c, 0x1cdfe6f,
  48028. 0x073e308, 0x11e4b24, 0x0372989, 0x0869a05, 0x17e8818, 0x13975d2,
  48029. 0x06de289, 0x07ab3ef, 0x0ea3a9e, 0x0e9783d, 0x14bc29f, 0x1a0bee9,
  48030. 0x0467824, 0x15b707f, 0x00045b7, 0x0410a2e, 0x137580b, 0x0f492c7,
  48031. 0x0ce70a9, 0x0e80e17, 0x18bd7a5, 0x1bec873, 0x01cae65, 0x08aa3f9,
  48032. 0x00db81b, 0x0d49e22, 0x0d2b5bb, 0x09facba, 0x04aaf0b },
  48033. { 0x114c7af, 0x192831a, 0x1ab66fb, 0x1b78303, 0x109e7da, 0x11f62c5,
  48034. 0x0ba1e3e, 0x10bde79, 0x1173b86, 0x06dfd5a, 0x14cb776, 0x1f81243,
  48035. 0x06b2490, 0x05ece23, 0x1bce1ae, 0x1b7b69d, 0x12fa061, 0x1e0e6ea,
  48036. 0x16f0136, 0x1d31344, 0x063664d, 0x15c2b94, 0x01be60d, 0x1c89540,
  48037. 0x1a8048b, 0x06388d2, 0x1825c06, 0x0dbdbc9, 0x011fb11, 0x02bbd96,
  48038. 0x165cabb, 0x14e43d9, 0x04dade1, 0x1f9d48a, 0x09af5ba, 0x0ff338a,
  48039. 0x1c2e14d, 0x0a0b2d8, 0x18cde87, 0x0730578, 0x08b2cbd },
  48040. { 0x052e991, 0x00df945, 0x0bb0a3b, 0x0d9f3a8, 0x0ba202f, 0x1a75228,
  48041. 0x144c318, 0x139060f, 0x1c5762b, 0x1e12bd9, 0x10a8b4f, 0x11a290f,
  48042. 0x0abd329, 0x118ca44, 0x053c69e, 0x00da594, 0x13b06ba, 0x0e38654,
  48043. 0x19017a2, 0x07e967d, 0x0ae79aa, 0x199aef7, 0x13193ba, 0x17e3a99,
  48044. 0x1f57803, 0x1fee8aa, 0x151585a, 0x083d816, 0x0e33f60, 0x0073043,
  48045. 0x1d48f7e, 0x1e04879, 0x19a79c8, 0x066ac1c, 0x093a1d3, 0x030d850,
  48046. 0x0fc5c83, 0x0775764, 0x0d9c088, 0x008fb7c, 0x057e283 },
  48047. { 0x1cdf666, 0x05b4c7d, 0x0749b98, 0x1317d76, 0x1dd06a9, 0x04c21b5,
  48048. 0x0b6ea01, 0x11a8089, 0x0522bc8, 0x1b5fbaf, 0x08ec835, 0x1736508,
  48049. 0x12655c4, 0x099cc53, 0x103d249, 0x0ec02cb, 0x0b70ca3, 0x13b6a79,
  48050. 0x00c3e96, 0x11324a4, 0x0705469, 0x03db02a, 0x05acdfa, 0x1bc365f,
  48051. 0x0f73153, 0x182f7cb, 0x12b553b, 0x1d97791, 0x1617b05, 0x0e85549,
  48052. 0x1f7aca2, 0x0f97442, 0x0c0fbd5, 0x0516b9d, 0x0d58675, 0x07a1a79,
  48053. 0x091d606, 0x1f74ea6, 0x1f69ba2, 0x06ed2df, 0x04f12e0 },
  48054. { 0x1f1a610, 0x1d2110a, 0x0669333, 0x0a6f0ca, 0x004a5c5, 0x01c09a4,
  48055. 0x09151ce, 0x054248d, 0x04b284e, 0x10ada42, 0x144c83e, 0x18ca28d,
  48056. 0x1a36464, 0x1854507, 0x1aea231, 0x1009df6, 0x0e793c4, 0x13a73e7,
  48057. 0x056b85a, 0x09a4597, 0x14dd8c3, 0x0ffce0e, 0x0767b62, 0x004a6e3,
  48058. 0x0866d32, 0x02530d0, 0x0a6f591, 0x0b64656, 0x17bab14, 0x1496793,
  48059. 0x00be223, 0x1528916, 0x1e69c6e, 0x10f65b9, 0x1aa56d4, 0x043492d,
  48060. 0x1858afb, 0x1bc753a, 0x1be46a3, 0x07d624c, 0x083d233 },
  48061. { 0x1b478d7, 0x1994433, 0x1270718, 0x02a145f, 0x01ee1ae, 0x09120dd,
  48062. 0x0acc063, 0x12c0b6d, 0x0893cd6, 0x0f8f944, 0x05ea1da, 0x0cc1502,
  48063. 0x17159d6, 0x18739eb, 0x0480465, 0x0be15d0, 0x10093f5, 0x12947f7,
  48064. 0x01537ec, 0x0f1b71b, 0x1fbbb39, 0x1b7a2ec, 0x15ad0fb, 0x17dc72f,
  48065. 0x04bfed5, 0x0d68bef, 0x05afddb, 0x003c1eb, 0x00754ca, 0x14071ea,
  48066. 0x1cca2c8, 0x1f1d0dd, 0x0db6122, 0x0f2c347, 0x1abedf4, 0x17044d6,
  48067. 0x0f40a55, 0x1a990a9, 0x0588518, 0x07d8b46, 0x07362f1 },
  48068. { 0x1c0c430, 0x1593e39, 0x195de4b, 0x1f4a386, 0x0cc0a65, 0x0ca78dc,
  48069. 0x13b3b48, 0x08ea14b, 0x0814b49, 0x04a2b44, 0x1eefd06, 0x103496d,
  48070. 0x08bbf0a, 0x1855430, 0x1bd3d63, 0x0f2bc6e, 0x1683987, 0x0ec9b0e,
  48071. 0x0ea3435, 0x0219b1c, 0x0455b65, 0x1fdb60d, 0x18f8bf6, 0x19123f2,
  48072. 0x1154eae, 0x1b21648, 0x17fd5a3, 0x1d63ce2, 0x0b399e0, 0x0e6b979,
  48073. 0x02f9ebe, 0x113e17e, 0x1c39bac, 0x01b4a8f, 0x164a426, 0x11e10c3,
  48074. 0x1a0a20a, 0x18b7816, 0x03ab766, 0x07f4718, 0x02f1069 },
  48075. { 0x006ded2, 0x1674886, 0x01ec1e9, 0x1e5fb21, 0x1974842, 0x1b1ad37,
  48076. 0x0ff5aa7, 0x04dc8d1, 0x11ed606, 0x05b0c48, 0x1b95201, 0x113e6d3,
  48077. 0x011fb2f, 0x0e4b510, 0x0f4444f, 0x0675939, 0x0fe10d6, 0x133acd6,
  48078. 0x1ea98a7, 0x14cdf91, 0x028364b, 0x04a3f9c, 0x09a1ab9, 0x139b533,
  48079. 0x03a05d5, 0x1b74146, 0x1023a8b, 0x18f5f62, 0x1953c87, 0x0472579,
  48080. 0x13c9547, 0x13b553c, 0x153d279, 0x18ca02d, 0x0352b5b, 0x163dfed,
  48081. 0x16437cd, 0x1aedeec, 0x0810c9d, 0x1c89fcf, 0x0985f83 },
  48082. { 0x0f45294, 0x01e0b75, 0x1d46258, 0x018496a, 0x1013116, 0x0b5a96b,
  48083. 0x08060e7, 0x0809822, 0x0ed9433, 0x03ce781, 0x106da1c, 0x0516e9e,
  48084. 0x010c5b0, 0x0e4560f, 0x10fc1da, 0x09e1c7b, 0x0a3f8b2, 0x12d62f7,
  48085. 0x0d31708, 0x0d0975c, 0x052aee6, 0x11cd5e2, 0x0949679, 0x1be8b99,
  48086. 0x12cd1e9, 0x07d583e, 0x0c6910f, 0x0e03392, 0x0003b30, 0x0d54c96,
  48087. 0x0b9a3f7, 0x01b1978, 0x19f179c, 0x00e5396, 0x09bc79e, 0x1377e2b,
  48088. 0x10dcc79, 0x0bbceaa, 0x18bc553, 0x0801fd2, 0x00c88e5 },
  48089. { 0x0f44357, 0x18d3574, 0x0daa13d, 0x0c74795, 0x175b4bf, 0x15e3407,
  48090. 0x076796b, 0x1e46699, 0x08a753e, 0x1657842, 0x18f23b3, 0x09820eb,
  48091. 0x1ae2801, 0x1ba7c69, 0x07568e3, 0x0655d77, 0x064b80e, 0x13acc42,
  48092. 0x0af0de4, 0x051cdfe, 0x01977b3, 0x17f7687, 0x1aeec7e, 0x0660cb5,
  48093. 0x0ac955a, 0x07433a7, 0x1e48b6f, 0x1833fb1, 0x1b907a8, 0x1742cc3,
  48094. 0x15e305e, 0x0767459, 0x1f33627, 0x1bb97c4, 0x0067ea1, 0x0dd75d4,
  48095. 0x1a25ced, 0x0ef24c9, 0x01c5539, 0x1715e22, 0x08e2560 },
  48096. { 0x141aba6, 0x1ba3618, 0x1e795b4, 0x1f75659, 0x05a1079, 0x0e93e3a,
  48097. 0x0a0c673, 0x01d6c70, 0x09dfd95, 0x111bb19, 0x1023fc8, 0x0b9a752,
  48098. 0x181e0b1, 0x188b008, 0x0a00802, 0x1774e93, 0x15da383, 0x0938ced,
  48099. 0x14411b5, 0x106814c, 0x1b1f607, 0x0f4ba91, 0x024a753, 0x0145157,
  48100. 0x0345c8e, 0x0e3a020, 0x082b7c2, 0x024eb58, 0x11d6116, 0x1932919,
  48101. 0x142d06a, 0x0a72394, 0x10cc77c, 0x1118a91, 0x124a3e4, 0x13117c1,
  48102. 0x12fd9a2, 0x19ec95c, 0x1cb97fb, 0x0450649, 0x059005f },
  48103. { 0x04c1c74, 0x0ba861e, 0x0de5aec, 0x01d2cdf, 0x1e73aac, 0x02cb9fd,
  48104. 0x176499b, 0x16d0b4e, 0x03a8656, 0x04bfc99, 0x11b37a3, 0x0762a08,
  48105. 0x1f2b704, 0x1ff9c4b, 0x0245bdc, 0x0e564a9, 0x01cb18b, 0x1489ee8,
  48106. 0x0230379, 0x0ea3e29, 0x0a58d0a, 0x0a42ac6, 0x0645d5c, 0x14cc7b4,
  48107. 0x1430144, 0x10c4bb8, 0x12c3821, 0x1be3215, 0x1ead9c2, 0x1e0679c,
  48108. 0x0840203, 0x02e705b, 0x085ac6e, 0x1519c00, 0x0144c98, 0x1bd2f23,
  48109. 0x143bae8, 0x04ac9b5, 0x17dbb91, 0x04daf07, 0x057a78e },
  48110. { 0x0dbddd8, 0x19a37a0, 0x0eb0586, 0x0f28218, 0x0b49a92, 0x03679d9,
  48111. 0x09e0c62, 0x1d718a8, 0x033b93d, 0x16f9919, 0x1d5e75c, 0x13ea81b,
  48112. 0x009c8d5, 0x01077a8, 0x15e99f7, 0x10c87cb, 0x11867f0, 0x1e2359c,
  48113. 0x165ab70, 0x14488b5, 0x04d0ecf, 0x0d8622a, 0x1963d62, 0x1082fae,
  48114. 0x09301e0, 0x1447376, 0x0b11538, 0x194bded, 0x0f462d6, 0x0247d60,
  48115. 0x0d90644, 0x011b140, 0x12407d8, 0x1adbf42, 0x0e9fdb4, 0x0f698a6,
  48116. 0x0f6ada8, 0x08f2094, 0x1cba0c9, 0x18b0388, 0x01ca370 },
  48117. { 0x001b68a, 0x0a8b8d4, 0x02ce52f, 0x19fa333, 0x1312879, 0x0b19013,
  48118. 0x0aafd04, 0x1b6920b, 0x0f5b01f, 0x0ff43fa, 0x084a2ed, 0x047539b,
  48119. 0x1778de5, 0x03de98f, 0x1c58687, 0x0986a17, 0x1d02390, 0x0daef67,
  48120. 0x0623c4b, 0x165105c, 0x0e74224, 0x0efcced, 0x0374a00, 0x19a39a4,
  48121. 0x067b508, 0x11ce56a, 0x170219f, 0x1862387, 0x0250726, 0x0b9015a,
  48122. 0x00dc684, 0x05dfb20, 0x1bf464e, 0x09d81c1, 0x122876f, 0x14a7a08,
  48123. 0x06265ba, 0x0da97a7, 0x0b1e4cb, 0x0989867, 0x02584b3 },
  48124. { 0x0eec688, 0x031c495, 0x148cf2e, 0x148bf7c, 0x05e740b, 0x105afc5,
  48125. 0x1c7dff5, 0x07a845c, 0x0487491, 0x0ae8c2e, 0x1f60351, 0x166df42,
  48126. 0x0404c2b, 0x1602a29, 0x09c6152, 0x14cae7e, 0x045a8b9, 0x03b6e98,
  48127. 0x0bb9f32, 0x0587c2c, 0x07d02e4, 0x0326fb6, 0x000999c, 0x0f96910,
  48128. 0x1dd51dc, 0x1f02c93, 0x1861e25, 0x167f557, 0x15737c6, 0x0917796,
  48129. 0x1fff9ab, 0x1fea353, 0x1b60269, 0x03dd557, 0x1515a60, 0x15c3906,
  48130. 0x151ca49, 0x0edb7fc, 0x0c216b3, 0x0e87f35, 0x07e8113 },
  48131. { 0x10a88b1, 0x11545c1, 0x1f86b5c, 0x119c222, 0x11918ea, 0x04da3ec,
  48132. 0x142e010, 0x1a67c05, 0x16c46d1, 0x09c0969, 0x059a72d, 0x1b61cb1,
  48133. 0x1e2fd09, 0x0ad866a, 0x1173418, 0x188a730, 0x15a2386, 0x1860e0a,
  48134. 0x17fd0f2, 0x0e9bcbe, 0x00cdda7, 0x0c71c8e, 0x0ec1dae, 0x009e50d,
  48135. 0x11eff50, 0x1ff4beb, 0x12bbb02, 0x07c168d, 0x01ad942, 0x0333995,
  48136. 0x08b914e, 0x072db48, 0x00c9f81, 0x195ff7f, 0x06898f6, 0x02c6ed8,
  48137. 0x1a56fa9, 0x0e3c8c5, 0x0169800, 0x0c9bf09, 0x0436b8c },
  48138. { 0x0b764bc, 0x0bf4ec5, 0x1e12204, 0x0940efb, 0x1fa61e9, 0x0c775ee,
  48139. 0x1974c30, 0x1b8b4ee, 0x1fc9451, 0x0448b57, 0x08d1e95, 0x1c660e3,
  48140. 0x1f01a52, 0x191da0e, 0x0ee577a, 0x1850cc6, 0x0c943c8, 0x06ebeb4,
  48141. 0x0365c1a, 0x13a83c3, 0x199de4f, 0x0846493, 0x1e6422e, 0x0e72946,
  48142. 0x0148ed4, 0x09ff30a, 0x1f35479, 0x0a030a2, 0x03dcb6e, 0x03af012,
  48143. 0x0154180, 0x02f2a88, 0x1dcde62, 0x0d2fff2, 0x03854df, 0x0cdef92,
  48144. 0x0768cb6, 0x1bd5720, 0x0578477, 0x13cdb7d, 0x05266ca },
  48145. { 0x186b3db, 0x0f73689, 0x1502137, 0x14f871c, 0x19e4af5, 0x027a4ef,
  48146. 0x01103ac, 0x1fb6683, 0x0fde5a4, 0x09c50f4, 0x15f3f08, 0x1248604,
  48147. 0x013e6e6, 0x0cfeb86, 0x0671b8c, 0x03fe06a, 0x17486c3, 0x0479a70,
  48148. 0x103387a, 0x0531fb2, 0x0d7cf1e, 0x0e8a4b0, 0x1bee32c, 0x05e77fe,
  48149. 0x013472b, 0x07f903e, 0x1051bbe, 0x1334416, 0x13e2208, 0x1b15bde,
  48150. 0x09df7b0, 0x0c4d7d4, 0x175044e, 0x065b3d4, 0x11253ed, 0x141e656,
  48151. 0x1fc6703, 0x1d04900, 0x128af05, 0x17339b0, 0x041f325 },
  48152. { 0x02843a4, 0x16a89e7, 0x0bf0c4b, 0x1c00e51, 0x0748498, 0x032672f,
  48153. 0x0a08936, 0x07751de, 0x0a62008, 0x0032382, 0x14ce34d, 0x03b297d,
  48154. 0x185905e, 0x031f3d9, 0x15e32d4, 0x0f77254, 0x196289e, 0x0cc13b6,
  48155. 0x05edcd0, 0x05b88fe, 0x0944dfe, 0x0f8ed64, 0x1648d48, 0x080154e,
  48156. 0x0d28d23, 0x1219edb, 0x1a9d86e, 0x0c8ee0b, 0x1d07ddc, 0x1d36cdf,
  48157. 0x1f6251e, 0x0485951, 0x0f2e3ac, 0x01a3400, 0x19c3ae3, 0x1a93de8,
  48158. 0x19aa18f, 0x19e9bde, 0x1aa79f6, 0x16dcb19, 0x056b30f },
  48159. { 0x180a428, 0x06e5566, 0x02441fb, 0x190e659, 0x1af922d, 0x0d220fb,
  48160. 0x01e60eb, 0x11441b1, 0x0924b00, 0x1f6cd22, 0x0070e8e, 0x067965d,
  48161. 0x1321235, 0x12fc03e, 0x13901d5, 0x15d9786, 0x1a51f2f, 0x085fd77,
  48162. 0x17a2a23, 0x0c694b5, 0x0a9178b, 0x1c4a1c9, 0x11382df, 0x17639b1,
  48163. 0x0237790, 0x0571849, 0x0be1c81, 0x1d5369f, 0x13cd83d, 0x00fac2e,
  48164. 0x1e4fb7e, 0x18ca474, 0x0f88c51, 0x06cb4ac, 0x0e2c5f0, 0x0fc8e5f,
  48165. 0x1ccf7f0, 0x0840f2e, 0x1451a26, 0x0aeb17b, 0x01353cc },
  48166. { 0x1bf6e18, 0x0b24b9c, 0x071ca29, 0x04c9371, 0x19e8b5a, 0x145c73a,
  48167. 0x0d28373, 0x0191b28, 0x1204704, 0x09adfa8, 0x0e3a0b6, 0x02c8d4f,
  48168. 0x142ab3a, 0x13fc094, 0x160fb58, 0x0e52fe2, 0x1e072d6, 0x1c20b53,
  48169. 0x14e790a, 0x10bb0d9, 0x1bad496, 0x03cac6e, 0x029e5ff, 0x0b9cdbd,
  48170. 0x0f92815, 0x11ad2ac, 0x03e28d8, 0x0be9cae, 0x077ae57, 0x07e0294,
  48171. 0x0f6f1a7, 0x14d62dd, 0x14193a9, 0x060f8c7, 0x10f2ec7, 0x131a3be,
  48172. 0x1a21e78, 0x1d41872, 0x17d61c8, 0x0bbe8a3, 0x03ec218 },
  48173. { 0x10bc2d7, 0x063eb8f, 0x104ae75, 0x18dca3a, 0x0982c6c, 0x0fc07b3,
  48174. 0x0b64e82, 0x13925c0, 0x1047ae0, 0x1ee9692, 0x0d47e6d, 0x093e6fe,
  48175. 0x1e35031, 0x03bc285, 0x1527387, 0x1a590d3, 0x0cb12f0, 0x0b01215,
  48176. 0x0f0a2e7, 0x1118acf, 0x0550ba1, 0x10835e0, 0x0390184, 0x0fa8653,
  48177. 0x04b1f8d, 0x0f0586c, 0x1f4e254, 0x094cf5c, 0x097607b, 0x02bdc5e,
  48178. 0x1cad49f, 0x0a92f54, 0x093c5f3, 0x0eb335e, 0x0330e6f, 0x06be3bd,
  48179. 0x09d447a, 0x03ee2e7, 0x0af94c2, 0x16d4423, 0x089b356 },
  48180. { 0x1dcc837, 0x0d857ef, 0x1ea7b5b, 0x1550e36, 0x0fb80ba, 0x0ea5b90,
  48181. 0x0ff2470, 0x0b88275, 0x1adac9e, 0x0dab5fb, 0x195e8fd, 0x05b5170,
  48182. 0x0e5664a, 0x0720eca, 0x0c13dc8, 0x06cb023, 0x1263743, 0x131f08e,
  48183. 0x109b6ba, 0x051d9de, 0x0dc2ee6, 0x04e58b1, 0x0045867, 0x0c90c86,
  48184. 0x1817f87, 0x0434e7a, 0x095612f, 0x03772e0, 0x1f7928e, 0x1e77805,
  48185. 0x194b309, 0x1b8c1dd, 0x0f3a80e, 0x0e17ca7, 0x0afa1eb, 0x04fc240,
  48186. 0x0a0d4f5, 0x178c704, 0x1449995, 0x01aaf8b, 0x039c4f1 },
  48187. { 0x08aecd3, 0x0db4674, 0x0a76cea, 0x114a315, 0x155b091, 0x0a772a2,
  48188. 0x136b52f, 0x109db83, 0x102068d, 0x0db45b3, 0x0b1cb5e, 0x01a1023,
  48189. 0x187dac8, 0x140d053, 0x079b4d6, 0x0c506da, 0x1ea3bd1, 0x06420f4,
  48190. 0x0531111, 0x182eeb1, 0x1202a7b, 0x12f8d50, 0x1cad8dc, 0x1a98aad,
  48191. 0x1767ec7, 0x08ddf63, 0x0f51bfd, 0x102fd76, 0x17e3392, 0x1f46b9f,
  48192. 0x113f796, 0x0b5da49, 0x0c6c977, 0x0bce7a2, 0x1c1edb9, 0x1817342,
  48193. 0x1069fbc, 0x18b23c4, 0x0ac033f, 0x05a922a, 0x0414b54 },
  48194. { 0x06e173b, 0x18f2c30, 0x04e8cf0, 0x1721cce, 0x1b7f4e1, 0x1d9057a,
  48195. 0x0d44b7a, 0x0e084bf, 0x105120e, 0x1c4630b, 0x0f93b31, 0x0c05202,
  48196. 0x173ef05, 0x00e3736, 0x074d6b2, 0x0d2153f, 0x08f9450, 0x17098f4,
  48197. 0x12bc20b, 0x1f36648, 0x0ea9708, 0x160dd15, 0x0cb9359, 0x01b6539,
  48198. 0x14a6e74, 0x003d78f, 0x034610c, 0x0957249, 0x156a6c7, 0x077c76a,
  48199. 0x0984cce, 0x04e1a2f, 0x08e623e, 0x07adffa, 0x0bea582, 0x0a78e6c,
  48200. 0x044e851, 0x0bbc3a2, 0x02ca90e, 0x0d5c017, 0x052678d },
  48201. { 0x136aeb4, 0x18e2cef, 0x02ad77f, 0x1952578, 0x12d6653, 0x1d2fc0a,
  48202. 0x1d25a49, 0x03e1c07, 0x02dfd49, 0x084ea0a, 0x07e26e1, 0x18a54ae,
  48203. 0x05258c2, 0x0999a24, 0x1586012, 0x13c1257, 0x14f3f7d, 0x10d19f4,
  48204. 0x106fe41, 0x0831a65, 0x095cfab, 0x072d52b, 0x1ce7124, 0x1a5afff,
  48205. 0x1196ef6, 0x0548720, 0x143de52, 0x1d9a80e, 0x053b4f3, 0x1cd9698,
  48206. 0x1252d63, 0x0bb32e9, 0x0ee842a, 0x17b415c, 0x1076fc8, 0x0c474b3,
  48207. 0x08efcea, 0x0d630a6, 0x1bb7411, 0x0b78219, 0x07040ba },
  48208. { 0x15a1a96, 0x127c0a8, 0x1f80b0d, 0x0630864, 0x11a6350, 0x0c9ea79,
  48209. 0x199406b, 0x0e61412, 0x1273b61, 0x0bb4a78, 0x16a74a7, 0x10eda59,
  48210. 0x178886d, 0x140a60b, 0x0069d08, 0x0d2d63c, 0x16b8667, 0x11a4913,
  48211. 0x0c97c01, 0x09e18cb, 0x0c4a2fd, 0x0ffd94a, 0x1949cd2, 0x03a66de,
  48212. 0x00d8ade, 0x10760ff, 0x039f8e1, 0x1f3447d, 0x14c31ea, 0x1b90dbb,
  48213. 0x12a5f4a, 0x086caf0, 0x0c3e582, 0x07551fd, 0x1d39c3d, 0x11fe5bf,
  48214. 0x1e87324, 0x140f0d7, 0x12704f4, 0x1ac17a3, 0x09043a6 },
  48215. { 0x06c7937, 0x0d07f3b, 0x0f8c544, 0x1957787, 0x1b2ded5, 0x0444560,
  48216. 0x1833380, 0x1e65582, 0x1616200, 0x143aa5e, 0x0ba81a4, 0x107a694,
  48217. 0x0fb801c, 0x0e5f083, 0x15e80ea, 0x19b2915, 0x022cedf, 0x04cb584,
  48218. 0x101a620, 0x068c75c, 0x1663c3c, 0x06facbf, 0x1ec4ba9, 0x19255f3,
  48219. 0x1383440, 0x0aa1646, 0x193a368, 0x13790b8, 0x0e801a7, 0x0fd16da,
  48220. 0x0ca55dc, 0x03c6af3, 0x1d2c138, 0x1683c3d, 0x177ffea, 0x0dc8b8e,
  48221. 0x173eac4, 0x1b051e5, 0x17cd6c1, 0x0907424, 0x026362b },
  48222. { 0x0fc3e89, 0x1469477, 0x19c4971, 0x0ed3d3d, 0x0d0ee87, 0x0f25ba9,
  48223. 0x0ee1abd, 0x067160f, 0x0cb86b3, 0x1b84839, 0x14aeb36, 0x01d5fea,
  48224. 0x09fd3d2, 0x0606d0f, 0x1bacac5, 0x0e28b4b, 0x08a44f9, 0x09c8fb4,
  48225. 0x181b521, 0x17a6203, 0x0d4921f, 0x12df54e, 0x11793ca, 0x17e43b4,
  48226. 0x0d464a7, 0x038bdb0, 0x0015355, 0x127f119, 0x00f2e91, 0x09e8df7,
  48227. 0x1cd6b39, 0x1828724, 0x0c26563, 0x15af749, 0x02ca5b1, 0x15390dc,
  48228. 0x09ff59b, 0x17f1188, 0x04d7914, 0x040aab9, 0x02e952b },
  48229. { 0x15f886e, 0x035e56b, 0x1160aa1, 0x1da87bf, 0x068a5db, 0x1d8dc37,
  48230. 0x116d801, 0x16a207c, 0x1355ff2, 0x0071764, 0x0fb3256, 0x1e4d44c,
  48231. 0x13bc702, 0x0c0f2f1, 0x0d6ce18, 0x040ec50, 0x1ec6c12, 0x0812889,
  48232. 0x1ef615b, 0x04dc74f, 0x1cb1a5c, 0x19ceb75, 0x03be0fe, 0x09a5f51,
  48233. 0x053f2a4, 0x14bbd55, 0x0d4ec7e, 0x1829de6, 0x159a307, 0x05088ba,
  48234. 0x183fd81, 0x16126ef, 0x1cd96b0, 0x1813995, 0x025b6cb, 0x0d4b829,
  48235. 0x0b53ef0, 0x054264f, 0x0392c70, 0x02e606f, 0x01236d0 },
  48236. { 0x084373b, 0x00e47e0, 0x1ebb5d2, 0x10c8c12, 0x09ae476, 0x1de1a59,
  48237. 0x17e8184, 0x1602601, 0x0934bc2, 0x18938a6, 0x0f9f88d, 0x0c521c5,
  48238. 0x0086524, 0x1680840, 0x13eee7f, 0x08aecaa, 0x1384231, 0x1787605,
  48239. 0x0c28ca0, 0x15eb286, 0x181765b, 0x1438377, 0x0ef7786, 0x0ea61d2,
  48240. 0x0727dba, 0x0e5be96, 0x19d3325, 0x1618bac, 0x18906db, 0x09b2921,
  48241. 0x1cecff3, 0x1a28cb1, 0x1881941, 0x1f8748c, 0x1555b25, 0x15cc2de,
  48242. 0x0b9ec7e, 0x1e16c2a, 0x0d5b8d4, 0x028c419, 0x002a480 },
  48243. { 0x06ccd38, 0x1691ea8, 0x0a98475, 0x0920b37, 0x029a1c5, 0x0808e29,
  48244. 0x0709da7, 0x0fae2f9, 0x0d82893, 0x03f0da3, 0x0d420fa, 0x1777070,
  48245. 0x18f5d63, 0x156d612, 0x09ed09e, 0x09a3fe1, 0x0bd9f15, 0x0ccd593,
  48246. 0x1b2557f, 0x01ff7f1, 0x1880dec, 0x13a4fe5, 0x1ba55f1, 0x00229bd,
  48247. 0x15dee1e, 0x163991c, 0x1cda7d1, 0x1254c96, 0x0b25991, 0x033048f,
  48248. 0x1690c11, 0x145d187, 0x02da887, 0x0b68c5f, 0x10970d5, 0x07489c5,
  48249. 0x155f75f, 0x1c820a5, 0x1ff80c4, 0x0df1e42, 0x01d8bde },
  48250. { 0x0028924, 0x09cfc51, 0x0e7c0f3, 0x1960dd9, 0x0e54f19, 0x182c233,
  48251. 0x0f2df5b, 0x0ed0c57, 0x05a0607, 0x1f0338b, 0x1fb0436, 0x12f5621,
  48252. 0x1c9397c, 0x178ddb2, 0x084e099, 0x17471e8, 0x0cba672, 0x120a6f6,
  48253. 0x022c179, 0x1a9a87f, 0x14d1594, 0x1d564a6, 0x1e64fd5, 0x162ec70,
  48254. 0x02a6abf, 0x0ad3a7e, 0x0edbf19, 0x1032d6b, 0x0d2139d, 0x0e42774,
  48255. 0x09b70dd, 0x06c1a74, 0x1b00a02, 0x09dc3dc, 0x0d737ae, 0x1d66dda,
  48256. 0x0c83209, 0x12d945e, 0x04f07d5, 0x0878c20, 0x0349c69 },
  48257. { 0x1e6c88a, 0x1ca2226, 0x01fb46c, 0x028e004, 0x15c2c47, 0x015bc06,
  48258. 0x1628887, 0x07d6de8, 0x0085099, 0x04fbab2, 0x1c3061d, 0x0af375d,
  48259. 0x10400ba, 0x19be387, 0x1d0a4e1, 0x0fd7e5a, 0x0ec2146, 0x1e2d471,
  48260. 0x0cdfd14, 0x14ccdca, 0x150a243, 0x03f685e, 0x12647c7, 0x17a3f23,
  48261. 0x13e90f4, 0x14d9d3f, 0x097c384, 0x0c113d1, 0x1896359, 0x10bb839,
  48262. 0x127434e, 0x04e3055, 0x0f842d5, 0x1e2e14e, 0x0a64205, 0x124232a,
  48263. 0x0725576, 0x17993f4, 0x163ea8c, 0x1571385, 0x0056587 },
  48264. { 0x0e4733d, 0x0b1768e, 0x1110021, 0x1731ca2, 0x1faff7c, 0x15a35ca,
  48265. 0x0087ea6, 0x026be06, 0x0b61a8c, 0x0a4a62f, 0x0d65da2, 0x006c6d6,
  48266. 0x1657c95, 0x1561697, 0x1a1323c, 0x0e07cd7, 0x0d89bd2, 0x1872d9a,
  48267. 0x1a1caae, 0x1b231ef, 0x0ee1c4a, 0x0fe2029, 0x10aa27a, 0x1216a3d,
  48268. 0x0ee3f31, 0x0a7e165, 0x1dbffc9, 0x11fa286, 0x1e09725, 0x06b4441,
  48269. 0x0e1bcf0, 0x01f62a8, 0x1d0a0e9, 0x1570031, 0x192fdb2, 0x198870e,
  48270. 0x1f1d0f6, 0x0f8ab29, 0x16f7a05, 0x1db70d9, 0x01b87f2 },
  48271. { 0x10b15b1, 0x095dd95, 0x1de4d5e, 0x0f9cd74, 0x03e4b5a, 0x079bbcd,
  48272. 0x1ff6776, 0x1dff759, 0x1c298d1, 0x02a285e, 0x00c7180, 0x0aad88e,
  48273. 0x060e3f5, 0x0aeb403, 0x1c3c1ea, 0x0a5840e, 0x0e02d10, 0x0671f42,
  48274. 0x0aa3315, 0x00f23cf, 0x03a3b05, 0x19dd191, 0x1358879, 0x0c65320,
  48275. 0x1b94d39, 0x0b6c3dc, 0x1dfae01, 0x1bf3968, 0x1ca0cc8, 0x06f476f,
  48276. 0x12b890c, 0x12e2541, 0x14bf416, 0x0454c9b, 0x11de221, 0x1d7c7e7,
  48277. 0x04a3e59, 0x15c3d8e, 0x0f08ec8, 0x1887d2b, 0x08e0227 },
  48278. { 0x010964d, 0x1115419, 0x1bac003, 0x0bfe0ad, 0x1ccd5df, 0x18f56be,
  48279. 0x0e87f6b, 0x1c6042e, 0x067cdca, 0x01419f0, 0x1324334, 0x099717b,
  48280. 0x151cc57, 0x19125a7, 0x1b29c50, 0x105310d, 0x03abb3f, 0x1e80730,
  48281. 0x106a37a, 0x1d9c361, 0x061db98, 0x121bc61, 0x08a291b, 0x02cbcba,
  48282. 0x1dd0da6, 0x071637c, 0x052dfbc, 0x075c713, 0x09f306b, 0x0b59ded,
  48283. 0x16ce8f0, 0x0714109, 0x09a26d3, 0x074a82f, 0x064d4e5, 0x18a51cb,
  48284. 0x0ea206b, 0x076588a, 0x175ba12, 0x16a80a8, 0x014b15a },
  48285. { 0x04c59a2, 0x0c364b3, 0x0a943db, 0x02c1faf, 0x1dfe2be, 0x1965c71,
  48286. 0x0d5a641, 0x1c067f3, 0x18176a7, 0x19192ec, 0x1c202d7, 0x09ce8b0,
  48287. 0x0579a0d, 0x06aea70, 0x1b837bc, 0x051c349, 0x1fac87b, 0x16056cf,
  48288. 0x1c26d3b, 0x031a5e7, 0x1d87d6f, 0x1394974, 0x13225ab, 0x128ec79,
  48289. 0x0953d60, 0x0fd6544, 0x0063efe, 0x17dd2f5, 0x03d701d, 0x1074a5b,
  48290. 0x0bf7c83, 0x08fd4e4, 0x1ba6e30, 0x1ab8fe5, 0x072984a, 0x0b9cafc,
  48291. 0x009a55f, 0x0b563b0, 0x078b878, 0x1b18871, 0x0742bbe },
  48292. { 0x1dc2c73, 0x1436e60, 0x0afc8fa, 0x1782c87, 0x0bbbfd5, 0x0c650fa,
  48293. 0x1e87c93, 0x18e0ff1, 0x08cb5ca, 0x1345370, 0x19a9f77, 0x0c96a9c,
  48294. 0x187d54c, 0x14dbd6b, 0x076e88a, 0x15728f1, 0x140e364, 0x0a6c46a,
  48295. 0x1dcb804, 0x05c05a3, 0x0278c8c, 0x0ba3715, 0x1320981, 0x030f8fa,
  48296. 0x15bb34b, 0x064f361, 0x1bae3f8, 0x1b167bf, 0x11e415e, 0x1a743e8,
  48297. 0x1e6daf0, 0x170cb8f, 0x1908bbf, 0x060be59, 0x139b87b, 0x16e2fa3,
  48298. 0x17cdd69, 0x0f19847, 0x1049054, 0x0296b92, 0x097bd5a },
  48299. { 0x1e82861, 0x0317f40, 0x103b807, 0x1bba858, 0x103d4b6, 0x0f48f2b,
  48300. 0x1956f99, 0x1bafca5, 0x05abbbf, 0x05a49ba, 0x0917d2e, 0x1ea58e5,
  48301. 0x18b4f15, 0x0a8794e, 0x010d6a1, 0x1cebf9d, 0x19b582d, 0x14efbb5,
  48302. 0x08322e5, 0x1098bf4, 0x0af452e, 0x0885450, 0x0bddf4b, 0x0c02787,
  48303. 0x1bbd8ca, 0x02f81c4, 0x089be0c, 0x01b3737, 0x0c8b9ab, 0x1424067,
  48304. 0x063c14f, 0x1ff57b4, 0x163367a, 0x1261526, 0x0f92990, 0x1ca1ea7,
  48305. 0x064fba2, 0x0962c64, 0x151a7e2, 0x0629198, 0x0317c6d },
  48306. { 0x0b7d42b, 0x092d816, 0x12b830d, 0x12621f5, 0x15240bc, 0x102047a,
  48307. 0x0808bfc, 0x1411aba, 0x1e0c10e, 0x180a017, 0x1ac8f5a, 0x0d14e31,
  48308. 0x197fbef, 0x0092950, 0x051ad69, 0x01add40, 0x048110e, 0x0acd7e7,
  48309. 0x08b7860, 0x03a4fe0, 0x09dae9a, 0x0b6e1fa, 0x1b6e5b4, 0x17c8010,
  48310. 0x0e3f5ef, 0x08e7e0d, 0x07b32f0, 0x13ae0c8, 0x1f8636f, 0x113ca92,
  48311. 0x0c12408, 0x184ec78, 0x169796a, 0x031859b, 0x00f0764, 0x0f39869,
  48312. 0x0e3d3f1, 0x0b28f87, 0x0e3f514, 0x0733b41, 0x06ae597 },
  48313. { 0x1f4d2ee, 0x09de3df, 0x0f615ec, 0x126162e, 0x0075422, 0x0a49b61,
  48314. 0x12f541e, 0x17d6c4a, 0x05efd55, 0x0af9195, 0x10ce247, 0x150a9c1,
  48315. 0x04c06f4, 0x0730fca, 0x0b16d66, 0x10f6f9e, 0x01ffd5f, 0x062b243,
  48316. 0x08abe93, 0x0c3f62b, 0x0774ee2, 0x1316cbd, 0x0c3fdc8, 0x19e00f5,
  48317. 0x1ae22d6, 0x10a0d44, 0x134d1bc, 0x11100a6, 0x16497e2, 0x1dffcbd,
  48318. 0x1f23f9c, 0x1f455ff, 0x08595b2, 0x0d39345, 0x1cfbc54, 0x173df39,
  48319. 0x0744b82, 0x0772f8f, 0x1f9caa1, 0x11b78c7, 0x0664904 },
  48320. { 0x08b760d, 0x1ddbc0f, 0x0a8246d, 0x104b55b, 0x147b0bd, 0x1a9137e,
  48321. 0x0f67fea, 0x11d0292, 0x0bffc14, 0x136e913, 0x0f8f6d2, 0x1f15453,
  48322. 0x0b5a032, 0x1a58558, 0x036f1c0, 0x090d063, 0x1b57d65, 0x16e665f,
  48323. 0x1160791, 0x0d566f3, 0x0ce2850, 0x1714187, 0x0244da9, 0x0d9018e,
  48324. 0x19356cf, 0x143245b, 0x1fbdac7, 0x142ec6e, 0x10f1c9f, 0x0e60c1f,
  48325. 0x174b270, 0x02d57db, 0x0f0526d, 0x186f24b, 0x038aa4e, 0x147c1d3,
  48326. 0x0f13873, 0x16bd6d0, 0x127b1bc, 0x0b9e7f4, 0x04eb93b },
  48327. { 0x11fae32, 0x0fbf2f0, 0x1d46f62, 0x0b88047, 0x113d74f, 0x0e1fb7e,
  48328. 0x0537d24, 0x16e3600, 0x1555279, 0x0c24d2b, 0x0801a07, 0x112e0b7,
  48329. 0x0abb9e8, 0x009e516, 0x0889067, 0x0cedf04, 0x085fd33, 0x157dddb,
  48330. 0x161e28a, 0x187ea4e, 0x1173931, 0x17f79ea, 0x04abbbf, 0x114d0f0,
  48331. 0x05cc8bd, 0x00b0c4d, 0x0f667c3, 0x059ffb6, 0x1d48b68, 0x0a0350c,
  48332. 0x182fd59, 0x1d38d89, 0x005e223, 0x020b92b, 0x077a1a0, 0x10a7cf0,
  48333. 0x07001cc, 0x1ae485e, 0x0fda337, 0x126f808, 0x02b582d },
  48334. { 0x1abc2ae, 0x12e4140, 0x1b2a845, 0x0bc56d3, 0x073380f, 0x1ffb37d,
  48335. 0x0cf481f, 0x00d812f, 0x0547765, 0x0b01c13, 0x1e88717, 0x13e76af,
  48336. 0x15dcbac, 0x04c6dee, 0x1d436d3, 0x1e654f0, 0x103d9ef, 0x042f108,
  48337. 0x1c47107, 0x1a2e585, 0x0c09cee, 0x124f1a4, 0x0a38e49, 0x03dbbf7,
  48338. 0x1936b83, 0x051b8e5, 0x1bd4219, 0x02b87a0, 0x1acfcd9, 0x19e6f49,
  48339. 0x0abfa38, 0x167e5ef, 0x1ee10d7, 0x0774d25, 0x0d23adf, 0x1b83b1d,
  48340. 0x1a574af, 0x124e71f, 0x0d3013e, 0x0130c5b, 0x0786151 },
  48341. { 0x0e72c21, 0x1fa403d, 0x1694ff8, 0x09fa1e1, 0x031aa14, 0x01d22a3,
  48342. 0x187a3e3, 0x1578edd, 0x051b4f1, 0x1cd704a, 0x16ec90d, 0x072faf9,
  48343. 0x0d2a3a4, 0x015eafe, 0x0533ffa, 0x1deb4f4, 0x112f427, 0x1ddf276,
  48344. 0x0134f33, 0x1487dc5, 0x0e1e9b0, 0x09c7763, 0x15ede2e, 0x171d0f6,
  48345. 0x004e467, 0x0100c6a, 0x14d0dd3, 0x1915b80, 0x08deb50, 0x1b02aa1,
  48346. 0x13d90dc, 0x1875f45, 0x0d80ec0, 0x0ab7cda, 0x04f0eaa, 0x10daa3f,
  48347. 0x04161c6, 0x0d1455c, 0x100967e, 0x16ed793, 0x0540b6b },
  48348. { 0x01d315d, 0x0b9a619, 0x1740138, 0x05b0dc0, 0x0ef5661, 0x1466c0a,
  48349. 0x18516ee, 0x135d5f5, 0x1acdc78, 0x1d83d24, 0x1d5c3c7, 0x135ab0e,
  48350. 0x1e6a21e, 0x1cde29e, 0x12a0dfa, 0x131d65c, 0x0931d62, 0x0a1b6d9,
  48351. 0x08d8bd1, 0x1f78f1d, 0x058543a, 0x0bd55fb, 0x0aa5cf6, 0x1249ac0,
  48352. 0x1dabe0c, 0x074ee73, 0x01f2b7c, 0x0d3b31e, 0x020538f, 0x02d0ba8,
  48353. 0x0a782d4, 0x088c39a, 0x1b7d1a3, 0x0740c1e, 0x1dd9788, 0x0dc3850,
  48354. 0x12dd50f, 0x112c33a, 0x0e230b2, 0x02925c0, 0x0897cab },
  48355. { 0x18bab8a, 0x09c0986, 0x002967b, 0x1948704, 0x011d364, 0x0c0a0ae,
  48356. 0x0fcb101, 0x0e80d0f, 0x07ac896, 0x156869d, 0x1046821, 0x020b72e,
  48357. 0x1c44928, 0x19c19b8, 0x0612c47, 0x1063ce9, 0x1840d1a, 0x0386976,
  48358. 0x1244bf8, 0x06c516d, 0x08d2d88, 0x1d8a7d4, 0x113e3df, 0x015927c,
  48359. 0x12a4dcf, 0x1d32b27, 0x0a9b093, 0x05ec535, 0x0cd9498, 0x15d1dfb,
  48360. 0x0b6ae41, 0x0414a30, 0x0822e67, 0x1c9d296, 0x16b0c3a, 0x145fe8f,
  48361. 0x1ff673a, 0x1162527, 0x03b1771, 0x0c68ed6, 0x064b007 },
  48362. { 0x1c9a404, 0x1a99f59, 0x054878f, 0x076fdf3, 0x11db7f7, 0x129b49d,
  48363. 0x0f8a5b0, 0x1a98fe2, 0x00738ee, 0x073fa62, 0x1b2b41f, 0x16679c4,
  48364. 0x11ccfd3, 0x00f62e7, 0x1e124d4, 0x09c03b0, 0x09ddc08, 0x19fc7e0,
  48365. 0x0e6d6b3, 0x1956658, 0x151c217, 0x1dcf7aa, 0x10b6bc2, 0x042f52a,
  48366. 0x16f56e1, 0x0157de3, 0x0b08dc0, 0x002f162, 0x10a2938, 0x01cfd83,
  48367. 0x1902d4b, 0x0aed952, 0x1925153, 0x1471b71, 0x1090675, 0x084aab2,
  48368. 0x09e50e8, 0x0fdc160, 0x1b630a4, 0x14ccc31, 0x07dd22e },
  48369. { 0x1cbb3bf, 0x14225a4, 0x0c95fff, 0x08aac5f, 0x1e0cc70, 0x0d422d6,
  48370. 0x194de7d, 0x1f83cdd, 0x0e51277, 0x0b6bf93, 0x0d5c625, 0x097260c,
  48371. 0x142c75d, 0x0b4abf9, 0x085224a, 0x0e85673, 0x13282e5, 0x1467a75,
  48372. 0x0c91edc, 0x1a7bbb0, 0x02376b0, 0x19900d2, 0x19ea7d8, 0x029490a,
  48373. 0x003c114, 0x08b20b2, 0x1edbdaa, 0x015fa88, 0x06f7906, 0x04986d6,
  48374. 0x00a57e5, 0x17a773b, 0x05ff94b, 0x16f87b4, 0x03f1472, 0x12b91f3,
  48375. 0x113b748, 0x0ce4455, 0x1f32255, 0x0ccbe31, 0x031377c },
  48376. { 0x1cfb35f, 0x0ef04be, 0x1be0d71, 0x1e03986, 0x0dccca9, 0x1b65b19,
  48377. 0x1a175d5, 0x0eafd27, 0x0f7b4b3, 0x016ea45, 0x0866d43, 0x1a9f613,
  48378. 0x079d95c, 0x18dff30, 0x0bb4565, 0x1b5a4ea, 0x0cf2596, 0x1a1cc40,
  48379. 0x07a429b, 0x1df6a6d, 0x060ae52, 0x1181e9f, 0x11025d9, 0x0a0e1c0,
  48380. 0x164faa9, 0x0e97e79, 0x1815893, 0x11f3276, 0x15e467d, 0x0c12006,
  48381. 0x092cd6a, 0x0191e8a, 0x089d024, 0x100bcf1, 0x08f1922, 0x1bde8a8,
  48382. 0x187edab, 0x0feb4aa, 0x149c4e9, 0x019423c, 0x03dacc5 },
  48383. { 0x099ae4c, 0x127ca32, 0x149f2cf, 0x02e0a78, 0x046dcbe, 0x1c17455,
  48384. 0x173a6f9, 0x08b00fe, 0x0d8481e, 0x1632694, 0x01bf42d, 0x0a31545,
  48385. 0x09f35e4, 0x0f8e6da, 0x0dee6eb, 0x07d5fef, 0x010aec2, 0x1f9fdb1,
  48386. 0x06ff4be, 0x17470b7, 0x13a00a9, 0x09c403f, 0x1946835, 0x0f65085,
  48387. 0x04404b1, 0x1853d59, 0x1fe7767, 0x1faaed0, 0x09df646, 0x1eda79f,
  48388. 0x137347b, 0x0c1be32, 0x1d2df7a, 0x0ef82ae, 0x0b0f81a, 0x037da7e,
  48389. 0x03248a3, 0x0dbab09, 0x113dd1a, 0x1c2d28e, 0x0866949 },
  48390. { 0x14ab07a, 0x106d29f, 0x1efcea6, 0x07ea94d, 0x0cd6f33, 0x1e79481,
  48391. 0x1a486c8, 0x0b01925, 0x0848e3d, 0x0ac0e1f, 0x0862af2, 0x1f7ba76,
  48392. 0x1793af1, 0x03365a6, 0x1663a84, 0x0074070, 0x14e990c, 0x0a8009c,
  48393. 0x1421ded, 0x0c963cf, 0x10913b6, 0x1deba63, 0x15e76c6, 0x05abba1,
  48394. 0x144354e, 0x1c14296, 0x0ccca76, 0x1a57083, 0x16d4800, 0x07583dc,
  48395. 0x11bea11, 0x1852bb8, 0x1a50569, 0x1f6271b, 0x0dce53d, 0x0f85a70,
  48396. 0x1b08317, 0x1c427fa, 0x0966370, 0x171163f, 0x0574352 },
  48397. { 0x15d7ce9, 0x0c9fb86, 0x1abfb48, 0x0c1690f, 0x1c19fd2, 0x132fe81,
  48398. 0x0ad65ef, 0x0acf889, 0x078270d, 0x0ced430, 0x1c06637, 0x1801754,
  48399. 0x1f8a84e, 0x142cc2e, 0x109f924, 0x051b05d, 0x0f0de20, 0x0ccb665,
  48400. 0x0708807, 0x0c918ec, 0x19eb4e7, 0x1e048e0, 0x0a58cd6, 0x1acf057,
  48401. 0x03a69f0, 0x049929d, 0x034a519, 0x1e40868, 0x1f68733, 0x10d084c,
  48402. 0x0691114, 0x0d32c02, 0x1cbcc09, 0x1d4a72f, 0x1763e14, 0x027109a,
  48403. 0x13b6a3a, 0x0c63126, 0x0f13c90, 0x1e40d5c, 0x03e431a },
  48404. { 0x1d381f1, 0x1ec9cc1, 0x0f0fe59, 0x1da1806, 0x16501aa, 0x0083b41,
  48405. 0x1d34151, 0x1a77e75, 0x05093a6, 0x0368acc, 0x1ca402a, 0x0e83b25,
  48406. 0x1543ae0, 0x1b785ba, 0x0cabe98, 0x0dadffd, 0x0a3aa45, 0x1684853,
  48407. 0x1bf6d91, 0x149fb55, 0x0f7d336, 0x020d4a1, 0x1f46ff9, 0x03dc83d,
  48408. 0x0a3ed85, 0x0e2bfe1, 0x1847a4d, 0x1e392d0, 0x1bb3434, 0x1b3329d,
  48409. 0x0ab355d, 0x15b12d8, 0x06931ba, 0x1fd20f9, 0x0f461ae, 0x03141f7,
  48410. 0x0203cef, 0x1ebec15, 0x134d470, 0x02bc4cc, 0x06dad3f },
  48411. { 0x0ec35a1, 0x005be89, 0x04a3465, 0x0dcfbf6, 0x0219c5b, 0x1990eab,
  48412. 0x1e31bc4, 0x16c5984, 0x033c58e, 0x13b4825, 0x00f10d7, 0x1eabb32,
  48413. 0x1915090, 0x01ecb50, 0x06f249b, 0x1974e0c, 0x1038c0a, 0x1cba54f,
  48414. 0x0662c86, 0x028042e, 0x0c6f7a4, 0x0efc4ac, 0x0c1a566, 0x17a0253,
  48415. 0x12f1dbe, 0x0e1a8bf, 0x0f7cea3, 0x02134c2, 0x0375c51, 0x0224339,
  48416. 0x14c2396, 0x12707a5, 0x0590ba4, 0x1c1be2b, 0x1f182ff, 0x1ff87dc,
  48417. 0x07d2d55, 0x1d29c81, 0x1e8ff21, 0x1a8bea2, 0x02438e9 },
  48418. { 0x015af3c, 0x0298444, 0x1b57129, 0x05e7937, 0x055f1a3, 0x1b2eeff,
  48419. 0x137265e, 0x16b5de3, 0x012e51e, 0x0e30eca, 0x1c92418, 0x18a9cc7,
  48420. 0x11bd0da, 0x0859f11, 0x0510a73, 0x0c020de, 0x1c2f1da, 0x0fb9be1,
  48421. 0x0ef13ec, 0x01c096d, 0x01cb715, 0x048df14, 0x0816d32, 0x0e03eb6,
  48422. 0x0633cd7, 0x04878da, 0x18a944d, 0x1667de8, 0x11f7f28, 0x1e39b47,
  48423. 0x19f76d1, 0x17a82d6, 0x0ada511, 0x0add9fa, 0x1f37fde, 0x0f3a552,
  48424. 0x16200e6, 0x145bd94, 0x0380402, 0x0235fc6, 0x013f390 },
  48425. { 0x1d0c827, 0x14b77bd, 0x1d18f74, 0x069453f, 0x106110f, 0x0d28ad2,
  48426. 0x0c1a072, 0x0eff0f2, 0x1268bca, 0x146c022, 0x01177f7, 0x0049330,
  48427. 0x04cbb83, 0x146072c, 0x0435c41, 0x0c0c47f, 0x0a8263b, 0x19541c6,
  48428. 0x0d71742, 0x176bcea, 0x1110293, 0x0aab20a, 0x13baa67, 0x17b400b,
  48429. 0x11ad01b, 0x00c7f18, 0x1e93634, 0x092fc17, 0x12b8662, 0x1bd00e7,
  48430. 0x02ccf75, 0x1b18975, 0x0075b73, 0x1bde4de, 0x1b51c8a, 0x165308c,
  48431. 0x0bda1b0, 0x13e7126, 0x00ed85e, 0x0d6d00e, 0x0458d4b },
  48432. { 0x154d8b2, 0x1510726, 0x0836289, 0x1c9a641, 0x05a5696, 0x0a7b800,
  48433. 0x16163e6, 0x150d316, 0x02f6549, 0x1256e1e, 0x134035e, 0x10326d2,
  48434. 0x1d1812e, 0x1982015, 0x0e6c001, 0x0c8208d, 0x049a1b3, 0x070850a,
  48435. 0x048c088, 0x12bd4b3, 0x00c3eae, 0x0d8da41, 0x0fbf0ba, 0x193d714,
  48436. 0x15cb585, 0x0327f2d, 0x065e11c, 0x035c063, 0x07d49f2, 0x05b8479,
  48437. 0x1ada3bc, 0x05ee4aa, 0x059ef18, 0x0d80d19, 0x115d893, 0x18015c0,
  48438. 0x1668f95, 0x071d832, 0x0fe458a, 0x1f56df7, 0x05f13f5 },
  48439. { 0x09b0dc6, 0x16cd71d, 0x1b21f1b, 0x12df107, 0x0ea1bde, 0x059b3bd,
  48440. 0x0fe23aa, 0x157d4cd, 0x09a66e3, 0x17d355e, 0x05fff77, 0x02f6d04,
  48441. 0x1cc4d33, 0x1486f82, 0x10723c8, 0x0ce9dee, 0x1177d11, 0x10f87ef,
  48442. 0x0d66272, 0x01d9cf8, 0x082dfdf, 0x0fb5ce2, 0x03bb64b, 0x17e394e,
  48443. 0x13e6655, 0x0ce39b8, 0x00973b2, 0x0159652, 0x03e69c9, 0x11d1740,
  48444. 0x068df27, 0x02ee274, 0x00a3c53, 0x10ba6be, 0x1595bd6, 0x0c6a1b8,
  48445. 0x05f802f, 0x112d220, 0x0928845, 0x0bb46f7, 0x0219649 },
  48446. { 0x1142680, 0x197e989, 0x13d0032, 0x0ecba29, 0x0b9e91d, 0x11334f5,
  48447. 0x13aaf7f, 0x18b8d41, 0x00ae22b, 0x177e72c, 0x1b0942f, 0x130d96d,
  48448. 0x1f3c2b7, 0x0b9c78f, 0x0b6c68b, 0x191d909, 0x028516e, 0x0cb84de,
  48449. 0x1a3df6d, 0x1262531, 0x17f9f36, 0x15cad8c, 0x1123bf1, 0x1554809,
  48450. 0x109529a, 0x0584ff8, 0x1451055, 0x1879197, 0x1f34352, 0x1de1a13,
  48451. 0x104cfbd, 0x1a4312f, 0x0a17940, 0x0a45002, 0x11f5b39, 0x04b5418,
  48452. 0x1d56fa6, 0x18e7539, 0x17c20a5, 0x160088e, 0x093ad0e },
  48453. { 0x08a9963, 0x1b4b3cc, 0x0375e82, 0x0eca2bd, 0x01e477f, 0x15a8793,
  48454. 0x18e18ed, 0x1bcc4e9, 0x1d33922, 0x1d4dc6a, 0x096cf58, 0x07f6d0f,
  48455. 0x033c38d, 0x0981719, 0x1dbc270, 0x1999e31, 0x1c3e02f, 0x192a602,
  48456. 0x1b998bd, 0x1da16e4, 0x0079c04, 0x1c0a1ff, 0x075591a, 0x002d918,
  48457. 0x09448c9, 0x1cbf7c5, 0x0fe08f5, 0x0ace989, 0x0de451e, 0x1b97de6,
  48458. 0x178161b, 0x0882fd5, 0x1fc88d5, 0x12c46e2, 0x08255db, 0x12572a4,
  48459. 0x1844d1f, 0x046ea12, 0x100d110, 0x1e1d483, 0x073f8c3 },
  48460. { 0x1f763dd, 0x1a7e42e, 0x00da254, 0x06758e3, 0x1b1427f, 0x078ad01,
  48461. 0x0f85dba, 0x11c1b6b, 0x0cb2088, 0x09c84a2, 0x12ba987, 0x135b0af,
  48462. 0x137804c, 0x08cfbdf, 0x16110a1, 0x1519f54, 0x0f1293a, 0x0b13776,
  48463. 0x08da805, 0x1c1b31d, 0x0dcd749, 0x171990f, 0x1bffdb6, 0x16f2399,
  48464. 0x1eea628, 0x1b0cb1e, 0x08b45b8, 0x029c0aa, 0x1ae206a, 0x0c7e58a,
  48465. 0x1928b81, 0x1f9464b, 0x1268745, 0x00d4507, 0x101c84d, 0x10f9f3a,
  48466. 0x1caa51b, 0x1692ecb, 0x175d77f, 0x0735b7d, 0x00108ae },
  48467. { 0x1e88f63, 0x0bc79d4, 0x0c95534, 0x1d5618e, 0x0a05b11, 0x10ec535,
  48468. 0x14f9b89, 0x190ee74, 0x08d0b91, 0x06dbed7, 0x0c01349, 0x00e7d37,
  48469. 0x0bde10b, 0x0a71848, 0x02fbf9d, 0x13913f9, 0x1990cc6, 0x10b5782,
  48470. 0x1565446, 0x1070073, 0x1afcddc, 0x0ca362e, 0x10fd96e, 0x1c14b33,
  48471. 0x04be81e, 0x18bfddf, 0x1becea6, 0x11123c6, 0x1dad008, 0x16baa22,
  48472. 0x07c326a, 0x1aa12fc, 0x1fc46ab, 0x0d270ef, 0x026eb21, 0x0710901,
  48473. 0x00c4523, 0x05da17d, 0x1077cd2, 0x1b1d627, 0x0807c06 },
  48474. { 0x0ee0ef6, 0x0b4f64c, 0x1ebc02a, 0x07176f6, 0x1a9d548, 0x17c7edd,
  48475. 0x1324a80, 0x0f84890, 0x08b7055, 0x1ed900d, 0x146bc9e, 0x07c8c15,
  48476. 0x1be5934, 0x0cc64af, 0x0a6a50a, 0x03a76a7, 0x1deda86, 0x14ba6d9,
  48477. 0x14e6703, 0x0a4b93d, 0x09bdce1, 0x00fb908, 0x026d5a2, 0x1042349,
  48478. 0x17d1599, 0x1ad047f, 0x0bbc3c9, 0x1beed67, 0x0f358b5, 0x007bfd1,
  48479. 0x0d24fc6, 0x187360c, 0x0c4ffcf, 0x01da9d5, 0x18985d6, 0x184d258,
  48480. 0x155399f, 0x1efd1b5, 0x1e986cb, 0x0d932c0, 0x016424c },
  48481. { 0x12744a9, 0x12e2aee, 0x1061775, 0x05fc75e, 0x0544c1c, 0x1458449,
  48482. 0x0ba67bf, 0x0346590, 0x1a9df69, 0x05bd592, 0x0659d0c, 0x0aa137d,
  48483. 0x0298384, 0x0579689, 0x1b34963, 0x0e4e579, 0x098bcc7, 0x0445720,
  48484. 0x0e3be83, 0x12c2829, 0x112cd43, 0x1cf6b26, 0x113fd9e, 0x0fe6808,
  48485. 0x055e42e, 0x0f5d4f3, 0x1516c3a, 0x1a2df88, 0x1ded283, 0x1f0a781,
  48486. 0x1711d28, 0x1599970, 0x1c9adff, 0x1d28dd1, 0x0f05c94, 0x027bfcd,
  48487. 0x1b5831b, 0x0d7a5cf, 0x11e2b77, 0x00549e8, 0x05544e6 },
  48488. { 0x0a80b4f, 0x02989dd, 0x03be25f, 0x1ec77b9, 0x0122716, 0x0162d40,
  48489. 0x10b6ded, 0x1195c4e, 0x1088330, 0x0ecf0f4, 0x106ac7a, 0x187e5a6,
  48490. 0x10352c8, 0x16ca2c3, 0x0f41403, 0x1b3b02c, 0x173c290, 0x0c1a4ee,
  48491. 0x1db1f4a, 0x078bc03, 0x033c205, 0x0365a10, 0x00c41d1, 0x1a135e3,
  48492. 0x08bd209, 0x140bb64, 0x1ac9e51, 0x01ee1cd, 0x11b540d, 0x0cef0cd,
  48493. 0x10dc82d, 0x0453296, 0x0b7ecdc, 0x029e7c0, 0x1738b7b, 0x0583499,
  48494. 0x1ed60f4, 0x1e9f6e8, 0x1498775, 0x0b9c483, 0x0573599 },
  48495. { 0x0237056, 0x1d1fdd0, 0x0e23712, 0x0867566, 0x0856c16, 0x0f63093,
  48496. 0x1aef49c, 0x1d9803d, 0x1e3031b, 0x1ef5819, 0x0287d6a, 0x0832c23,
  48497. 0x134eee4, 0x0db0079, 0x125d085, 0x10ee7d8, 0x1cf0886, 0x08db8c2,
  48498. 0x106df7f, 0x188d9af, 0x1e897b0, 0x0d25262, 0x1450ecb, 0x03ff29b,
  48499. 0x05984bb, 0x032edcd, 0x13273cd, 0x187209c, 0x0e64c9a, 0x0de0756,
  48500. 0x06be1ca, 0x0ed15b3, 0x0c22821, 0x0a0612e, 0x02062a5, 0x0f77a76,
  48501. 0x049a691, 0x1476af8, 0x17bc391, 0x1be7d88, 0x0885486 },
  48502. { 0x1dff464, 0x01649a5, 0x1145aa5, 0x1e4b4f6, 0x1db2719, 0x0df1921,
  48503. 0x01c2cc9, 0x0739960, 0x119fe33, 0x02ad18d, 0x1ba3fc8, 0x15d0483,
  48504. 0x0faca69, 0x0af7c6f, 0x01f7421, 0x0e78cec, 0x00f1a1b, 0x04f124b,
  48505. 0x074da04, 0x01d144e, 0x06b9bcb, 0x113442f, 0x0a7846a, 0x0bd5c32,
  48506. 0x1d0ab18, 0x08e4c5a, 0x103e07e, 0x14172dc, 0x0fc5031, 0x05e7cca,
  48507. 0x181343a, 0x1e233ad, 0x1d81697, 0x0670619, 0x0a1eaa9, 0x0e52106,
  48508. 0x091ff9d, 0x0ea69f6, 0x058b717, 0x1d1a957, 0x031cecf },
  48509. { 0x08b21e8, 0x1fecd7e, 0x1b7d0de, 0x0763286, 0x05dd32b, 0x0e1b507,
  48510. 0x00b5248, 0x121fcb2, 0x1a3d0fa, 0x14ef426, 0x148ef63, 0x0d5ab76,
  48511. 0x159663e, 0x1766b4b, 0x00288fe, 0x16b3930, 0x0d9b4fb, 0x08804e0,
  48512. 0x07483fc, 0x154f7b9, 0x1a3d839, 0x16f66b7, 0x1d40bd9, 0x0a2d953,
  48513. 0x0d4fbc5, 0x1622407, 0x19b1d0a, 0x0bff4be, 0x1252f86, 0x1ca2ff9,
  48514. 0x0f4adf1, 0x0ebb396, 0x0fefc05, 0x178e939, 0x18ef5b5, 0x0623610,
  48515. 0x1a6a4ec, 0x079e784, 0x11ecd76, 0x0d5b44a, 0x06961b4 },
  48516. { 0x135e2ac, 0x1ac3f65, 0x136741e, 0x16af5e2, 0x1ed5546, 0x1450260,
  48517. 0x1e96f6c, 0x1e1d942, 0x0709d54, 0x0fc8ea2, 0x1d003a8, 0x13fb38d,
  48518. 0x10a6e71, 0x1dc670c, 0x12e23b7, 0x07fa49c, 0x0dd246e, 0x0fcbc0f,
  48519. 0x1956bd7, 0x0241cd6, 0x1ca7d67, 0x0ec9a09, 0x169e0b4, 0x00ff443,
  48520. 0x020a297, 0x091b4bf, 0x0953a10, 0x1d6a3e6, 0x051f9f1, 0x06cf1b0,
  48521. 0x1a4b895, 0x0e79cb7, 0x1aec42b, 0x1bca7ee, 0x0cbb34f, 0x1313534,
  48522. 0x0781aad, 0x1271178, 0x1484865, 0x018a6ea, 0x06a63a9 },
  48523. { 0x17acbbb, 0x0a7001e, 0x0421d95, 0x156e9ec, 0x0c01668, 0x0628cd9,
  48524. 0x059c8e2, 0x09fc945, 0x03eb94d, 0x0b33b8a, 0x1b4bd80, 0x19be19a,
  48525. 0x1f086a3, 0x1d9b87b, 0x1960085, 0x07cf9f0, 0x0c15a4d, 0x0b2c440,
  48526. 0x0e8fd28, 0x1ab02cb, 0x11ddd6e, 0x09ae523, 0x0af31e0, 0x0894aed,
  48527. 0x1f074e8, 0x175404d, 0x0dba940, 0x0a75036, 0x021ed3a, 0x0983870,
  48528. 0x197082e, 0x10c2fe2, 0x027f892, 0x0e685c6, 0x111a08d, 0x034a8ec,
  48529. 0x0255296, 0x044ffec, 0x1643bff, 0x045a2a3, 0x051ed4a },
  48530. { 0x09701b4, 0x14b1d22, 0x0bc8df5, 0x07764f9, 0x0a8d91a, 0x194b2ff,
  48531. 0x0f856d5, 0x0fa7df3, 0x1db50bf, 0x0d3d02a, 0x10ee6dd, 0x101d9cc,
  48532. 0x1efd674, 0x1675aea, 0x09834b5, 0x1912fe5, 0x00c5ed7, 0x1b47e19,
  48533. 0x0339a17, 0x0a79ec5, 0x015e41c, 0x0fb8833, 0x038a5c4, 0x0a01d98,
  48534. 0x1213823, 0x1243d43, 0x01b0a7f, 0x1e1524c, 0x0f9712a, 0x1f9570f,
  48535. 0x0fe4f7c, 0x1a5a2d3, 0x15f6fb1, 0x0bc9e06, 0x1899d2a, 0x0dd6f5f,
  48536. 0x09f4925, 0x19eca57, 0x1739505, 0x1785716, 0x02d6951 },
  48537. { 0x04e222e, 0x03ecfc8, 0x0427740, 0x1f0de9c, 0x133f248, 0x014f771,
  48538. 0x13a2e3d, 0x031a932, 0x1cfc775, 0x0ab9a0a, 0x1d0bc4a, 0x1474161,
  48539. 0x196e7fe, 0x013a1a8, 0x0572df7, 0x0e3418f, 0x166711e, 0x0c10547,
  48540. 0x0e1d3d5, 0x12bb385, 0x162783d, 0x1c73870, 0x152d935, 0x1254e85,
  48541. 0x153f58b, 0x136c921, 0x0511ed7, 0x0440916, 0x1931a03, 0x19865e7,
  48542. 0x1a02eb5, 0x14f5e44, 0x1c4d089, 0x1c9fcba, 0x1306e0e, 0x1c8c920,
  48543. 0x165b3ae, 0x075d010, 0x117c289, 0x0f1c119, 0x065c48e },
  48544. { 0x0222c22, 0x039e76f, 0x0ed0687, 0x1bf9d44, 0x1683d8c, 0x0a1d832,
  48545. 0x12c52c8, 0x0ee0603, 0x159fcec, 0x0256fc7, 0x0133bca, 0x1038624,
  48546. 0x07fb1c5, 0x0a39a88, 0x134fbba, 0x11181ea, 0x10b4d31, 0x16dfb3f,
  48547. 0x03c6344, 0x07e5a22, 0x001376a, 0x1403e9f, 0x0e027e8, 0x1cfd9c0,
  48548. 0x10a4625, 0x0977837, 0x16ca257, 0x1050cfd, 0x10553ad, 0x1a44845,
  48549. 0x117841b, 0x1de48a8, 0x0280fa6, 0x0d1e5f1, 0x1e16a36, 0x1a805aa,
  48550. 0x1438ba2, 0x1eecffe, 0x089bfd8, 0x058f4d6, 0x036b5cd },
  48551. { 0x05679a7, 0x1a7102a, 0x1d421ff, 0x028a418, 0x04d80b4, 0x02ce6c3,
  48552. 0x15fea6d, 0x1472146, 0x1c85af1, 0x0cf579c, 0x0d697a8, 0x1af31b2,
  48553. 0x0a0d475, 0x1c0d33c, 0x140660d, 0x1d020e8, 0x1790cc2, 0x03a41cb,
  48554. 0x1d04891, 0x043a225, 0x1a37c6a, 0x1c9b528, 0x0343a17, 0x14e9bf1,
  48555. 0x0151eea, 0x0e27fa8, 0x1e4f3e6, 0x09c3054, 0x0a9ab61, 0x1ef89bb,
  48556. 0x1fd1564, 0x0a44713, 0x0f73caf, 0x02f450c, 0x0583dd1, 0x11a4f99,
  48557. 0x19a51dc, 0x097a629, 0x0ff601a, 0x089b673, 0x008d7c1 },
  48558. { 0x0cca773, 0x006cb1f, 0x055a027, 0x05a9184, 0x07ea919, 0x15eb20c,
  48559. 0x135d36d, 0x1bfe1d9, 0x02a678c, 0x19891ba, 0x01edf9d, 0x1b17a2b,
  48560. 0x067a966, 0x1098526, 0x1068405, 0x02f7be7, 0x0385fce, 0x03e6374,
  48561. 0x0379ea9, 0x12b7715, 0x08e395e, 0x1ac4c18, 0x0ff87a2, 0x08ed294,
  48562. 0x1243ee3, 0x15f80cb, 0x0aec334, 0x07fd388, 0x1b2b49f, 0x093207c,
  48563. 0x07ed641, 0x18e6cfa, 0x0385e8b, 0x10a3da6, 0x02bad7b, 0x123a60a,
  48564. 0x04004ad, 0x161c3c8, 0x0080a38, 0x1dd756e, 0x05f2aa8 },
  48565. { 0x066524b, 0x06a3209, 0x1d9b882, 0x01a1433, 0x17bf388, 0x08375fd,
  48566. 0x1a17b68, 0x08d4b54, 0x1e642dd, 0x134f469, 0x0b93582, 0x18c38d0,
  48567. 0x0cef349, 0x07e5a9a, 0x1dbb8ec, 0x0cf704d, 0x12705eb, 0x13ed5d0,
  48568. 0x02f817d, 0x1764fc3, 0x05d12ba, 0x1d4716c, 0x0566bf2, 0x1b3a70d,
  48569. 0x12d1ae2, 0x03776e7, 0x187a9bc, 0x13b8a5c, 0x0e5ae85, 0x1c5a433,
  48570. 0x11f0a09, 0x00579a7, 0x1ff0340, 0x1f417ec, 0x11d9e12, 0x09d1095,
  48571. 0x03c9f22, 0x0b24c04, 0x1e5268c, 0x13168df, 0x062501a },
  48572. { 0x1264086, 0x1becd56, 0x12f558f, 0x174bc1c, 0x0a6a33d, 0x069eb3e,
  48573. 0x0c00a32, 0x033d04a, 0x046e64b, 0x1446d64, 0x0914da8, 0x032e415,
  48574. 0x0cfa3c9, 0x16aa9f5, 0x0c326c3, 0x157a702, 0x0e02ea8, 0x1b11403,
  48575. 0x1b33f9d, 0x17ea9b9, 0x1b7052f, 0x18a7868, 0x0f66a38, 0x1362e83,
  48576. 0x12133d5, 0x14528ce, 0x1269bfa, 0x1ae8203, 0x04eb10f, 0x1bd05ae,
  48577. 0x17b46b3, 0x123f3b4, 0x0499b73, 0x152c33c, 0x1127037, 0x1557549,
  48578. 0x01f3531, 0x0e2fb9d, 0x1199732, 0x1fdfa7f, 0x0497b15 },
  48579. { 0x05568e9, 0x165d57a, 0x09be295, 0x1d8e325, 0x1491a0f, 0x1929cd7,
  48580. 0x0f74e6a, 0x153b760, 0x04ac37d, 0x032917c, 0x03d6d32, 0x1744054,
  48581. 0x1f8c8cd, 0x114e29c, 0x027f1d6, 0x1e05d02, 0x131ca90, 0x1ce6836,
  48582. 0x1885b6f, 0x03e0887, 0x1d918f3, 0x165d1f5, 0x066a9a2, 0x1800fe9,
  48583. 0x0d0d242, 0x1e71540, 0x1e1aa6d, 0x1b1bff7, 0x108edcd, 0x1f426b1,
  48584. 0x1290174, 0x00d0025, 0x0fa33fe, 0x10838ed, 0x144fb7a, 0x0d85dd7,
  48585. 0x0ff637e, 0x173f2e1, 0x132dede, 0x0d93ca2, 0x018d46a },
  48586. { 0x18b7802, 0x05d9153, 0x0bd21a3, 0x0492f97, 0x0745ddb, 0x17456e8,
  48587. 0x0bcf90a, 0x1c989d6, 0x0b4ceb4, 0x0055e6d, 0x17f502b, 0x064b464,
  48588. 0x052e0d8, 0x09d639a, 0x1f815c4, 0x0e372d9, 0x188b141, 0x1ba03d3,
  48589. 0x169e94a, 0x160c06d, 0x16ac70e, 0x1cec28b, 0x0ac2cdb, 0x052a9e7,
  48590. 0x09d297c, 0x0d68a08, 0x03735c1, 0x0e1bd39, 0x15e7513, 0x1ae6bdd,
  48591. 0x030fc36, 0x140dce1, 0x1f93d41, 0x18286a2, 0x1e29fa4, 0x1221aa9,
  48592. 0x1a38fef, 0x137c722, 0x0b901a7, 0x003a7ec, 0x0550446 },
  48593. { 0x0cb9cc9, 0x0e48803, 0x0053471, 0x0e83a00, 0x142074d, 0x11b7dc2,
  48594. 0x198f844, 0x104f9b0, 0x029ad5f, 0x0b90fff, 0x07f20ce, 0x17f452a,
  48595. 0x0f1d21f, 0x00068a2, 0x1781b9d, 0x05cd639, 0x16b9179, 0x148212c,
  48596. 0x06b5459, 0x0b91ca5, 0x1e98336, 0x02cd777, 0x188883a, 0x1855dc7,
  48597. 0x1318970, 0x05e5e5a, 0x0e7fc40, 0x0ef947b, 0x12973f4, 0x00bb7a9,
  48598. 0x06c9c1d, 0x13457a0, 0x12118ac, 0x1cfc9d0, 0x0824f75, 0x17e684a,
  48599. 0x06f5d7d, 0x1d47fbe, 0x1b13d58, 0x1f9af61, 0x00da313 },
  48600. { 0x1aa2557, 0x12d460a, 0x1a70dc4, 0x1801127, 0x0a21d70, 0x1c5411e,
  48601. 0x0e6519e, 0x05490e2, 0x07cb004, 0x09f4d3a, 0x0b38603, 0x09ff93c,
  48602. 0x022d2bf, 0x024d756, 0x14c6834, 0x00cc1aa, 0x016f03d, 0x02694d3,
  48603. 0x1c6dfc0, 0x1aa1ac3, 0x050c473, 0x1de51ef, 0x0ebc3b2, 0x1851e4e,
  48604. 0x19bea09, 0x132714a, 0x03e1c11, 0x1af85d4, 0x1083ef6, 0x1270b98,
  48605. 0x152b7eb, 0x128384a, 0x0940c26, 0x11681a8, 0x1042845, 0x1c882ce,
  48606. 0x1e82290, 0x01186c0, 0x12b3188, 0x1d1b682, 0x063630b },
  48607. { 0x07d2e41, 0x0a91145, 0x01e6fe3, 0x07d6c5f, 0x09e7582, 0x0016c4a,
  48608. 0x0cf75b1, 0x15a369a, 0x0de2c59, 0x01f026b, 0x0770e22, 0x11e8937,
  48609. 0x0cbf3f3, 0x1a5b862, 0x065f462, 0x1408b3b, 0x00c13ce, 0x08fb4d9,
  48610. 0x038981b, 0x1ae04ab, 0x1b79ca3, 0x1b930e8, 0x0f53f65, 0x0286df4,
  48611. 0x0afa85a, 0x003ab57, 0x02ed10f, 0x0d367d3, 0x18f6be3, 0x0c3672a,
  48612. 0x027f394, 0x1f1591f, 0x10cd478, 0x0d53975, 0x1cdf579, 0x00d00e9,
  48613. 0x08544eb, 0x0c22e03, 0x023b4a5, 0x0e3e2cd, 0x0306a98 },
  48614. { 0x14ec136, 0x08f4eb1, 0x163ef11, 0x141cdec, 0x1edf27c, 0x0da0900,
  48615. 0x0054b03, 0x0cf537c, 0x0c5bfee, 0x1db7790, 0x15808e1, 0x0471345,
  48616. 0x1935283, 0x03d7dc4, 0x1959363, 0x185bcc1, 0x1c00ac9, 0x1a57915,
  48617. 0x0aa748a, 0x0dec630, 0x101b28e, 0x00fa993, 0x101d71c, 0x00ebf23,
  48618. 0x018f882, 0x088fb6a, 0x146faa9, 0x13f4c51, 0x12a13df, 0x1d0bb73,
  48619. 0x0715479, 0x0efe980, 0x106215b, 0x0eac449, 0x1cc64f2, 0x08e3574,
  48620. 0x18e57cd, 0x01f5f02, 0x0f8dd91, 0x083d020, 0x02833ac },
  48621. { 0x1a5ec5c, 0x125c346, 0x0c91f95, 0x103811b, 0x0c3d9da, 0x0bd3945,
  48622. 0x07c2e31, 0x1853af8, 0x19d343d, 0x08957f3, 0x180ce4d, 0x099ffb8,
  48623. 0x01b438e, 0x0e7d0ca, 0x1689c03, 0x00892fa, 0x1f82732, 0x16af991,
  48624. 0x0e4f1b9, 0x0f4b1c2, 0x04311b8, 0x08825d5, 0x1b2da2f, 0x04569af,
  48625. 0x01c5a47, 0x1d5604e, 0x1c81ad7, 0x085f552, 0x16327ef, 0x1e6b4cb,
  48626. 0x1678772, 0x010ef0f, 0x15ba9e4, 0x000c8b2, 0x1d5f797, 0x117ab38,
  48627. 0x0bcf353, 0x1810768, 0x18c0d9c, 0x0a9493a, 0x0120cd4 },
  48628. { 0x0b0f9ee, 0x0dc7a65, 0x03bbaff, 0x00599cb, 0x1c003ef, 0x068332d,
  48629. 0x1a1056a, 0x0e936d4, 0x09b9577, 0x01769d3, 0x06ad719, 0x0fe08e4,
  48630. 0x133de48, 0x10d2786, 0x0bfce00, 0x1bb9bde, 0x15829db, 0x15e8b7a,
  48631. 0x1a4f7fc, 0x00b6961, 0x0ec12ef, 0x0905e4d, 0x1787ea8, 0x0cff525,
  48632. 0x0e2c2d4, 0x11a336d, 0x117accf, 0x0b1b5ec, 0x0103cb7, 0x0cfb478,
  48633. 0x0c299eb, 0x137c048, 0x11f693a, 0x02a5e0a, 0x125bad0, 0x1daad30,
  48634. 0x1019336, 0x18b3bf3, 0x1a8fa3b, 0x02cffbd, 0x0021cfd },
  48635. { 0x15c36f3, 0x1b8afef, 0x095171c, 0x0fac95a, 0x103bde3, 0x07bb89b,
  48636. 0x03443cb, 0x190aa6d, 0x10f3993, 0x12f63db, 0x0b93287, 0x0eec609,
  48637. 0x0bfdb16, 0x1e9dd8c, 0x03dc5f8, 0x07ab41b, 0x13f6634, 0x0a93383,
  48638. 0x158022d, 0x16a5de2, 0x070ffae, 0x1c91252, 0x0e5eb57, 0x0556a35,
  48639. 0x0e391ed, 0x01657c3, 0x1e65d0c, 0x1818fca, 0x0ae28ad, 0x140bfe8,
  48640. 0x073223e, 0x17f1dab, 0x07c22df, 0x145db40, 0x08c7ac4, 0x06bbdb8,
  48641. 0x020595a, 0x16e6ce5, 0x1de39c7, 0x08d8e79, 0x007265b },
  48642. { 0x166232f, 0x0ccf85e, 0x1c59cf7, 0x138804e, 0x059aaf8, 0x0307e26,
  48643. 0x1b7e96e, 0x0775f04, 0x07a943f, 0x1cf5455, 0x110a348, 0x1634a47,
  48644. 0x1a0e0e1, 0x14b9dca, 0x1a838e9, 0x0ea76ab, 0x0aa2557, 0x1f51cce,
  48645. 0x1a55ec7, 0x1bee5e0, 0x0302f8a, 0x009de9a, 0x00e27cd, 0x148752e,
  48646. 0x127d0f8, 0x0b7999f, 0x02b6bde, 0x1b38181, 0x012aa2c, 0x124da4e,
  48647. 0x1a5b732, 0x0f4158d, 0x188deee, 0x004076e, 0x1d74191, 0x1b1e8ea,
  48648. 0x0cc2f4b, 0x0eb33e8, 0x125b1ba, 0x09663a2, 0x036c575 },
  48649. { 0x123d84b, 0x0023779, 0x113e448, 0x04fcf13, 0x0699112, 0x0dc02ad,
  48650. 0x0bd3a48, 0x09c961d, 0x0807997, 0x19cc225, 0x1e31e58, 0x0cd4e81,
  48651. 0x09c9054, 0x06b6f7a, 0x06343df, 0x1c97438, 0x06b4b23, 0x0a94bed,
  48652. 0x1060031, 0x13bfe78, 0x07771c0, 0x0d9bf7b, 0x1b1241d, 0x0a27bda,
  48653. 0x03a4050, 0x182d4a6, 0x05ac2c5, 0x1ace85d, 0x0af5ae3, 0x024a624,
  48654. 0x17b01e1, 0x192b045, 0x0c01532, 0x06ca7a0, 0x1797059, 0x0b45bb5,
  48655. 0x02975eb, 0x054564d, 0x0513bf2, 0x0c2328d, 0x006fbf8 },
  48656. { 0x145aa97, 0x099c71f, 0x1facb59, 0x103a081, 0x183b58c, 0x0f7c5ce,
  48657. 0x1d66c3f, 0x0f80bfd, 0x0e4d741, 0x1f5838d, 0x08688de, 0x03eb661,
  48658. 0x03982b6, 0x1db2de8, 0x17ca8ab, 0x0d7e698, 0x09d5cbf, 0x0f2055e,
  48659. 0x01984a9, 0x1864dbe, 0x0e28422, 0x0ecab8d, 0x124879a, 0x1a6869d,
  48660. 0x0b10b23, 0x099be44, 0x1e7681e, 0x0da5d2a, 0x19cf4d9, 0x03509b0,
  48661. 0x0860cf5, 0x1b2bddf, 0x1d19653, 0x147876c, 0x104680f, 0x0254fb0,
  48662. 0x04bb5ab, 0x1214a98, 0x0a7a979, 0x1fa3e1f, 0x05e9ca0 },
  48663. { 0x17c5dc4, 0x0a2b88c, 0x16896f5, 0x1fcf152, 0x02da40b, 0x0d87597,
  48664. 0x07bf3ff, 0x0f8cbf7, 0x00d1746, 0x0a96e16, 0x031a8fa, 0x18f78eb,
  48665. 0x1ac1fc9, 0x0a01a54, 0x1e558b3, 0x096adf8, 0x1be61f6, 0x19371b7,
  48666. 0x1a11ca2, 0x18973c3, 0x0c8a6ad, 0x09d47cd, 0x1fc597f, 0x1c7c026,
  48667. 0x13a4503, 0x071bde4, 0x0d9591e, 0x1598aa2, 0x0ddc77e, 0x0b8b832,
  48668. 0x0534ce4, 0x0ed26d2, 0x1b318dc, 0x012533a, 0x071cd89, 0x08d363e,
  48669. 0x09955f3, 0x01022da, 0x1abe233, 0x1678d06, 0x0940622 },
  48670. { 0x1997973, 0x0665b86, 0x04551c4, 0x1ba7f1e, 0x1b29625, 0x0bd5ea9,
  48671. 0x113556e, 0x14b19e1, 0x0673e14, 0x1190f05, 0x18891b1, 0x1f3a7a4,
  48672. 0x110541a, 0x17e41d8, 0x1b61d51, 0x0a549bc, 0x1a8f016, 0x123f4be,
  48673. 0x16600ad, 0x05674d5, 0x04b20f8, 0x1ad74e2, 0x1a6a901, 0x1a57eee,
  48674. 0x15de2ce, 0x06d579f, 0x0925e90, 0x1de3d51, 0x03ba9c1, 0x03041e1,
  48675. 0x120b83e, 0x1e32145, 0x0a998a4, 0x119b46c, 0x12333f7, 0x03c5693,
  48676. 0x1de6bd7, 0x1a4c125, 0x1b6dae7, 0x0c8f0b7, 0x080bb16 },
  48677. { 0x1145cb5, 0x0baff7e, 0x020c179, 0x0358bcd, 0x155ee56, 0x09d9398,
  48678. 0x1c33e1e, 0x0708c3c, 0x0133b23, 0x18aa9ef, 0x1ee81e7, 0x0187454,
  48679. 0x1a2fb9e, 0x1f38437, 0x0ff5aa0, 0x1972787, 0x1008bb4, 0x0db5d42,
  48680. 0x1be0b6f, 0x0daf12e, 0x09ff0b6, 0x1b2a75a, 0x1f569bf, 0x0416644,
  48681. 0x1d2371f, 0x06e66b2, 0x09538a7, 0x13d4938, 0x118ff97, 0x0cb1e58,
  48682. 0x02d925d, 0x198b000, 0x09598dd, 0x03bce4b, 0x0460443, 0x0b2a20f,
  48683. 0x03b85a3, 0x1e0aa43, 0x08d43b7, 0x1d48242, 0x0077ba5 },
  48684. { 0x1d86f61, 0x11c69e6, 0x02ac2ce, 0x0a0a054, 0x0312144, 0x1681392,
  48685. 0x1b71601, 0x01e3225, 0x08a32f1, 0x0ee0fcc, 0x031d800, 0x03a21d0,
  48686. 0x13bb1d3, 0x1a32745, 0x1bb1f97, 0x093dda8, 0x1369abf, 0x1eab4d7,
  48687. 0x136b79d, 0x10dd4e5, 0x19209d2, 0x06a2d6a, 0x0af9c08, 0x1335cfe,
  48688. 0x1236e62, 0x003d5f2, 0x174fd57, 0x1262f37, 0x150e80c, 0x0cad291,
  48689. 0x01a04e2, 0x15fe0eb, 0x101265c, 0x1cb2984, 0x06cbd1c, 0x02b6790,
  48690. 0x1bc77d2, 0x1bac0ec, 0x08b8aeb, 0x1be8b23, 0x06b2006 },
  48691. { 0x05b1bc1, 0x128544b, 0x13f6cbf, 0x152c576, 0x131f536, 0x073fccc,
  48692. 0x034cc00, 0x0bdaae3, 0x153d512, 0x0394792, 0x0972be1, 0x0309a42,
  48693. 0x1e4f8a6, 0x1abfb3c, 0x1c69c04, 0x180b4a9, 0x00c1531, 0x0b854fa,
  48694. 0x1ea2ddd, 0x01972ed, 0x0ce910d, 0x0f4ee09, 0x0d1dbd0, 0x0abf129,
  48695. 0x17a7527, 0x0d22e46, 0x01895d0, 0x0d825c2, 0x17b16cd, 0x17dc648,
  48696. 0x08098a9, 0x071ad61, 0x0d116e6, 0x1c74192, 0x0300cb0, 0x19092a8,
  48697. 0x06868af, 0x0dc88e3, 0x0d54215, 0x14d7a4d, 0x053217e },
  48698. { 0x19f52b4, 0x0023992, 0x11b3f21, 0x17cc422, 0x168da9c, 0x05e9374,
  48699. 0x0e17b2b, 0x0892c9d, 0x1e4a543, 0x1bed516, 0x093fdea, 0x1090703,
  48700. 0x0f6dc3b, 0x00e40af, 0x1ea5acd, 0x163c340, 0x1e8c3d4, 0x0627d74,
  48701. 0x0b3a7aa, 0x071a3c8, 0x052f0f9, 0x061ae60, 0x09c9f6b, 0x140de0f,
  48702. 0x001c9e9, 0x0d0e40f, 0x0d29b59, 0x13c11b9, 0x04a9a6a, 0x08b9b02,
  48703. 0x16fe38b, 0x1e57a52, 0x1893dd0, 0x00d894c, 0x0de7e5e, 0x05411a6,
  48704. 0x01830ac, 0x1eb000b, 0x0fbbd92, 0x03db35b, 0x0038693 },
  48705. { 0x09885a5, 0x1d5d9e8, 0x0c1f435, 0x0fc6ab7, 0x0d9d2b6, 0x175d76f,
  48706. 0x0e33d4d, 0x1ac7784, 0x0699ce4, 0x0e5173c, 0x1653358, 0x088e222,
  48707. 0x12354ff, 0x0198b56, 0x12f9c24, 0x1eb88ab, 0x1fd49ff, 0x020c33c,
  48708. 0x1e71b10, 0x159aea1, 0x121a75b, 0x0414b93, 0x19dfb72, 0x1dea05e,
  48709. 0x16887e5, 0x107412c, 0x1efcc83, 0x0b3d26c, 0x1dccb24, 0x1b77c5d,
  48710. 0x0f60738, 0x16ecd0c, 0x1a097fc, 0x036dc0d, 0x075b563, 0x179a744,
  48711. 0x14a8748, 0x04b3e6d, 0x0708039, 0x0922a08, 0x02caaf7 },
  48712. { 0x0d20424, 0x0c00337, 0x151513e, 0x06448e2, 0x13e4ea2, 0x0d46435,
  48713. 0x14695e0, 0x0164d1d, 0x17ae5b7, 0x06855ba, 0x14e6092, 0x06406ad,
  48714. 0x046ca8b, 0x16f98fd, 0x1a39a04, 0x1b9e539, 0x032d925, 0x15c84e9,
  48715. 0x159c8f7, 0x191ef1e, 0x16f9302, 0x14d5d64, 0x045c975, 0x1a342e0,
  48716. 0x047ca57, 0x1f3b2b5, 0x070628a, 0x176baa2, 0x10d9d96, 0x02f8d6a,
  48717. 0x062d5b9, 0x0e160aa, 0x0e886e2, 0x07fc89b, 0x1cf4276, 0x1d8f8e3,
  48718. 0x1350361, 0x10ddf14, 0x0ef6196, 0x0648bfc, 0x086d7f5 },
  48719. { 0x0bf719a, 0x0b75b58, 0x044e67c, 0x111787b, 0x1697509, 0x0680da5,
  48720. 0x039489b, 0x039f5ca, 0x090898d, 0x1f1d62a, 0x1b199b4, 0x13b710f,
  48721. 0x184da3b, 0x1df522d, 0x0c01913, 0x160b0b0, 0x1d98355, 0x19b4f9d,
  48722. 0x1e6f304, 0x047350a, 0x18110fb, 0x1cb715e, 0x13d6d14, 0x0331fa4,
  48723. 0x13baf24, 0x08e803f, 0x0e20df5, 0x114cedb, 0x075b166, 0x1531757,
  48724. 0x0f1a3bb, 0x07b6c10, 0x1fe5f94, 0x1b62d2f, 0x143df60, 0x0aa5929,
  48725. 0x0bc1ff8, 0x061e37e, 0x0d37569, 0x1c70d81, 0x0682a55 },
  48726. { 0x07495aa, 0x11ad22c, 0x117723c, 0x18698e4, 0x0276026, 0x0d23719,
  48727. 0x03316dd, 0x1cfad5c, 0x1ecc3e5, 0x0869cb2, 0x0598a62, 0x085e285,
  48728. 0x071b133, 0x0543b91, 0x0649f9a, 0x14d1791, 0x07e2324, 0x10aa1f9,
  48729. 0x0737086, 0x08ed089, 0x10ac6c4, 0x078a296, 0x06f1ff5, 0x09608b9,
  48730. 0x10a31ff, 0x1089661, 0x0214bdd, 0x02ba8d4, 0x1dd7a64, 0x1829637,
  48731. 0x046b5cd, 0x0f698f9, 0x0ecc3ab, 0x06b866e, 0x006dda2, 0x0ba59be,
  48732. 0x040d390, 0x0792a17, 0x1373415, 0x14dfdfc, 0x002227f },
  48733. { 0x151948b, 0x0f7ecdb, 0x0974601, 0x0dfbfa4, 0x0efeed4, 0x1645914,
  48734. 0x038253c, 0x1cb9625, 0x196f7c5, 0x088485f, 0x0fb2827, 0x0089699,
  48735. 0x040959d, 0x0704658, 0x12557e6, 0x09f9c43, 0x19d68fa, 0x15e0f93,
  48736. 0x1c42ba6, 0x03c29c0, 0x07f4b02, 0x0fc408b, 0x19345ba, 0x193e34a,
  48737. 0x1c22ebb, 0x1757ad2, 0x1f8d083, 0x1e6e2db, 0x04e8435, 0x1c8aeae,
  48738. 0x0065c7a, 0x051ff75, 0x0fc55fc, 0x1babc32, 0x1535f74, 0x00684fc,
  48739. 0x15ebc7d, 0x1735310, 0x05de111, 0x134524d, 0x0547e24 },
  48740. { 0x1ffda27, 0x1434550, 0x1d411c1, 0x18f2ab9, 0x14e6cdc, 0x11f9ec5,
  48741. 0x1478429, 0x015eca2, 0x09de5e7, 0x1a093f5, 0x10a08d6, 0x1375f26,
  48742. 0x113d2c0, 0x1517bea, 0x126760e, 0x1804a31, 0x11dddee, 0x15062dd,
  48743. 0x0f73c73, 0x1bbf080, 0x1eda7ff, 0x14b0b7e, 0x195f934, 0x06543e1,
  48744. 0x1656979, 0x071e922, 0x00c6475, 0x08ebc1d, 0x00218b7, 0x1f50e11,
  48745. 0x014d1e6, 0x117964a, 0x0eb5c90, 0x099737e, 0x13a8f18, 0x1638d0b,
  48746. 0x1fe6c1e, 0x16e3a2d, 0x03bab10, 0x181a561, 0x045a41c },
  48747. { 0x1bbf0e1, 0x0d963a6, 0x1c38faa, 0x1f42f9e, 0x01ff962, 0x15a6332,
  48748. 0x09d617b, 0x0fdb83d, 0x0a9beb1, 0x1aa0969, 0x15d0693, 0x1ea5450,
  48749. 0x1f2c9e4, 0x0c27e88, 0x17df692, 0x0309d27, 0x1dc0df3, 0x0d957de,
  48750. 0x10878dd, 0x047a4a4, 0x181e963, 0x1224efb, 0x121ef87, 0x0b137d5,
  48751. 0x001ed3d, 0x16e8a2b, 0x14a3ffd, 0x1e17b37, 0x0f298c0, 0x0cea450,
  48752. 0x110b4c9, 0x1b11cd2, 0x02d7a77, 0x0157b1b, 0x1adadab, 0x0550980,
  48753. 0x1087da0, 0x028564e, 0x10322ea, 0x19285dc, 0x0128763 },
  48754. { 0x0bac178, 0x00783d6, 0x1db8a6a, 0x0869611, 0x1cc2004, 0x1f6f693,
  48755. 0x07451c3, 0x0cfd2c6, 0x1866157, 0x108aed1, 0x021522c, 0x0b89961,
  48756. 0x037c75f, 0x0d17470, 0x0a7484e, 0x02ea4b6, 0x0668b88, 0x07f4fed,
  48757. 0x0779faf, 0x1b1b118, 0x01233f1, 0x0f0190c, 0x0d1d959, 0x1932be7,
  48758. 0x05561b1, 0x18d839b, 0x02c4fad, 0x02c1963, 0x13a0eb2, 0x1289ccd,
  48759. 0x1d1fa36, 0x1641f9a, 0x08ca1f9, 0x136b92f, 0x019ed04, 0x1ed4fc0,
  48760. 0x08bb637, 0x01025bb, 0x1d3487a, 0x199f89e, 0x075e96b },
  48761. { 0x119716e, 0x08fee06, 0x1494627, 0x10f8708, 0x1f58505, 0x0c3e956,
  48762. 0x11b47aa, 0x01ec950, 0x16c0715, 0x15b5fc1, 0x1f56dc4, 0x1a8c9ad,
  48763. 0x1f91d85, 0x07a9faa, 0x1e220d9, 0x1225352, 0x1d88150, 0x030041d,
  48764. 0x0a1dbd2, 0x0e4d07d, 0x0489a76, 0x1d60ad9, 0x1a02cb9, 0x1a3b325,
  48765. 0x0f8d242, 0x0494c2f, 0x073cf79, 0x18af605, 0x0876279, 0x1c1e58a,
  48766. 0x01ff80b, 0x115cb6d, 0x0ba4fe4, 0x1c0cb57, 0x026d75a, 0x1b150de,
  48767. 0x016e523, 0x07ab35d, 0x0252762, 0x135744d, 0x0309a6e },
  48768. { 0x1fbe97a, 0x1f7285e, 0x1137bc9, 0x1f718a1, 0x1a5fe70, 0x104fae0,
  48769. 0x1ac05ff, 0x18b98f7, 0x1bed36c, 0x1d0ad42, 0x03b4ea3, 0x19b6eaa,
  48770. 0x01c0c3a, 0x15c8434, 0x007be1f, 0x0b9978b, 0x162c49d, 0x050ad99,
  48771. 0x1e8993a, 0x162e283, 0x0e880fb, 0x07c70f7, 0x099fe36, 0x1856c7a,
  48772. 0x0cfd621, 0x17ee98e, 0x154ef9f, 0x049b7cf, 0x0a358a9, 0x03bfed9,
  48773. 0x10750ba, 0x0ebad15, 0x19673c7, 0x1f52ae7, 0x03f5c53, 0x05c6b2f,
  48774. 0x1769b20, 0x19b329a, 0x0de27ba, 0x115aeb2, 0x0045825 },
  48775. { 0x042dbdf, 0x18d3a50, 0x1e8977d, 0x0eaef3b, 0x0d40585, 0x17332b9,
  48776. 0x12e9c34, 0x05c1ccd, 0x1ca2e89, 0x02eb3a2, 0x19ad7ca, 0x1bde1e1,
  48777. 0x03f56a8, 0x1183b3e, 0x1ba1476, 0x0d739c1, 0x0584334, 0x14c602b,
  48778. 0x1acf1d0, 0x1f9c4da, 0x1e00b35, 0x1f9cbbb, 0x102256f, 0x16db10d,
  48779. 0x0f6a6e7, 0x025c1e4, 0x0d3c0a4, 0x1dc2908, 0x04ec34b, 0x08ad974,
  48780. 0x045fdd2, 0x12da213, 0x0af663c, 0x1d6605d, 0x1d5f907, 0x1200970,
  48781. 0x0f86c02, 0x1c4072b, 0x1cd628a, 0x1c12b6e, 0x053f4a3 },
  48782. { 0x1fc48e7, 0x1846744, 0x0bac46e, 0x0f5f56b, 0x1a60c57, 0x00e5ad5,
  48783. 0x12fe283, 0x16de0d7, 0x079757c, 0x0977d75, 0x064581f, 0x0162ec6,
  48784. 0x09e26d9, 0x15bbdbd, 0x0a86ad8, 0x1e57e85, 0x0cd285d, 0x01c7760,
  48785. 0x0ea3dfc, 0x128febe, 0x15b5d35, 0x077e0e5, 0x05f2370, 0x0b08b9f,
  48786. 0x0cca0c4, 0x1797f5c, 0x0492789, 0x0dd1b31, 0x1ed89a1, 0x0736a41,
  48787. 0x1cdf099, 0x0a3b220, 0x1a3f145, 0x14cf809, 0x18b8c17, 0x070a02a,
  48788. 0x0908d56, 0x1cc6ba3, 0x148daab, 0x0a7ae47, 0x00a99e6 },
  48789. { 0x1bc0559, 0x1b7a355, 0x05808d4, 0x1735434, 0x0163067, 0x0b40dae,
  48790. 0x148a430, 0x00e453f, 0x11378e9, 0x092a5f0, 0x04e8b58, 0x0af556f,
  48791. 0x1bc60ff, 0x0332a96, 0x1cb7e2d, 0x0146d4d, 0x0938c17, 0x14d698c,
  48792. 0x06dd366, 0x1b357c5, 0x0523c5c, 0x19fbc24, 0x13dd1c9, 0x01c60c7,
  48793. 0x0a93a0d, 0x1ec6093, 0x0d09238, 0x1c4043c, 0x03ddfaf, 0x01f7419,
  48794. 0x19f65cd, 0x0664c73, 0x1768775, 0x12aa44f, 0x10c5d4c, 0x152ca1f,
  48795. 0x1eebf7e, 0x0aede89, 0x12f02d6, 0x08a021f, 0x03a95cb },
  48796. { 0x1d7ff2e, 0x134659c, 0x123e553, 0x1783ab8, 0x0dd1cb4, 0x14a1c54,
  48797. 0x0b1ddc5, 0x19c0552, 0x091cad8, 0x0b2e058, 0x142349e, 0x1156659,
  48798. 0x1a0c579, 0x134815e, 0x16f0f0e, 0x1a43034, 0x1255186, 0x1aa2e84,
  48799. 0x09f9936, 0x0ef9b7a, 0x12daf00, 0x1246684, 0x0055f2a, 0x0a65566,
  48800. 0x1a3a024, 0x1d19517, 0x0d0732a, 0x0bf6c73, 0x04aee6a, 0x16e0a3a,
  48801. 0x16805c0, 0x19b7527, 0x05bb436, 0x1c278a4, 0x1d98ca5, 0x0726b2f,
  48802. 0x1ad672c, 0x189e0ee, 0x1c91575, 0x05c0616, 0x0366d22 },
  48803. { 0x13ea5b2, 0x1a43aab, 0x1137542, 0x17521b4, 0x0fce401, 0x0d01880,
  48804. 0x1e995e8, 0x0c0f6a7, 0x1cf1144, 0x1154052, 0x02fd25c, 0x1e0b4a7,
  48805. 0x010b8eb, 0x0995669, 0x050451f, 0x1a0fb5c, 0x12c7b5a, 0x1b34938,
  48806. 0x1d23281, 0x0bfdce7, 0x18d86dc, 0x0c95c53, 0x063b452, 0x05e2eb3,
  48807. 0x13145dd, 0x1c72745, 0x057e5c6, 0x06811bc, 0x11b3684, 0x136ed6f,
  48808. 0x1f8157a, 0x1cb2656, 0x1b76e73, 0x049fea5, 0x054f4c2, 0x148850e,
  48809. 0x0661bfd, 0x1ee6690, 0x1f4945c, 0x132f3bd, 0x09072ba },
  48810. { 0x020ea39, 0x0f26ecb, 0x1ba11d3, 0x1f90639, 0x1bf1649, 0x1d4e21f,
  48811. 0x02ec734, 0x1aa161d, 0x13f3df1, 0x11c1437, 0x1b26cda, 0x05671e1,
  48812. 0x034ed07, 0x194e04f, 0x193261d, 0x044854d, 0x0c68ad1, 0x1751f45,
  48813. 0x0f7e96e, 0x01c457f, 0x15926ae, 0x07d8507, 0x1585c7b, 0x10e3f1a,
  48814. 0x0886d6b, 0x1ed19d9, 0x04d7846, 0x16337d5, 0x0f153f6, 0x0d203f8,
  48815. 0x1b93605, 0x0fad805, 0x0608d97, 0x047a33f, 0x0f66daa, 0x08fd1e4,
  48816. 0x039d165, 0x164b292, 0x1b0a49a, 0x17a6aa8, 0x08d92c6 },
  48817. { 0x1eb0ff7, 0x06be755, 0x0be2cf8, 0x087c1c8, 0x1be3525, 0x00424cf,
  48818. 0x0c89b7a, 0x186afa3, 0x11cd44b, 0x167170f, 0x13fb867, 0x1b7886b,
  48819. 0x1c1245a, 0x1c9fac0, 0x13ba103, 0x1728f0e, 0x19cbda0, 0x148b53b,
  48820. 0x095eb82, 0x1902b5f, 0x01b0abc, 0x16f8531, 0x05eb7b0, 0x1f217b9,
  48821. 0x0502b81, 0x11edf35, 0x054ef79, 0x097f3bc, 0x084c255, 0x0d5fbc4,
  48822. 0x1c2a23f, 0x19776a8, 0x0aa52b1, 0x09f7a98, 0x05b0a41, 0x15f00a7,
  48823. 0x0dd827e, 0x01ec4c4, 0x1970235, 0x02eb835, 0x04e4bec },
  48824. { 0x0c09676, 0x041d17e, 0x0a52fe1, 0x1e33d53, 0x057c4a3, 0x0152eea,
  48825. 0x0bbcf5c, 0x1b14d0a, 0x0843fe7, 0x1c8afe9, 0x0d45639, 0x15302dc,
  48826. 0x10644bb, 0x0f6ba37, 0x06e5742, 0x1e16b1a, 0x181b90a, 0x123b822,
  48827. 0x13f44d7, 0x0978d7a, 0x13a50bd, 0x13da741, 0x09b7381, 0x0ad5343,
  48828. 0x08f30ff, 0x1ff1607, 0x03b0b18, 0x1390100, 0x1508a8a, 0x1052cc7,
  48829. 0x0e91270, 0x0652502, 0x0b94cb3, 0x140d101, 0x14a3b1f, 0x0ec8fc7,
  48830. 0x1487767, 0x133e8d5, 0x1b491cb, 0x1eadf3b, 0x07a4aa3 },
  48831. { 0x07a0045, 0x178dd71, 0x0d41567, 0x1f64859, 0x1c812d4, 0x07c6926,
  48832. 0x1e390e7, 0x0a84748, 0x19b3f9c, 0x1aa27e2, 0x087f3e5, 0x02655ff,
  48833. 0x1b5ac68, 0x1a51641, 0x1e3fb80, 0x0976ee9, 0x00fcd3f, 0x14b6632,
  48834. 0x0144ba9, 0x1b9d3b6, 0x181e775, 0x0ee6e71, 0x19f7286, 0x1a7fcaa,
  48835. 0x0b3f3a9, 0x1a7e0f7, 0x0868649, 0x11c17e8, 0x169b123, 0x17da146,
  48836. 0x1e05664, 0x13fa13b, 0x0fcebde, 0x15aefa4, 0x093ed06, 0x0bb93bf,
  48837. 0x00a269c, 0x1ebee46, 0x0b78432, 0x0f7efe1, 0x060282a },
  48838. { 0x0eea2e7, 0x1f29c6e, 0x1875f01, 0x1078840, 0x18a322c, 0x0fb28b1,
  48839. 0x0a3e53c, 0x020ced0, 0x1c7776a, 0x10db4fd, 0x1ad017c, 0x082f6bc,
  48840. 0x02c63a3, 0x08d3db2, 0x067c962, 0x0288099, 0x0a82cad, 0x09c3496,
  48841. 0x021a6f3, 0x105ffc0, 0x066af1e, 0x070b7f2, 0x10c2dc5, 0x0032271,
  48842. 0x142f919, 0x1572fdb, 0x003e945, 0x1202cda, 0x073a43e, 0x1bd66c6,
  48843. 0x1c95543, 0x1f78b86, 0x16a407d, 0x01cf696, 0x14e5a33, 0x01c8f4e,
  48844. 0x0a5fbe7, 0x09436ca, 0x0e508ff, 0x18e478d, 0x05f4ae9 },
  48845. { 0x1f4d561, 0x116ed29, 0x064b65a, 0x002db43, 0x086d45d, 0x0a58289,
  48846. 0x007eff7, 0x1d48934, 0x19f2195, 0x0a44506, 0x1986cc9, 0x161546e,
  48847. 0x02c4151, 0x1cf2f70, 0x0311c7b, 0x1102f73, 0x06ea865, 0x1525e54,
  48848. 0x09a3f02, 0x15b70ef, 0x06a9bbc, 0x04b5b9b, 0x022cd19, 0x0cc385b,
  48849. 0x098d415, 0x1061977, 0x1b24050, 0x0b67698, 0x0752aff, 0x139a979,
  48850. 0x07288d4, 0x0a21c9b, 0x164ce73, 0x0554017, 0x1c9ab29, 0x072734f,
  48851. 0x001aa50, 0x09f148a, 0x0bf4a73, 0x047b88d, 0x092a014 },
  48852. { 0x02f7dbd, 0x125f08e, 0x1feba7c, 0x1f6faa4, 0x1a8c900, 0x0478946,
  48853. 0x096ee19, 0x0832c7c, 0x0481419, 0x15b89f1, 0x1d5bee6, 0x1a02f4c,
  48854. 0x1de87f7, 0x02c6c85, 0x1376178, 0x0d57a4e, 0x07a8256, 0x0c11ff7,
  48855. 0x1090065, 0x0461aee, 0x046e9f6, 0x16565af, 0x0115e7c, 0x14990fc,
  48856. 0x0626316, 0x02b9511, 0x0f666c2, 0x1943348, 0x08789e9, 0x15d1f24,
  48857. 0x0f61b70, 0x1280d87, 0x160b5b9, 0x04abf7c, 0x0a2e258, 0x16de588,
  48858. 0x161c515, 0x1a43830, 0x12e6e41, 0x03d5511, 0x00fc8fe },
  48859. { 0x0b90f2d, 0x10df6ff, 0x1565a2b, 0x1949162, 0x1393bb3, 0x074b1af,
  48860. 0x0be73d9, 0x18457cc, 0x0f8be75, 0x0a61208, 0x1dd4a4d, 0x0e06bcd,
  48861. 0x11bd7ea, 0x0b16559, 0x1921a38, 0x1e7ff84, 0x070c860, 0x1589c8f,
  48862. 0x16260df, 0x0cf8ea3, 0x0941df3, 0x1a15f99, 0x18542da, 0x182631f,
  48863. 0x0f46e78, 0x0b04af4, 0x0e8b12c, 0x167e3b5, 0x1afbf32, 0x1ae7380,
  48864. 0x1171b33, 0x0bd10e9, 0x0d27530, 0x16e5f1d, 0x1945771, 0x1a7250b,
  48865. 0x199892d, 0x0aa6c36, 0x1e27cf2, 0x0c5bfa6, 0x02d0ba8 },
  48866. { 0x072e1af, 0x0c7745a, 0x0f33ab3, 0x1d6ed57, 0x0b354ea, 0x0c9fdef,
  48867. 0x02fe343, 0x00d36a4, 0x1fe6fc7, 0x066b06b, 0x18bce7f, 0x1bbd49d,
  48868. 0x1ea9353, 0x0d40f28, 0x0c2497a, 0x0ceeebd, 0x1a1d136, 0x0f719a6,
  48869. 0x14d535a, 0x05193fa, 0x0d54c1d, 0x0ac952f, 0x0e5dc5d, 0x1ee1b03,
  48870. 0x0367fb7, 0x13d2e9f, 0x0aa4ceb, 0x17cfdd9, 0x1cfbb77, 0x18fcf11,
  48871. 0x0049933, 0x11292ed, 0x1129f4a, 0x111ad86, 0x169026d, 0x14e0a6e,
  48872. 0x08a376d, 0x1b263aa, 0x16ff333, 0x0249a83, 0x0963c87 },
  48873. { 0x036a814, 0x14865ef, 0x0ad6eb8, 0x0ae6762, 0x1bdb019, 0x1ff070c,
  48874. 0x1619fdd, 0x1d41d75, 0x129720c, 0x13e8cfe, 0x07b1c82, 0x0ca3205,
  48875. 0x1e434d7, 0x1da8c88, 0x1abfc5e, 0x0fec10a, 0x19ad80a, 0x168512e,
  48876. 0x0123041, 0x150d5ff, 0x149cffc, 0x1ca1d6b, 0x14fa2f7, 0x1cd2d76,
  48877. 0x00284e3, 0x10afdcf, 0x0bbbb90, 0x1d6cc61, 0x0f3c633, 0x1dcf176,
  48878. 0x102763e, 0x09c0181, 0x1da4ffa, 0x1df5638, 0x1965755, 0x1f652d7,
  48879. 0x08cec7e, 0x08fdd6d, 0x15ef45d, 0x079feab, 0x02d03eb },
  48880. { 0x0f2ec1d, 0x1492f82, 0x1b8bac5, 0x0c1a28f, 0x0878f27, 0x0cecf05,
  48881. 0x1d812ab, 0x0b6885b, 0x13f7103, 0x08efa25, 0x05756e2, 0x0567197,
  48882. 0x03c2827, 0x0f74769, 0x053bed5, 0x1e7c6de, 0x00f13b0, 0x179e223,
  48883. 0x0f5ccd7, 0x1f37aed, 0x1a6e889, 0x18fbaad, 0x0227b9d, 0x04336d9,
  48884. 0x184feed, 0x008b134, 0x1fb0bb9, 0x1a898e6, 0x0fcd372, 0x02d131f,
  48885. 0x1aee50e, 0x0cc6f04, 0x109321b, 0x15bd3ec, 0x09e4fb9, 0x0f849f1,
  48886. 0x07cf61b, 0x0546925, 0x0b3668f, 0x1838a97, 0x0842e40 },
  48887. { 0x061d843, 0x1476b53, 0x0335689, 0x149eb66, 0x02328cc, 0x08f0bb8,
  48888. 0x1fb444c, 0x0ce2dcd, 0x0c66959, 0x086f65a, 0x0b8a01a, 0x17ecaf6,
  48889. 0x10bdac5, 0x0f7f216, 0x1fe0b28, 0x1945f04, 0x00aca5f, 0x162aa76,
  48890. 0x1791541, 0x04ed83b, 0x1513ac5, 0x047183b, 0x0dfd32c, 0x10f2f99,
  48891. 0x16d9acc, 0x1694657, 0x10364cc, 0x0b2c902, 0x1a409fd, 0x114b942,
  48892. 0x04f31ab, 0x0c447a1, 0x173c2a5, 0x07e04bb, 0x1ab144a, 0x185aa4c,
  48893. 0x1c31fe6, 0x0b5be5d, 0x04ca296, 0x1359592, 0x00e6331 },
  48894. { 0x0360ac2, 0x097d6f8, 0x016ad73, 0x1c50bcc, 0x06b660d, 0x0dcd8a4,
  48895. 0x13c4389, 0x0a9058d, 0x1aa9ac5, 0x0afd1c6, 0x101c3a7, 0x0370a4d,
  48896. 0x0d3dfcf, 0x1fe6629, 0x1e6a5ac, 0x18fea06, 0x0290bfc, 0x0f1b2ce,
  48897. 0x074f9a8, 0x147b6ad, 0x02d55b1, 0x1acdbda, 0x0d054a2, 0x045400d,
  48898. 0x1efa49c, 0x1db49a6, 0x026d338, 0x01e7003, 0x0baf329, 0x1e0259d,
  48899. 0x18ac1ce, 0x1ff0713, 0x1a5a222, 0x0d1ad93, 0x1547fe9, 0x0416f53,
  48900. 0x08e1a7c, 0x1cf6779, 0x1c16924, 0x14430e4, 0x088839d },
  48901. { 0x01ce29a, 0x1361838, 0x15415ad, 0x0cb1303, 0x1acaf12, 0x0fcf909,
  48902. 0x1f03041, 0x027a9b5, 0x0373e3d, 0x172b8f3, 0x1b8f2bf, 0x190df45,
  48903. 0x1ae7269, 0x0e901c2, 0x132992b, 0x1d359eb, 0x1573000, 0x190bf93,
  48904. 0x19c9cfb, 0x09b68e1, 0x0776c93, 0x1b9aadb, 0x10a53d3, 0x180a300,
  48905. 0x036b96f, 0x0858fd5, 0x0ec1486, 0x1f1163b, 0x0aef528, 0x0dc874f,
  48906. 0x040d5e4, 0x1b6d037, 0x17fb2eb, 0x0e1b4f9, 0x1475105, 0x1273a14,
  48907. 0x1d2e21c, 0x0ce6538, 0x0309bf1, 0x1fd43ea, 0x064128c },
  48908. { 0x0f5b0b5, 0x13c5174, 0x0167c0d, 0x19a681e, 0x1c7e249, 0x053e762,
  48909. 0x011064f, 0x1308288, 0x0bc83af, 0x1ae51a3, 0x02eec01, 0x0067f55,
  48910. 0x17f39f0, 0x19c1187, 0x063c3b7, 0x1e68a7a, 0x00cd448, 0x0bc6ff8,
  48911. 0x146a91d, 0x045181a, 0x08d1849, 0x0418649, 0x175389c, 0x0259fa7,
  48912. 0x1a6868f, 0x1036335, 0x0e22ce8, 0x122093b, 0x0dae010, 0x082c80b,
  48913. 0x1f76197, 0x1c4a7c6, 0x199e905, 0x0c38da2, 0x0309f3a, 0x1c6459e,
  48914. 0x174a132, 0x07aa6d0, 0x12f6805, 0x0137b57, 0x093634a },
  48915. { 0x1a2e304, 0x13593d4, 0x04918a0, 0x0d83498, 0x057e186, 0x1c0b886,
  48916. 0x0e0c888, 0x1fd2275, 0x1a9847c, 0x14db5c2, 0x1d1bf5f, 0x19e256b,
  48917. 0x0d29655, 0x001c733, 0x0555cae, 0x0bd56e5, 0x0016fa9, 0x0f265d3,
  48918. 0x077b6a0, 0x0220e37, 0x161ebbc, 0x0d1f8e7, 0x05fc002, 0x07c19f7,
  48919. 0x0777b37, 0x11da9b9, 0x1344e75, 0x005f213, 0x07d78e3, 0x196d27c,
  48920. 0x18c7b59, 0x168090e, 0x02077a3, 0x011591b, 0x0cb6773, 0x0f88118,
  48921. 0x06deeee, 0x062df91, 0x0d5f92d, 0x0cf780c, 0x0266cb4 },
  48922. { 0x16363e8, 0x120aa5a, 0x136dbea, 0x1078354, 0x0b4fd07, 0x0f32cba,
  48923. 0x03778ae, 0x108286b, 0x0fa004b, 0x19a571f, 0x0446996, 0x05d9e33,
  48924. 0x18cf44b, 0x129b5fb, 0x12aa0ce, 0x1b92aab, 0x0b98870, 0x0b0370f,
  48925. 0x07cd447, 0x0650fa1, 0x1364e3c, 0x15ceae7, 0x1a2cbd3, 0x157193c,
  48926. 0x0e89263, 0x108e0aa, 0x1b0daad, 0x0a91051, 0x17d1201, 0x1fe5d0d,
  48927. 0x15c24ca, 0x0a62b71, 0x0e7b5bc, 0x19d60bf, 0x0347dd1, 0x06f05fa,
  48928. 0x1c8f2af, 0x1814d41, 0x13b86f2, 0x036a48a, 0x04b1d5a },
  48929. { 0x1d52c0c, 0x128ba31, 0x06744bf, 0x1c31181, 0x1735525, 0x071cab1,
  48930. 0x0558cd8, 0x086b8c4, 0x0acfa5a, 0x059f8e5, 0x1a041e2, 0x1414f2f,
  48931. 0x0a90123, 0x18af040, 0x0c7dad6, 0x1b5b574, 0x012fca3, 0x06bef2f,
  48932. 0x17d4472, 0x0e6c361, 0x1d4e328, 0x0a32bab, 0x1f32003, 0x00fd922,
  48933. 0x10f3d52, 0x0718840, 0x04c3ba8, 0x1a9cade, 0x05a2ec0, 0x17099f5,
  48934. 0x142efdf, 0x17cd577, 0x1c07762, 0x1fb0cb7, 0x1738482, 0x159063f,
  48935. 0x1622d42, 0x1a1cfd5, 0x12c9f81, 0x07ea11c, 0x08186b9 },
  48936. { 0x1312867, 0x0e8aa04, 0x16d3186, 0x0b7f5ef, 0x1e042c0, 0x0faeed3,
  48937. 0x059a07d, 0x105839e, 0x1a4fc3d, 0x055282b, 0x02e3f94, 0x1acb9cd,
  48938. 0x04ed30e, 0x1f5a6b2, 0x0c0702e, 0x0092fd9, 0x044831c, 0x03daee2,
  48939. 0x0df66c7, 0x1cd4013, 0x1c91351, 0x1ceca3b, 0x12ee18e, 0x1a82214,
  48940. 0x0589105, 0x1bd55d3, 0x110d602, 0x0010d9e, 0x1e357e3, 0x003b485,
  48941. 0x13ac4e7, 0x04f6a42, 0x0bfff1a, 0x1d5ab89, 0x1b5c8b0, 0x14f39f8,
  48942. 0x134a9bf, 0x01ef2bf, 0x0aca91d, 0x12f93dc, 0x00bf97e },
  48943. { 0x1a19e96, 0x027646e, 0x1a2e5bb, 0x14d860d, 0x14ce18e, 0x1b48c52,
  48944. 0x184ad97, 0x132fd06, 0x10d9a0d, 0x1637b45, 0x1730246, 0x0f48c5f,
  48945. 0x1398a69, 0x0ade1f0, 0x13897c6, 0x12e60cb, 0x0dab393, 0x10c4b76,
  48946. 0x0bc4a01, 0x10341e6, 0x07df9eb, 0x170e96e, 0x14f5d05, 0x08e6b33,
  48947. 0x07976ad, 0x01cf116, 0x0a7d7bd, 0x1bc6f53, 0x09d94e3, 0x0055cf3,
  48948. 0x121adeb, 0x0153a17, 0x0bfa9e0, 0x1789073, 0x1c3559d, 0x1eaed50,
  48949. 0x1eaac23, 0x0c8dda7, 0x0aaecef, 0x0587c81, 0x08fe548 },
  48950. { 0x09a4d1e, 0x133e167, 0x00e216b, 0x069e3a4, 0x0c3eb80, 0x0830c92,
  48951. 0x03ce897, 0x038b8d9, 0x1308fb4, 0x01ef056, 0x10a53a0, 0x0b79ce3,
  48952. 0x1a9961f, 0x1817586, 0x1881e37, 0x1d16db8, 0x115b64a, 0x1e43f7a,
  48953. 0x02d3463, 0x0f3e3ca, 0x1f43696, 0x10a90cc, 0x1170026, 0x0c814bf,
  48954. 0x084be0f, 0x0b353ea, 0x048f6ad, 0x1923176, 0x075d2c4, 0x08a6321,
  48955. 0x15a99f0, 0x195a5bd, 0x1a913b9, 0x1ae46ca, 0x062dad2, 0x0c313da,
  48956. 0x142d3bf, 0x15b1035, 0x0f0fd2b, 0x0d37791, 0x03928c6 },
  48957. { 0x0cb4b64, 0x1f5256d, 0x0687792, 0x09e4c2f, 0x03f62a4, 0x0889520,
  48958. 0x12539ea, 0x03de755, 0x1d36f33, 0x02247de, 0x0e17124, 0x057880f,
  48959. 0x1b42604, 0x1090dbb, 0x1629658, 0x1d308b5, 0x04f67ce, 0x098b3a5,
  48960. 0x18ecbc3, 0x1d177c9, 0x10eb7fa, 0x0ed3e49, 0x1a077db, 0x0b3a1a8,
  48961. 0x0fa98c2, 0x0fed6f7, 0x1afa870, 0x1629b3c, 0x1405d11, 0x0e4590e,
  48962. 0x150eeab, 0x0e7124e, 0x01dff93, 0x0e6f278, 0x0cfbc1c, 0x130386b,
  48963. 0x1150d0d, 0x026970c, 0x0d3d85c, 0x11e6aa2, 0x06ccc88 },
  48964. { 0x0d7504c, 0x1b7873d, 0x1777e34, 0x1fef2b3, 0x1ca3265, 0x0f33d55,
  48965. 0x07b7bfb, 0x05e1b9a, 0x0baebf3, 0x13b7a67, 0x1b73f04, 0x0dcc029,
  48966. 0x176825a, 0x0cd6c75, 0x0306a0a, 0x19c3c17, 0x0a909b8, 0x1189012,
  48967. 0x12f4d46, 0x1fb3173, 0x08becb8, 0x1c7d58f, 0x092104d, 0x0e7959f,
  48968. 0x10f5d39, 0x12a0bf6, 0x1096754, 0x02fc290, 0x191393a, 0x1c21ba5,
  48969. 0x1a54f56, 0x0359479, 0x1792b21, 0x07c0ac7, 0x0443230, 0x1a06bfe,
  48970. 0x0d4ed7b, 0x1d31abd, 0x0bbe5ab, 0x10164df, 0x02f1519 },
  48971. { 0x1d2d439, 0x118ed14, 0x0554321, 0x0578073, 0x121fbbc, 0x02dbad8,
  48972. 0x05e49b0, 0x1d87cb5, 0x0b6ce47, 0x0b67a60, 0x031961b, 0x0ecf3b1,
  48973. 0x17baaa1, 0x199aad0, 0x076e79f, 0x0b50a06, 0x1d80aef, 0x1c1c0f1,
  48974. 0x168c6f7, 0x1b65202, 0x1d7dc71, 0x1a4a4c7, 0x18e3dad, 0x17dddec,
  48975. 0x1f3f913, 0x1d9a276, 0x07d2ad9, 0x0c2e64e, 0x02df11e, 0x16387e9,
  48976. 0x048e880, 0x040b89d, 0x1be0389, 0x1cc907b, 0x0216a3a, 0x1438432,
  48977. 0x1eb54aa, 0x002e745, 0x03595b2, 0x16e158b, 0x0354b05 },
  48978. { 0x09170e9, 0x0f11b3d, 0x0335c5c, 0x1a995aa, 0x01eec42, 0x0ee67d8,
  48979. 0x0093cf3, 0x035ff7d, 0x1a66cae, 0x19f4671, 0x11f4069, 0x14ff2cb,
  48980. 0x1eb7138, 0x0e1ecb8, 0x01638fd, 0x14e5600, 0x0c32ff0, 0x1a92c8d,
  48981. 0x0ef39db, 0x1f6b797, 0x1a18a32, 0x1c54fc0, 0x1cc906a, 0x14d0c61,
  48982. 0x13332ec, 0x09df98e, 0x11120bc, 0x08f5f3f, 0x081be28, 0x110bd23,
  48983. 0x1e5865b, 0x1cabdf9, 0x138f932, 0x06382cc, 0x12e1c2b, 0x047cfb5,
  48984. 0x0f09fac, 0x0df449e, 0x08e8750, 0x1895c6a, 0x048dc55 },
  48985. { 0x1092193, 0x11c1352, 0x1c32398, 0x04d1312, 0x046ec36, 0x04f5a0f,
  48986. 0x15abc97, 0x08a5e26, 0x083c7d2, 0x0bc0320, 0x0038e10, 0x1ecf2fa,
  48987. 0x1c982de, 0x12890a8, 0x0badb9e, 0x110d270, 0x0778af5, 0x10aa708,
  48988. 0x09473c0, 0x00e0eb1, 0x1c58187, 0x1bb8989, 0x137aea7, 0x02ab209,
  48989. 0x1b973ba, 0x19d2eb3, 0x0c7435e, 0x0a393e9, 0x0af2cd8, 0x0eb8c5c,
  48990. 0x18867ca, 0x130d71a, 0x194ccff, 0x1ce19e5, 0x092ee4e, 0x110e4bc,
  48991. 0x06e38c6, 0x0e7262b, 0x1008501, 0x1ba16db, 0x05f6a8e },
  48992. { 0x19a8690, 0x02652c7, 0x101e0dc, 0x0c5eed4, 0x1f36976, 0x1008141,
  48993. 0x0b631a4, 0x19ff782, 0x0bce3a4, 0x06ac78b, 0x0ac9b53, 0x0c94095,
  48994. 0x0878046, 0x07522bd, 0x173eee9, 0x12f2800, 0x1b3b8a5, 0x0a9bca8,
  48995. 0x1f87dce, 0x0573c89, 0x17974ca, 0x06ef992, 0x1910a2b, 0x14487b7,
  48996. 0x1a3420e, 0x00f3246, 0x0fd0f38, 0x19ccac5, 0x1db490c, 0x0210f93,
  48997. 0x1c2103c, 0x117f6f9, 0x16ccb70, 0x1cbe98a, 0x00356a1, 0x1736669,
  48998. 0x1eb814b, 0x09703d4, 0x01eb0b8, 0x0e594ff, 0x01ca650 },
  48999. { 0x19d25a0, 0x190e795, 0x1b6feec, 0x14814e8, 0x06affdc, 0x11b45ab,
  49000. 0x14c3967, 0x11f8382, 0x07d8006, 0x1768f52, 0x1f75a15, 0x11fcac8,
  49001. 0x089b74d, 0x04dbc6d, 0x05ad41e, 0x067223b, 0x0438bbe, 0x19cdba9,
  49002. 0x1616317, 0x1a887c1, 0x0a34ef8, 0x04cb235, 0x1374b6d, 0x0cea878,
  49003. 0x13bd1e6, 0x0c2bfd6, 0x01a2602, 0x01ae218, 0x1acabad, 0x1f9924f,
  49004. 0x04a7deb, 0x029f343, 0x15dec1c, 0x183d082, 0x0e647ec, 0x09594cc,
  49005. 0x15ffff6, 0x027ec89, 0x0f3bab1, 0x16d975a, 0x0462caf },
  49006. { 0x03237dd, 0x05323ef, 0x1010598, 0x190570e, 0x15f735c, 0x1d2afc4,
  49007. 0x07d6777, 0x095ef0f, 0x0726b91, 0x0f7821f, 0x0f8a605, 0x127a392,
  49008. 0x1118753, 0x1778c19, 0x08af9d1, 0x1425743, 0x1fc25a9, 0x1a73f46,
  49009. 0x070e45f, 0x1f92fb5, 0x1e41dfe, 0x0185175, 0x0f21d74, 0x065a399,
  49010. 0x1d235a7, 0x16987ba, 0x1b66ea9, 0x0dfdcff, 0x1485760, 0x07d5b2f,
  49011. 0x102a9e1, 0x0a27f07, 0x1155e22, 0x1ce8991, 0x1c60fa3, 0x1ba5f6e,
  49012. 0x1546eaf, 0x148a81d, 0x0d820a8, 0x118d9b2, 0x01293c9 },
  49013. { 0x1d53b77, 0x00928a4, 0x0b1dc9e, 0x1b2dd5f, 0x06ab403, 0x1b5b88d,
  49014. 0x11f6d28, 0x1836faf, 0x087e771, 0x11c6384, 0x0dd48a0, 0x157e676,
  49015. 0x0d495f6, 0x0643a98, 0x0c0a272, 0x0223561, 0x186e77b, 0x16541e5,
  49016. 0x06f4627, 0x181f714, 0x17c7be1, 0x1d8d74e, 0x1633ecb, 0x08187d0,
  49017. 0x023c549, 0x083e82e, 0x05d2b64, 0x0dcf3c8, 0x0e71421, 0x1f82832,
  49018. 0x13e8291, 0x1fbfac2, 0x0929cd4, 0x14c45e3, 0x0130e51, 0x03db64b,
  49019. 0x046f8fb, 0x125af9f, 0x052e9cf, 0x142d1d5, 0x053b79a },
  49020. { 0x0bbb6a1, 0x1d7e722, 0x1ca085b, 0x00cf042, 0x13a5bba, 0x0ec9cd6,
  49021. 0x12cc2a7, 0x1fdde3c, 0x1f19efa, 0x117579e, 0x1b00500, 0x179cf69,
  49022. 0x18fed5a, 0x0896339, 0x05a3b99, 0x11344c9, 0x06929fe, 0x09188cc,
  49023. 0x1ce5f01, 0x073b1a8, 0x16c40d5, 0x0a11a2c, 0x19002f1, 0x08cc23a,
  49024. 0x07f5853, 0x107dc94, 0x0f27576, 0x0813320, 0x1af2a80, 0x04cbe41,
  49025. 0x18797bd, 0x06502a3, 0x09dc01b, 0x0088264, 0x12a5610, 0x1a2a1f6,
  49026. 0x13872c9, 0x137beaf, 0x1a0cd02, 0x1a2ad85, 0x08290d6 },
  49027. { 0x0546946, 0x11be36c, 0x1febe11, 0x12d3d8a, 0x1a134a3, 0x04803f6,
  49028. 0x166935e, 0x013a846, 0x00dc7b8, 0x012abff, 0x1e12a6d, 0x0a5a5ac,
  49029. 0x1fe62ae, 0x05e56da, 0x1c53298, 0x1f94b44, 0x1e633aa, 0x0e61046,
  49030. 0x1659e04, 0x01dab9d, 0x1660238, 0x14ed990, 0x1b9ad57, 0x0ea46b4,
  49031. 0x0d02ca6, 0x0708df5, 0x06ccfe8, 0x0398ddf, 0x0a2a085, 0x1f13783,
  49032. 0x13ff488, 0x1d88f67, 0x0f332e1, 0x14c2700, 0x05ee82a, 0x088b3e5,
  49033. 0x0e952e1, 0x10ecb4f, 0x0aec1be, 0x156609f, 0x0506ef1 },
  49034. { 0x1bff163, 0x075939a, 0x061046d, 0x1fd53f5, 0x1130b96, 0x1593e73,
  49035. 0x1acfe77, 0x1aacd59, 0x19dd1c3, 0x16d78d2, 0x01d6aa8, 0x14fd4e6,
  49036. 0x18f5090, 0x11838da, 0x09abce7, 0x15b386d, 0x13ddf73, 0x15146b1,
  49037. 0x1722685, 0x0a99597, 0x1c3cdd3, 0x11ea6e5, 0x17fa8d0, 0x13b25a3,
  49038. 0x074d237, 0x1b2b776, 0x1e3bb59, 0x02948ad, 0x0feb1fe, 0x1ba1fd4,
  49039. 0x11feaf9, 0x1731f97, 0x004ccf8, 0x138370a, 0x1effdc6, 0x10d99a5,
  49040. 0x0d85c67, 0x179feda, 0x00d136a, 0x17e2a40, 0x0415b7d },
  49041. { 0x18377a7, 0x082c33e, 0x09ca5c0, 0x1197006, 0x068a3d6, 0x1d26190,
  49042. 0x14a27c0, 0x121facf, 0x193c8f2, 0x1e384ae, 0x168ae12, 0x0279d3c,
  49043. 0x1b712fa, 0x07f5cf9, 0x1ab1b18, 0x0a985f8, 0x0d96e0e, 0x0866d1b,
  49044. 0x18c8280, 0x132ea30, 0x0f11454, 0x08cbf80, 0x1e4c632, 0x126ca11,
  49045. 0x04c3fe6, 0x05500ee, 0x0617c1a, 0x0d345df, 0x15511c7, 0x0778515,
  49046. 0x014d48b, 0x168245c, 0x06965ed, 0x0ea1f80, 0x0bf305d, 0x13f9c1f,
  49047. 0x0c831d5, 0x0ee4def, 0x01e7549, 0x1e35eb1, 0x01ec314 },
  49048. { 0x08310c2, 0x1ff7796, 0x1dd0198, 0x148afc7, 0x0a7e14d, 0x1a3443d,
  49049. 0x043f394, 0x18a7256, 0x1637ec2, 0x0f251c7, 0x0be37f3, 0x06416a8,
  49050. 0x1150773, 0x1bef0b8, 0x04c0be7, 0x1378c68, 0x063ae4b, 0x180c58e,
  49051. 0x14be79b, 0x0388ddb, 0x0fa0f00, 0x0b93766, 0x14eec2a, 0x08dc18f,
  49052. 0x1b99d77, 0x1765498, 0x1fd61d6, 0x01916de, 0x139c82e, 0x18be4b4,
  49053. 0x192eccb, 0x07bcb4c, 0x05135d2, 0x1fd35bb, 0x12d14aa, 0x1ce326d,
  49054. 0x0dc105d, 0x0e60479, 0x15e22b5, 0x024fffe, 0x017e91d },
  49055. { 0x1e051ca, 0x16769db, 0x1b52fa4, 0x1a338ee, 0x0644d4f, 0x033c25e,
  49056. 0x12d4802, 0x0639156, 0x1ce9d6b, 0x1533113, 0x07a71cf, 0x1347a51,
  49057. 0x0e39524, 0x08950cf, 0x1427997, 0x0b5d8a8, 0x0928c36, 0x153dea3,
  49058. 0x1e58f83, 0x132fc8e, 0x132d354, 0x0bdaccb, 0x035d965, 0x1a9476c,
  49059. 0x04aeb91, 0x1144cac, 0x1077acf, 0x1cca7d4, 0x0571df6, 0x0c76ab9,
  49060. 0x1e729f2, 0x16315c3, 0x101a38f, 0x1dcbf79, 0x1f098fd, 0x0a2c53e,
  49061. 0x0fc4a0d, 0x1211415, 0x030077c, 0x0967bba, 0x0118f3b },
  49062. { 0x0d4762b, 0x050543d, 0x05d5d28, 0x1518b1a, 0x1aef84d, 0x1bb6c30,
  49063. 0x1258133, 0x1162dfe, 0x07e60d9, 0x05f43c3, 0x1076eb0, 0x1ff67d9,
  49064. 0x1a83637, 0x0eeb0a3, 0x1129825, 0x08dcb84, 0x0345b08, 0x0d1f0bc,
  49065. 0x1de9301, 0x1d6d0dc, 0x0695735, 0x07efbac, 0x16f062d, 0x1bfca5e,
  49066. 0x18d0b1b, 0x1d08ab0, 0x1401c56, 0x0f1d981, 0x1d617f8, 0x1e8d616,
  49067. 0x04076f6, 0x0436c2e, 0x1d2b631, 0x0c9e110, 0x09e513d, 0x08459d1,
  49068. 0x04f1702, 0x0da9b52, 0x19c9cee, 0x0f91a07, 0x001d0a6 },
  49069. { 0x046533c, 0x1211b0f, 0x0ab9ee5, 0x01f7118, 0x0947799, 0x16250c7,
  49070. 0x1745a90, 0x08a0336, 0x1d83c7a, 0x09af40e, 0x198f8dc, 0x17ba996,
  49071. 0x0374a69, 0x13b606b, 0x19fb36f, 0x11b4cf6, 0x12111e6, 0x101eaa2,
  49072. 0x0ba1942, 0x199d6ba, 0x1b37596, 0x1e95781, 0x1355cb7, 0x17ab2a5,
  49073. 0x04ba1fa, 0x0b4a91b, 0x1ad3b61, 0x1e8fa8a, 0x10d5d47, 0x1ab964a,
  49074. 0x0116b62, 0x090dc5f, 0x0dd2dfa, 0x1d82265, 0x0d0f15a, 0x0dbaa4f,
  49075. 0x197c08e, 0x16dd124, 0x0c83f26, 0x00cfb4c, 0x01b625b },
  49076. { 0x1d8446d, 0x1d53da7, 0x0fad137, 0x035edfd, 0x001b2f0, 0x041c5ae,
  49077. 0x10e23fa, 0x1177e88, 0x1bba975, 0x19e21a7, 0x15af27c, 0x19750e2,
  49078. 0x0b2b971, 0x0fa484c, 0x0917970, 0x18bbad6, 0x1342b41, 0x1c3ee5a,
  49079. 0x13614b5, 0x1f018c6, 0x1a34db1, 0x0c1219e, 0x1b5b8c9, 0x0fbe184,
  49080. 0x020653f, 0x1b2fb34, 0x10d832c, 0x0994acf, 0x06656ac, 0x15614c1,
  49081. 0x1a0c87e, 0x17e0d2e, 0x1f5ca6f, 0x1b31c89, 0x04869c1, 0x1c2a72f,
  49082. 0x0400736, 0x18a1944, 0x05236f7, 0x12c33f9, 0x0333eca },
  49083. { 0x0775d81, 0x1bca456, 0x0f288cc, 0x1fa83b7, 0x18c2518, 0x1e74a41,
  49084. 0x1e93ef3, 0x1cec478, 0x054703f, 0x169b11b, 0x0ced6ea, 0x074827f,
  49085. 0x102b3a1, 0x1fae00f, 0x0cd5969, 0x12cc2bb, 0x0dc5235, 0x0eb9204,
  49086. 0x1585ba4, 0x0ff1ca3, 0x19995a1, 0x15e592d, 0x04305bb, 0x126e87d,
  49087. 0x08cf133, 0x053f9af, 0x0b952d9, 0x10fb4e9, 0x0d449d9, 0x191532e,
  49088. 0x17555ec, 0x06fcf62, 0x05082a5, 0x089a7bb, 0x1d0bcb3, 0x0c9a4b8,
  49089. 0x0ccf074, 0x0ece03a, 0x144d6ba, 0x0210e51, 0x072fc21 },
  49090. { 0x16004c8, 0x15901fc, 0x17fea41, 0x1e8b00a, 0x183f95c, 0x19ac84e,
  49091. 0x1619d57, 0x1ddaefa, 0x1e550c8, 0x14f537d, 0x0182052, 0x1952ab4,
  49092. 0x0291c8c, 0x1e74103, 0x07fb9e2, 0x1f0bc94, 0x0069a3d, 0x175cd6f,
  49093. 0x14f7999, 0x1b9e18f, 0x0d51fbb, 0x0dae99b, 0x08a28e4, 0x05ff878,
  49094. 0x18d285c, 0x12dbb07, 0x0cbdec5, 0x1dc91bc, 0x1770401, 0x1ec22b0,
  49095. 0x0800e00, 0x13bdff3, 0x173f648, 0x11ad272, 0x0e3a85f, 0x0dc344e,
  49096. 0x0840a6c, 0x0778be4, 0x164b48e, 0x1f1623d, 0x0480946 },
  49097. { 0x171f119, 0x1a3d47e, 0x1a56131, 0x1ca7d66, 0x19e65c5, 0x0c2c3d0,
  49098. 0x19e198a, 0x1e81c5e, 0x1ab18d6, 0x052444c, 0x02e3012, 0x00498c6,
  49099. 0x12a1a99, 0x16557c4, 0x05d4258, 0x1ac4909, 0x0bae20f, 0x064434d,
  49100. 0x10adf75, 0x05609ad, 0x17d03b7, 0x1b04c97, 0x189dd7a, 0x00dcd09,
  49101. 0x1c06e7d, 0x0038044, 0x0792ef4, 0x167686c, 0x0846e4c, 0x1335a5d,
  49102. 0x07a86b9, 0x08c8c9b, 0x01c2eb2, 0x029cfe0, 0x0f9b07e, 0x0ff0de5,
  49103. 0x0f68afc, 0x1474576, 0x1a4085b, 0x1fb8e70, 0x08dab61 },
  49104. { 0x14d1d45, 0x0e481ea, 0x0e890a9, 0x1dfe9f3, 0x0cd4297, 0x0a3c5a5,
  49105. 0x0d480d3, 0x0345b11, 0x108c462, 0x0d95d15, 0x195008d, 0x1376690,
  49106. 0x06d3d23, 0x088f997, 0x19dabb6, 0x1fb843b, 0x1cf3f06, 0x143bfc5,
  49107. 0x1b14540, 0x0e29833, 0x100d802, 0x15d2c83, 0x0841113, 0x1b992af,
  49108. 0x0229f31, 0x1f6c34a, 0x0ee05a7, 0x1d9cef5, 0x0f080e5, 0x050a965,
  49109. 0x1c556fa, 0x197af9d, 0x0b21b14, 0x0bf709f, 0x0b459ee, 0x193bdef,
  49110. 0x118f690, 0x1e543c8, 0x0a79f80, 0x05bf336, 0x06f77e6 },
  49111. { 0x00bbf59, 0x0def6f2, 0x0b5a89c, 0x06c8035, 0x177ba45, 0x0a0e688,
  49112. 0x180d5cd, 0x05e2eab, 0x04b71b0, 0x032da33, 0x0cd67cd, 0x0227502,
  49113. 0x0722eb7, 0x179c756, 0x04aa3f5, 0x1e76b2f, 0x12fff3b, 0x188d500,
  49114. 0x0170fef, 0x15f57ff, 0x0c4299a, 0x1783606, 0x047828b, 0x076f675,
  49115. 0x15d5777, 0x00518a6, 0x1b59a61, 0x1cbc5ce, 0x1a8be6a, 0x1039972,
  49116. 0x002184d, 0x1839eab, 0x06d7578, 0x1688177, 0x003da2f, 0x164689c,
  49117. 0x0184f0e, 0x0ebc434, 0x13e01e6, 0x12387a5, 0x063819c },
  49118. { 0x084b073, 0x1c970bc, 0x1fab294, 0x19d624c, 0x1ec3a1f, 0x181c53c,
  49119. 0x1d7c241, 0x0e07a0f, 0x0e4c47b, 0x195603e, 0x05ae472, 0x09dc37f,
  49120. 0x1ff9666, 0x157527d, 0x1d5d624, 0x0ca01d7, 0x191fade, 0x02d55f9,
  49121. 0x1c74481, 0x066ede2, 0x181ac5b, 0x08d069e, 0x07fd831, 0x0d50896,
  49122. 0x0cfe797, 0x12d0859, 0x0af6984, 0x0263993, 0x1d453ee, 0x0b69a75,
  49123. 0x10783f0, 0x0a096d7, 0x0d0319a, 0x1c655e0, 0x0f9c28b, 0x0fc8741,
  49124. 0x15e49b4, 0x057f762, 0x15fbb20, 0x02504cb, 0x067d48d },
  49125. { 0x02d56d6, 0x0acd3f5, 0x098c1a3, 0x1c4e901, 0x171abd0, 0x19b366e,
  49126. 0x076c2b9, 0x178d7a2, 0x007204e, 0x1db1ce5, 0x198a4fe, 0x05cfeef,
  49127. 0x1d89a24, 0x1add461, 0x19f28ad, 0x1f351bd, 0x03d64a2, 0x02396ee,
  49128. 0x1586804, 0x053be8e, 0x09d4842, 0x02e2db2, 0x057d8b2, 0x1924f9b,
  49129. 0x16b1b4d, 0x0cb7eea, 0x017b981, 0x1d17624, 0x129401f, 0x152855f,
  49130. 0x010fbf2, 0x021a383, 0x0900d0f, 0x00efaea, 0x0ea4a2c, 0x0a59e22,
  49131. 0x1f0e43f, 0x0bf5e18, 0x1371e8f, 0x071d070, 0x027950e },
  49132. { 0x1d0fa79, 0x10ff870, 0x17a7aac, 0x060916b, 0x0b9fd03, 0x11ba65a,
  49133. 0x11a24bf, 0x0d69926, 0x04eb21f, 0x1a413fd, 0x179f9ee, 0x1ef3524,
  49134. 0x1146716, 0x1eea629, 0x10afcd9, 0x0dbbe28, 0x14cd2e9, 0x09039ca,
  49135. 0x140aaa2, 0x02835d0, 0x0cc94e0, 0x0d4777b, 0x03b8038, 0x1019b5f,
  49136. 0x0849158, 0x0232ae7, 0x11a58a0, 0x1e7574b, 0x15dfbff, 0x027c2e8,
  49137. 0x094cd73, 0x13ed09e, 0x1f0440c, 0x12dec53, 0x14feec7, 0x175d008,
  49138. 0x1f2225a, 0x04cc09f, 0x175c687, 0x108f364, 0x054ff78 },
  49139. { 0x040b068, 0x177186f, 0x14789f1, 0x17cde74, 0x1226465, 0x1d90fb4,
  49140. 0x11813e8, 0x02bc494, 0x1c04181, 0x052d2d6, 0x0434ad4, 0x08831bf,
  49141. 0x0fe3285, 0x0e58600, 0x1d3963f, 0x011c776, 0x13b4a2c, 0x0e3478d,
  49142. 0x13367b2, 0x1be1021, 0x0a9f339, 0x0e5bc37, 0x0454d8b, 0x0ab5d5b,
  49143. 0x05e31c9, 0x035944a, 0x162da9b, 0x0d45803, 0x18a427d, 0x016e1b3,
  49144. 0x0b01a7a, 0x0519260, 0x1875500, 0x080f30b, 0x05967e8, 0x0d159b5,
  49145. 0x0e30b28, 0x0722b9f, 0x0c3f939, 0x10a7e30, 0x08adbad },
  49146. { 0x169d524, 0x1708f84, 0x11e4182, 0x0fe7379, 0x142fdaf, 0x00fe617,
  49147. 0x19d99f3, 0x09e79d8, 0x0e2336d, 0x0b5ce79, 0x103dfd1, 0x0bbd1c3,
  49148. 0x0e6aa1f, 0x04c27d8, 0x0f0ab48, 0x096519b, 0x1a61b46, 0x1a04867,
  49149. 0x090fcfb, 0x10de602, 0x07e740d, 0x0666af4, 0x056c5b3, 0x04d9a83,
  49150. 0x1168c30, 0x198201f, 0x0e05b01, 0x17c70d9, 0x007a1dd, 0x0379ac2,
  49151. 0x0bc53ae, 0x02e2fc3, 0x188b4f8, 0x1e4b67a, 0x06999b2, 0x036eb88,
  49152. 0x027e71c, 0x0160d50, 0x1797fcd, 0x06d8128, 0x0739300 },
  49153. { 0x0cdaf42, 0x1babe91, 0x0aae553, 0x1be8303, 0x188b591, 0x08a792b,
  49154. 0x1a067d5, 0x1791730, 0x0f18fd5, 0x0b21704, 0x13ae45a, 0x0ba2045,
  49155. 0x0592b30, 0x1527b4c, 0x05640f9, 0x1395c2e, 0x09d6117, 0x125ebeb,
  49156. 0x0a7006a, 0x1bfabba, 0x08ccdac, 0x0d6c888, 0x1c17775, 0x1591e2a,
  49157. 0x0c7b164, 0x197a1a5, 0x06d4918, 0x034a29c, 0x1fc4476, 0x130db98,
  49158. 0x0c516e7, 0x1c12c36, 0x1561348, 0x17911e7, 0x059dcfa, 0x0738515,
  49159. 0x0a7c99d, 0x0880c15, 0x197896f, 0x095c852, 0x08bc6ec },
  49160. { 0x1f2a32b, 0x172e073, 0x08c3425, 0x1812711, 0x1f54800, 0x0f1b067,
  49161. 0x10df100, 0x14c0dfc, 0x0bb6054, 0x12afe4e, 0x1ea9b99, 0x10c108a,
  49162. 0x17510e1, 0x1594d95, 0x0b3f288, 0x1b4c341, 0x1e351b7, 0x1399241,
  49163. 0x0f9b232, 0x08e3dcd, 0x09a1e31, 0x0e45b2e, 0x195950c, 0x1acb977,
  49164. 0x0c3b948, 0x1547e4d, 0x06ba6ca, 0x0611f84, 0x00aa6ad, 0x0f86d53,
  49165. 0x1535a9f, 0x1305f81, 0x044d96a, 0x1d26b94, 0x10b1611, 0x0b56025,
  49166. 0x1ceb895, 0x1e47b8e, 0x1f854ac, 0x0fb7d38, 0x08e8543 },
  49167. };
  49168. /* Perform the modular exponentiation in Fp* for SAKKE.
  49169. *
  49170. * Base is fixed to be the g parameter - a precomputed table is used.
  49171. *
  49172. * Striping: 128 points at a distance of 8 combined.
  49173. * Total of 256 points in table.
  49174. * Square and multiply performed in Fp*.
  49175. *
  49176. * base [in] Base. MP integer.
  49177. * exp [in] Exponent. MP integer.
  49178. * res [out] Result. MP integer.
  49179. * returns 0 on success, MP_READ_E if there are too many bytes in an array
  49180. * and MEMORY_E if memory allocation fails.
  49181. */
  49182. int sp_ModExp_Fp_star_1024(const mp_int* base, mp_int* exp, mp_int* res)
  49183. {
  49184. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  49185. !defined(WOLFSSL_SP_NO_MALLOC)
  49186. sp_digit* td;
  49187. sp_digit* t;
  49188. sp_digit* tx;
  49189. sp_digit* ty;
  49190. #else
  49191. sp_digit t[4 * 2 * 42];
  49192. sp_digit tx[2 * 42];
  49193. sp_digit ty[2 * 42];
  49194. #endif
  49195. sp_digit* r = NULL;
  49196. unsigned char e[128];
  49197. int err = MP_OKAY;
  49198. int i;
  49199. int y;
  49200. (void)base;
  49201. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  49202. !defined(WOLFSSL_SP_NO_MALLOC)
  49203. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 42 * 2, NULL,
  49204. DYNAMIC_TYPE_TMP_BUFFER);
  49205. if (td == NULL) {
  49206. err = MEMORY_E;
  49207. }
  49208. #endif
  49209. if (err == MP_OKAY) {
  49210. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  49211. !defined(WOLFSSL_SP_NO_MALLOC)
  49212. t = td;
  49213. tx = td + 4 * 42 * 2;
  49214. ty = td + 5 * 42 * 2;
  49215. #endif
  49216. r = ty;
  49217. (void)mp_to_unsigned_bin_len(exp, e, 128);
  49218. XMEMCPY(tx, p1024_norm_mod, sizeof(sp_digit) * 42);
  49219. y = e[112] >> 7;
  49220. y |= (e[96] >> 7) << 1;
  49221. y |= (e[80] >> 7) << 2;
  49222. y |= (e[64] >> 7) << 3;
  49223. y |= (e[48] >> 7) << 4;
  49224. y |= (e[32] >> 7) << 5;
  49225. y |= (e[16] >> 7) << 6;
  49226. y |= (e[0] >> 7) << 7;
  49227. XMEMCPY(ty, sp_1024_g_table[y], sizeof(sp_digit) * 42);
  49228. for (i = 126; i >= 0; i--) {
  49229. y = (e[127 - (i / 8)] >> (i & 0x7)) & 1;
  49230. y |= ((e[111 - (i / 8)] >> (i & 0x7)) & 1) << 1;
  49231. y |= ((e[95 - (i / 8)] >> (i & 0x7)) & 1) << 2;
  49232. y |= ((e[79 - (i / 8)] >> (i & 0x7)) & 1) << 3;
  49233. y |= ((e[63 - (i / 8)] >> (i & 0x7)) & 1) << 4;
  49234. y |= ((e[47 - (i / 8)] >> (i & 0x7)) & 1) << 5;
  49235. y |= ((e[31 - (i / 8)] >> (i & 0x7)) & 1) << 6;
  49236. y |= ((e[15 - (i / 8)] >> (i & 0x7)) & 1) << 7;
  49237. sp_1024_proj_sqr_42(tx, ty, t);
  49238. sp_1024_proj_mul_qx1_42(tx, ty, sp_1024_g_table[y], t);
  49239. }
  49240. }
  49241. if (err == MP_OKAY) {
  49242. sp_1024_mont_inv_42(tx, tx, t);
  49243. sp_1024_mont_mul_42(r, tx, ty, p1024_mod, p1024_mp_mod);
  49244. XMEMSET(r + 42, 0, sizeof(sp_digit) * 42);
  49245. sp_1024_mont_reduce_42(r, p1024_mod, p1024_mp_mod);
  49246. err = sp_1024_to_mp(r, res);
  49247. }
  49248. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  49249. !defined(WOLFSSL_SP_NO_MALLOC)
  49250. if (td != NULL) {
  49251. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  49252. }
  49253. #endif
  49254. return err;
  49255. }
  49256. #endif /* WOLFSSL_SP_SMALL */
  49257. /* Multiply p* by q* in projective co-ordinates.
  49258. *
  49259. * p.x' = (p.x * q.x) - (p.y * q.y)
  49260. * p.y' = (p.x * q.y) + (p.y * q.x)
  49261. * But applying Karatsuba:
  49262. * v0 = p.x * q.x
  49263. * v1 = p.y * q.y
  49264. * p.x' = v0 - v1
  49265. * p.y' = (px + py) * (qx + qy) - v0 - v1
  49266. *
  49267. * px [in,out] A single precision integer - X ordinate of number to multiply.
  49268. * py [in,out] A single precision integer - Y ordinate of number to multiply.
  49269. * qx [in] A single precision integer - X ordinate of number of
  49270. * multiplier.
  49271. * qy [in] A single precision integer - Y ordinate of number of
  49272. * multiplier.
  49273. * t [in] Two single precision integers - temps.
  49274. */
  49275. static void sp_1024_proj_mul_42(sp_digit* px, sp_digit* py,
  49276. const sp_digit* qx, const sp_digit* qy, sp_digit* t)
  49277. {
  49278. sp_digit* t1 = t;
  49279. sp_digit* t2 = t + 2 * 42;
  49280. /* t1 = px + py */
  49281. sp_1024_mont_add_42(t1, px, py, p1024_mod);
  49282. /* t2 = qx + qy */
  49283. sp_1024_mont_add_42(t2, qx, qy, p1024_mod);
  49284. /* t2 = (px + py) * (qx + qy) */
  49285. sp_1024_mont_mul_42(t2, t1, t2, p1024_mod, p1024_mp_mod);
  49286. /* t1 = py * qy */
  49287. sp_1024_mont_mul_42(t1, py, qy, p1024_mod, p1024_mp_mod);
  49288. /* t2 = (px + py) * (qx + qy) - (py * qy) */
  49289. sp_1024_mont_sub_42(t2, t2, t1, p1024_mod);
  49290. /* px = px * qx */
  49291. sp_1024_mont_mul_42(px, px, qx, p1024_mod, p1024_mp_mod);
  49292. /* py = (px + py) * (qx + qy) - (py * qy) - (px * qx) */
  49293. sp_1024_mont_sub_42(py, t2, px, p1024_mod);
  49294. /* px = (px * qx) - (py * qy)*/
  49295. sp_1024_mont_sub_42(px, px, t1, p1024_mod);
  49296. }
  49297. #ifndef WOLFSSL_SP_SMALL
  49298. /*
  49299. * Convert point from projective to affine but keep in Montgomery form.
  49300. *
  49301. * p [in,out] Point to convert.
  49302. * t [in] Temporary numbers: 2.
  49303. */
  49304. static void sp_1024_mont_map_42(sp_point_1024* p, sp_digit* t)
  49305. {
  49306. sp_digit* t1 = t;
  49307. sp_digit* t2 = t + 2 * 42;
  49308. sp_1024_mont_inv_42(t1, p->z, t2);
  49309. sp_1024_mont_sqr_42(t2, t1, p1024_mod, p1024_mp_mod);
  49310. sp_1024_mont_mul_42(t1, t2, t1, p1024_mod, p1024_mp_mod);
  49311. sp_1024_mont_mul_42(p->x, p->x, t2, p1024_mod, p1024_mp_mod);
  49312. sp_1024_mont_mul_42(p->y, p->y, t1, p1024_mod, p1024_mp_mod);
  49313. XMEMCPY(p->z, p1024_norm_mod, sizeof(sp_digit) * 42);
  49314. }
  49315. #endif /* WOLFSSL_SP_SMALL */
  49316. /*
  49317. * Calculate gradient of line through P, P and [-2]P, accumulate line and
  49318. * double P.
  49319. *
  49320. * Calculations:
  49321. * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2)
  49322. * r.x = l * (p.x + q.x * p.z^2) - 2 * p.y^2
  49323. * r.y = 2 * p.y * p.z^3 * q.y (= p'.z * p.z^2 * q.y)
  49324. * v* = v*^2 * r*
  49325. * p'.x = l^2 - 8 * p.y^2 * p.x
  49326. * p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4
  49327. * p'.z = 2 * p.y * p.z
  49328. *
  49329. * @param [in,out] vx X-ordinate of projective value in F*.
  49330. * @param [in,out] vy Y-ordinate of projective value in F*.
  49331. * @param [in,out] p ECC point - point on E(F_p^2) to double.
  49332. * @param [in] q ECC point - second point on E(F_P^2).
  49333. * @param [in] t SP temporaries (6 used).
  49334. */
  49335. static void sp_1024_accumulate_line_dbl_42(sp_digit* vx, sp_digit* vy,
  49336. sp_point_1024* p, const sp_point_1024* q, sp_digit* t)
  49337. {
  49338. sp_digit* t1 = t + 0 * 42;
  49339. sp_digit* pz2 = t + 2 * 42;
  49340. sp_digit* rx = t + 4 * 42;
  49341. sp_digit* ry = t + 6 * 42;
  49342. sp_digit* l = t + 8 * 42;
  49343. sp_digit* ty = t + 10 * 42;
  49344. /* v = v^2 */
  49345. sp_1024_proj_sqr_42(vx, vy, t);
  49346. /* pz2 = p.z^2 */
  49347. sp_1024_mont_sqr_42(pz2, p->z, p1024_mod, p1024_mp_mod);
  49348. /* t1 = p.x + p.z^2 */
  49349. sp_1024_mont_add_42(ty, p->x, pz2, p1024_mod);
  49350. /* l = p.x - p.z^2 */
  49351. sp_1024_mont_sub_42(l, p->x, pz2, p1024_mod);
  49352. /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */
  49353. sp_1024_mont_mul_42(t1, l, ty, p1024_mod, p1024_mp_mod);
  49354. /* l = 3 * (p.x^2 - p.z^4) */
  49355. sp_1024_mont_tpl_42(l, t1, p1024_mod);
  49356. /* t1 = q.x * p.z^2 */
  49357. sp_1024_mont_mul_42(t1, q->x, pz2, p1024_mod, p1024_mp_mod);
  49358. /* t1 = p.x + q.x * p.z^2 */
  49359. sp_1024_mont_add_42(t1, p->x, t1, p1024_mod);
  49360. /* r.x = l * (p.x + q.x * p.z^2) */
  49361. sp_1024_mont_mul_42(rx, l, t1, p1024_mod, p1024_mp_mod);
  49362. /* r.y = 2 * p.y */
  49363. sp_1024_mont_dbl_42(ry, p->y, p1024_mod);
  49364. /* ty = 4 * p.y ^ 2 */
  49365. sp_1024_mont_sqr_42(ty, ry, p1024_mod, p1024_mp_mod);
  49366. /* t1 = 2 * p.y ^ 2 */
  49367. sp_1024_div2_42(t1, ty, p1024_mod);
  49368. /* r.x -= 2 * (p.y ^ 2) */
  49369. sp_1024_mont_sub_42(rx, rx, t1, p1024_mod);
  49370. /* p'.z = p.y * 2 * p.z */
  49371. sp_1024_mont_mul_42(p->z, p->z, ry, p1024_mod, p1024_mp_mod);
  49372. /* r.y = p'.z * p.z^2 */
  49373. sp_1024_mont_mul_42(t1, p->z, pz2, p1024_mod, p1024_mp_mod);
  49374. /* r.y = p'.z * p.z^2 * q.y */
  49375. sp_1024_mont_mul_42(ry, t1, q->y, p1024_mod, p1024_mp_mod);
  49376. /* v = v^2 * r */
  49377. sp_1024_proj_mul_42(vx, vy, rx, ry, t);
  49378. /* Double point using previously calculated values
  49379. * l = 3 * (p.x - p.z^2).(p.x + p.z^2)
  49380. * ty = 4 * p.y^2
  49381. * p'.z = 2 * p.y * p.z
  49382. */
  49383. /* t1 = (4 * p.y^2) ^ 2 = 16 * p.y^4 */
  49384. sp_1024_mont_sqr_42(t1, ty, p1024_mod, p1024_mp_mod);
  49385. /* t1 = 16 * p.y^4 / 2 = 8 * p.y^4 */
  49386. sp_1024_div2_42(t1, t1, p1024_mod);
  49387. /* p'.y = 4 * p.y^2 * p.x */
  49388. sp_1024_mont_mul_42(p->y, ty, p->x, p1024_mod, p1024_mp_mod);
  49389. /* p'.x = l^2 */
  49390. sp_1024_mont_sqr_42(p->x, l, p1024_mod, p1024_mp_mod);
  49391. /* p'.x = l^2 - 4 * p.y^2 * p.x */
  49392. sp_1024_mont_sub_42(p->x, p->x, p->y, p1024_mod);
  49393. /* p'.x = l^2 - 8 * p.y^2 * p.x */
  49394. sp_1024_mont_sub_42(p->x, p->x, p->y, p1024_mod);
  49395. /* p'.y = 4 * p.y^2 * p.x - p.x' */
  49396. sp_1024_mont_sub_42(ty, p->y, p->x, p1024_mod);
  49397. /* p'.y = (4 * p.y^2 * p.x - p'.x) * l */
  49398. sp_1024_mont_mul_42(p->y, ty, l, p1024_mod, p1024_mp_mod);
  49399. /* p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4 */
  49400. sp_1024_mont_sub_42(p->y, p->y, t1, p1024_mod);
  49401. }
  49402. #ifdef WOLFSSL_SP_SMALL
  49403. /*
  49404. * Calculate gradient of line through C, P and -C-P, accumulate line and
  49405. * add P to C.
  49406. *
  49407. * Calculations:
  49408. * r.x = (q.x + p.x) * c.y - (q.x * c.z^2 + c.x) * p.y * c.z
  49409. * r.y = (c.x - p.x * c.z^2) * q.y * c.z
  49410. * v* = v* * r*
  49411. * r = p.y * c.z^3 - c.y
  49412. * c'.x = r^2 + h^3 - 2 * c.x * h^2
  49413. * c'.y = r * (c'.x - c.x * h^2) - c.y * h^3
  49414. * c'.z = (c.x - p.x * c.z^2) * c.z
  49415. *
  49416. * @param [in,out] vx X-ordinate of projective value in F*.
  49417. * @param [in,out] vy Y-ordinate of projective value in F*.
  49418. * @param [in,out] c ECC point - current point on E(F_p^2) to be added
  49419. * to.
  49420. * @param [in] p ECC point - point on E(F_p^2) to add.
  49421. * @param [in] q ECC point - second point on E(F_P^2).
  49422. * @param [in] qx_px SP that is a constant value across adds.
  49423. * @param [in] t SP temporaries (6 used).
  49424. */
  49425. static void sp_1024_accumulate_line_add_one_42(sp_digit* vx, sp_digit* vy,
  49426. sp_point_1024* c, sp_point_1024* p, sp_point_1024* q, sp_digit* qx_px,
  49427. sp_digit* t)
  49428. {
  49429. sp_digit* t1 = t;
  49430. sp_digit* t2 = t + 2 * 42;
  49431. sp_digit* rx = t + 4 * 42;
  49432. sp_digit* ry = t + 6 * 42;
  49433. sp_digit* h = t + 8 * 42;
  49434. sp_digit* r = t + 10 * 42;
  49435. /* r.x = (q.x + p.x) * c.y */
  49436. sp_1024_mont_mul_42(rx, qx_px, c->y, p1024_mod, p1024_mp_mod);
  49437. /* t2 = c.z^2 */
  49438. sp_1024_mont_sqr_42(t2, c->z, p1024_mod, p1024_mp_mod);
  49439. /* t1 = q.x * c.z^2 */
  49440. sp_1024_mont_mul_42(t1, q->x, t2, p1024_mod, p1024_mp_mod);
  49441. /* t1 = q.x * c.z^2 + c.x */
  49442. sp_1024_mont_add_42(h, t1, c->x, p1024_mod);
  49443. /* r = p.y * c.z */
  49444. sp_1024_mont_mul_42(ry, p->y, c->z, p1024_mod, p1024_mp_mod);
  49445. /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */
  49446. sp_1024_mont_mul_42(t1, h, ry, p1024_mod, p1024_mp_mod);
  49447. /* r = p.y * c.z * c.z^2 = p.y * c.z^3 */
  49448. sp_1024_mont_mul_42(r, ry, t2, p1024_mod, p1024_mp_mod);
  49449. /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */
  49450. sp_1024_mont_sub_42(rx, rx, t1, p1024_mod);
  49451. /* t1 = p.x * c.z^2 */
  49452. sp_1024_mont_mul_42(t1, p->x, t2, p1024_mod, p1024_mp_mod);
  49453. /* h = c.x - p.x * c.z^2 */
  49454. sp_1024_mont_sub_42(h, c->x, t1, p1024_mod);
  49455. /* c'.z = (c.x - p.x * c.z^2) * c.z */
  49456. sp_1024_mont_mul_42(c->z, h, c->z, p1024_mod, p1024_mp_mod);
  49457. /* r.y = (c.x - p.x * c.z^2) * c.z * q.y */
  49458. sp_1024_mont_mul_42(ry, c->z, q->y, p1024_mod, p1024_mp_mod);
  49459. /* v = v * r */
  49460. sp_1024_proj_mul_42(vx, vy, rx, ry, t);
  49461. /* Add p to c using previously calculated values.
  49462. * h = c.x - p.x * c.z^2
  49463. * r = p.y * c.z^3
  49464. * c'.z = (c.x - p.x * c.z^2) * c.z
  49465. */
  49466. /* r = p.y * c.z^3 - c.y */
  49467. sp_1024_mont_sub_42(r, r, c->y, p1024_mod);
  49468. /* t1 = r^2 */
  49469. sp_1024_mont_sqr_42(t1, r, p1024_mod, p1024_mp_mod);
  49470. /* t2 = h^2 */
  49471. sp_1024_mont_sqr_42(rx, h, p1024_mod, p1024_mp_mod);
  49472. /* ry = c.x * h^2 */
  49473. sp_1024_mont_mul_42(ry, c->x, rx, p1024_mod, p1024_mp_mod);
  49474. /* t2 = h^3 */
  49475. sp_1024_mont_mul_42(t2, rx, h, p1024_mod, p1024_mp_mod);
  49476. /* c->x = r^2 + h^3 */
  49477. sp_1024_mont_add_42(c->x, t1, t2, p1024_mod);
  49478. /* t1 = 2 * c.x * h^2 */
  49479. sp_1024_mont_dbl_42(t1, ry, p1024_mod);
  49480. /* c'.x = r^2 + h^3 - 2 * c.x * h^2 */
  49481. sp_1024_mont_sub_42(c->x, c->x, t1, p1024_mod);
  49482. /* ry = c'.x - c.x * h^2 */
  49483. sp_1024_mont_sub_42(t1, c->x, ry, p1024_mod);
  49484. /* ry = r * (c'.x - c.x * h^2) */
  49485. sp_1024_mont_mul_42(ry, t1, r, p1024_mod, p1024_mp_mod);
  49486. /* t2 = c.y * h^3 */
  49487. sp_1024_mont_mul_42(t1, t2, c->y, p1024_mod, p1024_mp_mod);
  49488. /* c'.y = r * (c'.x - c.x * h^2) - c.y * h^3 */
  49489. sp_1024_mont_sub_42(c->y, ry, t1, p1024_mod);
  49490. }
  49491. /*
  49492. * Calculate r = pairing <P, Q>.
  49493. *
  49494. * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
  49495. *
  49496. * @param [in] key SAKKE key.
  49497. * @param [in] p First point on E(F_p)[q].
  49498. * @param [in] q Second point on E(F_p)[q].
  49499. * @param [in] r Result of calculation.
  49500. * @return 0 on success.
  49501. * @return MEMORY_E when dynamic memory allocation fails.
  49502. * @return Other -ve value on internal failure.
  49503. */
  49504. int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
  49505. {
  49506. int err = MP_OKAY;
  49507. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  49508. !defined(WOLFSSL_SP_NO_MALLOC)
  49509. sp_digit* td = NULL;
  49510. sp_digit* t;
  49511. sp_digit* vx;
  49512. sp_digit* vy;
  49513. sp_digit* qx_px;
  49514. #else
  49515. sp_digit t[6 * 2 * 42];
  49516. sp_digit vx[2 * 42];
  49517. sp_digit vy[2 * 42];
  49518. sp_digit qx_px[2 * 42];
  49519. sp_point_1024 pd;
  49520. sp_point_1024 qd;
  49521. sp_point_1024 cd;
  49522. #endif
  49523. sp_point_1024* p = NULL;
  49524. sp_point_1024* q = NULL;
  49525. sp_point_1024* c = NULL;
  49526. sp_digit* r = NULL;
  49527. int i;
  49528. err = sp_1024_point_new_42(NULL, pd, p);
  49529. if (err == MP_OKAY) {
  49530. err = sp_1024_point_new_42(NULL, qd, q);
  49531. }
  49532. if (err == MP_OKAY) {
  49533. err = sp_1024_point_new_42(NULL, cd, c);
  49534. }
  49535. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  49536. !defined(WOLFSSL_SP_NO_MALLOC)
  49537. if (err == MP_OKAY) {
  49538. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9 * 42 * 2, NULL,
  49539. DYNAMIC_TYPE_TMP_BUFFER);
  49540. if (td == NULL) {
  49541. err = MEMORY_E;
  49542. }
  49543. }
  49544. #endif
  49545. if (err == MP_OKAY) {
  49546. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  49547. !defined(WOLFSSL_SP_NO_MALLOC)
  49548. t = td;
  49549. vx = td + 6 * 42 * 2;
  49550. vy = td + 7 * 42 * 2;
  49551. qx_px = td + 8 * 42 * 2;
  49552. #endif
  49553. r = vy;
  49554. sp_1024_point_from_ecc_point_42(p, pm);
  49555. sp_1024_point_from_ecc_point_42(q, qm);
  49556. err = sp_1024_mod_mul_norm_42(p->x, p->x, p1024_mod);
  49557. }
  49558. if (err == MP_OKAY) {
  49559. err = sp_1024_mod_mul_norm_42(p->y, p->y, p1024_mod);
  49560. }
  49561. if (err == MP_OKAY) {
  49562. err = sp_1024_mod_mul_norm_42(p->z, p->z, p1024_mod);
  49563. }
  49564. if (err == MP_OKAY) {
  49565. err = sp_1024_mod_mul_norm_42(q->x, q->x, p1024_mod);
  49566. }
  49567. if (err == MP_OKAY) {
  49568. err = sp_1024_mod_mul_norm_42(q->y, q->y, p1024_mod);
  49569. }
  49570. if (err == MP_OKAY) {
  49571. XMEMCPY(c, p, sizeof(sp_point_1024));
  49572. XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 42);
  49573. vx[0] = 1;
  49574. XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 42);
  49575. sp_1024_mont_add_42(qx_px, q->x, p->x, p1024_mod);
  49576. for (i = 1020; i >= 0; i--) {
  49577. /* Accumulate line into v and double point. */
  49578. sp_1024_accumulate_line_dbl_42(vx, vy, c, q, t);
  49579. if ((i > 0) && ((p1024_order[i / 25] >> (i % 25)) & 1)) {
  49580. /* Accumulate line into v and add P into C. */
  49581. sp_1024_accumulate_line_add_one_42(vx, vy, c, p, q, qx_px, t);
  49582. }
  49583. }
  49584. /* Final exponentiation */
  49585. sp_1024_proj_sqr_42(vx, vy, t);
  49586. sp_1024_proj_sqr_42(vx, vy, t);
  49587. /* Convert from PF_p[q] to F_p */
  49588. sp_1024_mont_inv_42(vx, vx, t);
  49589. sp_1024_mont_mul_42(r, vx, vy, p1024_mod, p1024_mp_mod);
  49590. XMEMSET(r + 42, 0, sizeof(sp_digit) * 42);
  49591. sp_1024_mont_reduce_42(r, p1024_mod, p1024_mp_mod);
  49592. err = sp_1024_to_mp(r, res);
  49593. }
  49594. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  49595. !defined(WOLFSSL_SP_NO_MALLOC)
  49596. if (td != NULL) {
  49597. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  49598. }
  49599. #endif
  49600. sp_1024_point_free_42(c, 1, NULL);
  49601. sp_1024_point_free_42(q, 1, NULL);
  49602. sp_1024_point_free_42(p, 1, NULL);
  49603. return err;
  49604. }
  49605. #else
  49606. /*
  49607. * Calculate gradient of line through C, P and -C-P, accumulate line and
  49608. * add P to C.
  49609. *
  49610. * Both C and P have z ordinates to use in the calculation.
  49611. *
  49612. * Calculations:
  49613. * r.x = (q.x * c.z^2 + c.x) * p.y * c.z - (q.x * p.z^2 + p.x) * c.y * p.z
  49614. * r.y = (p.x * c.z^2 - c.x * p.z^2) * q.y * p.z * c.z
  49615. * v* = v* * r*
  49616. * h = p.x * c.z^2 - c.x * p.z^2
  49617. * r = p.y * c.z^3 - c.y * p.z^3
  49618. * c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2
  49619. * c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3
  49620. * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z
  49621. *
  49622. * @param [in,out] vx X-ordinate of projective value in F*.
  49623. * @param [in,out] vy Y-ordinate of projective value in F*.
  49624. * @param [in,out] c ECC point - current point on E(F_p^2) to be added
  49625. * to.
  49626. * @param [in,out] p ECC point - point on E(F_p^2) to add.
  49627. * @param [in,out] q ECC point - second point on E(F_P^2).
  49628. * @param [in,out] t SP temporaries (6 used).
  49629. * @param [in,out] neg Indicates to use negative P.
  49630. * @return 0 on success.
  49631. * @return MEMORY_E when dynamic memory allocation fails.
  49632. * @return Other -ve value on internal failure.
  49633. */
  49634. static void sp_1024_accumulate_line_add_n_42(sp_digit* vx, sp_digit* vy,
  49635. const sp_point_1024* p, const sp_point_1024* q,
  49636. sp_point_1024* c, sp_digit* t, int neg)
  49637. {
  49638. sp_digit* t1 = t;
  49639. sp_digit* t2 = t + 2 * 42;
  49640. sp_digit* rx = t + 4 * 42;
  49641. sp_digit* ry = t + 6 * 42;
  49642. sp_digit* h = t + 8 * 42;
  49643. sp_digit* r = t + 10 * 42;
  49644. /* h = p.z^2 */
  49645. sp_1024_mont_sqr_42(h, p->z, p1024_mod, p1024_mp_mod);
  49646. /* rx = q.x * p.z^2 */
  49647. sp_1024_mont_mul_42(rx, q->x, h, p1024_mod, p1024_mp_mod);
  49648. /* rx = q.x * p.z^2 + p.x */
  49649. sp_1024_mont_add_42(t2, rx, p->x, p1024_mod);
  49650. /* c.y = c.y * p.z */
  49651. sp_1024_mont_mul_42(t1, c->y, p->z, p1024_mod, p1024_mp_mod);
  49652. /* r.x = (q.x * p.z^2 + p.x) * c.y * p.z */
  49653. sp_1024_mont_mul_42(rx, t2, t1, p1024_mod, p1024_mp_mod);
  49654. /* c.y = c.y * p.z^3 */
  49655. sp_1024_mont_mul_42(c->y, t1, h, p1024_mod, p1024_mp_mod);
  49656. /* t2 = c.z^2 */
  49657. sp_1024_mont_sqr_42(t2, c->z, p1024_mod, p1024_mp_mod);
  49658. /* t1 = q.x * c.z^2 */
  49659. sp_1024_mont_mul_42(t1, q->x, t2, p1024_mod, p1024_mp_mod);
  49660. /* t1 = q.x * c.z^2 + c.x */
  49661. sp_1024_mont_add_42(t1, t1, c->x, p1024_mod);
  49662. /* c.x = c.x * p.z^2 */
  49663. sp_1024_mont_mul_42(c->x, c->x, h, p1024_mod, p1024_mp_mod);
  49664. /* r = p.y * c.z */
  49665. sp_1024_mont_mul_42(r, p->y, c->z, p1024_mod, p1024_mp_mod);
  49666. if (neg) {
  49667. /* r = -p.y * c.z */
  49668. sp_1024_mont_sub_42(r, p1024_mod, r, p1024_mod);
  49669. }
  49670. /* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */
  49671. sp_1024_mont_mul_42(ry, t1, r, p1024_mod, p1024_mp_mod);
  49672. /* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */
  49673. sp_1024_mont_sub_42(rx, ry, rx, p1024_mod);
  49674. /* t1 = p.x * c.z^2 */
  49675. sp_1024_mont_mul_42(t1, p->x, t2, p1024_mod, p1024_mp_mod);
  49676. /* h = p.x * c.z^2 - c.x * p.z^2 */
  49677. sp_1024_mont_sub_42(h, t1, c->x, p1024_mod);
  49678. /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z */
  49679. sp_1024_mont_mul_42(t1, h, c->z, p1024_mod, p1024_mp_mod);
  49680. /* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z */
  49681. sp_1024_mont_mul_42(c->z, t1, p->z, p1024_mod, p1024_mp_mod);
  49682. /* r.y = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z * q.y */
  49683. sp_1024_mont_mul_42(ry, c->z, q->y, p1024_mod, p1024_mp_mod);
  49684. /* r = p.y * c.z^3 */
  49685. sp_1024_mont_mul_42(t1, r, t2, p1024_mod, p1024_mp_mod);
  49686. /* r = p.y * c.z^3 - c.y * p.z^3 */
  49687. sp_1024_mont_sub_42(r, t1, c->y, p1024_mod);
  49688. /* v = v * r */
  49689. sp_1024_proj_mul_42(vx, vy, rx, ry, t);
  49690. /* Add p to c using previously calculated values.
  49691. * h = p.x * c.z^2 - c.x * p.z^2
  49692. * r = p.y * c.z^3 - c.y * p.z^3
  49693. * c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z
  49694. */
  49695. /* t1 = r^2 */
  49696. sp_1024_mont_sqr_42(t1, r, p1024_mod, p1024_mp_mod);
  49697. /* t2 = h^2 */
  49698. sp_1024_mont_sqr_42(rx, h, p1024_mod, p1024_mp_mod);
  49699. /* ry = c.x * p.z^2 * h^2 */
  49700. sp_1024_mont_mul_42(ry, rx, c->x, p1024_mod, p1024_mp_mod);
  49701. /* t2 = h^3 */
  49702. sp_1024_mont_mul_42(t2, rx, h, p1024_mod, p1024_mp_mod);
  49703. /* c'.x = r^2 - h^3 */
  49704. sp_1024_mont_sub_42(c->x, t1, t2, p1024_mod);
  49705. /* t1 = 2 * c.x * p.z^2 * h^2 */
  49706. sp_1024_mont_dbl_42(t1, ry, p1024_mod);
  49707. /* c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 */
  49708. sp_1024_mont_sub_42(c->x, c->x, t1, p1024_mod);
  49709. /* ry = c.x * p.z^2 * h^2 - c'.x */
  49710. sp_1024_mont_sub_42(t1, ry, c->x, p1024_mod);
  49711. /* ry = r * (c.x * p.z^2 * h^2 - c'.x) */
  49712. sp_1024_mont_mul_42(ry, t1, r, p1024_mod, p1024_mp_mod);
  49713. /* t2 = c.y * p.z^3 * h^3 */
  49714. sp_1024_mont_mul_42(t1, t2, c->y, p1024_mod, p1024_mp_mod);
  49715. /* c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 */
  49716. sp_1024_mont_sub_42(c->y, ry, t1, p1024_mod);
  49717. }
  49718. /*
  49719. * Perform n accumulate doubles and doubles of P.
  49720. *
  49721. * py = 2 * p.y
  49722. *
  49723. * For each double:
  49724. * Calculate gradient of line through P, P and [-2]P, accumulate line and
  49725. * double P.
  49726. *
  49727. * Calculations:
  49728. * l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2)
  49729. * r.x = l * (p.x + q.x * p.z^2) - py^2 / 2
  49730. * r.y = py * p.z^3 * q.y (= p'.z * p.z^2 * q.y)
  49731. * v* = v*^2 * r*
  49732. * p'.x = l^2 - 2 * py^2 * p.x
  49733. * py' = (py^2 * p.x - p'.x) * l - py^4 (= 2 * p'.y)
  49734. * p'.z = py * p.z
  49735. *
  49736. * Finally:
  49737. * p'.y = py' / 2
  49738. *
  49739. * @param [in,out] vx X-ordinate of projective value in F*.
  49740. * @param [in,out] vy Y-ordinate of projective value in F*.
  49741. * @param [in,out] p ECC point - point on E(F_p^2) to double.
  49742. * @param [in] q ECC point - second point on E(F_P^2).
  49743. * @param [in] n Number of times to double.
  49744. * @param [in] t SP temporaries (6 used).
  49745. */
  49746. static void sp_1024_accumulate_line_dbl_n_42(sp_digit* vx, sp_digit* vy,
  49747. sp_point_1024* p, const sp_point_1024* q, int n, sp_digit* t)
  49748. {
  49749. sp_digit* t1 = t + 0 * 42;
  49750. sp_digit* pz2 = t + 2 * 42;
  49751. sp_digit* rx = t + 4 * 42;
  49752. sp_digit* ry = t + 6 * 42;
  49753. sp_digit* l = t + 8 * 42;
  49754. sp_digit* ty = t + 10 * 42;
  49755. int i;
  49756. /* py = 2 * p.y */
  49757. sp_1024_mont_dbl_42(p->y, p->y, p1024_mod);
  49758. for (i = 0; i < n; i++) {
  49759. /* v = v^2 */
  49760. sp_1024_proj_sqr_42(vx, vy, t);
  49761. /* pz2 = p.z^2 */
  49762. sp_1024_mont_sqr_42(pz2, p->z, p1024_mod, p1024_mp_mod);
  49763. /* t1 = p.x + p.z^2 */
  49764. sp_1024_mont_add_42(t1, p->x, pz2, p1024_mod);
  49765. /* l = p.x - p.z^2 */
  49766. sp_1024_mont_sub_42(l, p->x, pz2, p1024_mod);
  49767. /* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */
  49768. sp_1024_mont_mul_42(ty, l, t1, p1024_mod, p1024_mp_mod);
  49769. /* l = 3 * (p.x^2 - p.z^4) */
  49770. sp_1024_mont_tpl_42(l, ty, p1024_mod);
  49771. /* t1 = q.x * p.z^2 */
  49772. sp_1024_mont_mul_42(t1, q->x, pz2, p1024_mod, p1024_mp_mod);
  49773. /* t1 = p.x + q.x * p.z^2 */
  49774. sp_1024_mont_add_42(t1, p->x, t1, p1024_mod);
  49775. /* r.x = l * (p.x + q.x * p.z^2) */
  49776. sp_1024_mont_mul_42(rx, l, t1, p1024_mod, p1024_mp_mod);
  49777. /* ty = py ^ 2 */
  49778. sp_1024_mont_sqr_42(ty, p->y, p1024_mod, p1024_mp_mod);
  49779. /* t1 = py ^ 2 / 2 */
  49780. sp_1024_div2_42(t1, ty, p1024_mod);
  49781. /* r.x -= py ^ 2 / 2 */
  49782. sp_1024_mont_sub_42(rx, rx, t1, p1024_mod);
  49783. /* p'.z = py * pz */
  49784. sp_1024_mont_mul_42(p->z, p->z, p->y, p1024_mod, p1024_mp_mod);
  49785. /* r.y = p'.z * p.z^2 */
  49786. sp_1024_mont_mul_42(t1, p->z, pz2, p1024_mod, p1024_mp_mod);
  49787. /* r.y = p'.z * p.z^2 * q.y */
  49788. sp_1024_mont_mul_42(ry, t1, q->y, p1024_mod, p1024_mp_mod);
  49789. /* v = v^2 * r */
  49790. sp_1024_proj_mul_42(vx, vy, rx, ry, t);
  49791. /* Double point using previously calculated values
  49792. * l = 3 * (p.x - p.z^2).(p.x + p.z^2)
  49793. * ty = py^2
  49794. * p'.z = py * p.z
  49795. */
  49796. /* t1 = py^2 ^ 2 = py^4 */
  49797. sp_1024_mont_sqr_42(t1, ty, p1024_mod, p1024_mp_mod);
  49798. /* py' = py^2 * p. x */
  49799. sp_1024_mont_mul_42(p->y, ty, p->x, p1024_mod, p1024_mp_mod);
  49800. /* p'.x = l^2 */
  49801. sp_1024_mont_sqr_42(p->x, l, p1024_mod, p1024_mp_mod);
  49802. /* p'.x = l^2 - py^2 * p.x */
  49803. sp_1024_mont_sub_42(p->x, p->x, p->y, p1024_mod);
  49804. /* p'.x = l^2 - 2 * p.y^2 * p.x */
  49805. sp_1024_mont_sub_42(p->x, p->x, p->y, p1024_mod);
  49806. /* py' = py^2 * p.x - p.x' */
  49807. sp_1024_mont_sub_42(ty, p->y, p->x, p1024_mod);
  49808. /* py' = (p.y^2 * p.x - p'.x) * l */
  49809. sp_1024_mont_mul_42(p->y, ty, l, p1024_mod, p1024_mp_mod);
  49810. /* py' = (p.y^2 * p.x - p'.x) * l * 2 */
  49811. sp_1024_mont_dbl_42(p->y, p->y, p1024_mod);
  49812. /* py' = (p.y^2 * p.x - p'.x) * l * 2 - p.y^4 */
  49813. sp_1024_mont_sub_42(p->y, p->y, t1, p1024_mod);
  49814. }
  49815. /* p'.y = py' / 2 */
  49816. sp_1024_div2_42(p->y, p->y, p1024_mod);
  49817. }
  49818. /* Operations to perform based on order - 1.
  49819. * Sliding window. Start at bottom and stop when bottom bit is one.
  49820. * Subtract if top bit in window is one.
  49821. * Width of 6 bits.
  49822. * Pairs: #dbls, add/subtract window value
  49823. */
  49824. static const signed char sp_1024_order_op[] = {
  49825. 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9,
  49826. -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6,
  49827. -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8,
  49828. 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7,
  49829. -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6,
  49830. -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7,
  49831. -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7,
  49832. -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7,
  49833. -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6,
  49834. 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6,
  49835. -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6,
  49836. -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10,
  49837. 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7,
  49838. -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7,
  49839. 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6,
  49840. -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12,
  49841. 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8,
  49842. -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10,
  49843. -3, 1,
  49844. };
  49845. /*
  49846. * Calculate r = pairing <P, Q>.
  49847. *
  49848. * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
  49849. *
  49850. * Sliding window. Start at bottom and stop when bottom bit is one.
  49851. * Subtract if top bit in window is one.
  49852. * Width of 6 bits.
  49853. *
  49854. * @param [in] pm First point on E(F_p)[q].
  49855. * @param [in] qm Second point on E(F_p)[q].
  49856. * @param [in] res Result of calculation.
  49857. * @return 0 on success.
  49858. * @return MEMORY_E when dynamic memory allocation fails.
  49859. */
  49860. int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
  49861. {
  49862. int err;
  49863. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  49864. !defined(WOLFSSL_SP_NO_MALLOC)
  49865. sp_digit* td = NULL;
  49866. sp_digit* t;
  49867. sp_digit* vx;
  49868. sp_digit* vy;
  49869. sp_digit (*pre_vx)[84];
  49870. sp_digit (*pre_vy)[84];
  49871. sp_digit (*pre_nvy)[84];
  49872. sp_point_1024* pre_p;
  49873. #else
  49874. sp_digit t[6 * 2 * 42];
  49875. sp_digit vx[2 * 42];
  49876. sp_digit vy[2 * 42];
  49877. sp_digit pre_vx[16][84];
  49878. sp_digit pre_vy[16][84];
  49879. sp_digit pre_nvy[16][84];
  49880. sp_point_1024 pre_p[16];
  49881. sp_point_1024 pd;
  49882. sp_point_1024 qd;
  49883. sp_point_1024 cd;
  49884. #endif
  49885. sp_point_1024* p = NULL;
  49886. sp_point_1024* q = NULL;
  49887. sp_point_1024* c = NULL;
  49888. sp_digit* r = NULL;
  49889. int i;
  49890. int j;
  49891. err = sp_1024_point_new_42(NULL, pd, p);
  49892. if (err == MP_OKAY) {
  49893. err = sp_1024_point_new_42(NULL, qd, q);
  49894. }
  49895. if (err == MP_OKAY) {
  49896. err = sp_1024_point_new_42(NULL, cd, c);
  49897. }
  49898. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  49899. !defined(WOLFSSL_SP_NO_MALLOC)
  49900. if (err == MP_OKAY) {
  49901. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 42 * 2 + 16 * sizeof(sp_point_1024), NULL,
  49902. DYNAMIC_TYPE_TMP_BUFFER);
  49903. if (td == NULL) {
  49904. err = MEMORY_E;
  49905. }
  49906. }
  49907. #endif
  49908. if (err == MP_OKAY) {
  49909. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  49910. !defined(WOLFSSL_SP_NO_MALLOC)
  49911. t = td;
  49912. vx = td + 6 * 42 * 2;
  49913. vy = td + 7 * 42 * 2;
  49914. pre_vx = (sp_digit(*)[84])(td + 8 * 42 * 2);
  49915. pre_vy = (sp_digit(*)[84])(td + 24 * 42 * 2);
  49916. pre_nvy = (sp_digit(*)[84])(td + 40 * 42 * 2);
  49917. pre_p = (sp_point_1024*)(td + 56 * 42 * 2);
  49918. #endif
  49919. r = vy;
  49920. sp_1024_point_from_ecc_point_42(p, pm);
  49921. sp_1024_point_from_ecc_point_42(q, qm);
  49922. err = sp_1024_mod_mul_norm_42(p->x, p->x, p1024_mod);
  49923. }
  49924. if (err == MP_OKAY) {
  49925. err = sp_1024_mod_mul_norm_42(p->y, p->y, p1024_mod);
  49926. }
  49927. if (err == MP_OKAY) {
  49928. err = sp_1024_mod_mul_norm_42(p->z, p->z, p1024_mod);
  49929. }
  49930. if (err == MP_OKAY) {
  49931. err = sp_1024_mod_mul_norm_42(q->x, q->x, p1024_mod);
  49932. }
  49933. if (err == MP_OKAY) {
  49934. err = sp_1024_mod_mul_norm_42(q->y, q->y, p1024_mod);
  49935. }
  49936. if (err == MP_OKAY) {
  49937. /* Generate pre-computation table: 1, 3, ... , 31 */
  49938. XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024));
  49939. XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 42);
  49940. pre_vx[0][0] = 1;
  49941. XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 42);
  49942. sp_1024_mont_sub_42(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod);
  49943. /* [2]P for adding */
  49944. XMEMCPY(c, p, sizeof(sp_point_1024));
  49945. XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 42);
  49946. vx[0] = 1;
  49947. XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 42);
  49948. sp_1024_accumulate_line_dbl_42(vx, vy, c, q, t);
  49949. /* 3, 5, ... */
  49950. for (i = 1; i < 16; i++) {
  49951. XMEMCPY(&pre_p[i], &pre_p[i-1], sizeof(sp_point_1024));
  49952. XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 42);
  49953. XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 42);
  49954. sp_1024_proj_mul_42(pre_vx[i], pre_vy[i], vx, vy, t);
  49955. sp_1024_accumulate_line_add_n_42(pre_vx[i], pre_vy[i], c,
  49956. q, &pre_p[i], t, 0);
  49957. sp_1024_mont_sub_42(pre_nvy[i], p1024_mod, pre_vy[i], p1024_mod);
  49958. }
  49959. j = sp_1024_order_op[0] / 2;
  49960. XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024));
  49961. XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 42);
  49962. XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 42);
  49963. /* Accumulate line into v and double point n times. */
  49964. sp_1024_accumulate_line_dbl_n_42(vx, vy, c, q,
  49965. sp_1024_order_op[1], t);
  49966. for (i = 2; i < 290; i += 2) {
  49967. j = sp_1024_order_op[i];
  49968. if (j > 0) {
  49969. j /= 2;
  49970. /* Accumulate line into v and add P into C. */
  49971. sp_1024_proj_mul_42(vx, vy, pre_vx[j], pre_vy[j], t);
  49972. sp_1024_accumulate_line_add_n_42(vx, vy, &pre_p[j], q, c,
  49973. t, 0);
  49974. }
  49975. else {
  49976. j = -j / 2;
  49977. /* Accumulate line into v and add P into C. */
  49978. sp_1024_proj_mul_42(vx, vy, pre_vx[j], pre_nvy[j], t);
  49979. sp_1024_accumulate_line_add_n_42(vx, vy, &pre_p[j], q, c,
  49980. t, 1);
  49981. }
  49982. /* Accumulate line into v and double point n times. */
  49983. sp_1024_accumulate_line_dbl_n_42(vx, vy, c, q,
  49984. sp_1024_order_op[i + 1], t);
  49985. }
  49986. /* Final exponentiation */
  49987. sp_1024_proj_sqr_42(vx, vy, t);
  49988. sp_1024_proj_sqr_42(vx, vy, t);
  49989. /* Convert from PF_p[q] to F_p */
  49990. sp_1024_mont_inv_42(vx, vx, t);
  49991. sp_1024_mont_mul_42(r, vx, vy, p1024_mod, p1024_mp_mod);
  49992. XMEMSET(r + 42, 0, sizeof(sp_digit) * 42);
  49993. sp_1024_mont_reduce_42(r, p1024_mod, p1024_mp_mod);
  49994. err = sp_1024_to_mp(r, res);
  49995. }
  49996. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  49997. !defined(WOLFSSL_SP_NO_MALLOC)
  49998. if (td != NULL) {
  49999. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  50000. }
  50001. #endif
  50002. sp_1024_point_free_42(c, 1, NULL);
  50003. sp_1024_point_free_42(q, 1, NULL);
  50004. sp_1024_point_free_42(p, 1, NULL);
  50005. return err;
  50006. }
  50007. #endif /* WOLFSSL_SP_SMALL */
  50008. #ifdef WOLFSSL_SP_SMALL
  50009. /*
  50010. * Generate table for pairing.
  50011. *
  50012. * Small implementation does not use a table - returns 0 length.
  50013. *
  50014. * pm [in] Point to generate table for.
  50015. * table [in] Generated table.
  50016. * len [in,out] On in, the size of the buffer.
  50017. * On out, length of table generated.
  50018. * @return 0 on success.
  50019. * LENGTH_ONLY_E when table is NULL and only length returned.
  50020. * BUFFER_E when len is too small.
  50021. */
  50022. int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table,
  50023. word32* len)
  50024. {
  50025. int err = 0;
  50026. if (table == NULL) {
  50027. *len = 0;
  50028. err = LENGTH_ONLY_E;
  50029. }
  50030. else if (*len != 0) {
  50031. err = BUFFER_E;
  50032. }
  50033. (void)*pm;
  50034. return err;
  50035. }
  50036. /*
  50037. * Calculate r = pairing <P, Q>.
  50038. *
  50039. * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
  50040. *
  50041. * Small implementation does not use a table - use the normal implementation.
  50042. *
  50043. * @param [in] pm First point on E(F_p)[q].
  50044. * @param [in] qm Second point on E(F_p)[q].
  50045. * @param [in] res Result of calculation.
  50046. * @param [in] table Precomputed table of values.
  50047. * @param [in] len Length of precomputed table of values in bytes.
  50048. * @return 0 on success.
  50049. * @return MEMORY_E when dynamic memory allocation fails.
  50050. */
  50051. int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm,
  50052. mp_int* res, const byte* table, word32 len)
  50053. {
  50054. (void)table;
  50055. (void)len;
  50056. return sp_Pairing_1024(pm, qm, res);
  50057. }
  50058. #else
  50059. /*
  50060. * Calc l and c for the point when doubling p.
  50061. *
  50062. * l = 3 * (p.x^2 - 1) / (2 * p.y)
  50063. * c = l * p.x - p.y
  50064. *
  50065. * @param [out] lr Gradient result - table entry.
  50066. * @param [out] cr Constant result - table entry.
  50067. * @param [in] px X-ordinate of point to double.
  50068. * @param [in] py Y-ordinate of point to double.
  50069. * @param [in] t SP temporaries (3 used).
  50070. */
  50071. static void sp_1024_accum_dbl_calc_lc_42(sp_digit* lr, sp_digit* cr,
  50072. const sp_digit* px, const sp_digit* py, sp_digit* t)
  50073. {
  50074. sp_digit* t1 = t + 0 * 2 * 42;
  50075. sp_digit* t2 = t + 2 * 2 * 42;
  50076. sp_digit* l = t + 4 * 2 * 42;
  50077. /* l = 1 / 2 * p.y */
  50078. sp_1024_mont_dbl_42(l, py, p1024_mod);
  50079. sp_1024_mont_inv_42(l, l, t);
  50080. /* t1 = p.x^2 */
  50081. sp_1024_mont_sqr_42(t1, px, p1024_mod, p1024_mp_mod);
  50082. /* t1 = p.x - 1 */
  50083. sp_1024_mont_sub_42(t1, t1, p1024_norm_mod, p1024_mod);
  50084. /* t1 = 3 * (p.x^2 - 1) */
  50085. sp_1024_mont_dbl_42(t2, t1, p1024_mod);
  50086. sp_1024_mont_add_42(t1, t1, t2, p1024_mod);
  50087. /* t1 = 3 * (p.x^2 - 1) / (2 * p.y) */
  50088. sp_1024_mont_mul_42(l, l, t1, p1024_mod, p1024_mp_mod);
  50089. /* t2 = l * p.x */
  50090. sp_1024_mont_mul_42(t2, l, px, p1024_mod, p1024_mp_mod);
  50091. /* c = t2 = l * p.x - p.y */
  50092. sp_1024_mont_sub_42(t2, t2, py, p1024_mod);
  50093. XMEMCPY(lr, l, sizeof(sp_digit) * 42);
  50094. XMEMCPY(cr, t2, sizeof(sp_digit) * 42);
  50095. }
  50096. /*
  50097. * Calc l and c when adding p and c.
  50098. *
  50099. * l = (c.y - p.y) / (c.x - p.x)
  50100. * c = (p.x * c.y - cx * p.y) / (cx - p.x)
  50101. *
  50102. * @param [out] lr Gradient result - table entry.
  50103. * @param [out] cr Constant result - table entry.
  50104. * @param [in] px X-ordinate of point to add.
  50105. * @param [in] py Y-ordinate of point to add.
  50106. * @param [in] cx X-ordinate of current point.
  50107. * @param [in] cy Y-ordinate of current point.
  50108. * @param [in] t SP temporaries (3 used).
  50109. */
  50110. static void sp_1024_accum_add_calc_lc_42(sp_digit* lr, sp_digit* cr,
  50111. const sp_digit* px, const sp_digit* py, const sp_digit* cx,
  50112. const sp_digit* cy, sp_digit* t)
  50113. {
  50114. sp_digit* t1 = t + 0 * 2 * 42;
  50115. sp_digit* c = t + 2 * 2 * 42;
  50116. sp_digit* l = t + 4 * 2 * 42;
  50117. /* l = 1 / (c.x - p.x) */
  50118. sp_1024_mont_sub_42(l, cx, px, p1024_mod);
  50119. sp_1024_mont_inv_42(l, l, t);
  50120. /* c = p.x * c.y */
  50121. sp_1024_mont_mul_42(c, px, cy, p1024_mod, p1024_mp_mod);
  50122. /* t1 = c.x * p.y */
  50123. sp_1024_mont_mul_42(t1, cx, py, p1024_mod, p1024_mp_mod);
  50124. /* c = (p.x * c.y) - (c.x * p.y) */
  50125. sp_1024_mont_sub_42(c, c, t1, p1024_mod);
  50126. /* c = ((p.x * c.y) - (c.x * p.y)) / (c.x - p.x) */
  50127. sp_1024_mont_mul_42(c, c, l, p1024_mod, p1024_mp_mod);
  50128. /* t1 = c.y - p.y */
  50129. sp_1024_mont_sub_42(t1, cy, py, p1024_mod);
  50130. /* l = (c.y - p.y) / (c.x - p.x) */
  50131. sp_1024_mont_mul_42(l, t1, l, p1024_mod, p1024_mp_mod);
  50132. XMEMCPY(lr, l, sizeof(sp_digit) * 42);
  50133. XMEMCPY(cr, c, sizeof(sp_digit) * 42);
  50134. }
  50135. /*
  50136. * Calculate vx and vy given gradient l and constant c and point q.
  50137. *
  50138. * l is a the gradient and is multiplied by q->x.
  50139. * c is a the constant that is added to the multiplicative result.
  50140. * q->y is the y-ordinate in result to multiply.
  50141. *
  50142. * if dbl
  50143. * v* = v*^2
  50144. * r.x = l * q.x + c
  50145. * r.y = q->y
  50146. * v* = v* * r*
  50147. *
  50148. * @param [in,out] vx X-ordinate of projective value in F*.
  50149. * @param [in,out] vy Y-ordinate of projective value in F*.
  50150. * @param [in] l Gradient to multiply with.
  50151. * @param [in] c Constant to add with.
  50152. * @param [in] q ECC point - second point on E(F_P^2).
  50153. * @param [in] t SP temporaries (3 used).
  50154. * @param [in] dbl Indicates whether this is for doubling. Otherwise
  50155. * adding.
  50156. */
  50157. static void sp_1024_accumulate_line_lc_42(sp_digit* vx, sp_digit* vy,
  50158. const sp_digit* l, const sp_digit* c, const sp_point_1024* q,
  50159. sp_digit* t, int dbl)
  50160. {
  50161. sp_digit* rx = t + 4 * 2 * 42;
  50162. /* v = v^2 */
  50163. if (dbl) {
  50164. sp_1024_proj_sqr_42(vx, vy, t);
  50165. }
  50166. /* rx = l * q.x + c */
  50167. sp_1024_mont_mul_42(rx, l, q->x, p1024_mod, p1024_mp_mod);
  50168. sp_1024_mont_add_42(rx, rx, c, p1024_mod);
  50169. /* v = v^2 * r */
  50170. sp_1024_proj_mul_42(vx, vy, rx, q->y, t);
  50171. }
  50172. /* Operations to perform based on order - 1.
  50173. * Sliding window. Start at bottom and stop when bottom bit is one.
  50174. * Subtract if top bit in window is one.
  50175. * Width of 6 bits.
  50176. * Pairs: #dbls, add/subtract window value
  50177. */
  50178. static const signed char sp_1024_order_op_pre[] = {
  50179. 5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9,
  50180. -1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6,
  50181. -19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8,
  50182. 13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7,
  50183. -21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6,
  50184. -21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7,
  50185. -13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7,
  50186. -7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7,
  50187. -21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6,
  50188. 17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6,
  50189. -19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6,
  50190. -13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10,
  50191. 25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7,
  50192. -7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7,
  50193. 27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6,
  50194. -7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12,
  50195. 25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8,
  50196. -19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10,
  50197. -3, 1,
  50198. };
  50199. /*
  50200. * Generate table for pairing.
  50201. *
  50202. * Calculate the graident (l) and constant (c) at each step of the way.
  50203. * Sliding window. Start at bottom and stop when bottom bit is one.
  50204. * Subtract if top bit in window is one.
  50205. * Width of 6 bits.
  50206. *
  50207. * pm [in] Point to generate table for.
  50208. * table [in] Generated table.
  50209. * len [in,out] On in, the size of the buffer.
  50210. * On out, length of table generated.
  50211. * @return 0 on success.
  50212. * LENGTH_ONLY_E when table is NULL and only length returned.
  50213. * BUFFER_E when len is too small.
  50214. * MEMORY_E when dynamic memory allocation fauls.
  50215. */
  50216. int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table,
  50217. word32* len)
  50218. {
  50219. int err = 0;
  50220. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  50221. !defined(WOLFSSL_SP_NO_MALLOC)
  50222. sp_digit* td = NULL;
  50223. sp_digit* t;
  50224. sp_point_1024* pre_p;
  50225. #else
  50226. sp_digit t[6 * 2 * 42];
  50227. sp_point_1024 pre_p[16];
  50228. sp_point_1024 pd;
  50229. sp_point_1024 cd;
  50230. sp_point_1024 negd;
  50231. #endif
  50232. sp_point_1024* p = NULL;
  50233. sp_point_1024* c = NULL;
  50234. sp_point_1024* neg = NULL;
  50235. int i;
  50236. int j;
  50237. int k;
  50238. sp_table_entry_1024* precomp = (sp_table_entry_1024*)table;
  50239. if (table == NULL) {
  50240. *len = sizeof(sp_table_entry_1024) * 1167;
  50241. err = LENGTH_ONLY_E;
  50242. }
  50243. if ((err == MP_OKAY) &&
  50244. (*len < (int)(sizeof(sp_table_entry_1024) * 1167))) {
  50245. err = BUFFER_E;
  50246. }
  50247. if (err == MP_OKAY) {
  50248. err = sp_1024_point_new_42(NULL, pd, p);
  50249. }
  50250. if (err == MP_OKAY) {
  50251. err = sp_1024_point_new_42(NULL, cd, c);
  50252. }
  50253. if (err == MP_OKAY) {
  50254. err = sp_1024_point_new_42(NULL, negd, neg);
  50255. }
  50256. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  50257. !defined(WOLFSSL_SP_NO_MALLOC)
  50258. if (err == MP_OKAY) {
  50259. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 6 * 42 * 2 + 16 * sizeof(sp_point_1024), NULL,
  50260. DYNAMIC_TYPE_TMP_BUFFER);
  50261. if (td == NULL) {
  50262. err = MEMORY_E;
  50263. }
  50264. }
  50265. #endif
  50266. if (err == MP_OKAY) {
  50267. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  50268. !defined(WOLFSSL_SP_NO_MALLOC)
  50269. t = td;
  50270. pre_p = (sp_point_1024*)(td + 6 * 42 * 2);
  50271. #endif
  50272. sp_1024_point_from_ecc_point_42(p, pm);
  50273. err = sp_1024_mod_mul_norm_42(p->x, p->x, p1024_mod);
  50274. }
  50275. if (err == MP_OKAY) {
  50276. err = sp_1024_mod_mul_norm_42(p->y, p->y, p1024_mod);
  50277. }
  50278. if (err == MP_OKAY) {
  50279. XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod));
  50280. neg->infinity = 0;
  50281. c->infinity = 0;
  50282. /* Generate pre-computation table: 1, 3, ... , 31 */
  50283. XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024));
  50284. /* [2]P for adding */
  50285. sp_1024_proj_point_dbl_42(c, p, t);
  50286. /* 1, 3, ... */
  50287. for (i = 1; i < 16; i++) {
  50288. sp_1024_proj_point_add_42(&pre_p[i], &pre_p[i-1], c, t);
  50289. sp_1024_mont_map_42(&pre_p[i], t);
  50290. }
  50291. k = 0;
  50292. j = sp_1024_order_op_pre[0] / 2;
  50293. XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024));
  50294. for (j = 0; j < sp_1024_order_op_pre[1]; j++) {
  50295. sp_1024_accum_dbl_calc_lc_42(precomp[k].x, precomp[k].y, c->x, c->y, t);
  50296. k++;
  50297. sp_1024_proj_point_dbl_42(c, c, t);
  50298. sp_1024_mont_map_42(c, t);
  50299. }
  50300. for (i = 2; i < 290; i += 2) {
  50301. j = sp_1024_order_op_pre[i];
  50302. if (j > 0) {
  50303. sp_1024_accum_add_calc_lc_42(precomp[k].x, precomp[k].y,
  50304. pre_p[j/2].x, pre_p[j/2].y, c->x, c->y, t);
  50305. k++;
  50306. sp_1024_proj_point_add_42(c, c, &pre_p[j/2], t);
  50307. sp_1024_mont_map_42(c, t);
  50308. }
  50309. else {
  50310. XMEMCPY(neg->x, pre_p[-j / 2].x, sizeof(pre_p->x));
  50311. sp_1024_mont_sub_42(neg->y, p1024_mod, pre_p[-j / 2].y,
  50312. p1024_mod);
  50313. XMEMCPY(neg->z, pre_p[-j / 2].z, sizeof(pre_p->z));
  50314. sp_1024_accum_add_calc_lc_42(precomp[k].x, precomp[k].y,
  50315. neg->x, neg->y, c->x, c->y, t);
  50316. k++;
  50317. sp_1024_proj_point_add_42(c, c, neg, t);
  50318. sp_1024_mont_map_42(c, t);
  50319. }
  50320. for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) {
  50321. sp_1024_accum_dbl_calc_lc_42(precomp[k].x, precomp[k].y, c->x, c->y, t);
  50322. k++;
  50323. sp_1024_proj_point_dbl_42(c, c, t);
  50324. sp_1024_mont_map_42(c, t);
  50325. }
  50326. }
  50327. *len = sizeof(sp_table_entry_1024) * 1167;
  50328. }
  50329. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  50330. !defined(WOLFSSL_SP_NO_MALLOC)
  50331. if (td != NULL) {
  50332. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  50333. }
  50334. #endif
  50335. sp_1024_point_free_42(neg, 1, NULL);
  50336. sp_1024_point_free_42(c, 1, NULL);
  50337. sp_1024_point_free_42(p, 1, NULL);
  50338. return err;
  50339. }
  50340. /*
  50341. * Calculate r = pairing <P, Q>.
  50342. *
  50343. * That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
  50344. *
  50345. * Sliding window. Start at bottom and stop when bottom bit is one.
  50346. * Subtract if top bit in window is one.
  50347. * Width of 6 bits.
  50348. * Pre-generate values in window (1, 3, ...) - only V.
  50349. * Table contains all gradient l and a constant for each point on the path.
  50350. *
  50351. * @param [in] pm First point on E(F_p)[q].
  50352. * @param [in] qm Second point on E(F_p)[q].
  50353. * @param [in] res Result of calculation.
  50354. * @param [in] table Precomputed table of values.
  50355. * @param [in] len Length of precomputed table of values in bytes.
  50356. * @return 0 on success.
  50357. * @return MEMORY_E when dynamic memory allocation fails.
  50358. */
  50359. int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm,
  50360. mp_int* res, const byte* table, word32 len)
  50361. {
  50362. int err = 0;
  50363. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  50364. !defined(WOLFSSL_SP_NO_MALLOC)
  50365. sp_digit* td = NULL;
  50366. sp_digit* t;
  50367. sp_digit* vx;
  50368. sp_digit* vy;
  50369. sp_digit (*pre_vx)[84];
  50370. sp_digit (*pre_vy)[84];
  50371. sp_digit (*pre_nvy)[84];
  50372. #else
  50373. sp_digit t[6 * 2 * 42];
  50374. sp_digit vx[2 * 42];
  50375. sp_digit vy[2 * 42];
  50376. sp_digit pre_vx[16][84];
  50377. sp_digit pre_vy[16][84];
  50378. sp_digit pre_nvy[16][84];
  50379. sp_point_1024 pd;
  50380. sp_point_1024 qd;
  50381. sp_point_1024 cd;
  50382. #endif
  50383. sp_point_1024* p = NULL;
  50384. sp_point_1024* q = NULL;
  50385. sp_point_1024* c = NULL;
  50386. sp_digit* r = NULL;
  50387. int i;
  50388. int j;
  50389. int k;
  50390. const sp_table_entry_1024* precomp = (const sp_table_entry_1024*)table;
  50391. if (len < (int)(sizeof(sp_table_entry_1024) * 1167)) {
  50392. err = BUFFER_E;
  50393. }
  50394. if (err == MP_OKAY) {
  50395. err = sp_1024_point_new_42(NULL, pd, p);
  50396. }
  50397. if (err == MP_OKAY) {
  50398. err = sp_1024_point_new_42(NULL, qd, q);
  50399. }
  50400. if (err == MP_OKAY) {
  50401. err = sp_1024_point_new_42(NULL, cd, c);
  50402. }
  50403. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  50404. !defined(WOLFSSL_SP_NO_MALLOC)
  50405. if (err == MP_OKAY) {
  50406. td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 42 * 2, NULL,
  50407. DYNAMIC_TYPE_TMP_BUFFER);
  50408. if (td == NULL) {
  50409. err = MEMORY_E;
  50410. }
  50411. }
  50412. #endif
  50413. if (err == MP_OKAY) {
  50414. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  50415. !defined(WOLFSSL_SP_NO_MALLOC)
  50416. t = td;
  50417. vx = td + 6 * 42 * 2;
  50418. vy = td + 7 * 42 * 2;
  50419. pre_vx = (sp_digit(*)[84])(td + 8 * 42 * 2);
  50420. pre_vy = (sp_digit(*)[84])(td + 24 * 42 * 2);
  50421. pre_nvy = (sp_digit(*)[84])(td + 40 * 42 * 2);
  50422. #endif
  50423. r = vy;
  50424. sp_1024_point_from_ecc_point_42(p, pm);
  50425. sp_1024_point_from_ecc_point_42(q, qm);
  50426. err = sp_1024_mod_mul_norm_42(p->x, p->x, p1024_mod);
  50427. }
  50428. if (err == MP_OKAY) {
  50429. err = sp_1024_mod_mul_norm_42(p->y, p->y, p1024_mod);
  50430. }
  50431. if (err == MP_OKAY) {
  50432. err = sp_1024_mod_mul_norm_42(p->z, p->z, p1024_mod);
  50433. }
  50434. if (err == MP_OKAY) {
  50435. err = sp_1024_mod_mul_norm_42(q->x, q->x, p1024_mod);
  50436. }
  50437. if (err == MP_OKAY) {
  50438. err = sp_1024_mod_mul_norm_42(q->y, q->y, p1024_mod);
  50439. }
  50440. if (err == MP_OKAY) {
  50441. /* Generate pre-computation table: 1, 3, ... , 31 */
  50442. XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 42);
  50443. pre_vx[0][0] = 1;
  50444. XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 42);
  50445. sp_1024_mont_sub_42(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod);
  50446. /* [2]P for adding */
  50447. XMEMCPY(c, p, sizeof(sp_point_1024));
  50448. XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 42);
  50449. vx[0] = 1;
  50450. XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 42);
  50451. sp_1024_accumulate_line_dbl_42(vx, vy, c, q, t);
  50452. /* 3, 5, ... */
  50453. for (i = 1; i < 16; i++) {
  50454. XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 42);
  50455. XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 42);
  50456. sp_1024_proj_mul_42(pre_vx[i], pre_vy[i], vx, vy, t);
  50457. sp_1024_accumulate_line_add_n_42(pre_vx[i], pre_vy[i], c,
  50458. q, p, t, 0);
  50459. sp_1024_mont_sub_42(pre_nvy[i], p1024_mod, pre_vy[i],
  50460. p1024_mod);
  50461. }
  50462. XMEMCPY(c->z, p1024_norm_mod, sizeof(sp_digit) * 42);
  50463. c->infinity = 0;
  50464. j = sp_1024_order_op_pre[0] / 2;
  50465. XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 42);
  50466. XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 42);
  50467. k = 0;
  50468. for (j = 0; j < sp_1024_order_op_pre[1]; j++) {
  50469. /* Accumulate line into v and double point. */
  50470. sp_1024_accumulate_line_lc_42(vx, vy, precomp[k].x,
  50471. precomp[k].y, q, t, 1);
  50472. k++;
  50473. }
  50474. for (i = 2; i < 290; i += 2) {
  50475. sp_1024_accumulate_line_lc_42(vx, vy, precomp[k].x,
  50476. precomp[k].y, q, t, 0);
  50477. k++;
  50478. j = sp_1024_order_op_pre[i];
  50479. if (j > 0) {
  50480. j /= 2;
  50481. /* Accumulate line into v. */
  50482. sp_1024_proj_mul_42(vx, vy, pre_vx[j], pre_vy[j], t);
  50483. }
  50484. else {
  50485. j = -j / 2;
  50486. /* Accumulate line into v. */
  50487. sp_1024_proj_mul_42(vx, vy, pre_vx[j], pre_nvy[j], t);
  50488. }
  50489. for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) {
  50490. /* Accumulate line into v and double point. */
  50491. sp_1024_accumulate_line_lc_42(vx, vy, precomp[k].x,
  50492. precomp[k].y, q, t, 1);
  50493. k++;
  50494. }
  50495. }
  50496. /* Final exponentiation */
  50497. sp_1024_proj_sqr_42(vx, vy, t);
  50498. sp_1024_proj_sqr_42(vx, vy, t);
  50499. /* Convert from PF_p[q] to F_p */
  50500. sp_1024_mont_inv_42(vx, vx, t);
  50501. sp_1024_mont_mul_42(r, vx, vy, p1024_mod, p1024_mp_mod);
  50502. XMEMSET(r + 42, 0, sizeof(sp_digit) * 42);
  50503. sp_1024_mont_reduce_42(r, p1024_mod, p1024_mp_mod);
  50504. err = sp_1024_to_mp(r, res);
  50505. }
  50506. #if (defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)) && \
  50507. !defined(WOLFSSL_SP_NO_MALLOC)
  50508. if (td != NULL) {
  50509. XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
  50510. }
  50511. #endif
  50512. sp_1024_point_free_42(c, 1, NULL);
  50513. sp_1024_point_free_42(q, 1, NULL);
  50514. sp_1024_point_free_42(p, 1, NULL);
  50515. return err;
  50516. }
  50517. #endif /* WOLFSSL_SP_SMALL */
  50518. #ifdef HAVE_ECC_CHECK_KEY
  50519. /* Read big endian unsigned byte array into r.
  50520. *
  50521. * r A single precision integer.
  50522. * size Maximum number of bytes to convert
  50523. * a Byte array.
  50524. * n Number of bytes in array to read.
  50525. */
  50526. static void sp_1024_from_bin(sp_digit* r, int size, const byte* a, int n)
  50527. {
  50528. int i;
  50529. int j = 0;
  50530. word32 s = 0;
  50531. r[0] = 0;
  50532. for (i = n-1; i >= 0; i--) {
  50533. r[j] |= (((sp_digit)a[i]) << s);
  50534. if (s >= 17U) {
  50535. r[j] &= 0x1ffffff;
  50536. s = 25U - s;
  50537. if (j + 1 >= size) {
  50538. break;
  50539. }
  50540. r[++j] = (sp_digit)a[i] >> s;
  50541. s = 8U - s;
  50542. }
  50543. else {
  50544. s += 8U;
  50545. }
  50546. }
  50547. for (j++; j < size; j++) {
  50548. r[j] = 0;
  50549. }
  50550. }
  50551. /* Check that the x and y oridinates are a valid point on the curve.
  50552. *
  50553. * point EC point.
  50554. * heap Heap to use if dynamically allocating.
  50555. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  50556. * not on the curve and MP_OKAY otherwise.
  50557. */
  50558. static int sp_1024_ecc_is_point_42(const sp_point_1024* point,
  50559. void* heap)
  50560. {
  50561. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  50562. sp_digit* t1 = NULL;
  50563. #else
  50564. sp_digit t1[42 * 4];
  50565. #endif
  50566. sp_digit* t2 = NULL;
  50567. sp_int32 n;
  50568. int err = MP_OKAY;
  50569. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  50570. t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 42 * 4, heap, DYNAMIC_TYPE_ECC);
  50571. if (t1 == NULL)
  50572. err = MEMORY_E;
  50573. #endif
  50574. (void)heap;
  50575. if (err == MP_OKAY) {
  50576. t2 = t1 + 2 * 42;
  50577. sp_1024_sqr_42(t1, point->y);
  50578. (void)sp_1024_mod_42(t1, t1, p1024_mod);
  50579. sp_1024_sqr_42(t2, point->x);
  50580. (void)sp_1024_mod_42(t2, t2, p1024_mod);
  50581. sp_1024_mul_42(t2, t2, point->x);
  50582. (void)sp_1024_mod_42(t2, t2, p1024_mod);
  50583. (void)sp_1024_sub_42(t2, p1024_mod, t2);
  50584. sp_1024_mont_add_42(t1, t1, t2, p1024_mod);
  50585. sp_1024_mont_add_42(t1, t1, point->x, p1024_mod);
  50586. sp_1024_mont_add_42(t1, t1, point->x, p1024_mod);
  50587. sp_1024_mont_add_42(t1, t1, point->x, p1024_mod);
  50588. n = sp_1024_cmp_42(t1, p1024_mod);
  50589. sp_1024_cond_sub_42(t1, t1, p1024_mod, ~(n >> 24));
  50590. sp_1024_norm_42(t1);
  50591. if (!sp_1024_iszero_42(t1)) {
  50592. err = MP_VAL;
  50593. }
  50594. }
  50595. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  50596. if (t1 != NULL)
  50597. XFREE(t1, heap, DYNAMIC_TYPE_ECC);
  50598. #endif
  50599. return err;
  50600. }
  50601. /* Check that the x and y oridinates are a valid point on the curve.
  50602. *
  50603. * pX X ordinate of EC point.
  50604. * pY Y ordinate of EC point.
  50605. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  50606. * not on the curve and MP_OKAY otherwise.
  50607. */
  50608. int sp_ecc_is_point_1024(const mp_int* pX, const mp_int* pY)
  50609. {
  50610. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  50611. sp_point_1024* pub = NULL;
  50612. #else
  50613. sp_point_1024 pub[1];
  50614. #endif
  50615. const byte one[1] = { 1 };
  50616. int err = MP_OKAY;
  50617. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  50618. pub = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), NULL,
  50619. DYNAMIC_TYPE_ECC);
  50620. if (pub == NULL)
  50621. err = MEMORY_E;
  50622. #endif
  50623. if (err == MP_OKAY) {
  50624. sp_1024_from_mp(pub->x, 42, pX);
  50625. sp_1024_from_mp(pub->y, 42, pY);
  50626. sp_1024_from_bin(pub->z, 42, one, (int)sizeof(one));
  50627. err = sp_1024_ecc_is_point_42(pub, NULL);
  50628. }
  50629. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  50630. if (pub != NULL)
  50631. XFREE(pub, NULL, DYNAMIC_TYPE_ECC);
  50632. #endif
  50633. return err;
  50634. }
  50635. /* Check that the private scalar generates the EC point (px, py), the point is
  50636. * on the curve and the point has the correct order.
  50637. *
  50638. * pX X ordinate of EC point.
  50639. * pY Y ordinate of EC point.
  50640. * privm Private scalar that generates EC point.
  50641. * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
  50642. * not on the curve, ECC_INF_E if the point does not have the correct order,
  50643. * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
  50644. * MP_OKAY otherwise.
  50645. */
  50646. int sp_ecc_check_key_1024(const mp_int* pX, const mp_int* pY,
  50647. const mp_int* privm, void* heap)
  50648. {
  50649. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  50650. sp_digit* priv = NULL;
  50651. sp_point_1024* pub = NULL;
  50652. #else
  50653. sp_digit priv[42];
  50654. sp_point_1024 pub[2];
  50655. #endif
  50656. sp_point_1024* p = NULL;
  50657. const byte one[1] = { 1 };
  50658. int err = MP_OKAY;
  50659. /* Quick check the lengs of public key ordinates and private key are in
  50660. * range. Proper check later.
  50661. */
  50662. if (((mp_count_bits(pX) > 1024) ||
  50663. (mp_count_bits(pY) > 1024) ||
  50664. ((privm != NULL) && (mp_count_bits(privm) > 1024)))) {
  50665. err = ECC_OUT_OF_RANGE_E;
  50666. }
  50667. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  50668. if (err == MP_OKAY) {
  50669. pub = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap,
  50670. DYNAMIC_TYPE_ECC);
  50671. if (pub == NULL)
  50672. err = MEMORY_E;
  50673. }
  50674. if (err == MP_OKAY && privm) {
  50675. priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 42, heap,
  50676. DYNAMIC_TYPE_ECC);
  50677. if (priv == NULL)
  50678. err = MEMORY_E;
  50679. }
  50680. #endif
  50681. if (err == MP_OKAY) {
  50682. p = pub + 1;
  50683. sp_1024_from_mp(pub->x, 42, pX);
  50684. sp_1024_from_mp(pub->y, 42, pY);
  50685. sp_1024_from_bin(pub->z, 42, one, (int)sizeof(one));
  50686. if (privm)
  50687. sp_1024_from_mp(priv, 42, privm);
  50688. /* Check point at infinitiy. */
  50689. if ((sp_1024_iszero_42(pub->x) != 0) &&
  50690. (sp_1024_iszero_42(pub->y) != 0)) {
  50691. err = ECC_INF_E;
  50692. }
  50693. }
  50694. /* Check range of X and Y */
  50695. if ((err == MP_OKAY) &&
  50696. ((sp_1024_cmp_42(pub->x, p1024_mod) >= 0) ||
  50697. (sp_1024_cmp_42(pub->y, p1024_mod) >= 0))) {
  50698. err = ECC_OUT_OF_RANGE_E;
  50699. }
  50700. if (err == MP_OKAY) {
  50701. /* Check point is on curve */
  50702. err = sp_1024_ecc_is_point_42(pub, heap);
  50703. }
  50704. if (err == MP_OKAY) {
  50705. /* Point * order = infinity */
  50706. err = sp_1024_ecc_mulmod_42(p, pub, p1024_order, 1, 1, heap);
  50707. }
  50708. /* Check result is infinity */
  50709. if ((err == MP_OKAY) && ((sp_1024_iszero_42(p->x) == 0) ||
  50710. (sp_1024_iszero_42(p->y) == 0))) {
  50711. err = ECC_INF_E;
  50712. }
  50713. if (privm) {
  50714. if (err == MP_OKAY) {
  50715. /* Base * private = point */
  50716. err = sp_1024_ecc_mulmod_base_42(p, priv, 1, 1, heap);
  50717. }
  50718. /* Check result is public key */
  50719. if ((err == MP_OKAY) &&
  50720. ((sp_1024_cmp_42(p->x, pub->x) != 0) ||
  50721. (sp_1024_cmp_42(p->y, pub->y) != 0))) {
  50722. err = ECC_PRIV_KEY_E;
  50723. }
  50724. }
  50725. #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
  50726. if (pub != NULL)
  50727. XFREE(pub, heap, DYNAMIC_TYPE_ECC);
  50728. if (priv != NULL)
  50729. XFREE(priv, heap, DYNAMIC_TYPE_ECC);
  50730. #endif
  50731. return err;
  50732. }
  50733. #endif
  50734. #endif /* WOLFSSL_SP_1024 */
  50735. #endif /* WOLFSSL_HAVE_SP_ECC */
  50736. #endif /* SP_WORD_SIZE == 32 */
  50737. #endif /* !WOLFSSL_SP_ASM */
  50738. #endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH | WOLFSSL_HAVE_SP_ECC */