mpi.c 213 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813
  1. /* Start: bn_error.c */
  2. #include <ltc_tommath.h>
  3. #ifdef BN_ERROR_C
  4. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  5. *
  6. * LibTomMath is a library that provides multiple-precision
  7. * integer arithmetic as well as number theoretic functionality.
  8. *
  9. * The library was designed directly after the MPI library by
  10. * Michael Fromberger but has been written from scratch with
  11. * additional optimizations in place.
  12. *
  13. * The library is free for all purposes without any express
  14. * guarantee it works.
  15. *
  16. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  17. */
  18. static const struct {
  19. int code;
  20. char *msg;
  21. } msgs[] = {
  22. { MP_OKAY, "Successful" },
  23. { MP_MEM, "Out of heap" },
  24. { MP_VAL, "Value out of range" }
  25. };
  26. /* return a char * string for a given code */
  27. char *mp_error_to_string(int code)
  28. {
  29. int x;
  30. /* scan the lookup table for the given message */
  31. for (x = 0; x < (int)(sizeof(msgs) / sizeof(msgs[0])); x++) {
  32. if (msgs[x].code == code) {
  33. return msgs[x].msg;
  34. }
  35. }
  36. /* generic reply for invalid code */
  37. return "Invalid error code";
  38. }
  39. #endif
  40. /* End: bn_error.c */
  41. /* Start: bn_fast_mp_invmod.c */
  42. #include <ltc_tommath.h>
  43. #ifdef BN_FAST_MP_INVMOD_C
  44. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  45. *
  46. * LibTomMath is a library that provides multiple-precision
  47. * integer arithmetic as well as number theoretic functionality.
  48. *
  49. * The library was designed directly after the MPI library by
  50. * Michael Fromberger but has been written from scratch with
  51. * additional optimizations in place.
  52. *
  53. * The library is free for all purposes without any express
  54. * guarantee it works.
  55. *
  56. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  57. */
  58. /* computes the modular inverse via binary extended euclidean algorithm,
  59. * that is c = 1/a mod b
  60. *
  61. * Based on slow invmod except this is optimized for the case where b is
  62. * odd as per HAC Note 14.64 on pp. 610
  63. */
  64. int
  65. fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c)
  66. {
  67. mp_int x, y, u, v, B, D;
  68. int res, neg;
  69. /* 2. [modified] b must be odd */
  70. if (mp_iseven (b) == 1) {
  71. return MP_VAL;
  72. }
  73. /* init all our temps */
  74. if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) {
  75. return res;
  76. }
  77. /* x == modulus, y == value to invert */
  78. if ((res = mp_copy (b, &x)) != MP_OKAY) {
  79. goto __ERR;
  80. }
  81. /* we need y = |a| */
  82. if ((res = mp_abs (a, &y)) != MP_OKAY) {
  83. goto __ERR;
  84. }
  85. /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
  86. if ((res = mp_copy (&x, &u)) != MP_OKAY) {
  87. goto __ERR;
  88. }
  89. if ((res = mp_copy (&y, &v)) != MP_OKAY) {
  90. goto __ERR;
  91. }
  92. mp_set (&D, 1);
  93. top:
  94. /* 4. while u is even do */
  95. while (mp_iseven (&u) == 1) {
  96. /* 4.1 u = u/2 */
  97. if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
  98. goto __ERR;
  99. }
  100. /* 4.2 if B is odd then */
  101. if (mp_isodd (&B) == 1) {
  102. if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
  103. goto __ERR;
  104. }
  105. }
  106. /* B = B/2 */
  107. if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
  108. goto __ERR;
  109. }
  110. }
  111. /* 5. while v is even do */
  112. while (mp_iseven (&v) == 1) {
  113. /* 5.1 v = v/2 */
  114. if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
  115. goto __ERR;
  116. }
  117. /* 5.2 if D is odd then */
  118. if (mp_isodd (&D) == 1) {
  119. /* D = (D-x)/2 */
  120. if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
  121. goto __ERR;
  122. }
  123. }
  124. /* D = D/2 */
  125. if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
  126. goto __ERR;
  127. }
  128. }
  129. /* 6. if u >= v then */
  130. if (mp_cmp (&u, &v) != MP_LT) {
  131. /* u = u - v, B = B - D */
  132. if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
  133. goto __ERR;
  134. }
  135. if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
  136. goto __ERR;
  137. }
  138. } else {
  139. /* v - v - u, D = D - B */
  140. if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
  141. goto __ERR;
  142. }
  143. if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
  144. goto __ERR;
  145. }
  146. }
  147. /* if not zero goto step 4 */
  148. if (mp_iszero (&u) == 0) {
  149. goto top;
  150. }
  151. /* now a = C, b = D, gcd == g*v */
  152. /* if v != 1 then there is no inverse */
  153. if (mp_cmp_d (&v, 1) != MP_EQ) {
  154. res = MP_VAL;
  155. goto __ERR;
  156. }
  157. /* b is now the inverse */
  158. neg = a->sign;
  159. while (D.sign == MP_NEG) {
  160. if ((res = mp_add (&D, b, &D)) != MP_OKAY) {
  161. goto __ERR;
  162. }
  163. }
  164. mp_exch (&D, c);
  165. c->sign = neg;
  166. res = MP_OKAY;
  167. __ERR:mp_clear_multi (&x, &y, &u, &v, &B, &D, NULL);
  168. return res;
  169. }
  170. #endif
  171. /* End: bn_fast_mp_invmod.c */
  172. /* Start: bn_fast_mp_montgomery_reduce.c */
  173. #include <ltc_tommath.h>
  174. #ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
  175. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  176. *
  177. * LibTomMath is a library that provides multiple-precision
  178. * integer arithmetic as well as number theoretic functionality.
  179. *
  180. * The library was designed directly after the MPI library by
  181. * Michael Fromberger but has been written from scratch with
  182. * additional optimizations in place.
  183. *
  184. * The library is free for all purposes without any express
  185. * guarantee it works.
  186. *
  187. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  188. */
  189. /* computes xR**-1 == x (mod N) via Montgomery Reduction
  190. *
  191. * This is an optimized implementation of montgomery_reduce
  192. * which uses the comba method to quickly calculate the columns of the
  193. * reduction.
  194. *
  195. * Based on Algorithm 14.32 on pp.601 of HAC.
  196. */
  197. int
  198. fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
  199. {
  200. int ix, res, olduse;
  201. mp_word W[MP_WARRAY];
  202. /* get old used count */
  203. olduse = x->used;
  204. /* grow a as required */
  205. if (x->alloc < n->used + 1) {
  206. if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) {
  207. return res;
  208. }
  209. }
  210. /* first we have to get the digits of the input into
  211. * an array of double precision words W[...]
  212. */
  213. {
  214. register mp_word *_W;
  215. register mp_digit *tmpx;
  216. /* alias for the W[] array */
  217. _W = W;
  218. /* alias for the digits of x*/
  219. tmpx = x->dp;
  220. /* copy the digits of a into W[0..a->used-1] */
  221. for (ix = 0; ix < x->used; ix++) {
  222. *_W++ = *tmpx++;
  223. }
  224. /* zero the high words of W[a->used..m->used*2] */
  225. for (; ix < n->used * 2 + 1; ix++) {
  226. *_W++ = 0;
  227. }
  228. }
  229. /* now we proceed to zero successive digits
  230. * from the least significant upwards
  231. */
  232. for (ix = 0; ix < n->used; ix++) {
  233. /* mu = ai * m' mod b
  234. *
  235. * We avoid a double precision multiplication (which isn't required)
  236. * by casting the value down to a mp_digit. Note this requires
  237. * that W[ix-1] have the carry cleared (see after the inner loop)
  238. */
  239. register mp_digit mu;
  240. mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);
  241. /* a = a + mu * m * b**i
  242. *
  243. * This is computed in place and on the fly. The multiplication
  244. * by b**i is handled by offseting which columns the results
  245. * are added to.
  246. *
  247. * Note the comba method normally doesn't handle carries in the
  248. * inner loop In this case we fix the carry from the previous
  249. * column since the Montgomery reduction requires digits of the
  250. * result (so far) [see above] to work. This is
  251. * handled by fixing up one carry after the inner loop. The
  252. * carry fixups are done in order so after these loops the
  253. * first m->used words of W[] have the carries fixed
  254. */
  255. {
  256. register int iy;
  257. register mp_digit *tmpn;
  258. register mp_word *_W;
  259. /* alias for the digits of the modulus */
  260. tmpn = n->dp;
  261. /* Alias for the columns set by an offset of ix */
  262. _W = W + ix;
  263. /* inner loop */
  264. for (iy = 0; iy < n->used; iy++) {
  265. *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++);
  266. }
  267. }
  268. /* now fix carry for next digit, W[ix+1] */
  269. W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT);
  270. }
  271. /* now we have to propagate the carries and
  272. * shift the words downward [all those least
  273. * significant digits we zeroed].
  274. */
  275. {
  276. register mp_digit *tmpx;
  277. register mp_word *_W, *_W1;
  278. /* nox fix rest of carries */
  279. /* alias for current word */
  280. _W1 = W + ix;
  281. /* alias for next word, where the carry goes */
  282. _W = W + ++ix;
  283. for (; ix <= n->used * 2 + 1; ix++) {
  284. *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT);
  285. }
  286. /* copy out, A = A/b**n
  287. *
  288. * The result is A/b**n but instead of converting from an
  289. * array of mp_word to mp_digit than calling mp_rshd
  290. * we just copy them in the right order
  291. */
  292. /* alias for destination word */
  293. tmpx = x->dp;
  294. /* alias for shifted double precision result */
  295. _W = W + n->used;
  296. for (ix = 0; ix < n->used + 1; ix++) {
  297. *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK));
  298. }
  299. /* zero oldused digits, if the input a was larger than
  300. * m->used+1 we'll have to clear the digits
  301. */
  302. for (; ix < olduse; ix++) {
  303. *tmpx++ = 0;
  304. }
  305. }
  306. /* set the max used and clamp */
  307. x->used = n->used + 1;
  308. mp_clamp (x);
  309. /* if A >= m then A = A - m */
  310. if (mp_cmp_mag (x, n) != MP_LT) {
  311. return s_mp_sub (x, n, x);
  312. }
  313. return MP_OKAY;
  314. }
  315. #endif
  316. /* End: bn_fast_mp_montgomery_reduce.c */
  317. /* Start: bn_fast_s_mp_mul_digs.c */
  318. #include <ltc_tommath.h>
  319. #ifdef BN_FAST_S_MP_MUL_DIGS_C
  320. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  321. *
  322. * LibTomMath is a library that provides multiple-precision
  323. * integer arithmetic as well as number theoretic functionality.
  324. *
  325. * The library was designed directly after the MPI library by
  326. * Michael Fromberger but has been written from scratch with
  327. * additional optimizations in place.
  328. *
  329. * The library is free for all purposes without any express
  330. * guarantee it works.
  331. *
  332. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  333. */
  334. /* Fast (comba) multiplier
  335. *
  336. * This is the fast column-array [comba] multiplier. It is
  337. * designed to compute the columns of the product first
  338. * then handle the carries afterwards. This has the effect
  339. * of making the nested loops that compute the columns very
  340. * simple and schedulable on super-scalar processors.
  341. *
  342. * This has been modified to produce a variable number of
  343. * digits of output so if say only a half-product is required
  344. * you don't have to compute the upper half (a feature
  345. * required for fast Barrett reduction).
  346. *
  347. * Based on Algorithm 14.12 on pp.595 of HAC.
  348. *
  349. */
  350. int
  351. fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
  352. {
  353. int olduse, res, pa, ix, iz;
  354. mp_digit W[MP_WARRAY];
  355. register mp_word _W;
  356. /* grow the destination as required */
  357. if (c->alloc < digs) {
  358. if ((res = mp_grow (c, digs)) != MP_OKAY) {
  359. return res;
  360. }
  361. }
  362. /* number of output digits to produce */
  363. pa = MIN(digs, a->used + b->used);
  364. /* clear the carry */
  365. _W = 0;
  366. for (ix = 0; ix <= pa; ix++) {
  367. int tx, ty;
  368. int iy;
  369. mp_digit *tmpx, *tmpy;
  370. /* get offsets into the two bignums */
  371. ty = MIN(b->used-1, ix);
  372. tx = ix - ty;
  373. /* setup temp aliases */
  374. tmpx = a->dp + tx;
  375. tmpy = b->dp + ty;
  376. /* this is the number of times the loop will iterrate, essentially its
  377. while (tx++ < a->used && ty-- >= 0) { ... }
  378. */
  379. iy = MIN(a->used-tx, ty+1);
  380. /* execute loop */
  381. for (iz = 0; iz < iy; ++iz) {
  382. _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
  383. }
  384. /* store term */
  385. W[ix] = ((mp_digit)_W) & MP_MASK;
  386. /* make next carry */
  387. _W = _W >> ((mp_word)DIGIT_BIT);
  388. }
  389. /* setup dest */
  390. olduse = c->used;
  391. c->used = digs;
  392. {
  393. register mp_digit *tmpc;
  394. tmpc = c->dp;
  395. for (ix = 0; ix < digs; ix++) {
  396. /* now extract the previous digit [below the carry] */
  397. *tmpc++ = W[ix];
  398. }
  399. /* clear unused digits [that existed in the old copy of c] */
  400. for (; ix < olduse; ix++) {
  401. *tmpc++ = 0;
  402. }
  403. }
  404. mp_clamp (c);
  405. return MP_OKAY;
  406. }
  407. #endif
  408. /* End: bn_fast_s_mp_mul_digs.c */
  409. /* Start: bn_fast_s_mp_mul_high_digs.c */
  410. #include <ltc_tommath.h>
  411. #ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
  412. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  413. *
  414. * LibTomMath is a library that provides multiple-precision
  415. * integer arithmetic as well as number theoretic functionality.
  416. *
  417. * The library was designed directly after the MPI library by
  418. * Michael Fromberger but has been written from scratch with
  419. * additional optimizations in place.
  420. *
  421. * The library is free for all purposes without any express
  422. * guarantee it works.
  423. *
  424. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  425. */
  426. /* this is a modified version of fast_s_mul_digs that only produces
  427. * output digits *above* digs. See the comments for fast_s_mul_digs
  428. * to see how it works.
  429. *
  430. * This is used in the Barrett reduction since for one of the multiplications
  431. * only the higher digits were needed. This essentially halves the work.
  432. *
  433. * Based on Algorithm 14.12 on pp.595 of HAC.
  434. */
  435. int
  436. fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
  437. {
  438. int olduse, res, pa, ix, iz;
  439. mp_digit W[MP_WARRAY];
  440. mp_word _W;
  441. /* grow the destination as required */
  442. pa = a->used + b->used;
  443. if (c->alloc < pa) {
  444. if ((res = mp_grow (c, pa)) != MP_OKAY) {
  445. return res;
  446. }
  447. }
  448. /* number of output digits to produce */
  449. pa = a->used + b->used;
  450. _W = 0;
  451. for (ix = digs; ix <= pa; ix++) {
  452. int tx, ty, iy;
  453. mp_digit *tmpx, *tmpy;
  454. /* get offsets into the two bignums */
  455. ty = MIN(b->used-1, ix);
  456. tx = ix - ty;
  457. /* setup temp aliases */
  458. tmpx = a->dp + tx;
  459. tmpy = b->dp + ty;
  460. /* this is the number of times the loop will iterrate, essentially its
  461. while (tx++ < a->used && ty-- >= 0) { ... }
  462. */
  463. iy = MIN(a->used-tx, ty+1);
  464. /* execute loop */
  465. for (iz = 0; iz < iy; iz++) {
  466. _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
  467. }
  468. /* store term */
  469. W[ix] = ((mp_digit)_W) & MP_MASK;
  470. /* make next carry */
  471. _W = _W >> ((mp_word)DIGIT_BIT);
  472. }
  473. /* setup dest */
  474. olduse = c->used;
  475. c->used = pa;
  476. {
  477. register mp_digit *tmpc;
  478. tmpc = c->dp + digs;
  479. for (ix = digs; ix <= pa; ix++) {
  480. /* now extract the previous digit [below the carry] */
  481. *tmpc++ = W[ix];
  482. }
  483. /* clear unused digits [that existed in the old copy of c] */
  484. for (; ix < olduse; ix++) {
  485. *tmpc++ = 0;
  486. }
  487. }
  488. mp_clamp (c);
  489. return MP_OKAY;
  490. }
  491. #endif
  492. /* End: bn_fast_s_mp_mul_high_digs.c */
  493. /* Start: bn_fast_s_mp_sqr.c */
  494. #include <ltc_tommath.h>
  495. #ifdef BN_FAST_S_MP_SQR_C
  496. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  497. *
  498. * LibTomMath is a library that provides multiple-precision
  499. * integer arithmetic as well as number theoretic functionality.
  500. *
  501. * The library was designed directly after the MPI library by
  502. * Michael Fromberger but has been written from scratch with
  503. * additional optimizations in place.
  504. *
  505. * The library is free for all purposes without any express
  506. * guarantee it works.
  507. *
  508. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  509. */
  510. /* fast squaring
  511. *
  512. * This is the comba method where the columns of the product
  513. * are computed first then the carries are computed. This
  514. * has the effect of making a very simple inner loop that
  515. * is executed the most
  516. *
  517. * W2 represents the outer products and W the inner.
  518. *
  519. * A further optimizations is made because the inner
  520. * products are of the form "A * B * 2". The *2 part does
  521. * not need to be computed until the end which is good
  522. * because 64-bit shifts are slow!
  523. *
  524. * Based on Algorithm 14.16 on pp.597 of HAC.
  525. *
  526. */
  527. /* the jist of squaring...
  528. you do like mult except the offset of the tmpx [one that starts closer to zero]
  529. can't equal the offset of tmpy. So basically you set up iy like before then you min it with
  530. (ty-tx) so that it never happens. You double all those you add in the inner loop
  531. After that loop you do the squares and add them in.
  532. Remove W2 and don't memset W
  533. */
  534. int fast_s_mp_sqr (mp_int * a, mp_int * b)
  535. {
  536. int olduse, res, pa, ix, iz;
  537. mp_digit W[MP_WARRAY], *tmpx;
  538. mp_word W1;
  539. /* grow the destination as required */
  540. pa = a->used + a->used;
  541. if (b->alloc < pa) {
  542. if ((res = mp_grow (b, pa)) != MP_OKAY) {
  543. return res;
  544. }
  545. }
  546. /* number of output digits to produce */
  547. W1 = 0;
  548. for (ix = 0; ix <= pa; ix++) {
  549. int tx, ty, iy;
  550. mp_word _W;
  551. mp_digit *tmpy;
  552. /* clear counter */
  553. _W = 0;
  554. /* get offsets into the two bignums */
  555. ty = MIN(a->used-1, ix);
  556. tx = ix - ty;
  557. /* setup temp aliases */
  558. tmpx = a->dp + tx;
  559. tmpy = a->dp + ty;
  560. /* this is the number of times the loop will iterrate, essentially its
  561. while (tx++ < a->used && ty-- >= 0) { ... }
  562. */
  563. iy = MIN(a->used-tx, ty+1);
  564. /* now for squaring tx can never equal ty
  565. * we halve the distance since they approach at a rate of 2x
  566. * and we have to round because odd cases need to be executed
  567. */
  568. iy = MIN(iy, (ty-tx+1)>>1);
  569. /* execute loop */
  570. for (iz = 0; iz < iy; iz++) {
  571. _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
  572. }
  573. /* double the inner product and add carry */
  574. _W = _W + _W + W1;
  575. /* even columns have the square term in them */
  576. if ((ix&1) == 0) {
  577. _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]);
  578. }
  579. /* store it */
  580. W[ix] = _W;
  581. /* make next carry */
  582. W1 = _W >> ((mp_word)DIGIT_BIT);
  583. }
  584. /* setup dest */
  585. olduse = b->used;
  586. b->used = a->used+a->used;
  587. {
  588. mp_digit *tmpb;
  589. tmpb = b->dp;
  590. for (ix = 0; ix < pa; ix++) {
  591. *tmpb++ = W[ix] & MP_MASK;
  592. }
  593. /* clear unused digits [that existed in the old copy of c] */
  594. for (; ix < olduse; ix++) {
  595. *tmpb++ = 0;
  596. }
  597. }
  598. mp_clamp (b);
  599. return MP_OKAY;
  600. }
  601. #endif
  602. /* End: bn_fast_s_mp_sqr.c */
  603. /* Start: bn_mp_2expt.c */
  604. #include <ltc_tommath.h>
  605. #ifdef BN_MP_2EXPT_C
  606. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  607. *
  608. * LibTomMath is a library that provides multiple-precision
  609. * integer arithmetic as well as number theoretic functionality.
  610. *
  611. * The library was designed directly after the MPI library by
  612. * Michael Fromberger but has been written from scratch with
  613. * additional optimizations in place.
  614. *
  615. * The library is free for all purposes without any express
  616. * guarantee it works.
  617. *
  618. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  619. */
  620. /* computes a = 2**b
  621. *
  622. * Simple algorithm which zeroes the int, grows it then just sets one bit
  623. * as required.
  624. */
  625. int
  626. mp_2expt (mp_int * a, int b)
  627. {
  628. int res;
  629. /* zero a as per default */
  630. mp_zero (a);
  631. /* grow a to accomodate the single bit */
  632. if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) {
  633. return res;
  634. }
  635. /* set the used count of where the bit will go */
  636. a->used = b / DIGIT_BIT + 1;
  637. /* put the single bit in its place */
  638. a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT);
  639. return MP_OKAY;
  640. }
  641. #endif
  642. /* End: bn_mp_2expt.c */
  643. /* Start: bn_mp_abs.c */
  644. #include <ltc_tommath.h>
  645. #ifdef BN_MP_ABS_C
  646. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  647. *
  648. * LibTomMath is a library that provides multiple-precision
  649. * integer arithmetic as well as number theoretic functionality.
  650. *
  651. * The library was designed directly after the MPI library by
  652. * Michael Fromberger but has been written from scratch with
  653. * additional optimizations in place.
  654. *
  655. * The library is free for all purposes without any express
  656. * guarantee it works.
  657. *
  658. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  659. */
  660. /* b = |a|
  661. *
  662. * Simple function copies the input and fixes the sign to positive
  663. */
  664. int
  665. mp_abs (mp_int * a, mp_int * b)
  666. {
  667. int res;
  668. /* copy a to b */
  669. if (a != b) {
  670. if ((res = mp_copy (a, b)) != MP_OKAY) {
  671. return res;
  672. }
  673. }
  674. /* force the sign of b to positive */
  675. b->sign = MP_ZPOS;
  676. return MP_OKAY;
  677. }
  678. #endif
  679. /* End: bn_mp_abs.c */
  680. /* Start: bn_mp_add.c */
  681. #include <ltc_tommath.h>
  682. #ifdef BN_MP_ADD_C
  683. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  684. *
  685. * LibTomMath is a library that provides multiple-precision
  686. * integer arithmetic as well as number theoretic functionality.
  687. *
  688. * The library was designed directly after the MPI library by
  689. * Michael Fromberger but has been written from scratch with
  690. * additional optimizations in place.
  691. *
  692. * The library is free for all purposes without any express
  693. * guarantee it works.
  694. *
  695. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  696. */
  697. /* high level addition (handles signs) */
  698. int mp_add (mp_int * a, mp_int * b, mp_int * c)
  699. {
  700. int sa, sb, res;
  701. /* get sign of both inputs */
  702. sa = a->sign;
  703. sb = b->sign;
  704. /* handle two cases, not four */
  705. if (sa == sb) {
  706. /* both positive or both negative */
  707. /* add their magnitudes, copy the sign */
  708. c->sign = sa;
  709. res = s_mp_add (a, b, c);
  710. } else {
  711. /* one positive, the other negative */
  712. /* subtract the one with the greater magnitude from */
  713. /* the one of the lesser magnitude. The result gets */
  714. /* the sign of the one with the greater magnitude. */
  715. if (mp_cmp_mag (a, b) == MP_LT) {
  716. c->sign = sb;
  717. res = s_mp_sub (b, a, c);
  718. } else {
  719. c->sign = sa;
  720. res = s_mp_sub (a, b, c);
  721. }
  722. }
  723. return res;
  724. }
  725. #endif
  726. /* End: bn_mp_add.c */
  727. /* Start: bn_mp_add_d.c */
  728. #include <ltc_tommath.h>
  729. #ifdef BN_MP_ADD_D_C
  730. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  731. *
  732. * LibTomMath is a library that provides multiple-precision
  733. * integer arithmetic as well as number theoretic functionality.
  734. *
  735. * The library was designed directly after the MPI library by
  736. * Michael Fromberger but has been written from scratch with
  737. * additional optimizations in place.
  738. *
  739. * The library is free for all purposes without any express
  740. * guarantee it works.
  741. *
  742. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  743. */
  744. /* single digit addition */
  745. int
  746. mp_add_d (mp_int * a, mp_digit b, mp_int * c)
  747. {
  748. int res, ix, oldused;
  749. mp_digit *tmpa, *tmpc, mu;
  750. /* grow c as required */
  751. if (c->alloc < a->used + 1) {
  752. if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
  753. return res;
  754. }
  755. }
  756. /* if a is negative and |a| >= b, call c = |a| - b */
  757. if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) {
  758. /* temporarily fix sign of a */
  759. a->sign = MP_ZPOS;
  760. /* c = |a| - b */
  761. res = mp_sub_d(a, b, c);
  762. /* fix sign */
  763. a->sign = c->sign = MP_NEG;
  764. return res;
  765. }
  766. /* old number of used digits in c */
  767. oldused = c->used;
  768. /* sign always positive */
  769. c->sign = MP_ZPOS;
  770. /* source alias */
  771. tmpa = a->dp;
  772. /* destination alias */
  773. tmpc = c->dp;
  774. /* if a is positive */
  775. if (a->sign == MP_ZPOS) {
  776. /* add digit, after this we're propagating
  777. * the carry.
  778. */
  779. *tmpc = *tmpa++ + b;
  780. mu = *tmpc >> DIGIT_BIT;
  781. *tmpc++ &= MP_MASK;
  782. /* now handle rest of the digits */
  783. for (ix = 1; ix < a->used; ix++) {
  784. *tmpc = *tmpa++ + mu;
  785. mu = *tmpc >> DIGIT_BIT;
  786. *tmpc++ &= MP_MASK;
  787. }
  788. /* set final carry */
  789. ix++;
  790. *tmpc++ = mu;
  791. /* setup size */
  792. c->used = a->used + 1;
  793. } else {
  794. /* a was negative and |a| < b */
  795. c->used = 1;
  796. /* the result is a single digit */
  797. if (a->used == 1) {
  798. *tmpc++ = b - a->dp[0];
  799. } else {
  800. *tmpc++ = b;
  801. }
  802. /* setup count so the clearing of oldused
  803. * can fall through correctly
  804. */
  805. ix = 1;
  806. }
  807. /* now zero to oldused */
  808. while (ix++ < oldused) {
  809. *tmpc++ = 0;
  810. }
  811. mp_clamp(c);
  812. return MP_OKAY;
  813. }
  814. #endif
  815. /* End: bn_mp_add_d.c */
  816. /* Start: bn_mp_addmod.c */
  817. #include <ltc_tommath.h>
  818. #ifdef BN_MP_ADDMOD_C
  819. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  820. *
  821. * LibTomMath is a library that provides multiple-precision
  822. * integer arithmetic as well as number theoretic functionality.
  823. *
  824. * The library was designed directly after the MPI library by
  825. * Michael Fromberger but has been written from scratch with
  826. * additional optimizations in place.
  827. *
  828. * The library is free for all purposes without any express
  829. * guarantee it works.
  830. *
  831. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  832. */
  833. /* d = a + b (mod c) */
  834. int
  835. mp_addmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
  836. {
  837. int res;
  838. mp_int t;
  839. if ((res = mp_init (&t)) != MP_OKAY) {
  840. return res;
  841. }
  842. if ((res = mp_add (a, b, &t)) != MP_OKAY) {
  843. mp_clear (&t);
  844. return res;
  845. }
  846. res = mp_mod (&t, c, d);
  847. mp_clear (&t);
  848. return res;
  849. }
  850. #endif
  851. /* End: bn_mp_addmod.c */
  852. /* Start: bn_mp_and.c */
  853. #include <ltc_tommath.h>
  854. #ifdef BN_MP_AND_C
  855. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  856. *
  857. * LibTomMath is a library that provides multiple-precision
  858. * integer arithmetic as well as number theoretic functionality.
  859. *
  860. * The library was designed directly after the MPI library by
  861. * Michael Fromberger but has been written from scratch with
  862. * additional optimizations in place.
  863. *
  864. * The library is free for all purposes without any express
  865. * guarantee it works.
  866. *
  867. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  868. */
  869. /* AND two ints together */
  870. int
  871. mp_and (mp_int * a, mp_int * b, mp_int * c)
  872. {
  873. int res, ix, px;
  874. mp_int t, *x;
  875. if (a->used > b->used) {
  876. if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
  877. return res;
  878. }
  879. px = b->used;
  880. x = b;
  881. } else {
  882. if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
  883. return res;
  884. }
  885. px = a->used;
  886. x = a;
  887. }
  888. for (ix = 0; ix < px; ix++) {
  889. t.dp[ix] &= x->dp[ix];
  890. }
  891. /* zero digits above the last from the smallest mp_int */
  892. for (; ix < t.used; ix++) {
  893. t.dp[ix] = 0;
  894. }
  895. mp_clamp (&t);
  896. mp_exch (c, &t);
  897. mp_clear (&t);
  898. return MP_OKAY;
  899. }
  900. #endif
  901. /* End: bn_mp_and.c */
  902. /* Start: bn_mp_clamp.c */
  903. #include <ltc_tommath.h>
  904. #ifdef BN_MP_CLAMP_C
  905. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  906. *
  907. * LibTomMath is a library that provides multiple-precision
  908. * integer arithmetic as well as number theoretic functionality.
  909. *
  910. * The library was designed directly after the MPI library by
  911. * Michael Fromberger but has been written from scratch with
  912. * additional optimizations in place.
  913. *
  914. * The library is free for all purposes without any express
  915. * guarantee it works.
  916. *
  917. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  918. */
  919. /* trim unused digits
  920. *
  921. * This is used to ensure that leading zero digits are
  922. * trimed and the leading "used" digit will be non-zero
  923. * Typically very fast. Also fixes the sign if there
  924. * are no more leading digits
  925. */
  926. void
  927. mp_clamp (mp_int * a)
  928. {
  929. /* decrease used while the most significant digit is
  930. * zero.
  931. */
  932. while (a->used > 0 && a->dp[a->used - 1] == 0) {
  933. --(a->used);
  934. }
  935. /* reset the sign flag if used == 0 */
  936. if (a->used == 0) {
  937. a->sign = MP_ZPOS;
  938. }
  939. }
  940. #endif
  941. /* End: bn_mp_clamp.c */
  942. /* Start: bn_mp_clear.c */
  943. #include <ltc_tommath.h>
  944. #ifdef BN_MP_CLEAR_C
  945. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  946. *
  947. * LibTomMath is a library that provides multiple-precision
  948. * integer arithmetic as well as number theoretic functionality.
  949. *
  950. * The library was designed directly after the MPI library by
  951. * Michael Fromberger but has been written from scratch with
  952. * additional optimizations in place.
  953. *
  954. * The library is free for all purposes without any express
  955. * guarantee it works.
  956. *
  957. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  958. */
  959. /* clear one (frees) */
  960. void
  961. mp_clear (mp_int * a)
  962. {
  963. int i;
  964. /* only do anything if a hasn't been freed previously */
  965. if (a->dp != NULL) {
  966. /* first zero the digits */
  967. for (i = 0; i < a->used; i++) {
  968. a->dp[i] = 0;
  969. }
  970. /* free ram */
  971. XFREE(a->dp);
  972. /* reset members to make debugging easier */
  973. a->dp = NULL;
  974. a->alloc = a->used = 0;
  975. a->sign = MP_ZPOS;
  976. }
  977. }
  978. #endif
  979. /* End: bn_mp_clear.c */
  980. /* Start: bn_mp_clear_multi.c */
  981. #include <ltc_tommath.h>
  982. #ifdef BN_MP_CLEAR_MULTI_C
  983. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  984. *
  985. * LibTomMath is a library that provides multiple-precision
  986. * integer arithmetic as well as number theoretic functionality.
  987. *
  988. * The library was designed directly after the MPI library by
  989. * Michael Fromberger but has been written from scratch with
  990. * additional optimizations in place.
  991. *
  992. * The library is free for all purposes without any express
  993. * guarantee it works.
  994. *
  995. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  996. */
  997. #include <stdarg.h>
  998. void mp_clear_multi(mp_int *mp, ...)
  999. {
  1000. mp_int* next_mp = mp;
  1001. va_list args;
  1002. va_start(args, mp);
  1003. while (next_mp != NULL) {
  1004. mp_clear(next_mp);
  1005. next_mp = va_arg(args, mp_int*);
  1006. }
  1007. va_end(args);
  1008. }
  1009. #endif
  1010. /* End: bn_mp_clear_multi.c */
  1011. /* Start: bn_mp_cmp.c */
  1012. #include <ltc_tommath.h>
  1013. #ifdef BN_MP_CMP_C
  1014. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  1015. *
  1016. * LibTomMath is a library that provides multiple-precision
  1017. * integer arithmetic as well as number theoretic functionality.
  1018. *
  1019. * The library was designed directly after the MPI library by
  1020. * Michael Fromberger but has been written from scratch with
  1021. * additional optimizations in place.
  1022. *
  1023. * The library is free for all purposes without any express
  1024. * guarantee it works.
  1025. *
  1026. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  1027. */
  1028. /* compare two ints (signed)*/
  1029. int
  1030. mp_cmp (mp_int * a, mp_int * b)
  1031. {
  1032. /* compare based on sign */
  1033. if (a->sign != b->sign) {
  1034. if (a->sign == MP_NEG) {
  1035. return MP_LT;
  1036. } else {
  1037. return MP_GT;
  1038. }
  1039. }
  1040. /* compare digits */
  1041. if (a->sign == MP_NEG) {
  1042. /* if negative compare opposite direction */
  1043. return mp_cmp_mag(b, a);
  1044. } else {
  1045. return mp_cmp_mag(a, b);
  1046. }
  1047. }
  1048. #endif
  1049. /* End: bn_mp_cmp.c */
  1050. /* Start: bn_mp_cmp_d.c */
  1051. #include <ltc_tommath.h>
  1052. #ifdef BN_MP_CMP_D_C
  1053. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  1054. *
  1055. * LibTomMath is a library that provides multiple-precision
  1056. * integer arithmetic as well as number theoretic functionality.
  1057. *
  1058. * The library was designed directly after the MPI library by
  1059. * Michael Fromberger but has been written from scratch with
  1060. * additional optimizations in place.
  1061. *
  1062. * The library is free for all purposes without any express
  1063. * guarantee it works.
  1064. *
  1065. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  1066. */
  1067. /* compare a digit */
  1068. int mp_cmp_d(mp_int * a, mp_digit b)
  1069. {
  1070. /* compare based on sign */
  1071. if (a->sign == MP_NEG) {
  1072. return MP_LT;
  1073. }
  1074. /* compare based on magnitude */
  1075. if (a->used > 1) {
  1076. return MP_GT;
  1077. }
  1078. /* compare the only digit of a to b */
  1079. if (a->dp[0] > b) {
  1080. return MP_GT;
  1081. } else if (a->dp[0] < b) {
  1082. return MP_LT;
  1083. } else {
  1084. return MP_EQ;
  1085. }
  1086. }
  1087. #endif
  1088. /* End: bn_mp_cmp_d.c */
  1089. /* Start: bn_mp_cmp_mag.c */
  1090. #include <ltc_tommath.h>
  1091. #ifdef BN_MP_CMP_MAG_C
  1092. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  1093. *
  1094. * LibTomMath is a library that provides multiple-precision
  1095. * integer arithmetic as well as number theoretic functionality.
  1096. *
  1097. * The library was designed directly after the MPI library by
  1098. * Michael Fromberger but has been written from scratch with
  1099. * additional optimizations in place.
  1100. *
  1101. * The library is free for all purposes without any express
  1102. * guarantee it works.
  1103. *
  1104. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  1105. */
  1106. /* compare maginitude of two ints (unsigned) */
  1107. int mp_cmp_mag (mp_int * a, mp_int * b)
  1108. {
  1109. int n;
  1110. mp_digit *tmpa, *tmpb;
  1111. /* compare based on # of non-zero digits */
  1112. if (a->used > b->used) {
  1113. return MP_GT;
  1114. }
  1115. if (a->used < b->used) {
  1116. return MP_LT;
  1117. }
  1118. /* alias for a */
  1119. tmpa = a->dp + (a->used - 1);
  1120. /* alias for b */
  1121. tmpb = b->dp + (a->used - 1);
  1122. /* compare based on digits */
  1123. for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
  1124. if (*tmpa > *tmpb) {
  1125. return MP_GT;
  1126. }
  1127. if (*tmpa < *tmpb) {
  1128. return MP_LT;
  1129. }
  1130. }
  1131. return MP_EQ;
  1132. }
  1133. #endif
  1134. /* End: bn_mp_cmp_mag.c */
  1135. /* Start: bn_mp_cnt_lsb.c */
  1136. #include <ltc_tommath.h>
  1137. #ifdef BN_MP_CNT_LSB_C
  1138. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  1139. *
  1140. * LibTomMath is a library that provides multiple-precision
  1141. * integer arithmetic as well as number theoretic functionality.
  1142. *
  1143. * The library was designed directly after the MPI library by
  1144. * Michael Fromberger but has been written from scratch with
  1145. * additional optimizations in place.
  1146. *
  1147. * The library is free for all purposes without any express
  1148. * guarantee it works.
  1149. *
  1150. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  1151. */
  1152. static const int lnz[16] = {
  1153. 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
  1154. };
  1155. /* Counts the number of lsbs which are zero before the first zero bit */
  1156. int mp_cnt_lsb(mp_int *a)
  1157. {
  1158. int x;
  1159. mp_digit q, qq;
  1160. /* easy out */
  1161. if (mp_iszero(a) == 1) {
  1162. return 0;
  1163. }
  1164. /* scan lower digits until non-zero */
  1165. for (x = 0; x < a->used && a->dp[x] == 0; x++);
  1166. q = a->dp[x];
  1167. x *= DIGIT_BIT;
  1168. /* now scan this digit until a 1 is found */
  1169. if ((q & 1) == 0) {
  1170. do {
  1171. qq = q & 15;
  1172. x += lnz[qq];
  1173. q >>= 4;
  1174. } while (qq == 0);
  1175. }
  1176. return x;
  1177. }
  1178. #endif
  1179. /* End: bn_mp_cnt_lsb.c */
  1180. /* Start: bn_mp_copy.c */
  1181. #include <ltc_tommath.h>
  1182. #ifdef BN_MP_COPY_C
  1183. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  1184. *
  1185. * LibTomMath is a library that provides multiple-precision
  1186. * integer arithmetic as well as number theoretic functionality.
  1187. *
  1188. * The library was designed directly after the MPI library by
  1189. * Michael Fromberger but has been written from scratch with
  1190. * additional optimizations in place.
  1191. *
  1192. * The library is free for all purposes without any express
  1193. * guarantee it works.
  1194. *
  1195. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  1196. */
  1197. /* copy, b = a */
  1198. int
  1199. mp_copy (mp_int * a, mp_int * b)
  1200. {
  1201. int res, n;
  1202. /* if dst == src do nothing */
  1203. if (a == b) {
  1204. return MP_OKAY;
  1205. }
  1206. /* grow dest */
  1207. if (b->alloc < a->used) {
  1208. if ((res = mp_grow (b, a->used)) != MP_OKAY) {
  1209. return res;
  1210. }
  1211. }
  1212. /* zero b and copy the parameters over */
  1213. {
  1214. register mp_digit *tmpa, *tmpb;
  1215. /* pointer aliases */
  1216. /* source */
  1217. tmpa = a->dp;
  1218. /* destination */
  1219. tmpb = b->dp;
  1220. /* copy all the digits */
  1221. for (n = 0; n < a->used; n++) {
  1222. *tmpb++ = *tmpa++;
  1223. }
  1224. /* clear high digits */
  1225. for (; n < b->used; n++) {
  1226. *tmpb++ = 0;
  1227. }
  1228. }
  1229. /* copy used count and sign */
  1230. b->used = a->used;
  1231. b->sign = a->sign;
  1232. return MP_OKAY;
  1233. }
  1234. #endif
  1235. /* End: bn_mp_copy.c */
  1236. /* Start: bn_mp_count_bits.c */
  1237. #include <ltc_tommath.h>
  1238. #ifdef BN_MP_COUNT_BITS_C
  1239. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  1240. *
  1241. * LibTomMath is a library that provides multiple-precision
  1242. * integer arithmetic as well as number theoretic functionality.
  1243. *
  1244. * The library was designed directly after the MPI library by
  1245. * Michael Fromberger but has been written from scratch with
  1246. * additional optimizations in place.
  1247. *
  1248. * The library is free for all purposes without any express
  1249. * guarantee it works.
  1250. *
  1251. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  1252. */
  1253. /* returns the number of bits in an int */
  1254. int
  1255. mp_count_bits (mp_int * a)
  1256. {
  1257. int r;
  1258. mp_digit q;
  1259. /* shortcut */
  1260. if (a->used == 0) {
  1261. return 0;
  1262. }
  1263. /* get number of digits and add that */
  1264. r = (a->used - 1) * DIGIT_BIT;
  1265. /* take the last digit and count the bits in it */
  1266. q = a->dp[a->used - 1];
  1267. while (q > ((mp_digit) 0)) {
  1268. ++r;
  1269. q >>= ((mp_digit) 1);
  1270. }
  1271. return r;
  1272. }
  1273. #endif
  1274. /* End: bn_mp_count_bits.c */
  1275. /* Start: bn_mp_div.c */
  1276. #include <ltc_tommath.h>
  1277. #ifdef BN_MP_DIV_C
  1278. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  1279. *
  1280. * LibTomMath is a library that provides multiple-precision
  1281. * integer arithmetic as well as number theoretic functionality.
  1282. *
  1283. * The library was designed directly after the MPI library by
  1284. * Michael Fromberger but has been written from scratch with
  1285. * additional optimizations in place.
  1286. *
  1287. * The library is free for all purposes without any express
  1288. * guarantee it works.
  1289. *
  1290. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  1291. */
  1292. #ifdef BN_MP_DIV_SMALL
  1293. /* slower bit-bang division... also smaller */
  1294. int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
  1295. {
  1296. mp_int ta, tb, tq, q;
  1297. int res, n, n2;
  1298. /* is divisor zero ? */
  1299. if (mp_iszero (b) == 1) {
  1300. return MP_VAL;
  1301. }
  1302. /* if a < b then q=0, r = a */
  1303. if (mp_cmp_mag (a, b) == MP_LT) {
  1304. if (d != NULL) {
  1305. res = mp_copy (a, d);
  1306. } else {
  1307. res = MP_OKAY;
  1308. }
  1309. if (c != NULL) {
  1310. mp_zero (c);
  1311. }
  1312. return res;
  1313. }
  1314. /* init our temps */
  1315. if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) {
  1316. return res;
  1317. }
  1318. mp_set(&tq, 1);
  1319. n = mp_count_bits(a) - mp_count_bits(b);
  1320. if (((res = mp_copy(a, &ta)) != MP_OKAY) ||
  1321. ((res = mp_copy(b, &tb)) != MP_OKAY) ||
  1322. ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) ||
  1323. ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) {
  1324. goto __ERR;
  1325. }
  1326. while (n-- >= 0) {
  1327. if (mp_cmp(&tb, &ta) != MP_GT) {
  1328. if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) ||
  1329. ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) {
  1330. goto __ERR;
  1331. }
  1332. }
  1333. if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) ||
  1334. ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) {
  1335. goto __ERR;
  1336. }
  1337. }
  1338. /* now q == quotient and ta == remainder */
  1339. n = a->sign;
  1340. n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG);
  1341. if (c != NULL) {
  1342. mp_exch(c, &q);
  1343. c->sign = n2;
  1344. }
  1345. if (d != NULL) {
  1346. mp_exch(d, &ta);
  1347. d->sign = n;
  1348. }
  1349. __ERR:
  1350. mp_clear_multi(&ta, &tb, &tq, &q, NULL);
  1351. return res;
  1352. }
  1353. #else
  1354. /* integer signed division.
  1355. * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
  1356. * HAC pp.598 Algorithm 14.20
  1357. *
  1358. * Note that the description in HAC is horribly
  1359. * incomplete. For example, it doesn't consider
  1360. * the case where digits are removed from 'x' in
  1361. * the inner loop. It also doesn't consider the
  1362. * case that y has fewer than three digits, etc..
  1363. *
  1364. * The overall algorithm is as described as
  1365. * 14.20 from HAC but fixed to treat these cases.
  1366. */
  1367. int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
  1368. {
  1369. mp_int q, x, y, t1, t2;
  1370. int res, n, t, i, norm, neg;
  1371. /* is divisor zero ? */
  1372. if (mp_iszero (b) == 1) {
  1373. return MP_VAL;
  1374. }
  1375. /* if a < b then q=0, r = a */
  1376. if (mp_cmp_mag (a, b) == MP_LT) {
  1377. if (d != NULL) {
  1378. res = mp_copy (a, d);
  1379. } else {
  1380. res = MP_OKAY;
  1381. }
  1382. if (c != NULL) {
  1383. mp_zero (c);
  1384. }
  1385. return res;
  1386. }
  1387. if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) {
  1388. return res;
  1389. }
  1390. q.used = a->used + 2;
  1391. if ((res = mp_init (&t1)) != MP_OKAY) {
  1392. goto __Q;
  1393. }
  1394. if ((res = mp_init (&t2)) != MP_OKAY) {
  1395. goto __T1;
  1396. }
  1397. if ((res = mp_init_copy (&x, a)) != MP_OKAY) {
  1398. goto __T2;
  1399. }
  1400. if ((res = mp_init_copy (&y, b)) != MP_OKAY) {
  1401. goto __X;
  1402. }
  1403. /* fix the sign */
  1404. neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
  1405. x.sign = y.sign = MP_ZPOS;
  1406. /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
  1407. norm = mp_count_bits(&y) % DIGIT_BIT;
  1408. if (norm < (int)(DIGIT_BIT-1)) {
  1409. norm = (DIGIT_BIT-1) - norm;
  1410. if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) {
  1411. goto __Y;
  1412. }
  1413. if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) {
  1414. goto __Y;
  1415. }
  1416. } else {
  1417. norm = 0;
  1418. }
  1419. /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
  1420. n = x.used - 1;
  1421. t = y.used - 1;
  1422. /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
  1423. if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */
  1424. goto __Y;
  1425. }
  1426. while (mp_cmp (&x, &y) != MP_LT) {
  1427. ++(q.dp[n - t]);
  1428. if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) {
  1429. goto __Y;
  1430. }
  1431. }
  1432. /* reset y by shifting it back down */
  1433. mp_rshd (&y, n - t);
  1434. /* step 3. for i from n down to (t + 1) */
  1435. for (i = n; i >= (t + 1); i--) {
  1436. if (i > x.used) {
  1437. continue;
  1438. }
  1439. /* step 3.1 if xi == yt then set q{i-t-1} to b-1,
  1440. * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
  1441. if (x.dp[i] == y.dp[t]) {
  1442. q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1);
  1443. } else {
  1444. mp_word tmp;
  1445. tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT);
  1446. tmp |= ((mp_word) x.dp[i - 1]);
  1447. tmp /= ((mp_word) y.dp[t]);
  1448. if (tmp > (mp_word) MP_MASK)
  1449. tmp = MP_MASK;
  1450. q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK));
  1451. }
  1452. /* while (q{i-t-1} * (yt * b + y{t-1})) >
  1453. xi * b**2 + xi-1 * b + xi-2
  1454. do q{i-t-1} -= 1;
  1455. */
  1456. q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK;
  1457. do {
  1458. q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK;
  1459. /* find left hand */
  1460. mp_zero (&t1);
  1461. t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
  1462. t1.dp[1] = y.dp[t];
  1463. t1.used = 2;
  1464. if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) {
  1465. goto __Y;
  1466. }
  1467. /* find right hand */
  1468. t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
  1469. t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
  1470. t2.dp[2] = x.dp[i];
  1471. t2.used = 3;
  1472. } while (mp_cmp_mag(&t1, &t2) == MP_GT);
  1473. /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
  1474. if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) {
  1475. goto __Y;
  1476. }
  1477. if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
  1478. goto __Y;
  1479. }
  1480. if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) {
  1481. goto __Y;
  1482. }
  1483. /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
  1484. if (x.sign == MP_NEG) {
  1485. if ((res = mp_copy (&y, &t1)) != MP_OKAY) {
  1486. goto __Y;
  1487. }
  1488. if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
  1489. goto __Y;
  1490. }
  1491. if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) {
  1492. goto __Y;
  1493. }
  1494. q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK;
  1495. }
  1496. }
  1497. /* now q is the quotient and x is the remainder
  1498. * [which we have to normalize]
  1499. */
  1500. /* get sign before writing to c */
  1501. x.sign = x.used == 0 ? MP_ZPOS : a->sign;
  1502. if (c != NULL) {
  1503. mp_clamp (&q);
  1504. mp_exch (&q, c);
  1505. c->sign = neg;
  1506. }
  1507. if (d != NULL) {
  1508. mp_div_2d (&x, norm, &x, NULL);
  1509. mp_exch (&x, d);
  1510. }
  1511. res = MP_OKAY;
  1512. __Y:mp_clear (&y);
  1513. __X:mp_clear (&x);
  1514. __T2:mp_clear (&t2);
  1515. __T1:mp_clear (&t1);
  1516. __Q:mp_clear (&q);
  1517. return res;
  1518. }
  1519. #endif
  1520. #endif
  1521. /* End: bn_mp_div.c */
  1522. /* Start: bn_mp_div_2.c */
  1523. #include <ltc_tommath.h>
  1524. #ifdef BN_MP_DIV_2_C
  1525. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  1526. *
  1527. * LibTomMath is a library that provides multiple-precision
  1528. * integer arithmetic as well as number theoretic functionality.
  1529. *
  1530. * The library was designed directly after the MPI library by
  1531. * Michael Fromberger but has been written from scratch with
  1532. * additional optimizations in place.
  1533. *
  1534. * The library is free for all purposes without any express
  1535. * guarantee it works.
  1536. *
  1537. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  1538. */
  1539. /* b = a/2 */
  1540. int mp_div_2(mp_int * a, mp_int * b)
  1541. {
  1542. int x, res, oldused;
  1543. /* copy */
  1544. if (b->alloc < a->used) {
  1545. if ((res = mp_grow (b, a->used)) != MP_OKAY) {
  1546. return res;
  1547. }
  1548. }
  1549. oldused = b->used;
  1550. b->used = a->used;
  1551. {
  1552. register mp_digit r, rr, *tmpa, *tmpb;
  1553. /* source alias */
  1554. tmpa = a->dp + b->used - 1;
  1555. /* dest alias */
  1556. tmpb = b->dp + b->used - 1;
  1557. /* carry */
  1558. r = 0;
  1559. for (x = b->used - 1; x >= 0; x--) {
  1560. /* get the carry for the next iteration */
  1561. rr = *tmpa & 1;
  1562. /* shift the current digit, add in carry and store */
  1563. *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
  1564. /* forward carry to next iteration */
  1565. r = rr;
  1566. }
  1567. /* zero excess digits */
  1568. tmpb = b->dp + b->used;
  1569. for (x = b->used; x < oldused; x++) {
  1570. *tmpb++ = 0;
  1571. }
  1572. }
  1573. b->sign = a->sign;
  1574. mp_clamp (b);
  1575. return MP_OKAY;
  1576. }
  1577. #endif
  1578. /* End: bn_mp_div_2.c */
  1579. /* Start: bn_mp_div_2d.c */
  1580. #include <ltc_tommath.h>
  1581. #ifdef BN_MP_DIV_2D_C
  1582. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  1583. *
  1584. * LibTomMath is a library that provides multiple-precision
  1585. * integer arithmetic as well as number theoretic functionality.
  1586. *
  1587. * The library was designed directly after the MPI library by
  1588. * Michael Fromberger but has been written from scratch with
  1589. * additional optimizations in place.
  1590. *
  1591. * The library is free for all purposes without any express
  1592. * guarantee it works.
  1593. *
  1594. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  1595. */
  1596. /* shift right by a certain bit count (store quotient in c, optional remainder in d) */
  1597. int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
  1598. {
  1599. mp_digit D, r, rr;
  1600. int x, res;
  1601. mp_int t;
  1602. /* if the shift count is <= 0 then we do no work */
  1603. if (b <= 0) {
  1604. res = mp_copy (a, c);
  1605. if (d != NULL) {
  1606. mp_zero (d);
  1607. }
  1608. return res;
  1609. }
  1610. if ((res = mp_init (&t)) != MP_OKAY) {
  1611. return res;
  1612. }
  1613. /* get the remainder */
  1614. if (d != NULL) {
  1615. if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) {
  1616. mp_clear (&t);
  1617. return res;
  1618. }
  1619. }
  1620. /* copy */
  1621. if ((res = mp_copy (a, c)) != MP_OKAY) {
  1622. mp_clear (&t);
  1623. return res;
  1624. }
  1625. /* shift by as many digits in the bit count */
  1626. if (b >= (int)DIGIT_BIT) {
  1627. mp_rshd (c, b / DIGIT_BIT);
  1628. }
  1629. /* shift any bit count < DIGIT_BIT */
  1630. D = (mp_digit) (b % DIGIT_BIT);
  1631. if (D != 0) {
  1632. register mp_digit *tmpc, mask, shift;
  1633. /* mask */
  1634. mask = (((mp_digit)1) << D) - 1;
  1635. /* shift for lsb */
  1636. shift = DIGIT_BIT - D;
  1637. /* alias */
  1638. tmpc = c->dp + (c->used - 1);
  1639. /* carry */
  1640. r = 0;
  1641. for (x = c->used - 1; x >= 0; x--) {
  1642. /* get the lower bits of this word in a temp */
  1643. rr = *tmpc & mask;
  1644. /* shift the current word and mix in the carry bits from the previous word */
  1645. *tmpc = (*tmpc >> D) | (r << shift);
  1646. --tmpc;
  1647. /* set the carry to the carry bits of the current word found above */
  1648. r = rr;
  1649. }
  1650. }
  1651. mp_clamp (c);
  1652. if (d != NULL) {
  1653. mp_exch (&t, d);
  1654. }
  1655. mp_clear (&t);
  1656. return MP_OKAY;
  1657. }
  1658. #endif
  1659. /* End: bn_mp_div_2d.c */
  1660. /* Start: bn_mp_div_3.c */
  1661. #include <ltc_tommath.h>
  1662. #ifdef BN_MP_DIV_3_C
  1663. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  1664. *
  1665. * LibTomMath is a library that provides multiple-precision
  1666. * integer arithmetic as well as number theoretic functionality.
  1667. *
  1668. * The library was designed directly after the MPI library by
  1669. * Michael Fromberger but has been written from scratch with
  1670. * additional optimizations in place.
  1671. *
  1672. * The library is free for all purposes without any express
  1673. * guarantee it works.
  1674. *
  1675. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  1676. */
  1677. /* divide by three (based on routine from MPI and the GMP manual) */
  1678. int
  1679. mp_div_3 (mp_int * a, mp_int *c, mp_digit * d)
  1680. {
  1681. mp_int q;
  1682. mp_word w, t;
  1683. mp_digit b;
  1684. int res, ix;
  1685. /* b = 2**DIGIT_BIT / 3 */
  1686. b = (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3);
  1687. if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
  1688. return res;
  1689. }
  1690. q.used = a->used;
  1691. q.sign = a->sign;
  1692. w = 0;
  1693. for (ix = a->used - 1; ix >= 0; ix--) {
  1694. w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
  1695. if (w >= 3) {
  1696. /* multiply w by [1/3] */
  1697. t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT);
  1698. /* now subtract 3 * [w/3] from w, to get the remainder */
  1699. w -= t+t+t;
  1700. /* fixup the remainder as required since
  1701. * the optimization is not exact.
  1702. */
  1703. while (w >= 3) {
  1704. t += 1;
  1705. w -= 3;
  1706. }
  1707. } else {
  1708. t = 0;
  1709. }
  1710. q.dp[ix] = (mp_digit)t;
  1711. }
  1712. /* [optional] store the remainder */
  1713. if (d != NULL) {
  1714. *d = (mp_digit)w;
  1715. }
  1716. /* [optional] store the quotient */
  1717. if (c != NULL) {
  1718. mp_clamp(&q);
  1719. mp_exch(&q, c);
  1720. }
  1721. mp_clear(&q);
  1722. return res;
  1723. }
  1724. #endif
  1725. /* End: bn_mp_div_3.c */
  1726. /* Start: bn_mp_div_d.c */
  1727. #include <ltc_tommath.h>
  1728. #ifdef BN_MP_DIV_D_C
  1729. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  1730. *
  1731. * LibTomMath is a library that provides multiple-precision
  1732. * integer arithmetic as well as number theoretic functionality.
  1733. *
  1734. * The library was designed directly after the MPI library by
  1735. * Michael Fromberger but has been written from scratch with
  1736. * additional optimizations in place.
  1737. *
  1738. * The library is free for all purposes without any express
  1739. * guarantee it works.
  1740. *
  1741. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  1742. */
  1743. static int s_is_power_of_two(mp_digit b, int *p)
  1744. {
  1745. int x;
  1746. for (x = 1; x < DIGIT_BIT; x++) {
  1747. if (b == (((mp_digit)1)<<x)) {
  1748. *p = x;
  1749. return 1;
  1750. }
  1751. }
  1752. return 0;
  1753. }
  1754. /* single digit division (based on routine from MPI) */
  1755. int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
  1756. {
  1757. mp_int q;
  1758. mp_word w;
  1759. mp_digit t;
  1760. int res, ix;
  1761. /* cannot divide by zero */
  1762. if (b == 0) {
  1763. return MP_VAL;
  1764. }
  1765. /* quick outs */
  1766. if (b == 1 || mp_iszero(a) == 1) {
  1767. if (d != NULL) {
  1768. *d = 0;
  1769. }
  1770. if (c != NULL) {
  1771. return mp_copy(a, c);
  1772. }
  1773. return MP_OKAY;
  1774. }
  1775. /* power of two ? */
  1776. if (s_is_power_of_two(b, &ix) == 1) {
  1777. if (d != NULL) {
  1778. *d = a->dp[0] & ((((mp_digit)1)<<ix) - 1);
  1779. }
  1780. if (c != NULL) {
  1781. return mp_div_2d(a, ix, c, NULL);
  1782. }
  1783. return MP_OKAY;
  1784. }
  1785. #ifdef BN_MP_DIV_3_C
  1786. /* three? */
  1787. if (b == 3) {
  1788. return mp_div_3(a, c, d);
  1789. }
  1790. #endif
  1791. /* no easy answer [c'est la vie]. Just division */
  1792. if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
  1793. return res;
  1794. }
  1795. q.used = a->used;
  1796. q.sign = a->sign;
  1797. w = 0;
  1798. for (ix = a->used - 1; ix >= 0; ix--) {
  1799. w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
  1800. if (w >= b) {
  1801. t = (mp_digit)(w / b);
  1802. w -= ((mp_word)t) * ((mp_word)b);
  1803. } else {
  1804. t = 0;
  1805. }
  1806. q.dp[ix] = (mp_digit)t;
  1807. }
  1808. if (d != NULL) {
  1809. *d = (mp_digit)w;
  1810. }
  1811. if (c != NULL) {
  1812. mp_clamp(&q);
  1813. mp_exch(&q, c);
  1814. }
  1815. mp_clear(&q);
  1816. return res;
  1817. }
  1818. #endif
  1819. /* End: bn_mp_div_d.c */
  1820. /* Start: bn_mp_dr_is_modulus.c */
  1821. #include <ltc_tommath.h>
  1822. #ifdef BN_MP_DR_IS_MODULUS_C
  1823. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  1824. *
  1825. * LibTomMath is a library that provides multiple-precision
  1826. * integer arithmetic as well as number theoretic functionality.
  1827. *
  1828. * The library was designed directly after the MPI library by
  1829. * Michael Fromberger but has been written from scratch with
  1830. * additional optimizations in place.
  1831. *
  1832. * The library is free for all purposes without any express
  1833. * guarantee it works.
  1834. *
  1835. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  1836. */
  1837. /* determines if a number is a valid DR modulus */
  1838. int mp_dr_is_modulus(mp_int *a)
  1839. {
  1840. int ix;
  1841. /* must be at least two digits */
  1842. if (a->used < 2) {
  1843. return 0;
  1844. }
  1845. /* must be of the form b**k - a [a <= b] so all
  1846. * but the first digit must be equal to -1 (mod b).
  1847. */
  1848. for (ix = 1; ix < a->used; ix++) {
  1849. if (a->dp[ix] != MP_MASK) {
  1850. return 0;
  1851. }
  1852. }
  1853. return 1;
  1854. }
  1855. #endif
  1856. /* End: bn_mp_dr_is_modulus.c */
  1857. /* Start: bn_mp_dr_reduce.c */
  1858. #include <ltc_tommath.h>
  1859. #ifdef BN_MP_DR_REDUCE_C
  1860. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  1861. *
  1862. * LibTomMath is a library that provides multiple-precision
  1863. * integer arithmetic as well as number theoretic functionality.
  1864. *
  1865. * The library was designed directly after the MPI library by
  1866. * Michael Fromberger but has been written from scratch with
  1867. * additional optimizations in place.
  1868. *
  1869. * The library is free for all purposes without any express
  1870. * guarantee it works.
  1871. *
  1872. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  1873. */
  1874. /* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
  1875. *
  1876. * Based on algorithm from the paper
  1877. *
  1878. * "Generating Efficient Primes for Discrete Log Cryptosystems"
  1879. * Chae Hoon Lim, Pil Loong Lee,
  1880. * POSTECH Information Research Laboratories
  1881. *
  1882. * The modulus must be of a special format [see manual]
  1883. *
  1884. * Has been modified to use algorithm 7.10 from the LTM book instead
  1885. *
  1886. * Input x must be in the range 0 <= x <= (n-1)**2
  1887. */
  1888. int
  1889. mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k)
  1890. {
  1891. int err, i, m;
  1892. mp_word r;
  1893. mp_digit mu, *tmpx1, *tmpx2;
  1894. /* m = digits in modulus */
  1895. m = n->used;
  1896. /* ensure that "x" has at least 2m digits */
  1897. if (x->alloc < m + m) {
  1898. if ((err = mp_grow (x, m + m)) != MP_OKAY) {
  1899. return err;
  1900. }
  1901. }
  1902. /* top of loop, this is where the code resumes if
  1903. * another reduction pass is required.
  1904. */
  1905. top:
  1906. /* aliases for digits */
  1907. /* alias for lower half of x */
  1908. tmpx1 = x->dp;
  1909. /* alias for upper half of x, or x/B**m */
  1910. tmpx2 = x->dp + m;
  1911. /* set carry to zero */
  1912. mu = 0;
  1913. /* compute (x mod B**m) + k * [x/B**m] inline and inplace */
  1914. for (i = 0; i < m; i++) {
  1915. r = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu;
  1916. *tmpx1++ = (mp_digit)(r & MP_MASK);
  1917. mu = (mp_digit)(r >> ((mp_word)DIGIT_BIT));
  1918. }
  1919. /* set final carry */
  1920. *tmpx1++ = mu;
  1921. /* zero words above m */
  1922. for (i = m + 1; i < x->used; i++) {
  1923. *tmpx1++ = 0;
  1924. }
  1925. /* clamp, sub and return */
  1926. mp_clamp (x);
  1927. /* if x >= n then subtract and reduce again
  1928. * Each successive "recursion" makes the input smaller and smaller.
  1929. */
  1930. if (mp_cmp_mag (x, n) != MP_LT) {
  1931. s_mp_sub(x, n, x);
  1932. goto top;
  1933. }
  1934. return MP_OKAY;
  1935. }
  1936. #endif
  1937. /* End: bn_mp_dr_reduce.c */
  1938. /* Start: bn_mp_dr_setup.c */
  1939. #include <ltc_tommath.h>
  1940. #ifdef BN_MP_DR_SETUP_C
  1941. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  1942. *
  1943. * LibTomMath is a library that provides multiple-precision
  1944. * integer arithmetic as well as number theoretic functionality.
  1945. *
  1946. * The library was designed directly after the MPI library by
  1947. * Michael Fromberger but has been written from scratch with
  1948. * additional optimizations in place.
  1949. *
  1950. * The library is free for all purposes without any express
  1951. * guarantee it works.
  1952. *
  1953. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  1954. */
  1955. /* determines the setup value */
  1956. void mp_dr_setup(mp_int *a, mp_digit *d)
  1957. {
  1958. /* the casts are required if DIGIT_BIT is one less than
  1959. * the number of bits in a mp_digit [e.g. DIGIT_BIT==31]
  1960. */
  1961. *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) -
  1962. ((mp_word)a->dp[0]));
  1963. }
  1964. #endif
  1965. /* End: bn_mp_dr_setup.c */
  1966. /* Start: bn_mp_exch.c */
  1967. #include <ltc_tommath.h>
  1968. #ifdef BN_MP_EXCH_C
  1969. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  1970. *
  1971. * LibTomMath is a library that provides multiple-precision
  1972. * integer arithmetic as well as number theoretic functionality.
  1973. *
  1974. * The library was designed directly after the MPI library by
  1975. * Michael Fromberger but has been written from scratch with
  1976. * additional optimizations in place.
  1977. *
  1978. * The library is free for all purposes without any express
  1979. * guarantee it works.
  1980. *
  1981. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  1982. */
  1983. /* swap the elements of two integers, for cases where you can't simply swap the
  1984. * mp_int pointers around
  1985. */
  1986. void
  1987. mp_exch (mp_int * a, mp_int * b)
  1988. {
  1989. mp_int t;
  1990. t = *a;
  1991. *a = *b;
  1992. *b = t;
  1993. }
  1994. #endif
  1995. /* End: bn_mp_exch.c */
  1996. /* Start: bn_mp_expt_d.c */
  1997. #include <ltc_tommath.h>
  1998. #ifdef BN_MP_EXPT_D_C
  1999. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  2000. *
  2001. * LibTomMath is a library that provides multiple-precision
  2002. * integer arithmetic as well as number theoretic functionality.
  2003. *
  2004. * The library was designed directly after the MPI library by
  2005. * Michael Fromberger but has been written from scratch with
  2006. * additional optimizations in place.
  2007. *
  2008. * The library is free for all purposes without any express
  2009. * guarantee it works.
  2010. *
  2011. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  2012. */
  2013. /* calculate c = a**b using a square-multiply algorithm */
  2014. int mp_expt_d (mp_int * a, mp_digit b, mp_int * c)
  2015. {
  2016. int res, x;
  2017. mp_int g;
  2018. if ((res = mp_init_copy (&g, a)) != MP_OKAY) {
  2019. return res;
  2020. }
  2021. /* set initial result */
  2022. mp_set (c, 1);
  2023. for (x = 0; x < (int) DIGIT_BIT; x++) {
  2024. /* square */
  2025. if ((res = mp_sqr (c, c)) != MP_OKAY) {
  2026. mp_clear (&g);
  2027. return res;
  2028. }
  2029. /* if the bit is set multiply */
  2030. if ((b & (mp_digit) (((mp_digit)1) << (DIGIT_BIT - 1))) != 0) {
  2031. if ((res = mp_mul (c, &g, c)) != MP_OKAY) {
  2032. mp_clear (&g);
  2033. return res;
  2034. }
  2035. }
  2036. /* shift to next bit */
  2037. b <<= 1;
  2038. }
  2039. mp_clear (&g);
  2040. return MP_OKAY;
  2041. }
  2042. #endif
  2043. /* End: bn_mp_expt_d.c */
  2044. /* Start: bn_mp_exptmod.c */
  2045. #include <ltc_tommath.h>
  2046. #ifdef BN_MP_EXPTMOD_C
  2047. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  2048. *
  2049. * LibTomMath is a library that provides multiple-precision
  2050. * integer arithmetic as well as number theoretic functionality.
  2051. *
  2052. * The library was designed directly after the MPI library by
  2053. * Michael Fromberger but has been written from scratch with
  2054. * additional optimizations in place.
  2055. *
  2056. * The library is free for all purposes without any express
  2057. * guarantee it works.
  2058. *
  2059. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  2060. */
  2061. /* this is a shell function that calls either the normal or Montgomery
  2062. * exptmod functions. Originally the call to the montgomery code was
  2063. * embedded in the normal function but that wasted alot of stack space
  2064. * for nothing (since 99% of the time the Montgomery code would be called)
  2065. */
  2066. int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
  2067. {
  2068. int dr;
  2069. /* modulus P must be positive */
  2070. if (P->sign == MP_NEG) {
  2071. return MP_VAL;
  2072. }
  2073. /* if exponent X is negative we have to recurse */
  2074. if (X->sign == MP_NEG) {
  2075. #ifdef BN_MP_INVMOD_C
  2076. mp_int tmpG, tmpX;
  2077. int err;
  2078. /* first compute 1/G mod P */
  2079. if ((err = mp_init(&tmpG)) != MP_OKAY) {
  2080. return err;
  2081. }
  2082. if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
  2083. mp_clear(&tmpG);
  2084. return err;
  2085. }
  2086. /* now get |X| */
  2087. if ((err = mp_init(&tmpX)) != MP_OKAY) {
  2088. mp_clear(&tmpG);
  2089. return err;
  2090. }
  2091. if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
  2092. mp_clear_multi(&tmpG, &tmpX, NULL);
  2093. return err;
  2094. }
  2095. /* and now compute (1/G)**|X| instead of G**X [X < 0] */
  2096. err = mp_exptmod(&tmpG, &tmpX, P, Y);
  2097. mp_clear_multi(&tmpG, &tmpX, NULL);
  2098. return err;
  2099. #else
  2100. /* no invmod */
  2101. return MP_VAL
  2102. #endif
  2103. }
  2104. #ifdef BN_MP_DR_IS_MODULUS_C
  2105. /* is it a DR modulus? */
  2106. dr = mp_dr_is_modulus(P);
  2107. #else
  2108. dr = 0;
  2109. #endif
  2110. #ifdef BN_MP_REDUCE_IS_2K_C
  2111. /* if not, is it a uDR modulus? */
  2112. if (dr == 0) {
  2113. dr = mp_reduce_is_2k(P) << 1;
  2114. }
  2115. #endif
  2116. /* if the modulus is odd or dr != 0 use the fast method */
  2117. #ifdef BN_MP_EXPTMOD_FAST_C
  2118. if (mp_isodd (P) == 1 || dr != 0) {
  2119. return mp_exptmod_fast (G, X, P, Y, dr);
  2120. } else {
  2121. #endif
  2122. #ifdef BN_S_MP_EXPTMOD_C
  2123. /* otherwise use the generic Barrett reduction technique */
  2124. return s_mp_exptmod (G, X, P, Y);
  2125. #else
  2126. /* no exptmod for evens */
  2127. return MP_VAL;
  2128. #endif
  2129. #ifdef BN_MP_EXPTMOD_FAST_C
  2130. }
  2131. #endif
  2132. }
  2133. #endif
  2134. /* End: bn_mp_exptmod.c */
  2135. /* Start: bn_mp_exptmod_fast.c */
  2136. #include <ltc_tommath.h>
  2137. #ifdef BN_MP_EXPTMOD_FAST_C
  2138. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  2139. *
  2140. * LibTomMath is a library that provides multiple-precision
  2141. * integer arithmetic as well as number theoretic functionality.
  2142. *
  2143. * The library was designed directly after the MPI library by
  2144. * Michael Fromberger but has been written from scratch with
  2145. * additional optimizations in place.
  2146. *
  2147. * The library is free for all purposes without any express
  2148. * guarantee it works.
  2149. *
  2150. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  2151. */
  2152. /* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
  2153. *
  2154. * Uses a left-to-right k-ary sliding window to compute the modular exponentiation.
  2155. * The value of k changes based on the size of the exponent.
  2156. *
  2157. * Uses Montgomery or Diminished Radix reduction [whichever appropriate]
  2158. */
  2159. #ifdef MP_LOW_MEM
  2160. #define TAB_SIZE 32
  2161. #else
  2162. #define TAB_SIZE 256
  2163. #endif
  2164. int
  2165. mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
  2166. {
  2167. mp_int M[TAB_SIZE], res;
  2168. mp_digit buf, mp;
  2169. int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
  2170. /* use a pointer to the reduction algorithm. This allows us to use
  2171. * one of many reduction algorithms without modding the guts of
  2172. * the code with if statements everywhere.
  2173. */
  2174. int (*redux)(mp_int*,mp_int*,mp_digit);
  2175. /* find window size */
  2176. x = mp_count_bits (X);
  2177. if (x <= 7) {
  2178. winsize = 2;
  2179. } else if (x <= 36) {
  2180. winsize = 3;
  2181. } else if (x <= 140) {
  2182. winsize = 4;
  2183. } else if (x <= 450) {
  2184. winsize = 5;
  2185. } else if (x <= 1303) {
  2186. winsize = 6;
  2187. } else if (x <= 3529) {
  2188. winsize = 7;
  2189. } else {
  2190. winsize = 8;
  2191. }
  2192. #ifdef MP_LOW_MEM
  2193. if (winsize > 5) {
  2194. winsize = 5;
  2195. }
  2196. #endif
  2197. /* init M array */
  2198. /* init first cell */
  2199. if ((err = mp_init(&M[1])) != MP_OKAY) {
  2200. return err;
  2201. }
  2202. /* now init the second half of the array */
  2203. for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
  2204. if ((err = mp_init(&M[x])) != MP_OKAY) {
  2205. for (y = 1<<(winsize-1); y < x; y++) {
  2206. mp_clear (&M[y]);
  2207. }
  2208. mp_clear(&M[1]);
  2209. return err;
  2210. }
  2211. }
  2212. /* determine and setup reduction code */
  2213. if (redmode == 0) {
  2214. #ifdef BN_MP_MONTGOMERY_SETUP_C
  2215. /* now setup montgomery */
  2216. if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) {
  2217. goto __M;
  2218. }
  2219. #else
  2220. err = MP_VAL;
  2221. goto __M;
  2222. #endif
  2223. /* automatically pick the comba one if available (saves quite a few calls/ifs) */
  2224. #ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
  2225. if (((P->used * 2 + 1) < MP_WARRAY) &&
  2226. P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
  2227. redux = fast_mp_montgomery_reduce;
  2228. } else
  2229. #endif
  2230. {
  2231. #ifdef BN_MP_MONTGOMERY_REDUCE_C
  2232. /* use slower baseline Montgomery method */
  2233. redux = mp_montgomery_reduce;
  2234. #else
  2235. err = MP_VAL;
  2236. goto __M;
  2237. #endif
  2238. }
  2239. } else if (redmode == 1) {
  2240. #if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C)
  2241. /* setup DR reduction for moduli of the form B**k - b */
  2242. mp_dr_setup(P, &mp);
  2243. redux = mp_dr_reduce;
  2244. #else
  2245. err = MP_VAL;
  2246. goto __M;
  2247. #endif
  2248. } else {
  2249. #if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C)
  2250. /* setup DR reduction for moduli of the form 2**k - b */
  2251. if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) {
  2252. goto __M;
  2253. }
  2254. redux = mp_reduce_2k;
  2255. #else
  2256. err = MP_VAL;
  2257. goto __M;
  2258. #endif
  2259. }
  2260. /* setup result */
  2261. if ((err = mp_init (&res)) != MP_OKAY) {
  2262. goto __M;
  2263. }
  2264. /* create M table
  2265. *
  2266. *
  2267. * The first half of the table is not computed though accept for M[0] and M[1]
  2268. */
  2269. if (redmode == 0) {
  2270. #ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
  2271. /* now we need R mod m */
  2272. if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) {
  2273. goto __RES;
  2274. }
  2275. #else
  2276. err = MP_VAL;
  2277. goto __RES;
  2278. #endif
  2279. /* now set M[1] to G * R mod m */
  2280. if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) {
  2281. goto __RES;
  2282. }
  2283. } else {
  2284. mp_set(&res, 1);
  2285. if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) {
  2286. goto __RES;
  2287. }
  2288. }
  2289. /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
  2290. if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
  2291. goto __RES;
  2292. }
  2293. for (x = 0; x < (winsize - 1); x++) {
  2294. if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) {
  2295. goto __RES;
  2296. }
  2297. if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) {
  2298. goto __RES;
  2299. }
  2300. }
  2301. /* create upper table */
  2302. for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
  2303. if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
  2304. goto __RES;
  2305. }
  2306. if ((err = redux (&M[x], P, mp)) != MP_OKAY) {
  2307. goto __RES;
  2308. }
  2309. }
  2310. /* set initial mode and bit cnt */
  2311. mode = 0;
  2312. bitcnt = 1;
  2313. buf = 0;
  2314. digidx = X->used - 1;
  2315. bitcpy = 0;
  2316. bitbuf = 0;
  2317. for (;;) {
  2318. /* grab next digit as required */
  2319. if (--bitcnt == 0) {
  2320. /* if digidx == -1 we are out of digits so break */
  2321. if (digidx == -1) {
  2322. break;
  2323. }
  2324. /* read next digit and reset bitcnt */
  2325. buf = X->dp[digidx--];
  2326. bitcnt = (int)DIGIT_BIT;
  2327. }
  2328. /* grab the next msb from the exponent */
  2329. y = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
  2330. buf <<= (mp_digit)1;
  2331. /* if the bit is zero and mode == 0 then we ignore it
  2332. * These represent the leading zero bits before the first 1 bit
  2333. * in the exponent. Technically this opt is not required but it
  2334. * does lower the # of trivial squaring/reductions used
  2335. */
  2336. if (mode == 0 && y == 0) {
  2337. continue;
  2338. }
  2339. /* if the bit is zero and mode == 1 then we square */
  2340. if (mode == 1 && y == 0) {
  2341. if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
  2342. goto __RES;
  2343. }
  2344. if ((err = redux (&res, P, mp)) != MP_OKAY) {
  2345. goto __RES;
  2346. }
  2347. continue;
  2348. }
  2349. /* else we add it to the window */
  2350. bitbuf |= (y << (winsize - ++bitcpy));
  2351. mode = 2;
  2352. if (bitcpy == winsize) {
  2353. /* ok window is filled so square as required and multiply */
  2354. /* square first */
  2355. for (x = 0; x < winsize; x++) {
  2356. if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
  2357. goto __RES;
  2358. }
  2359. if ((err = redux (&res, P, mp)) != MP_OKAY) {
  2360. goto __RES;
  2361. }
  2362. }
  2363. /* then multiply */
  2364. if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
  2365. goto __RES;
  2366. }
  2367. if ((err = redux (&res, P, mp)) != MP_OKAY) {
  2368. goto __RES;
  2369. }
  2370. /* empty window and reset */
  2371. bitcpy = 0;
  2372. bitbuf = 0;
  2373. mode = 1;
  2374. }
  2375. }
  2376. /* if bits remain then square/multiply */
  2377. if (mode == 2 && bitcpy > 0) {
  2378. /* square then multiply if the bit is set */
  2379. for (x = 0; x < bitcpy; x++) {
  2380. if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
  2381. goto __RES;
  2382. }
  2383. if ((err = redux (&res, P, mp)) != MP_OKAY) {
  2384. goto __RES;
  2385. }
  2386. /* get next bit of the window */
  2387. bitbuf <<= 1;
  2388. if ((bitbuf & (1 << winsize)) != 0) {
  2389. /* then multiply */
  2390. if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
  2391. goto __RES;
  2392. }
  2393. if ((err = redux (&res, P, mp)) != MP_OKAY) {
  2394. goto __RES;
  2395. }
  2396. }
  2397. }
  2398. }
  2399. if (redmode == 0) {
  2400. /* fixup result if Montgomery reduction is used
  2401. * recall that any value in a Montgomery system is
  2402. * actually multiplied by R mod n. So we have
  2403. * to reduce one more time to cancel out the factor
  2404. * of R.
  2405. */
  2406. if ((err = redux(&res, P, mp)) != MP_OKAY) {
  2407. goto __RES;
  2408. }
  2409. }
  2410. /* swap res with Y */
  2411. mp_exch (&res, Y);
  2412. err = MP_OKAY;
  2413. __RES:mp_clear (&res);
  2414. __M:
  2415. mp_clear(&M[1]);
  2416. for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
  2417. mp_clear (&M[x]);
  2418. }
  2419. return err;
  2420. }
  2421. #endif
  2422. /* End: bn_mp_exptmod_fast.c */
  2423. /* Start: bn_mp_exteuclid.c */
  2424. #include <ltc_tommath.h>
  2425. #ifdef BN_MP_EXTEUCLID_C
  2426. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  2427. *
  2428. * LibTomMath is a library that provides multiple-precision
  2429. * integer arithmetic as well as number theoretic functionality.
  2430. *
  2431. * The library was designed directly after the MPI library by
  2432. * Michael Fromberger but has been written from scratch with
  2433. * additional optimizations in place.
  2434. *
  2435. * The library is free for all purposes without any express
  2436. * guarantee it works.
  2437. *
  2438. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  2439. */
  2440. /* Extended euclidean algorithm of (a, b) produces
  2441. a*u1 + b*u2 = u3
  2442. */
  2443. int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3)
  2444. {
  2445. mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp;
  2446. int err;
  2447. if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) {
  2448. return err;
  2449. }
  2450. /* initialize, (u1,u2,u3) = (1,0,a) */
  2451. mp_set(&u1, 1);
  2452. if ((err = mp_copy(a, &u3)) != MP_OKAY) { goto _ERR; }
  2453. /* initialize, (v1,v2,v3) = (0,1,b) */
  2454. mp_set(&v2, 1);
  2455. if ((err = mp_copy(b, &v3)) != MP_OKAY) { goto _ERR; }
  2456. /* loop while v3 != 0 */
  2457. while (mp_iszero(&v3) == MP_NO) {
  2458. /* q = u3/v3 */
  2459. if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY) { goto _ERR; }
  2460. /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */
  2461. if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY) { goto _ERR; }
  2462. if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY) { goto _ERR; }
  2463. if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY) { goto _ERR; }
  2464. if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY) { goto _ERR; }
  2465. if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY) { goto _ERR; }
  2466. if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY) { goto _ERR; }
  2467. /* (u1,u2,u3) = (v1,v2,v3) */
  2468. if ((err = mp_copy(&v1, &u1)) != MP_OKAY) { goto _ERR; }
  2469. if ((err = mp_copy(&v2, &u2)) != MP_OKAY) { goto _ERR; }
  2470. if ((err = mp_copy(&v3, &u3)) != MP_OKAY) { goto _ERR; }
  2471. /* (v1,v2,v3) = (t1,t2,t3) */
  2472. if ((err = mp_copy(&t1, &v1)) != MP_OKAY) { goto _ERR; }
  2473. if ((err = mp_copy(&t2, &v2)) != MP_OKAY) { goto _ERR; }
  2474. if ((err = mp_copy(&t3, &v3)) != MP_OKAY) { goto _ERR; }
  2475. }
  2476. /* copy result out */
  2477. if (U1 != NULL) { mp_exch(U1, &u1); }
  2478. if (U2 != NULL) { mp_exch(U2, &u2); }
  2479. if (U3 != NULL) { mp_exch(U3, &u3); }
  2480. err = MP_OKAY;
  2481. _ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL);
  2482. return err;
  2483. }
  2484. #endif
  2485. /* End: bn_mp_exteuclid.c */
  2486. /* Start: bn_mp_fread.c */
  2487. #include <ltc_tommath.h>
  2488. #ifdef BN_MP_FREAD_C
  2489. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  2490. *
  2491. * LibTomMath is a library that provides multiple-precision
  2492. * integer arithmetic as well as number theoretic functionality.
  2493. *
  2494. * The library was designed directly after the MPI library by
  2495. * Michael Fromberger but has been written from scratch with
  2496. * additional optimizations in place.
  2497. *
  2498. * The library is free for all purposes without any express
  2499. * guarantee it works.
  2500. *
  2501. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  2502. */
  2503. /* read a bigint from a file stream in ASCII */
  2504. int mp_fread(mp_int *a, int radix, FILE *stream)
  2505. {
  2506. int err, ch, neg, y;
  2507. /* clear a */
  2508. mp_zero(a);
  2509. /* if first digit is - then set negative */
  2510. ch = fgetc(stream);
  2511. if (ch == '-') {
  2512. neg = MP_NEG;
  2513. ch = fgetc(stream);
  2514. } else {
  2515. neg = MP_ZPOS;
  2516. }
  2517. for (;;) {
  2518. /* find y in the radix map */
  2519. for (y = 0; y < radix; y++) {
  2520. if (mp_s_rmap[y] == ch) {
  2521. break;
  2522. }
  2523. }
  2524. if (y == radix) {
  2525. break;
  2526. }
  2527. /* shift up and add */
  2528. if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) {
  2529. return err;
  2530. }
  2531. if ((err = mp_add_d(a, y, a)) != MP_OKAY) {
  2532. return err;
  2533. }
  2534. ch = fgetc(stream);
  2535. }
  2536. if (mp_cmp_d(a, 0) != MP_EQ) {
  2537. a->sign = neg;
  2538. }
  2539. return MP_OKAY;
  2540. }
  2541. #endif
  2542. /* End: bn_mp_fread.c */
  2543. /* Start: bn_mp_fwrite.c */
  2544. #include <ltc_tommath.h>
  2545. #ifdef BN_MP_FWRITE_C
  2546. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  2547. *
  2548. * LibTomMath is a library that provides multiple-precision
  2549. * integer arithmetic as well as number theoretic functionality.
  2550. *
  2551. * The library was designed directly after the MPI library by
  2552. * Michael Fromberger but has been written from scratch with
  2553. * additional optimizations in place.
  2554. *
  2555. * The library is free for all purposes without any express
  2556. * guarantee it works.
  2557. *
  2558. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  2559. */
  2560. int mp_fwrite(mp_int *a, int radix, FILE *stream)
  2561. {
  2562. char *buf;
  2563. int err, len, x;
  2564. if ((err = mp_radix_size(a, radix, &len)) != MP_OKAY) {
  2565. return err;
  2566. }
  2567. buf = OPT_CAST(char) XMALLOC (len);
  2568. if (buf == NULL) {
  2569. return MP_MEM;
  2570. }
  2571. if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) {
  2572. XFREE (buf);
  2573. return err;
  2574. }
  2575. for (x = 0; x < len; x++) {
  2576. if (fputc(buf[x], stream) == EOF) {
  2577. XFREE (buf);
  2578. return MP_VAL;
  2579. }
  2580. }
  2581. XFREE (buf);
  2582. return MP_OKAY;
  2583. }
  2584. #endif
  2585. /* End: bn_mp_fwrite.c */
  2586. /* Start: bn_mp_gcd.c */
  2587. #include <ltc_tommath.h>
  2588. #ifdef BN_MP_GCD_C
  2589. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  2590. *
  2591. * LibTomMath is a library that provides multiple-precision
  2592. * integer arithmetic as well as number theoretic functionality.
  2593. *
  2594. * The library was designed directly after the MPI library by
  2595. * Michael Fromberger but has been written from scratch with
  2596. * additional optimizations in place.
  2597. *
  2598. * The library is free for all purposes without any express
  2599. * guarantee it works.
  2600. *
  2601. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  2602. */
  2603. /* Greatest Common Divisor using the binary method */
  2604. int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
  2605. {
  2606. mp_int u, v;
  2607. int k, u_lsb, v_lsb, res;
  2608. /* either zero than gcd is the largest */
  2609. if (mp_iszero (a) == 1 && mp_iszero (b) == 0) {
  2610. return mp_abs (b, c);
  2611. }
  2612. if (mp_iszero (a) == 0 && mp_iszero (b) == 1) {
  2613. return mp_abs (a, c);
  2614. }
  2615. /* optimized. At this point if a == 0 then
  2616. * b must equal zero too
  2617. */
  2618. if (mp_iszero (a) == 1) {
  2619. mp_zero(c);
  2620. return MP_OKAY;
  2621. }
  2622. /* get copies of a and b we can modify */
  2623. if ((res = mp_init_copy (&u, a)) != MP_OKAY) {
  2624. return res;
  2625. }
  2626. if ((res = mp_init_copy (&v, b)) != MP_OKAY) {
  2627. goto __U;
  2628. }
  2629. /* must be positive for the remainder of the algorithm */
  2630. u.sign = v.sign = MP_ZPOS;
  2631. /* B1. Find the common power of two for u and v */
  2632. u_lsb = mp_cnt_lsb(&u);
  2633. v_lsb = mp_cnt_lsb(&v);
  2634. k = MIN(u_lsb, v_lsb);
  2635. if (k > 0) {
  2636. /* divide the power of two out */
  2637. if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) {
  2638. goto __V;
  2639. }
  2640. if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) {
  2641. goto __V;
  2642. }
  2643. }
  2644. /* divide any remaining factors of two out */
  2645. if (u_lsb != k) {
  2646. if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) {
  2647. goto __V;
  2648. }
  2649. }
  2650. if (v_lsb != k) {
  2651. if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) {
  2652. goto __V;
  2653. }
  2654. }
  2655. while (mp_iszero(&v) == 0) {
  2656. /* make sure v is the largest */
  2657. if (mp_cmp_mag(&u, &v) == MP_GT) {
  2658. /* swap u and v to make sure v is >= u */
  2659. mp_exch(&u, &v);
  2660. }
  2661. /* subtract smallest from largest */
  2662. if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) {
  2663. goto __V;
  2664. }
  2665. /* Divide out all factors of two */
  2666. if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) {
  2667. goto __V;
  2668. }
  2669. }
  2670. /* multiply by 2**k which we divided out at the beginning */
  2671. if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) {
  2672. goto __V;
  2673. }
  2674. c->sign = MP_ZPOS;
  2675. res = MP_OKAY;
  2676. __V:mp_clear (&u);
  2677. __U:mp_clear (&v);
  2678. return res;
  2679. }
  2680. #endif
  2681. /* End: bn_mp_gcd.c */
  2682. /* Start: bn_mp_get_int.c */
  2683. #include <ltc_tommath.h>
  2684. #ifdef BN_MP_GET_INT_C
  2685. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  2686. *
  2687. * LibTomMath is a library that provides multiple-precision
  2688. * integer arithmetic as well as number theoretic functionality.
  2689. *
  2690. * The library was designed directly after the MPI library by
  2691. * Michael Fromberger but has been written from scratch with
  2692. * additional optimizations in place.
  2693. *
  2694. * The library is free for all purposes without any express
  2695. * guarantee it works.
  2696. *
  2697. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  2698. */
  2699. /* get the lower 32-bits of an mp_int */
  2700. unsigned long mp_get_int(mp_int * a)
  2701. {
  2702. int i;
  2703. unsigned long res;
  2704. if (a->used == 0) {
  2705. return 0;
  2706. }
  2707. /* get number of digits of the lsb we have to read */
  2708. i = MIN(a->used,(int)((sizeof(unsigned long)*CHAR_BIT+DIGIT_BIT-1)/DIGIT_BIT))-1;
  2709. /* get most significant digit of result */
  2710. res = DIGIT(a,i);
  2711. while (--i >= 0) {
  2712. res = (res << DIGIT_BIT) | DIGIT(a,i);
  2713. }
  2714. /* force result to 32-bits always so it is consistent on non 32-bit platforms */
  2715. return res & 0xFFFFFFFFUL;
  2716. }
  2717. #endif
  2718. /* End: bn_mp_get_int.c */
  2719. /* Start: bn_mp_grow.c */
  2720. #include <ltc_tommath.h>
  2721. #ifdef BN_MP_GROW_C
  2722. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  2723. *
  2724. * LibTomMath is a library that provides multiple-precision
  2725. * integer arithmetic as well as number theoretic functionality.
  2726. *
  2727. * The library was designed directly after the MPI library by
  2728. * Michael Fromberger but has been written from scratch with
  2729. * additional optimizations in place.
  2730. *
  2731. * The library is free for all purposes without any express
  2732. * guarantee it works.
  2733. *
  2734. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  2735. */
  2736. /* grow as required */
  2737. int mp_grow (mp_int * a, int size)
  2738. {
  2739. int i;
  2740. mp_digit *tmp;
  2741. /* if the alloc size is smaller alloc more ram */
  2742. if (a->alloc < size) {
  2743. /* ensure there are always at least MP_PREC digits extra on top */
  2744. size += (MP_PREC * 2) - (size % MP_PREC);
  2745. /* reallocate the array a->dp
  2746. *
  2747. * We store the return in a temporary variable
  2748. * in case the operation failed we don't want
  2749. * to overwrite the dp member of a.
  2750. */
  2751. tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size);
  2752. if (tmp == NULL) {
  2753. /* reallocation failed but "a" is still valid [can be freed] */
  2754. return MP_MEM;
  2755. }
  2756. /* reallocation succeeded so set a->dp */
  2757. a->dp = tmp;
  2758. /* zero excess digits */
  2759. i = a->alloc;
  2760. a->alloc = size;
  2761. for (; i < a->alloc; i++) {
  2762. a->dp[i] = 0;
  2763. }
  2764. }
  2765. return MP_OKAY;
  2766. }
  2767. #endif
  2768. /* End: bn_mp_grow.c */
  2769. /* Start: bn_mp_init.c */
  2770. #include <ltc_tommath.h>
  2771. #ifdef BN_MP_INIT_C
  2772. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  2773. *
  2774. * LibTomMath is a library that provides multiple-precision
  2775. * integer arithmetic as well as number theoretic functionality.
  2776. *
  2777. * The library was designed directly after the MPI library by
  2778. * Michael Fromberger but has been written from scratch with
  2779. * additional optimizations in place.
  2780. *
  2781. * The library is free for all purposes without any express
  2782. * guarantee it works.
  2783. *
  2784. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  2785. */
  2786. /* init a new mp_int */
  2787. int mp_init (mp_int * a)
  2788. {
  2789. int i;
  2790. /* allocate memory required and clear it */
  2791. a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC);
  2792. if (a->dp == NULL) {
  2793. return MP_MEM;
  2794. }
  2795. /* set the digits to zero */
  2796. for (i = 0; i < MP_PREC; i++) {
  2797. a->dp[i] = 0;
  2798. }
  2799. /* set the used to zero, allocated digits to the default precision
  2800. * and sign to positive */
  2801. a->used = 0;
  2802. a->alloc = MP_PREC;
  2803. a->sign = MP_ZPOS;
  2804. return MP_OKAY;
  2805. }
  2806. #endif
  2807. /* End: bn_mp_init.c */
  2808. /* Start: bn_mp_init_copy.c */
  2809. #include <ltc_tommath.h>
  2810. #ifdef BN_MP_INIT_COPY_C
  2811. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  2812. *
  2813. * LibTomMath is a library that provides multiple-precision
  2814. * integer arithmetic as well as number theoretic functionality.
  2815. *
  2816. * The library was designed directly after the MPI library by
  2817. * Michael Fromberger but has been written from scratch with
  2818. * additional optimizations in place.
  2819. *
  2820. * The library is free for all purposes without any express
  2821. * guarantee it works.
  2822. *
  2823. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  2824. */
  2825. /* creates "a" then copies b into it */
  2826. int mp_init_copy (mp_int * a, mp_int * b)
  2827. {
  2828. int res;
  2829. if ((res = mp_init (a)) != MP_OKAY) {
  2830. return res;
  2831. }
  2832. return mp_copy (b, a);
  2833. }
  2834. #endif
  2835. /* End: bn_mp_init_copy.c */
  2836. /* Start: bn_mp_init_multi.c */
  2837. #include <ltc_tommath.h>
  2838. #ifdef BN_MP_INIT_MULTI_C
  2839. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  2840. *
  2841. * LibTomMath is a library that provides multiple-precision
  2842. * integer arithmetic as well as number theoretic functionality.
  2843. *
  2844. * The library was designed directly after the MPI library by
  2845. * Michael Fromberger but has been written from scratch with
  2846. * additional optimizations in place.
  2847. *
  2848. * The library is free for all purposes without any express
  2849. * guarantee it works.
  2850. *
  2851. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  2852. */
  2853. #include <stdarg.h>
  2854. int mp_init_multi(mp_int *mp, ...)
  2855. {
  2856. mp_err res = MP_OKAY; /* Assume ok until proven otherwise */
  2857. int n = 0; /* Number of ok inits */
  2858. mp_int* cur_arg = mp;
  2859. va_list args;
  2860. va_start(args, mp); /* init args to next argument from caller */
  2861. while (cur_arg != NULL) {
  2862. if (mp_init(cur_arg) != MP_OKAY) {
  2863. /* Oops - error! Back-track and mp_clear what we already
  2864. succeeded in init-ing, then return error.
  2865. */
  2866. va_list clean_args;
  2867. /* end the current list */
  2868. va_end(args);
  2869. /* now start cleaning up */
  2870. cur_arg = mp;
  2871. va_start(clean_args, mp);
  2872. while (n--) {
  2873. mp_clear(cur_arg);
  2874. cur_arg = va_arg(clean_args, mp_int*);
  2875. }
  2876. va_end(clean_args);
  2877. res = MP_MEM;
  2878. break;
  2879. }
  2880. n++;
  2881. cur_arg = va_arg(args, mp_int*);
  2882. }
  2883. va_end(args);
  2884. return res; /* Assumed ok, if error flagged above. */
  2885. }
  2886. #endif
  2887. /* End: bn_mp_init_multi.c */
  2888. /* Start: bn_mp_init_set.c */
  2889. #include <ltc_tommath.h>
  2890. #ifdef BN_MP_INIT_SET_C
  2891. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  2892. *
  2893. * LibTomMath is a library that provides multiple-precision
  2894. * integer arithmetic as well as number theoretic functionality.
  2895. *
  2896. * The library was designed directly after the MPI library by
  2897. * Michael Fromberger but has been written from scratch with
  2898. * additional optimizations in place.
  2899. *
  2900. * The library is free for all purposes without any express
  2901. * guarantee it works.
  2902. *
  2903. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  2904. */
  2905. /* initialize and set a digit */
  2906. int mp_init_set (mp_int * a, mp_digit b)
  2907. {
  2908. int err;
  2909. if ((err = mp_init(a)) != MP_OKAY) {
  2910. return err;
  2911. }
  2912. mp_set(a, b);
  2913. return err;
  2914. }
  2915. #endif
  2916. /* End: bn_mp_init_set.c */
  2917. /* Start: bn_mp_init_set_int.c */
  2918. #include <ltc_tommath.h>
  2919. #ifdef BN_MP_INIT_SET_INT_C
  2920. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  2921. *
  2922. * LibTomMath is a library that provides multiple-precision
  2923. * integer arithmetic as well as number theoretic functionality.
  2924. *
  2925. * The library was designed directly after the MPI library by
  2926. * Michael Fromberger but has been written from scratch with
  2927. * additional optimizations in place.
  2928. *
  2929. * The library is free for all purposes without any express
  2930. * guarantee it works.
  2931. *
  2932. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  2933. */
  2934. /* initialize and set a digit */
  2935. int mp_init_set_int (mp_int * a, unsigned long b)
  2936. {
  2937. int err;
  2938. if ((err = mp_init(a)) != MP_OKAY) {
  2939. return err;
  2940. }
  2941. return mp_set_int(a, b);
  2942. }
  2943. #endif
  2944. /* End: bn_mp_init_set_int.c */
  2945. /* Start: bn_mp_init_size.c */
  2946. #include <ltc_tommath.h>
  2947. #ifdef BN_MP_INIT_SIZE_C
  2948. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  2949. *
  2950. * LibTomMath is a library that provides multiple-precision
  2951. * integer arithmetic as well as number theoretic functionality.
  2952. *
  2953. * The library was designed directly after the MPI library by
  2954. * Michael Fromberger but has been written from scratch with
  2955. * additional optimizations in place.
  2956. *
  2957. * The library is free for all purposes without any express
  2958. * guarantee it works.
  2959. *
  2960. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  2961. */
  2962. /* init an mp_init for a given size */
  2963. int mp_init_size (mp_int * a, int size)
  2964. {
  2965. int x;
  2966. /* pad size so there are always extra digits */
  2967. size += (MP_PREC * 2) - (size % MP_PREC);
  2968. /* alloc mem */
  2969. a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size);
  2970. if (a->dp == NULL) {
  2971. return MP_MEM;
  2972. }
  2973. /* set the members */
  2974. a->used = 0;
  2975. a->alloc = size;
  2976. a->sign = MP_ZPOS;
  2977. /* zero the digits */
  2978. for (x = 0; x < size; x++) {
  2979. a->dp[x] = 0;
  2980. }
  2981. return MP_OKAY;
  2982. }
  2983. #endif
  2984. /* End: bn_mp_init_size.c */
  2985. /* Start: bn_mp_invmod.c */
  2986. #include <ltc_tommath.h>
  2987. #ifdef BN_MP_INVMOD_C
  2988. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  2989. *
  2990. * LibTomMath is a library that provides multiple-precision
  2991. * integer arithmetic as well as number theoretic functionality.
  2992. *
  2993. * The library was designed directly after the MPI library by
  2994. * Michael Fromberger but has been written from scratch with
  2995. * additional optimizations in place.
  2996. *
  2997. * The library is free for all purposes without any express
  2998. * guarantee it works.
  2999. *
  3000. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  3001. */
  3002. /* hac 14.61, pp608 */
  3003. int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
  3004. {
  3005. /* b cannot be negative */
  3006. if (b->sign == MP_NEG || mp_iszero(b) == 1) {
  3007. return MP_VAL;
  3008. }
  3009. #ifdef BN_FAST_MP_INVMOD_C
  3010. /* if the modulus is odd we can use a faster routine instead */
  3011. if (mp_isodd (b) == 1) {
  3012. return fast_mp_invmod (a, b, c);
  3013. }
  3014. #endif
  3015. #ifdef BN_MP_INVMOD_SLOW_C
  3016. return mp_invmod_slow(a, b, c);
  3017. #endif
  3018. return MP_VAL;
  3019. }
  3020. #endif
  3021. /* End: bn_mp_invmod.c */
  3022. /* Start: bn_mp_invmod_slow.c */
  3023. #include <ltc_tommath.h>
  3024. #ifdef BN_MP_INVMOD_SLOW_C
  3025. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  3026. *
  3027. * LibTomMath is a library that provides multiple-precision
  3028. * integer arithmetic as well as number theoretic functionality.
  3029. *
  3030. * The library was designed directly after the MPI library by
  3031. * Michael Fromberger but has been written from scratch with
  3032. * additional optimizations in place.
  3033. *
  3034. * The library is free for all purposes without any express
  3035. * guarantee it works.
  3036. *
  3037. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  3038. */
  3039. /* hac 14.61, pp608 */
  3040. int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c)
  3041. {
  3042. mp_int x, y, u, v, A, B, C, D;
  3043. int res;
  3044. /* b cannot be negative */
  3045. if (b->sign == MP_NEG || mp_iszero(b) == 1) {
  3046. return MP_VAL;
  3047. }
  3048. /* init temps */
  3049. if ((res = mp_init_multi(&x, &y, &u, &v,
  3050. &A, &B, &C, &D, NULL)) != MP_OKAY) {
  3051. return res;
  3052. }
  3053. /* x = a, y = b */
  3054. if ((res = mp_copy (a, &x)) != MP_OKAY) {
  3055. goto __ERR;
  3056. }
  3057. if ((res = mp_copy (b, &y)) != MP_OKAY) {
  3058. goto __ERR;
  3059. }
  3060. /* 2. [modified] if x,y are both even then return an error! */
  3061. if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) {
  3062. res = MP_VAL;
  3063. goto __ERR;
  3064. }
  3065. /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
  3066. if ((res = mp_copy (&x, &u)) != MP_OKAY) {
  3067. goto __ERR;
  3068. }
  3069. if ((res = mp_copy (&y, &v)) != MP_OKAY) {
  3070. goto __ERR;
  3071. }
  3072. mp_set (&A, 1);
  3073. mp_set (&D, 1);
  3074. top:
  3075. /* 4. while u is even do */
  3076. while (mp_iseven (&u) == 1) {
  3077. /* 4.1 u = u/2 */
  3078. if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
  3079. goto __ERR;
  3080. }
  3081. /* 4.2 if A or B is odd then */
  3082. if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) {
  3083. /* A = (A+y)/2, B = (B-x)/2 */
  3084. if ((res = mp_add (&A, &y, &A)) != MP_OKAY) {
  3085. goto __ERR;
  3086. }
  3087. if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
  3088. goto __ERR;
  3089. }
  3090. }
  3091. /* A = A/2, B = B/2 */
  3092. if ((res = mp_div_2 (&A, &A)) != MP_OKAY) {
  3093. goto __ERR;
  3094. }
  3095. if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
  3096. goto __ERR;
  3097. }
  3098. }
  3099. /* 5. while v is even do */
  3100. while (mp_iseven (&v) == 1) {
  3101. /* 5.1 v = v/2 */
  3102. if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
  3103. goto __ERR;
  3104. }
  3105. /* 5.2 if C or D is odd then */
  3106. if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) {
  3107. /* C = (C+y)/2, D = (D-x)/2 */
  3108. if ((res = mp_add (&C, &y, &C)) != MP_OKAY) {
  3109. goto __ERR;
  3110. }
  3111. if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
  3112. goto __ERR;
  3113. }
  3114. }
  3115. /* C = C/2, D = D/2 */
  3116. if ((res = mp_div_2 (&C, &C)) != MP_OKAY) {
  3117. goto __ERR;
  3118. }
  3119. if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
  3120. goto __ERR;
  3121. }
  3122. }
  3123. /* 6. if u >= v then */
  3124. if (mp_cmp (&u, &v) != MP_LT) {
  3125. /* u = u - v, A = A - C, B = B - D */
  3126. if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
  3127. goto __ERR;
  3128. }
  3129. if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) {
  3130. goto __ERR;
  3131. }
  3132. if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
  3133. goto __ERR;
  3134. }
  3135. } else {
  3136. /* v - v - u, C = C - A, D = D - B */
  3137. if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
  3138. goto __ERR;
  3139. }
  3140. if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) {
  3141. goto __ERR;
  3142. }
  3143. if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
  3144. goto __ERR;
  3145. }
  3146. }
  3147. /* if not zero goto step 4 */
  3148. if (mp_iszero (&u) == 0)
  3149. goto top;
  3150. /* now a = C, b = D, gcd == g*v */
  3151. /* if v != 1 then there is no inverse */
  3152. if (mp_cmp_d (&v, 1) != MP_EQ) {
  3153. res = MP_VAL;
  3154. goto __ERR;
  3155. }
  3156. /* if its too low */
  3157. while (mp_cmp_d(&C, 0) == MP_LT) {
  3158. if ((res = mp_add(&C, b, &C)) != MP_OKAY) {
  3159. goto __ERR;
  3160. }
  3161. }
  3162. /* too big */
  3163. while (mp_cmp_mag(&C, b) != MP_LT) {
  3164. if ((res = mp_sub(&C, b, &C)) != MP_OKAY) {
  3165. goto __ERR;
  3166. }
  3167. }
  3168. /* C is now the inverse */
  3169. mp_exch (&C, c);
  3170. res = MP_OKAY;
  3171. __ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL);
  3172. return res;
  3173. }
  3174. #endif
  3175. /* End: bn_mp_invmod_slow.c */
  3176. /* Start: bn_mp_is_square.c */
  3177. #include <ltc_tommath.h>
  3178. #ifdef BN_MP_IS_SQUARE_C
  3179. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  3180. *
  3181. * LibTomMath is a library that provides multiple-precision
  3182. * integer arithmetic as well as number theoretic functionality.
  3183. *
  3184. * The library was designed directly after the MPI library by
  3185. * Michael Fromberger but has been written from scratch with
  3186. * additional optimizations in place.
  3187. *
  3188. * The library is free for all purposes without any express
  3189. * guarantee it works.
  3190. *
  3191. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  3192. */
  3193. /* Check if remainders are possible squares - fast exclude non-squares */
  3194. static const char rem_128[128] = {
  3195. 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
  3196. 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
  3197. 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
  3198. 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
  3199. 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
  3200. 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
  3201. 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
  3202. 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1
  3203. };
  3204. static const char rem_105[105] = {
  3205. 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
  3206. 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
  3207. 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1,
  3208. 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
  3209. 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
  3210. 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1,
  3211. 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1
  3212. };
  3213. /* Store non-zero to ret if arg is square, and zero if not */
  3214. int mp_is_square(mp_int *arg,int *ret)
  3215. {
  3216. int res;
  3217. mp_digit c;
  3218. mp_int t;
  3219. unsigned long r;
  3220. /* Default to Non-square :) */
  3221. *ret = MP_NO;
  3222. if (arg->sign == MP_NEG) {
  3223. return MP_VAL;
  3224. }
  3225. /* digits used? (TSD) */
  3226. if (arg->used == 0) {
  3227. return MP_OKAY;
  3228. }
  3229. /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */
  3230. if (rem_128[127 & DIGIT(arg,0)] == 1) {
  3231. return MP_OKAY;
  3232. }
  3233. /* Next check mod 105 (3*5*7) */
  3234. if ((res = mp_mod_d(arg,105,&c)) != MP_OKAY) {
  3235. return res;
  3236. }
  3237. if (rem_105[c] == 1) {
  3238. return MP_OKAY;
  3239. }
  3240. if ((res = mp_init_set_int(&t,11L*13L*17L*19L*23L*29L*31L)) != MP_OKAY) {
  3241. return res;
  3242. }
  3243. if ((res = mp_mod(arg,&t,&t)) != MP_OKAY) {
  3244. goto ERR;
  3245. }
  3246. r = mp_get_int(&t);
  3247. /* Check for other prime modules, note it's not an ERROR but we must
  3248. * free "t" so the easiest way is to goto ERR. We know that res
  3249. * is already equal to MP_OKAY from the mp_mod call
  3250. */
  3251. if ( (1L<<(r%11)) & 0x5C4L ) goto ERR;
  3252. if ( (1L<<(r%13)) & 0x9E4L ) goto ERR;
  3253. if ( (1L<<(r%17)) & 0x5CE8L ) goto ERR;
  3254. if ( (1L<<(r%19)) & 0x4F50CL ) goto ERR;
  3255. if ( (1L<<(r%23)) & 0x7ACCA0L ) goto ERR;
  3256. if ( (1L<<(r%29)) & 0xC2EDD0CL ) goto ERR;
  3257. if ( (1L<<(r%31)) & 0x6DE2B848L ) goto ERR;
  3258. /* Final check - is sqr(sqrt(arg)) == arg ? */
  3259. if ((res = mp_sqrt(arg,&t)) != MP_OKAY) {
  3260. goto ERR;
  3261. }
  3262. if ((res = mp_sqr(&t,&t)) != MP_OKAY) {
  3263. goto ERR;
  3264. }
  3265. *ret = (mp_cmp_mag(&t,arg) == MP_EQ) ? MP_YES : MP_NO;
  3266. ERR:mp_clear(&t);
  3267. return res;
  3268. }
  3269. #endif
  3270. /* End: bn_mp_is_square.c */
  3271. /* Start: bn_mp_jacobi.c */
  3272. #include <ltc_tommath.h>
  3273. #ifdef BN_MP_JACOBI_C
  3274. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  3275. *
  3276. * LibTomMath is a library that provides multiple-precision
  3277. * integer arithmetic as well as number theoretic functionality.
  3278. *
  3279. * The library was designed directly after the MPI library by
  3280. * Michael Fromberger but has been written from scratch with
  3281. * additional optimizations in place.
  3282. *
  3283. * The library is free for all purposes without any express
  3284. * guarantee it works.
  3285. *
  3286. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  3287. */
  3288. /* computes the jacobi c = (a | n) (or Legendre if n is prime)
  3289. * HAC pp. 73 Algorithm 2.149
  3290. */
  3291. int mp_jacobi (mp_int * a, mp_int * p, int *c)
  3292. {
  3293. mp_int a1, p1;
  3294. int k, s, r, res;
  3295. mp_digit residue;
  3296. /* if p <= 0 return MP_VAL */
  3297. if (mp_cmp_d(p, 0) != MP_GT) {
  3298. return MP_VAL;
  3299. }
  3300. /* step 1. if a == 0, return 0 */
  3301. if (mp_iszero (a) == 1) {
  3302. *c = 0;
  3303. return MP_OKAY;
  3304. }
  3305. /* step 2. if a == 1, return 1 */
  3306. if (mp_cmp_d (a, 1) == MP_EQ) {
  3307. *c = 1;
  3308. return MP_OKAY;
  3309. }
  3310. /* default */
  3311. s = 0;
  3312. /* step 3. write a = a1 * 2**k */
  3313. if ((res = mp_init_copy (&a1, a)) != MP_OKAY) {
  3314. return res;
  3315. }
  3316. if ((res = mp_init (&p1)) != MP_OKAY) {
  3317. goto __A1;
  3318. }
  3319. /* divide out larger power of two */
  3320. k = mp_cnt_lsb(&a1);
  3321. if ((res = mp_div_2d(&a1, k, &a1, NULL)) != MP_OKAY) {
  3322. goto __P1;
  3323. }
  3324. /* step 4. if e is even set s=1 */
  3325. if ((k & 1) == 0) {
  3326. s = 1;
  3327. } else {
  3328. /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */
  3329. residue = p->dp[0] & 7;
  3330. if (residue == 1 || residue == 7) {
  3331. s = 1;
  3332. } else if (residue == 3 || residue == 5) {
  3333. s = -1;
  3334. }
  3335. }
  3336. /* step 5. if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */
  3337. if ( ((p->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) {
  3338. s = -s;
  3339. }
  3340. /* if a1 == 1 we're done */
  3341. if (mp_cmp_d (&a1, 1) == MP_EQ) {
  3342. *c = s;
  3343. } else {
  3344. /* n1 = n mod a1 */
  3345. if ((res = mp_mod (p, &a1, &p1)) != MP_OKAY) {
  3346. goto __P1;
  3347. }
  3348. if ((res = mp_jacobi (&p1, &a1, &r)) != MP_OKAY) {
  3349. goto __P1;
  3350. }
  3351. *c = s * r;
  3352. }
  3353. /* done */
  3354. res = MP_OKAY;
  3355. __P1:mp_clear (&p1);
  3356. __A1:mp_clear (&a1);
  3357. return res;
  3358. }
  3359. #endif
  3360. /* End: bn_mp_jacobi.c */
  3361. /* Start: bn_mp_karatsuba_mul.c */
  3362. #include <ltc_tommath.h>
  3363. #ifdef BN_MP_KARATSUBA_MUL_C
  3364. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  3365. *
  3366. * LibTomMath is a library that provides multiple-precision
  3367. * integer arithmetic as well as number theoretic functionality.
  3368. *
  3369. * The library was designed directly after the MPI library by
  3370. * Michael Fromberger but has been written from scratch with
  3371. * additional optimizations in place.
  3372. *
  3373. * The library is free for all purposes without any express
  3374. * guarantee it works.
  3375. *
  3376. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  3377. */
  3378. /* c = |a| * |b| using Karatsuba Multiplication using
  3379. * three half size multiplications
  3380. *
  3381. * Let B represent the radix [e.g. 2**DIGIT_BIT] and
  3382. * let n represent half of the number of digits in
  3383. * the min(a,b)
  3384. *
  3385. * a = a1 * B**n + a0
  3386. * b = b1 * B**n + b0
  3387. *
  3388. * Then, a * b =>
  3389. a1b1 * B**2n + ((a1 - a0)(b1 - b0) + a0b0 + a1b1) * B + a0b0
  3390. *
  3391. * Note that a1b1 and a0b0 are used twice and only need to be
  3392. * computed once. So in total three half size (half # of
  3393. * digit) multiplications are performed, a0b0, a1b1 and
  3394. * (a1-b1)(a0-b0)
  3395. *
  3396. * Note that a multiplication of half the digits requires
  3397. * 1/4th the number of single precision multiplications so in
  3398. * total after one call 25% of the single precision multiplications
  3399. * are saved. Note also that the call to mp_mul can end up back
  3400. * in this function if the a0, a1, b0, or b1 are above the threshold.
  3401. * This is known as divide-and-conquer and leads to the famous
  3402. * O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than
  3403. * the standard O(N**2) that the baseline/comba methods use.
  3404. * Generally though the overhead of this method doesn't pay off
  3405. * until a certain size (N ~ 80) is reached.
  3406. */
  3407. int mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c)
  3408. {
  3409. mp_int x0, x1, y0, y1, t1, x0y0, x1y1;
  3410. int B, err;
  3411. /* default the return code to an error */
  3412. err = MP_MEM;
  3413. /* min # of digits */
  3414. B = MIN (a->used, b->used);
  3415. /* now divide in two */
  3416. B = B >> 1;
  3417. /* init copy all the temps */
  3418. if (mp_init_size (&x0, B) != MP_OKAY)
  3419. goto ERR;
  3420. if (mp_init_size (&x1, a->used - B) != MP_OKAY)
  3421. goto X0;
  3422. if (mp_init_size (&y0, B) != MP_OKAY)
  3423. goto X1;
  3424. if (mp_init_size (&y1, b->used - B) != MP_OKAY)
  3425. goto Y0;
  3426. /* init temps */
  3427. if (mp_init_size (&t1, B * 2) != MP_OKAY)
  3428. goto Y1;
  3429. if (mp_init_size (&x0y0, B * 2) != MP_OKAY)
  3430. goto T1;
  3431. if (mp_init_size (&x1y1, B * 2) != MP_OKAY)
  3432. goto X0Y0;
  3433. /* now shift the digits */
  3434. x0.used = y0.used = B;
  3435. x1.used = a->used - B;
  3436. y1.used = b->used - B;
  3437. {
  3438. register int x;
  3439. register mp_digit *tmpa, *tmpb, *tmpx, *tmpy;
  3440. /* we copy the digits directly instead of using higher level functions
  3441. * since we also need to shift the digits
  3442. */
  3443. tmpa = a->dp;
  3444. tmpb = b->dp;
  3445. tmpx = x0.dp;
  3446. tmpy = y0.dp;
  3447. for (x = 0; x < B; x++) {
  3448. *tmpx++ = *tmpa++;
  3449. *tmpy++ = *tmpb++;
  3450. }
  3451. tmpx = x1.dp;
  3452. for (x = B; x < a->used; x++) {
  3453. *tmpx++ = *tmpa++;
  3454. }
  3455. tmpy = y1.dp;
  3456. for (x = B; x < b->used; x++) {
  3457. *tmpy++ = *tmpb++;
  3458. }
  3459. }
  3460. /* only need to clamp the lower words since by definition the
  3461. * upper words x1/y1 must have a known number of digits
  3462. */
  3463. mp_clamp (&x0);
  3464. mp_clamp (&y0);
  3465. /* now calc the products x0y0 and x1y1 */
  3466. /* after this x0 is no longer required, free temp [x0==t2]! */
  3467. if (mp_mul (&x0, &y0, &x0y0) != MP_OKAY)
  3468. goto X1Y1; /* x0y0 = x0*y0 */
  3469. if (mp_mul (&x1, &y1, &x1y1) != MP_OKAY)
  3470. goto X1Y1; /* x1y1 = x1*y1 */
  3471. /* now calc x1-x0 and y1-y0 */
  3472. if (mp_sub (&x1, &x0, &t1) != MP_OKAY)
  3473. goto X1Y1; /* t1 = x1 - x0 */
  3474. if (mp_sub (&y1, &y0, &x0) != MP_OKAY)
  3475. goto X1Y1; /* t2 = y1 - y0 */
  3476. if (mp_mul (&t1, &x0, &t1) != MP_OKAY)
  3477. goto X1Y1; /* t1 = (x1 - x0) * (y1 - y0) */
  3478. /* add x0y0 */
  3479. if (mp_add (&x0y0, &x1y1, &x0) != MP_OKAY)
  3480. goto X1Y1; /* t2 = x0y0 + x1y1 */
  3481. if (mp_sub (&x0, &t1, &t1) != MP_OKAY)
  3482. goto X1Y1; /* t1 = x0y0 + x1y1 - (x1-x0)*(y1-y0) */
  3483. /* shift by B */
  3484. if (mp_lshd (&t1, B) != MP_OKAY)
  3485. goto X1Y1; /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<<B */
  3486. if (mp_lshd (&x1y1, B * 2) != MP_OKAY)
  3487. goto X1Y1; /* x1y1 = x1y1 << 2*B */
  3488. if (mp_add (&x0y0, &t1, &t1) != MP_OKAY)
  3489. goto X1Y1; /* t1 = x0y0 + t1 */
  3490. if (mp_add (&t1, &x1y1, c) != MP_OKAY)
  3491. goto X1Y1; /* t1 = x0y0 + t1 + x1y1 */
  3492. /* Algorithm succeeded set the return code to MP_OKAY */
  3493. err = MP_OKAY;
  3494. X1Y1:mp_clear (&x1y1);
  3495. X0Y0:mp_clear (&x0y0);
  3496. T1:mp_clear (&t1);
  3497. Y1:mp_clear (&y1);
  3498. Y0:mp_clear (&y0);
  3499. X1:mp_clear (&x1);
  3500. X0:mp_clear (&x0);
  3501. ERR:
  3502. return err;
  3503. }
  3504. #endif
  3505. /* End: bn_mp_karatsuba_mul.c */
  3506. /* Start: bn_mp_karatsuba_sqr.c */
  3507. #include <ltc_tommath.h>
  3508. #ifdef BN_MP_KARATSUBA_SQR_C
  3509. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  3510. *
  3511. * LibTomMath is a library that provides multiple-precision
  3512. * integer arithmetic as well as number theoretic functionality.
  3513. *
  3514. * The library was designed directly after the MPI library by
  3515. * Michael Fromberger but has been written from scratch with
  3516. * additional optimizations in place.
  3517. *
  3518. * The library is free for all purposes without any express
  3519. * guarantee it works.
  3520. *
  3521. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  3522. */
  3523. /* Karatsuba squaring, computes b = a*a using three
  3524. * half size squarings
  3525. *
  3526. * See comments of karatsuba_mul for details. It
  3527. * is essentially the same algorithm but merely
  3528. * tuned to perform recursive squarings.
  3529. */
  3530. int mp_karatsuba_sqr (mp_int * a, mp_int * b)
  3531. {
  3532. mp_int x0, x1, t1, t2, x0x0, x1x1;
  3533. int B, err;
  3534. err = MP_MEM;
  3535. /* min # of digits */
  3536. B = a->used;
  3537. /* now divide in two */
  3538. B = B >> 1;
  3539. /* init copy all the temps */
  3540. if (mp_init_size (&x0, B) != MP_OKAY)
  3541. goto ERR;
  3542. if (mp_init_size (&x1, a->used - B) != MP_OKAY)
  3543. goto X0;
  3544. /* init temps */
  3545. if (mp_init_size (&t1, a->used * 2) != MP_OKAY)
  3546. goto X1;
  3547. if (mp_init_size (&t2, a->used * 2) != MP_OKAY)
  3548. goto T1;
  3549. if (mp_init_size (&x0x0, B * 2) != MP_OKAY)
  3550. goto T2;
  3551. if (mp_init_size (&x1x1, (a->used - B) * 2) != MP_OKAY)
  3552. goto X0X0;
  3553. {
  3554. register int x;
  3555. register mp_digit *dst, *src;
  3556. src = a->dp;
  3557. /* now shift the digits */
  3558. dst = x0.dp;
  3559. for (x = 0; x < B; x++) {
  3560. *dst++ = *src++;
  3561. }
  3562. dst = x1.dp;
  3563. for (x = B; x < a->used; x++) {
  3564. *dst++ = *src++;
  3565. }
  3566. }
  3567. x0.used = B;
  3568. x1.used = a->used - B;
  3569. mp_clamp (&x0);
  3570. /* now calc the products x0*x0 and x1*x1 */
  3571. if (mp_sqr (&x0, &x0x0) != MP_OKAY)
  3572. goto X1X1; /* x0x0 = x0*x0 */
  3573. if (mp_sqr (&x1, &x1x1) != MP_OKAY)
  3574. goto X1X1; /* x1x1 = x1*x1 */
  3575. /* now calc (x1-x0)**2 */
  3576. if (mp_sub (&x1, &x0, &t1) != MP_OKAY)
  3577. goto X1X1; /* t1 = x1 - x0 */
  3578. if (mp_sqr (&t1, &t1) != MP_OKAY)
  3579. goto X1X1; /* t1 = (x1 - x0) * (x1 - x0) */
  3580. /* add x0y0 */
  3581. if (s_mp_add (&x0x0, &x1x1, &t2) != MP_OKAY)
  3582. goto X1X1; /* t2 = x0x0 + x1x1 */
  3583. if (mp_sub (&t2, &t1, &t1) != MP_OKAY)
  3584. goto X1X1; /* t1 = x0x0 + x1x1 - (x1-x0)*(x1-x0) */
  3585. /* shift by B */
  3586. if (mp_lshd (&t1, B) != MP_OKAY)
  3587. goto X1X1; /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))<<B */
  3588. if (mp_lshd (&x1x1, B * 2) != MP_OKAY)
  3589. goto X1X1; /* x1x1 = x1x1 << 2*B */
  3590. if (mp_add (&x0x0, &t1, &t1) != MP_OKAY)
  3591. goto X1X1; /* t1 = x0x0 + t1 */
  3592. if (mp_add (&t1, &x1x1, b) != MP_OKAY)
  3593. goto X1X1; /* t1 = x0x0 + t1 + x1x1 */
  3594. err = MP_OKAY;
  3595. X1X1:mp_clear (&x1x1);
  3596. X0X0:mp_clear (&x0x0);
  3597. T2:mp_clear (&t2);
  3598. T1:mp_clear (&t1);
  3599. X1:mp_clear (&x1);
  3600. X0:mp_clear (&x0);
  3601. ERR:
  3602. return err;
  3603. }
  3604. #endif
  3605. /* End: bn_mp_karatsuba_sqr.c */
  3606. /* Start: bn_mp_lcm.c */
  3607. #include <ltc_tommath.h>
  3608. #ifdef BN_MP_LCM_C
  3609. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  3610. *
  3611. * LibTomMath is a library that provides multiple-precision
  3612. * integer arithmetic as well as number theoretic functionality.
  3613. *
  3614. * The library was designed directly after the MPI library by
  3615. * Michael Fromberger but has been written from scratch with
  3616. * additional optimizations in place.
  3617. *
  3618. * The library is free for all purposes without any express
  3619. * guarantee it works.
  3620. *
  3621. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  3622. */
  3623. /* computes least common multiple as |a*b|/(a, b) */
  3624. int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
  3625. {
  3626. int res;
  3627. mp_int t1, t2;
  3628. if ((res = mp_init_multi (&t1, &t2, NULL)) != MP_OKAY) {
  3629. return res;
  3630. }
  3631. /* t1 = get the GCD of the two inputs */
  3632. if ((res = mp_gcd (a, b, &t1)) != MP_OKAY) {
  3633. goto __T;
  3634. }
  3635. /* divide the smallest by the GCD */
  3636. if (mp_cmp_mag(a, b) == MP_LT) {
  3637. /* store quotient in t2 such that t2 * b is the LCM */
  3638. if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) {
  3639. goto __T;
  3640. }
  3641. res = mp_mul(b, &t2, c);
  3642. } else {
  3643. /* store quotient in t2 such that t2 * a is the LCM */
  3644. if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) {
  3645. goto __T;
  3646. }
  3647. res = mp_mul(a, &t2, c);
  3648. }
  3649. /* fix the sign to positive */
  3650. c->sign = MP_ZPOS;
  3651. __T:
  3652. mp_clear_multi (&t1, &t2, NULL);
  3653. return res;
  3654. }
  3655. #endif
  3656. /* End: bn_mp_lcm.c */
  3657. /* Start: bn_mp_lshd.c */
  3658. #include <ltc_tommath.h>
  3659. #ifdef BN_MP_LSHD_C
  3660. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  3661. *
  3662. * LibTomMath is a library that provides multiple-precision
  3663. * integer arithmetic as well as number theoretic functionality.
  3664. *
  3665. * The library was designed directly after the MPI library by
  3666. * Michael Fromberger but has been written from scratch with
  3667. * additional optimizations in place.
  3668. *
  3669. * The library is free for all purposes without any express
  3670. * guarantee it works.
  3671. *
  3672. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  3673. */
  3674. /* shift left a certain amount of digits */
  3675. int mp_lshd (mp_int * a, int b)
  3676. {
  3677. int x, res;
  3678. /* if its less than zero return */
  3679. if (b <= 0) {
  3680. return MP_OKAY;
  3681. }
  3682. /* grow to fit the new digits */
  3683. if (a->alloc < a->used + b) {
  3684. if ((res = mp_grow (a, a->used + b)) != MP_OKAY) {
  3685. return res;
  3686. }
  3687. }
  3688. {
  3689. register mp_digit *top, *bottom;
  3690. /* increment the used by the shift amount then copy upwards */
  3691. a->used += b;
  3692. /* top */
  3693. top = a->dp + a->used - 1;
  3694. /* base */
  3695. bottom = a->dp + a->used - 1 - b;
  3696. /* much like mp_rshd this is implemented using a sliding window
  3697. * except the window goes the otherway around. Copying from
  3698. * the bottom to the top. see bn_mp_rshd.c for more info.
  3699. */
  3700. for (x = a->used - 1; x >= b; x--) {
  3701. *top-- = *bottom--;
  3702. }
  3703. /* zero the lower digits */
  3704. top = a->dp;
  3705. for (x = 0; x < b; x++) {
  3706. *top++ = 0;
  3707. }
  3708. }
  3709. return MP_OKAY;
  3710. }
  3711. #endif
  3712. /* End: bn_mp_lshd.c */
  3713. /* Start: bn_mp_mod.c */
  3714. #include <ltc_tommath.h>
  3715. #ifdef BN_MP_MOD_C
  3716. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  3717. *
  3718. * LibTomMath is a library that provides multiple-precision
  3719. * integer arithmetic as well as number theoretic functionality.
  3720. *
  3721. * The library was designed directly after the MPI library by
  3722. * Michael Fromberger but has been written from scratch with
  3723. * additional optimizations in place.
  3724. *
  3725. * The library is free for all purposes without any express
  3726. * guarantee it works.
  3727. *
  3728. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  3729. */
  3730. /* c = a mod b, 0 <= c < b */
  3731. int
  3732. mp_mod (mp_int * a, mp_int * b, mp_int * c)
  3733. {
  3734. mp_int t;
  3735. int res;
  3736. if ((res = mp_init (&t)) != MP_OKAY) {
  3737. return res;
  3738. }
  3739. if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) {
  3740. mp_clear (&t);
  3741. return res;
  3742. }
  3743. if (t.sign != b->sign) {
  3744. res = mp_add (b, &t, c);
  3745. } else {
  3746. res = MP_OKAY;
  3747. mp_exch (&t, c);
  3748. }
  3749. mp_clear (&t);
  3750. return res;
  3751. }
  3752. #endif
  3753. /* End: bn_mp_mod.c */
  3754. /* Start: bn_mp_mod_2d.c */
  3755. #include <ltc_tommath.h>
  3756. #ifdef BN_MP_MOD_2D_C
  3757. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  3758. *
  3759. * LibTomMath is a library that provides multiple-precision
  3760. * integer arithmetic as well as number theoretic functionality.
  3761. *
  3762. * The library was designed directly after the MPI library by
  3763. * Michael Fromberger but has been written from scratch with
  3764. * additional optimizations in place.
  3765. *
  3766. * The library is free for all purposes without any express
  3767. * guarantee it works.
  3768. *
  3769. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  3770. */
  3771. /* calc a value mod 2**b */
  3772. int
  3773. mp_mod_2d (mp_int * a, int b, mp_int * c)
  3774. {
  3775. int x, res;
  3776. /* if b is <= 0 then zero the int */
  3777. if (b <= 0) {
  3778. mp_zero (c);
  3779. return MP_OKAY;
  3780. }
  3781. /* if the modulus is larger than the value than return */
  3782. if (b > (int) (a->used * DIGIT_BIT)) {
  3783. res = mp_copy (a, c);
  3784. return res;
  3785. }
  3786. /* copy */
  3787. if ((res = mp_copy (a, c)) != MP_OKAY) {
  3788. return res;
  3789. }
  3790. /* zero digits above the last digit of the modulus */
  3791. for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
  3792. c->dp[x] = 0;
  3793. }
  3794. /* clear the digit that is not completely outside/inside the modulus */
  3795. c->dp[b / DIGIT_BIT] &=
  3796. (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1));
  3797. mp_clamp (c);
  3798. return MP_OKAY;
  3799. }
  3800. #endif
  3801. /* End: bn_mp_mod_2d.c */
  3802. /* Start: bn_mp_mod_d.c */
  3803. #include <ltc_tommath.h>
  3804. #ifdef BN_MP_MOD_D_C
  3805. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  3806. *
  3807. * LibTomMath is a library that provides multiple-precision
  3808. * integer arithmetic as well as number theoretic functionality.
  3809. *
  3810. * The library was designed directly after the MPI library by
  3811. * Michael Fromberger but has been written from scratch with
  3812. * additional optimizations in place.
  3813. *
  3814. * The library is free for all purposes without any express
  3815. * guarantee it works.
  3816. *
  3817. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  3818. */
  3819. int
  3820. mp_mod_d (mp_int * a, mp_digit b, mp_digit * c)
  3821. {
  3822. return mp_div_d(a, b, NULL, c);
  3823. }
  3824. #endif
  3825. /* End: bn_mp_mod_d.c */
  3826. /* Start: bn_mp_montgomery_calc_normalization.c */
  3827. #include <ltc_tommath.h>
  3828. #ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
  3829. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  3830. *
  3831. * LibTomMath is a library that provides multiple-precision
  3832. * integer arithmetic as well as number theoretic functionality.
  3833. *
  3834. * The library was designed directly after the MPI library by
  3835. * Michael Fromberger but has been written from scratch with
  3836. * additional optimizations in place.
  3837. *
  3838. * The library is free for all purposes without any express
  3839. * guarantee it works.
  3840. *
  3841. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  3842. */
  3843. /*
  3844. * shifts with subtractions when the result is greater than b.
  3845. *
  3846. * The method is slightly modified to shift B unconditionally upto just under
  3847. * the leading bit of b. This saves alot of multiple precision shifting.
  3848. */
  3849. int mp_montgomery_calc_normalization (mp_int * a, mp_int * b)
  3850. {
  3851. int x, bits, res;
  3852. /* how many bits of last digit does b use */
  3853. bits = mp_count_bits (b) % DIGIT_BIT;
  3854. if (b->used > 1) {
  3855. if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) {
  3856. return res;
  3857. }
  3858. } else {
  3859. mp_set(a, 1);
  3860. bits = 1;
  3861. }
  3862. /* now compute C = A * B mod b */
  3863. for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
  3864. if ((res = mp_mul_2 (a, a)) != MP_OKAY) {
  3865. return res;
  3866. }
  3867. if (mp_cmp_mag (a, b) != MP_LT) {
  3868. if ((res = s_mp_sub (a, b, a)) != MP_OKAY) {
  3869. return res;
  3870. }
  3871. }
  3872. }
  3873. return MP_OKAY;
  3874. }
  3875. #endif
  3876. /* End: bn_mp_montgomery_calc_normalization.c */
  3877. /* Start: bn_mp_montgomery_reduce.c */
  3878. #include <ltc_tommath.h>
  3879. #ifdef BN_MP_MONTGOMERY_REDUCE_C
  3880. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  3881. *
  3882. * LibTomMath is a library that provides multiple-precision
  3883. * integer arithmetic as well as number theoretic functionality.
  3884. *
  3885. * The library was designed directly after the MPI library by
  3886. * Michael Fromberger but has been written from scratch with
  3887. * additional optimizations in place.
  3888. *
  3889. * The library is free for all purposes without any express
  3890. * guarantee it works.
  3891. *
  3892. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  3893. */
  3894. /* computes xR**-1 == x (mod N) via Montgomery Reduction */
  3895. int
  3896. mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
  3897. {
  3898. int ix, res, digs;
  3899. mp_digit mu;
  3900. /* can the fast reduction [comba] method be used?
  3901. *
  3902. * Note that unlike in mul you're safely allowed *less*
  3903. * than the available columns [255 per default] since carries
  3904. * are fixed up in the inner loop.
  3905. */
  3906. digs = n->used * 2 + 1;
  3907. if ((digs < MP_WARRAY) &&
  3908. n->used <
  3909. (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
  3910. return fast_mp_montgomery_reduce (x, n, rho);
  3911. }
  3912. /* grow the input as required */
  3913. if (x->alloc < digs) {
  3914. if ((res = mp_grow (x, digs)) != MP_OKAY) {
  3915. return res;
  3916. }
  3917. }
  3918. x->used = digs;
  3919. for (ix = 0; ix < n->used; ix++) {
  3920. /* mu = ai * rho mod b
  3921. *
  3922. * The value of rho must be precalculated via
  3923. * montgomery_setup() such that
  3924. * it equals -1/n0 mod b this allows the
  3925. * following inner loop to reduce the
  3926. * input one digit at a time
  3927. */
  3928. mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK);
  3929. /* a = a + mu * m * b**i */
  3930. {
  3931. register int iy;
  3932. register mp_digit *tmpn, *tmpx, u;
  3933. register mp_word r;
  3934. /* alias for digits of the modulus */
  3935. tmpn = n->dp;
  3936. /* alias for the digits of x [the input] */
  3937. tmpx = x->dp + ix;
  3938. /* set the carry to zero */
  3939. u = 0;
  3940. /* Multiply and add in place */
  3941. for (iy = 0; iy < n->used; iy++) {
  3942. /* compute product and sum */
  3943. r = ((mp_word)mu) * ((mp_word)*tmpn++) +
  3944. ((mp_word) u) + ((mp_word) * tmpx);
  3945. /* get carry */
  3946. u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
  3947. /* fix digit */
  3948. *tmpx++ = (mp_digit)(r & ((mp_word) MP_MASK));
  3949. }
  3950. /* At this point the ix'th digit of x should be zero */
  3951. /* propagate carries upwards as required*/
  3952. while (u) {
  3953. *tmpx += u;
  3954. u = *tmpx >> DIGIT_BIT;
  3955. *tmpx++ &= MP_MASK;
  3956. }
  3957. }
  3958. }
  3959. /* at this point the n.used'th least
  3960. * significant digits of x are all zero
  3961. * which means we can shift x to the
  3962. * right by n.used digits and the
  3963. * residue is unchanged.
  3964. */
  3965. /* x = x/b**n.used */
  3966. mp_clamp(x);
  3967. mp_rshd (x, n->used);
  3968. /* if x >= n then x = x - n */
  3969. if (mp_cmp_mag (x, n) != MP_LT) {
  3970. return s_mp_sub (x, n, x);
  3971. }
  3972. return MP_OKAY;
  3973. }
  3974. #endif
  3975. /* End: bn_mp_montgomery_reduce.c */
  3976. /* Start: bn_mp_montgomery_setup.c */
  3977. #include <ltc_tommath.h>
  3978. #ifdef BN_MP_MONTGOMERY_SETUP_C
  3979. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  3980. *
  3981. * LibTomMath is a library that provides multiple-precision
  3982. * integer arithmetic as well as number theoretic functionality.
  3983. *
  3984. * The library was designed directly after the MPI library by
  3985. * Michael Fromberger but has been written from scratch with
  3986. * additional optimizations in place.
  3987. *
  3988. * The library is free for all purposes without any express
  3989. * guarantee it works.
  3990. *
  3991. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  3992. */
  3993. /* setups the montgomery reduction stuff */
  3994. int
  3995. mp_montgomery_setup (mp_int * n, mp_digit * rho)
  3996. {
  3997. mp_digit x, b;
  3998. /* fast inversion mod 2**k
  3999. *
  4000. * Based on the fact that
  4001. *
  4002. * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n)
  4003. * => 2*X*A - X*X*A*A = 1
  4004. * => 2*(1) - (1) = 1
  4005. */
  4006. b = n->dp[0];
  4007. if ((b & 1) == 0) {
  4008. return MP_VAL;
  4009. }
  4010. x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
  4011. x *= 2 - b * x; /* here x*a==1 mod 2**8 */
  4012. #if !defined(MP_8BIT)
  4013. x *= 2 - b * x; /* here x*a==1 mod 2**16 */
  4014. #endif
  4015. #if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))
  4016. x *= 2 - b * x; /* here x*a==1 mod 2**32 */
  4017. #endif
  4018. #ifdef MP_64BIT
  4019. x *= 2 - b * x; /* here x*a==1 mod 2**64 */
  4020. #endif
  4021. /* rho = -1/m mod b */
  4022. *rho = (((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK;
  4023. return MP_OKAY;
  4024. }
  4025. #endif
  4026. /* End: bn_mp_montgomery_setup.c */
  4027. /* Start: bn_mp_mul.c */
  4028. #include <ltc_tommath.h>
  4029. #ifdef BN_MP_MUL_C
  4030. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  4031. *
  4032. * LibTomMath is a library that provides multiple-precision
  4033. * integer arithmetic as well as number theoretic functionality.
  4034. *
  4035. * The library was designed directly after the MPI library by
  4036. * Michael Fromberger but has been written from scratch with
  4037. * additional optimizations in place.
  4038. *
  4039. * The library is free for all purposes without any express
  4040. * guarantee it works.
  4041. *
  4042. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  4043. */
  4044. /* high level multiplication (handles sign) */
  4045. int mp_mul (mp_int * a, mp_int * b, mp_int * c)
  4046. {
  4047. int res, neg;
  4048. neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
  4049. /* use Toom-Cook? */
  4050. #ifdef BN_MP_TOOM_MUL_C
  4051. if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) {
  4052. res = mp_toom_mul(a, b, c);
  4053. } else
  4054. #endif
  4055. #ifdef BN_MP_KARATSUBA_MUL_C
  4056. /* use Karatsuba? */
  4057. if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) {
  4058. res = mp_karatsuba_mul (a, b, c);
  4059. } else
  4060. #endif
  4061. {
  4062. /* can we use the fast multiplier?
  4063. *
  4064. * The fast multiplier can be used if the output will
  4065. * have less than MP_WARRAY digits and the number of
  4066. * digits won't affect carry propagation
  4067. */
  4068. int digs = a->used + b->used + 1;
  4069. #ifdef BN_FAST_S_MP_MUL_DIGS_C
  4070. if ((digs < MP_WARRAY) &&
  4071. MIN(a->used, b->used) <=
  4072. (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
  4073. res = fast_s_mp_mul_digs (a, b, c, digs);
  4074. } else
  4075. #endif
  4076. #ifdef BN_S_MP_MUL_DIGS_C
  4077. res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */
  4078. #else
  4079. res = MP_VAL;
  4080. #endif
  4081. }
  4082. c->sign = (c->used > 0) ? neg : MP_ZPOS;
  4083. return res;
  4084. }
  4085. #endif
  4086. /* End: bn_mp_mul.c */
  4087. /* Start: bn_mp_mul_2.c */
  4088. #include <ltc_tommath.h>
  4089. #ifdef BN_MP_MUL_2_C
  4090. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  4091. *
  4092. * LibTomMath is a library that provides multiple-precision
  4093. * integer arithmetic as well as number theoretic functionality.
  4094. *
  4095. * The library was designed directly after the MPI library by
  4096. * Michael Fromberger but has been written from scratch with
  4097. * additional optimizations in place.
  4098. *
  4099. * The library is free for all purposes without any express
  4100. * guarantee it works.
  4101. *
  4102. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  4103. */
  4104. /* b = a*2 */
  4105. int mp_mul_2(mp_int * a, mp_int * b)
  4106. {
  4107. int x, res, oldused;
  4108. /* grow to accomodate result */
  4109. if (b->alloc < a->used + 1) {
  4110. if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) {
  4111. return res;
  4112. }
  4113. }
  4114. oldused = b->used;
  4115. b->used = a->used;
  4116. {
  4117. register mp_digit r, rr, *tmpa, *tmpb;
  4118. /* alias for source */
  4119. tmpa = a->dp;
  4120. /* alias for dest */
  4121. tmpb = b->dp;
  4122. /* carry */
  4123. r = 0;
  4124. for (x = 0; x < a->used; x++) {
  4125. /* get what will be the *next* carry bit from the
  4126. * MSB of the current digit
  4127. */
  4128. rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
  4129. /* now shift up this digit, add in the carry [from the previous] */
  4130. *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK;
  4131. /* copy the carry that would be from the source
  4132. * digit into the next iteration
  4133. */
  4134. r = rr;
  4135. }
  4136. /* new leading digit? */
  4137. if (r != 0) {
  4138. /* add a MSB which is always 1 at this point */
  4139. *tmpb = 1;
  4140. ++(b->used);
  4141. }
  4142. /* now zero any excess digits on the destination
  4143. * that we didn't write to
  4144. */
  4145. tmpb = b->dp + b->used;
  4146. for (x = b->used; x < oldused; x++) {
  4147. *tmpb++ = 0;
  4148. }
  4149. }
  4150. b->sign = a->sign;
  4151. return MP_OKAY;
  4152. }
  4153. #endif
  4154. /* End: bn_mp_mul_2.c */
  4155. /* Start: bn_mp_mul_2d.c */
  4156. #include <ltc_tommath.h>
  4157. #ifdef BN_MP_MUL_2D_C
  4158. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  4159. *
  4160. * LibTomMath is a library that provides multiple-precision
  4161. * integer arithmetic as well as number theoretic functionality.
  4162. *
  4163. * The library was designed directly after the MPI library by
  4164. * Michael Fromberger but has been written from scratch with
  4165. * additional optimizations in place.
  4166. *
  4167. * The library is free for all purposes without any express
  4168. * guarantee it works.
  4169. *
  4170. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  4171. */
  4172. /* shift left by a certain bit count */
  4173. int mp_mul_2d (mp_int * a, int b, mp_int * c)
  4174. {
  4175. mp_digit d;
  4176. int res;
  4177. /* copy */
  4178. if (a != c) {
  4179. if ((res = mp_copy (a, c)) != MP_OKAY) {
  4180. return res;
  4181. }
  4182. }
  4183. if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) {
  4184. if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) {
  4185. return res;
  4186. }
  4187. }
  4188. /* shift by as many digits in the bit count */
  4189. if (b >= (int)DIGIT_BIT) {
  4190. if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) {
  4191. return res;
  4192. }
  4193. }
  4194. /* shift any bit count < DIGIT_BIT */
  4195. d = (mp_digit) (b % DIGIT_BIT);
  4196. if (d != 0) {
  4197. register mp_digit *tmpc, shift, mask, r, rr;
  4198. register int x;
  4199. /* bitmask for carries */
  4200. mask = (((mp_digit)1) << d) - 1;
  4201. /* shift for msbs */
  4202. shift = DIGIT_BIT - d;
  4203. /* alias */
  4204. tmpc = c->dp;
  4205. /* carry */
  4206. r = 0;
  4207. for (x = 0; x < c->used; x++) {
  4208. /* get the higher bits of the current word */
  4209. rr = (*tmpc >> shift) & mask;
  4210. /* shift the current word and OR in the carry */
  4211. *tmpc = ((*tmpc << d) | r) & MP_MASK;
  4212. ++tmpc;
  4213. /* set the carry to the carry bits of the current word */
  4214. r = rr;
  4215. }
  4216. /* set final carry */
  4217. if (r != 0) {
  4218. c->dp[(c->used)++] = r;
  4219. }
  4220. }
  4221. mp_clamp (c);
  4222. return MP_OKAY;
  4223. }
  4224. #endif
  4225. /* End: bn_mp_mul_2d.c */
  4226. /* Start: bn_mp_mul_d.c */
  4227. #include <ltc_tommath.h>
  4228. #ifdef BN_MP_MUL_D_C
  4229. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  4230. *
  4231. * LibTomMath is a library that provides multiple-precision
  4232. * integer arithmetic as well as number theoretic functionality.
  4233. *
  4234. * The library was designed directly after the MPI library by
  4235. * Michael Fromberger but has been written from scratch with
  4236. * additional optimizations in place.
  4237. *
  4238. * The library is free for all purposes without any express
  4239. * guarantee it works.
  4240. *
  4241. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  4242. */
  4243. /* multiply by a digit */
  4244. int
  4245. mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
  4246. {
  4247. mp_digit u, *tmpa, *tmpc;
  4248. mp_word r;
  4249. int ix, res, olduse;
  4250. /* make sure c is big enough to hold a*b */
  4251. if (c->alloc < a->used + 1) {
  4252. if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) {
  4253. return res;
  4254. }
  4255. }
  4256. /* get the original destinations used count */
  4257. olduse = c->used;
  4258. /* set the sign */
  4259. c->sign = a->sign;
  4260. /* alias for a->dp [source] */
  4261. tmpa = a->dp;
  4262. /* alias for c->dp [dest] */
  4263. tmpc = c->dp;
  4264. /* zero carry */
  4265. u = 0;
  4266. /* compute columns */
  4267. for (ix = 0; ix < a->used; ix++) {
  4268. /* compute product and carry sum for this term */
  4269. r = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);
  4270. /* mask off higher bits to get a single digit */
  4271. *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));
  4272. /* send carry into next iteration */
  4273. u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
  4274. }
  4275. /* store final carry [if any] */
  4276. *tmpc++ = u;
  4277. /* now zero digits above the top */
  4278. while (ix++ < olduse) {
  4279. *tmpc++ = 0;
  4280. }
  4281. /* set used count */
  4282. c->used = a->used + 1;
  4283. mp_clamp(c);
  4284. return MP_OKAY;
  4285. }
  4286. #endif
  4287. /* End: bn_mp_mul_d.c */
  4288. /* Start: bn_mp_mulmod.c */
  4289. #include <ltc_tommath.h>
  4290. #ifdef BN_MP_MULMOD_C
  4291. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  4292. *
  4293. * LibTomMath is a library that provides multiple-precision
  4294. * integer arithmetic as well as number theoretic functionality.
  4295. *
  4296. * The library was designed directly after the MPI library by
  4297. * Michael Fromberger but has been written from scratch with
  4298. * additional optimizations in place.
  4299. *
  4300. * The library is free for all purposes without any express
  4301. * guarantee it works.
  4302. *
  4303. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  4304. */
  4305. /* d = a * b (mod c) */
  4306. int
  4307. mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
  4308. {
  4309. int res;
  4310. mp_int t;
  4311. if ((res = mp_init (&t)) != MP_OKAY) {
  4312. return res;
  4313. }
  4314. if ((res = mp_mul (a, b, &t)) != MP_OKAY) {
  4315. mp_clear (&t);
  4316. return res;
  4317. }
  4318. res = mp_mod (&t, c, d);
  4319. mp_clear (&t);
  4320. return res;
  4321. }
  4322. #endif
  4323. /* End: bn_mp_mulmod.c */
  4324. /* Start: bn_mp_n_root.c */
  4325. #include <ltc_tommath.h>
  4326. #ifdef BN_MP_N_ROOT_C
  4327. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  4328. *
  4329. * LibTomMath is a library that provides multiple-precision
  4330. * integer arithmetic as well as number theoretic functionality.
  4331. *
  4332. * The library was designed directly after the MPI library by
  4333. * Michael Fromberger but has been written from scratch with
  4334. * additional optimizations in place.
  4335. *
  4336. * The library is free for all purposes without any express
  4337. * guarantee it works.
  4338. *
  4339. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  4340. */
  4341. /* find the n'th root of an integer
  4342. *
  4343. * Result found such that (c)**b <= a and (c+1)**b > a
  4344. *
  4345. * This algorithm uses Newton's approximation
  4346. * x[i+1] = x[i] - f(x[i])/f'(x[i])
  4347. * which will find the root in log(N) time where
  4348. * each step involves a fair bit. This is not meant to
  4349. * find huge roots [square and cube, etc].
  4350. */
  4351. int mp_n_root (mp_int * a, mp_digit b, mp_int * c)
  4352. {
  4353. mp_int t1, t2, t3;
  4354. int res, neg;
  4355. /* input must be positive if b is even */
  4356. if ((b & 1) == 0 && a->sign == MP_NEG) {
  4357. return MP_VAL;
  4358. }
  4359. if ((res = mp_init (&t1)) != MP_OKAY) {
  4360. return res;
  4361. }
  4362. if ((res = mp_init (&t2)) != MP_OKAY) {
  4363. goto __T1;
  4364. }
  4365. if ((res = mp_init (&t3)) != MP_OKAY) {
  4366. goto __T2;
  4367. }
  4368. /* if a is negative fudge the sign but keep track */
  4369. neg = a->sign;
  4370. a->sign = MP_ZPOS;
  4371. /* t2 = 2 */
  4372. mp_set (&t2, 2);
  4373. do {
  4374. /* t1 = t2 */
  4375. if ((res = mp_copy (&t2, &t1)) != MP_OKAY) {
  4376. goto __T3;
  4377. }
  4378. /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */
  4379. /* t3 = t1**(b-1) */
  4380. if ((res = mp_expt_d (&t1, b - 1, &t3)) != MP_OKAY) {
  4381. goto __T3;
  4382. }
  4383. /* numerator */
  4384. /* t2 = t1**b */
  4385. if ((res = mp_mul (&t3, &t1, &t2)) != MP_OKAY) {
  4386. goto __T3;
  4387. }
  4388. /* t2 = t1**b - a */
  4389. if ((res = mp_sub (&t2, a, &t2)) != MP_OKAY) {
  4390. goto __T3;
  4391. }
  4392. /* denominator */
  4393. /* t3 = t1**(b-1) * b */
  4394. if ((res = mp_mul_d (&t3, b, &t3)) != MP_OKAY) {
  4395. goto __T3;
  4396. }
  4397. /* t3 = (t1**b - a)/(b * t1**(b-1)) */
  4398. if ((res = mp_div (&t2, &t3, &t3, NULL)) != MP_OKAY) {
  4399. goto __T3;
  4400. }
  4401. if ((res = mp_sub (&t1, &t3, &t2)) != MP_OKAY) {
  4402. goto __T3;
  4403. }
  4404. } while (mp_cmp (&t1, &t2) != MP_EQ);
  4405. /* result can be off by a few so check */
  4406. for (;;) {
  4407. if ((res = mp_expt_d (&t1, b, &t2)) != MP_OKAY) {
  4408. goto __T3;
  4409. }
  4410. if (mp_cmp (&t2, a) == MP_GT) {
  4411. if ((res = mp_sub_d (&t1, 1, &t1)) != MP_OKAY) {
  4412. goto __T3;
  4413. }
  4414. } else {
  4415. break;
  4416. }
  4417. }
  4418. /* reset the sign of a first */
  4419. a->sign = neg;
  4420. /* set the result */
  4421. mp_exch (&t1, c);
  4422. /* set the sign of the result */
  4423. c->sign = neg;
  4424. res = MP_OKAY;
  4425. __T3:mp_clear (&t3);
  4426. __T2:mp_clear (&t2);
  4427. __T1:mp_clear (&t1);
  4428. return res;
  4429. }
  4430. #endif
  4431. /* End: bn_mp_n_root.c */
  4432. /* Start: bn_mp_neg.c */
  4433. #include <ltc_tommath.h>
  4434. #ifdef BN_MP_NEG_C
  4435. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  4436. *
  4437. * LibTomMath is a library that provides multiple-precision
  4438. * integer arithmetic as well as number theoretic functionality.
  4439. *
  4440. * The library was designed directly after the MPI library by
  4441. * Michael Fromberger but has been written from scratch with
  4442. * additional optimizations in place.
  4443. *
  4444. * The library is free for all purposes without any express
  4445. * guarantee it works.
  4446. *
  4447. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  4448. */
  4449. /* b = -a */
  4450. int mp_neg (mp_int * a, mp_int * b)
  4451. {
  4452. int res;
  4453. if ((res = mp_copy (a, b)) != MP_OKAY) {
  4454. return res;
  4455. }
  4456. if (mp_iszero(b) != MP_YES) {
  4457. b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS;
  4458. }
  4459. return MP_OKAY;
  4460. }
  4461. #endif
  4462. /* End: bn_mp_neg.c */
  4463. /* Start: bn_mp_or.c */
  4464. #include <ltc_tommath.h>
  4465. #ifdef BN_MP_OR_C
  4466. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  4467. *
  4468. * LibTomMath is a library that provides multiple-precision
  4469. * integer arithmetic as well as number theoretic functionality.
  4470. *
  4471. * The library was designed directly after the MPI library by
  4472. * Michael Fromberger but has been written from scratch with
  4473. * additional optimizations in place.
  4474. *
  4475. * The library is free for all purposes without any express
  4476. * guarantee it works.
  4477. *
  4478. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  4479. */
  4480. /* OR two ints together */
  4481. int mp_or (mp_int * a, mp_int * b, mp_int * c)
  4482. {
  4483. int res, ix, px;
  4484. mp_int t, *x;
  4485. if (a->used > b->used) {
  4486. if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
  4487. return res;
  4488. }
  4489. px = b->used;
  4490. x = b;
  4491. } else {
  4492. if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
  4493. return res;
  4494. }
  4495. px = a->used;
  4496. x = a;
  4497. }
  4498. for (ix = 0; ix < px; ix++) {
  4499. t.dp[ix] |= x->dp[ix];
  4500. }
  4501. mp_clamp (&t);
  4502. mp_exch (c, &t);
  4503. mp_clear (&t);
  4504. return MP_OKAY;
  4505. }
  4506. #endif
  4507. /* End: bn_mp_or.c */
  4508. /* Start: bn_mp_prime_fermat.c */
  4509. #include <ltc_tommath.h>
  4510. #ifdef BN_MP_PRIME_FERMAT_C
  4511. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  4512. *
  4513. * LibTomMath is a library that provides multiple-precision
  4514. * integer arithmetic as well as number theoretic functionality.
  4515. *
  4516. * The library was designed directly after the MPI library by
  4517. * Michael Fromberger but has been written from scratch with
  4518. * additional optimizations in place.
  4519. *
  4520. * The library is free for all purposes without any express
  4521. * guarantee it works.
  4522. *
  4523. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  4524. */
  4525. /* performs one Fermat test.
  4526. *
  4527. * If "a" were prime then b**a == b (mod a) since the order of
  4528. * the multiplicative sub-group would be phi(a) = a-1. That means
  4529. * it would be the same as b**(a mod (a-1)) == b**1 == b (mod a).
  4530. *
  4531. * Sets result to 1 if the congruence holds, or zero otherwise.
  4532. */
  4533. int mp_prime_fermat (mp_int * a, mp_int * b, int *result)
  4534. {
  4535. mp_int t;
  4536. int err;
  4537. /* default to composite */
  4538. *result = MP_NO;
  4539. /* ensure b > 1 */
  4540. if (mp_cmp_d(b, 1) != MP_GT) {
  4541. return MP_VAL;
  4542. }
  4543. /* init t */
  4544. if ((err = mp_init (&t)) != MP_OKAY) {
  4545. return err;
  4546. }
  4547. /* compute t = b**a mod a */
  4548. if ((err = mp_exptmod (b, a, a, &t)) != MP_OKAY) {
  4549. goto __T;
  4550. }
  4551. /* is it equal to b? */
  4552. if (mp_cmp (&t, b) == MP_EQ) {
  4553. *result = MP_YES;
  4554. }
  4555. err = MP_OKAY;
  4556. __T:mp_clear (&t);
  4557. return err;
  4558. }
  4559. #endif
  4560. /* End: bn_mp_prime_fermat.c */
  4561. /* Start: bn_mp_prime_is_divisible.c */
  4562. #include <ltc_tommath.h>
  4563. #ifdef BN_MP_PRIME_IS_DIVISIBLE_C
  4564. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  4565. *
  4566. * LibTomMath is a library that provides multiple-precision
  4567. * integer arithmetic as well as number theoretic functionality.
  4568. *
  4569. * The library was designed directly after the MPI library by
  4570. * Michael Fromberger but has been written from scratch with
  4571. * additional optimizations in place.
  4572. *
  4573. * The library is free for all purposes without any express
  4574. * guarantee it works.
  4575. *
  4576. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  4577. */
  4578. /* determines if an integers is divisible by one
  4579. * of the first PRIME_SIZE primes or not
  4580. *
  4581. * sets result to 0 if not, 1 if yes
  4582. */
  4583. int mp_prime_is_divisible (mp_int * a, int *result)
  4584. {
  4585. int err, ix;
  4586. mp_digit res;
  4587. /* default to not */
  4588. *result = MP_NO;
  4589. for (ix = 0; ix < PRIME_SIZE; ix++) {
  4590. /* what is a mod __prime_tab[ix] */
  4591. if ((err = mp_mod_d (a, __prime_tab[ix], &res)) != MP_OKAY) {
  4592. return err;
  4593. }
  4594. /* is the residue zero? */
  4595. if (res == 0) {
  4596. *result = MP_YES;
  4597. return MP_OKAY;
  4598. }
  4599. }
  4600. return MP_OKAY;
  4601. }
  4602. #endif
  4603. /* End: bn_mp_prime_is_divisible.c */
  4604. /* Start: bn_mp_prime_is_prime.c */
  4605. #include <ltc_tommath.h>
  4606. #ifdef BN_MP_PRIME_IS_PRIME_C
  4607. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  4608. *
  4609. * LibTomMath is a library that provides multiple-precision
  4610. * integer arithmetic as well as number theoretic functionality.
  4611. *
  4612. * The library was designed directly after the MPI library by
  4613. * Michael Fromberger but has been written from scratch with
  4614. * additional optimizations in place.
  4615. *
  4616. * The library is free for all purposes without any express
  4617. * guarantee it works.
  4618. *
  4619. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  4620. */
  4621. /* performs a variable number of rounds of Miller-Rabin
  4622. *
  4623. * Probability of error after t rounds is no more than
  4624. *
  4625. * Sets result to 1 if probably prime, 0 otherwise
  4626. */
  4627. int mp_prime_is_prime (mp_int * a, int t, int *result)
  4628. {
  4629. mp_int b;
  4630. int ix, err, res;
  4631. /* default to no */
  4632. *result = MP_NO;
  4633. /* valid value of t? */
  4634. if (t <= 0 || t > PRIME_SIZE) {
  4635. return MP_VAL;
  4636. }
  4637. /* is the input equal to one of the primes in the table? */
  4638. for (ix = 0; ix < PRIME_SIZE; ix++) {
  4639. if (mp_cmp_d(a, __prime_tab[ix]) == MP_EQ) {
  4640. *result = 1;
  4641. return MP_OKAY;
  4642. }
  4643. }
  4644. /* first perform trial division */
  4645. if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) {
  4646. return err;
  4647. }
  4648. /* return if it was trivially divisible */
  4649. if (res == MP_YES) {
  4650. return MP_OKAY;
  4651. }
  4652. /* now perform the miller-rabin rounds */
  4653. if ((err = mp_init (&b)) != MP_OKAY) {
  4654. return err;
  4655. }
  4656. for (ix = 0; ix < t; ix++) {
  4657. /* set the prime */
  4658. mp_set (&b, __prime_tab[ix]);
  4659. if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) {
  4660. goto __B;
  4661. }
  4662. if (res == MP_NO) {
  4663. goto __B;
  4664. }
  4665. }
  4666. /* passed the test */
  4667. *result = MP_YES;
  4668. __B:mp_clear (&b);
  4669. return err;
  4670. }
  4671. #endif
  4672. /* End: bn_mp_prime_is_prime.c */
  4673. /* Start: bn_mp_prime_miller_rabin.c */
  4674. #include <ltc_tommath.h>
  4675. #ifdef BN_MP_PRIME_MILLER_RABIN_C
  4676. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  4677. *
  4678. * LibTomMath is a library that provides multiple-precision
  4679. * integer arithmetic as well as number theoretic functionality.
  4680. *
  4681. * The library was designed directly after the MPI library by
  4682. * Michael Fromberger but has been written from scratch with
  4683. * additional optimizations in place.
  4684. *
  4685. * The library is free for all purposes without any express
  4686. * guarantee it works.
  4687. *
  4688. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  4689. */
  4690. /* Miller-Rabin test of "a" to the base of "b" as described in
  4691. * HAC pp. 139 Algorithm 4.24
  4692. *
  4693. * Sets result to 0 if definitely composite or 1 if probably prime.
  4694. * Randomly the chance of error is no more than 1/4 and often
  4695. * very much lower.
  4696. */
  4697. int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
  4698. {
  4699. mp_int n1, y, r;
  4700. int s, j, err;
  4701. /* default */
  4702. *result = MP_NO;
  4703. /* ensure b > 1 */
  4704. if (mp_cmp_d(b, 1) != MP_GT) {
  4705. return MP_VAL;
  4706. }
  4707. /* get n1 = a - 1 */
  4708. if ((err = mp_init_copy (&n1, a)) != MP_OKAY) {
  4709. return err;
  4710. }
  4711. if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) {
  4712. goto __N1;
  4713. }
  4714. /* set 2**s * r = n1 */
  4715. if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) {
  4716. goto __N1;
  4717. }
  4718. /* count the number of least significant bits
  4719. * which are zero
  4720. */
  4721. s = mp_cnt_lsb(&r);
  4722. /* now divide n - 1 by 2**s */
  4723. if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) {
  4724. goto __R;
  4725. }
  4726. /* compute y = b**r mod a */
  4727. if ((err = mp_init (&y)) != MP_OKAY) {
  4728. goto __R;
  4729. }
  4730. if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) {
  4731. goto __Y;
  4732. }
  4733. /* if y != 1 and y != n1 do */
  4734. if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) {
  4735. j = 1;
  4736. /* while j <= s-1 and y != n1 */
  4737. while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) {
  4738. if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) {
  4739. goto __Y;
  4740. }
  4741. /* if y == 1 then composite */
  4742. if (mp_cmp_d (&y, 1) == MP_EQ) {
  4743. goto __Y;
  4744. }
  4745. ++j;
  4746. }
  4747. /* if y != n1 then composite */
  4748. if (mp_cmp (&y, &n1) != MP_EQ) {
  4749. goto __Y;
  4750. }
  4751. }
  4752. /* probably prime now */
  4753. *result = MP_YES;
  4754. __Y:mp_clear (&y);
  4755. __R:mp_clear (&r);
  4756. __N1:mp_clear (&n1);
  4757. return err;
  4758. }
  4759. #endif
  4760. /* End: bn_mp_prime_miller_rabin.c */
  4761. /* Start: bn_mp_prime_next_prime.c */
  4762. #include <ltc_tommath.h>
  4763. #ifdef BN_MP_PRIME_NEXT_PRIME_C
  4764. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  4765. *
  4766. * LibTomMath is a library that provides multiple-precision
  4767. * integer arithmetic as well as number theoretic functionality.
  4768. *
  4769. * The library was designed directly after the MPI library by
  4770. * Michael Fromberger but has been written from scratch with
  4771. * additional optimizations in place.
  4772. *
  4773. * The library is free for all purposes without any express
  4774. * guarantee it works.
  4775. *
  4776. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  4777. */
  4778. /* finds the next prime after the number "a" using "t" trials
  4779. * of Miller-Rabin.
  4780. *
  4781. * bbs_style = 1 means the prime must be congruent to 3 mod 4
  4782. */
  4783. int mp_prime_next_prime(mp_int *a, int t, int bbs_style)
  4784. {
  4785. int err, res, x, y;
  4786. mp_digit res_tab[PRIME_SIZE], step, kstep;
  4787. mp_int b;
  4788. /* ensure t is valid */
  4789. if (t <= 0 || t > PRIME_SIZE) {
  4790. return MP_VAL;
  4791. }
  4792. /* force positive */
  4793. a->sign = MP_ZPOS;
  4794. /* simple algo if a is less than the largest prime in the table */
  4795. if (mp_cmp_d(a, __prime_tab[PRIME_SIZE-1]) == MP_LT) {
  4796. /* find which prime it is bigger than */
  4797. for (x = PRIME_SIZE - 2; x >= 0; x--) {
  4798. if (mp_cmp_d(a, __prime_tab[x]) != MP_LT) {
  4799. if (bbs_style == 1) {
  4800. /* ok we found a prime smaller or
  4801. * equal [so the next is larger]
  4802. *
  4803. * however, the prime must be
  4804. * congruent to 3 mod 4
  4805. */
  4806. if ((__prime_tab[x + 1] & 3) != 3) {
  4807. /* scan upwards for a prime congruent to 3 mod 4 */
  4808. for (y = x + 1; y < PRIME_SIZE; y++) {
  4809. if ((__prime_tab[y] & 3) == 3) {
  4810. mp_set(a, __prime_tab[y]);
  4811. return MP_OKAY;
  4812. }
  4813. }
  4814. }
  4815. } else {
  4816. mp_set(a, __prime_tab[x + 1]);
  4817. return MP_OKAY;
  4818. }
  4819. }
  4820. }
  4821. /* at this point a maybe 1 */
  4822. if (mp_cmp_d(a, 1) == MP_EQ) {
  4823. mp_set(a, 2);
  4824. return MP_OKAY;
  4825. }
  4826. /* fall through to the sieve */
  4827. }
  4828. /* generate a prime congruent to 3 mod 4 or 1/3 mod 4? */
  4829. if (bbs_style == 1) {
  4830. kstep = 4;
  4831. } else {
  4832. kstep = 2;
  4833. }
  4834. /* at this point we will use a combination of a sieve and Miller-Rabin */
  4835. if (bbs_style == 1) {
  4836. /* if a mod 4 != 3 subtract the correct value to make it so */
  4837. if ((a->dp[0] & 3) != 3) {
  4838. if ((err = mp_sub_d(a, (a->dp[0] & 3) + 1, a)) != MP_OKAY) { return err; };
  4839. }
  4840. } else {
  4841. if (mp_iseven(a) == 1) {
  4842. /* force odd */
  4843. if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) {
  4844. return err;
  4845. }
  4846. }
  4847. }
  4848. /* generate the restable */
  4849. for (x = 1; x < PRIME_SIZE; x++) {
  4850. if ((err = mp_mod_d(a, __prime_tab[x], res_tab + x)) != MP_OKAY) {
  4851. return err;
  4852. }
  4853. }
  4854. /* init temp used for Miller-Rabin Testing */
  4855. if ((err = mp_init(&b)) != MP_OKAY) {
  4856. return err;
  4857. }
  4858. for (;;) {
  4859. /* skip to the next non-trivially divisible candidate */
  4860. step = 0;
  4861. do {
  4862. /* y == 1 if any residue was zero [e.g. cannot be prime] */
  4863. y = 0;
  4864. /* increase step to next candidate */
  4865. step += kstep;
  4866. /* compute the new residue without using division */
  4867. for (x = 1; x < PRIME_SIZE; x++) {
  4868. /* add the step to each residue */
  4869. res_tab[x] += kstep;
  4870. /* subtract the modulus [instead of using division] */
  4871. if (res_tab[x] >= __prime_tab[x]) {
  4872. res_tab[x] -= __prime_tab[x];
  4873. }
  4874. /* set flag if zero */
  4875. if (res_tab[x] == 0) {
  4876. y = 1;
  4877. }
  4878. }
  4879. } while (y == 1 && step < ((((mp_digit)1)<<DIGIT_BIT) - kstep));
  4880. /* add the step */
  4881. if ((err = mp_add_d(a, step, a)) != MP_OKAY) {
  4882. goto __ERR;
  4883. }
  4884. /* if didn't pass sieve and step == MAX then skip test */
  4885. if (y == 1 && step >= ((((mp_digit)1)<<DIGIT_BIT) - kstep)) {
  4886. continue;
  4887. }
  4888. /* is this prime? */
  4889. for (x = 0; x < t; x++) {
  4890. mp_set(&b, __prime_tab[t]);
  4891. if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {
  4892. goto __ERR;
  4893. }
  4894. if (res == MP_NO) {
  4895. break;
  4896. }
  4897. }
  4898. if (res == MP_YES) {
  4899. break;
  4900. }
  4901. }
  4902. err = MP_OKAY;
  4903. __ERR:
  4904. mp_clear(&b);
  4905. return err;
  4906. }
  4907. #endif
  4908. /* End: bn_mp_prime_next_prime.c */
  4909. /* Start: bn_mp_prime_rabin_miller_trials.c */
  4910. #include <ltc_tommath.h>
  4911. #ifdef BN_MP_PRIME_RABIN_MILLER_TRIALS_C
  4912. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  4913. *
  4914. * LibTomMath is a library that provides multiple-precision
  4915. * integer arithmetic as well as number theoretic functionality.
  4916. *
  4917. * The library was designed directly after the MPI library by
  4918. * Michael Fromberger but has been written from scratch with
  4919. * additional optimizations in place.
  4920. *
  4921. * The library is free for all purposes without any express
  4922. * guarantee it works.
  4923. *
  4924. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  4925. */
  4926. static const struct {
  4927. int k, t;
  4928. } sizes[] = {
  4929. { 128, 28 },
  4930. { 256, 16 },
  4931. { 384, 10 },
  4932. { 512, 7 },
  4933. { 640, 6 },
  4934. { 768, 5 },
  4935. { 896, 4 },
  4936. { 1024, 4 }
  4937. };
  4938. /* returns # of RM trials required for a given bit size */
  4939. int mp_prime_rabin_miller_trials(int size)
  4940. {
  4941. int x;
  4942. for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) {
  4943. if (sizes[x].k == size) {
  4944. return sizes[x].t;
  4945. } else if (sizes[x].k > size) {
  4946. return (x == 0) ? sizes[0].t : sizes[x - 1].t;
  4947. }
  4948. }
  4949. return sizes[x-1].t + 1;
  4950. }
  4951. #endif
  4952. /* End: bn_mp_prime_rabin_miller_trials.c */
  4953. /* Start: bn_mp_prime_random_ex.c */
  4954. #include <ltc_tommath.h>
  4955. #ifdef BN_MP_PRIME_RANDOM_EX_C
  4956. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  4957. *
  4958. * LibTomMath is a library that provides multiple-precision
  4959. * integer arithmetic as well as number theoretic functionality.
  4960. *
  4961. * The library was designed directly after the MPI library by
  4962. * Michael Fromberger but has been written from scratch with
  4963. * additional optimizations in place.
  4964. *
  4965. * The library is free for all purposes without any express
  4966. * guarantee it works.
  4967. *
  4968. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  4969. */
  4970. /* makes a truly random prime of a given size (bits),
  4971. *
  4972. * Flags are as follows:
  4973. *
  4974. * LTM_PRIME_BBS - make prime congruent to 3 mod 4
  4975. * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
  4976. * LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
  4977. * LTM_PRIME_2MSB_ON - make the 2nd highest bit one
  4978. *
  4979. * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can
  4980. * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself
  4981. * so it can be NULL
  4982. *
  4983. */
  4984. /* This is possibly the mother of all prime generation functions, muahahahahaha! */
  4985. int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat)
  4986. {
  4987. unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb;
  4988. int res, err, bsize, maskOR_msb_offset;
  4989. /* sanity check the input */
  4990. if (size <= 1 || t <= 0) {
  4991. return MP_VAL;
  4992. }
  4993. /* LTM_PRIME_SAFE implies LTM_PRIME_BBS */
  4994. if (flags & LTM_PRIME_SAFE) {
  4995. flags |= LTM_PRIME_BBS;
  4996. }
  4997. /* calc the byte size */
  4998. bsize = (size>>3)+(size&7?1:0);
  4999. /* we need a buffer of bsize bytes */
  5000. tmp = OPT_CAST(unsigned char) XMALLOC(bsize);
  5001. if (tmp == NULL) {
  5002. return MP_MEM;
  5003. }
  5004. /* calc the maskAND value for the MSbyte*/
  5005. maskAND = 0xFF >> (8 - (size & 7));
  5006. /* calc the maskOR_msb */
  5007. maskOR_msb = 0;
  5008. maskOR_msb_offset = (size - 2) >> 3;
  5009. if (flags & LTM_PRIME_2MSB_ON) {
  5010. maskOR_msb |= 1 << ((size - 2) & 7);
  5011. } else if (flags & LTM_PRIME_2MSB_OFF) {
  5012. maskAND &= ~(1 << ((size - 2) & 7));
  5013. }
  5014. /* get the maskOR_lsb */
  5015. maskOR_lsb = 0;
  5016. if (flags & LTM_PRIME_BBS) {
  5017. maskOR_lsb |= 3;
  5018. }
  5019. do {
  5020. /* read the bytes */
  5021. if (cb(tmp, bsize, dat) != bsize) {
  5022. err = MP_VAL;
  5023. goto error;
  5024. }
  5025. /* work over the MSbyte */
  5026. tmp[0] &= maskAND;
  5027. tmp[0] |= 1 << ((size - 1) & 7);
  5028. /* mix in the maskORs */
  5029. tmp[maskOR_msb_offset] |= maskOR_msb;
  5030. tmp[bsize-1] |= maskOR_lsb;
  5031. /* read it in */
  5032. if ((err = mp_read_unsigned_bin(a, tmp, bsize)) != MP_OKAY) { goto error; }
  5033. /* is it prime? */
  5034. if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { goto error; }
  5035. if (res == MP_NO) {
  5036. continue;
  5037. }
  5038. if (flags & LTM_PRIME_SAFE) {
  5039. /* see if (a-1)/2 is prime */
  5040. if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) { goto error; }
  5041. if ((err = mp_div_2(a, a)) != MP_OKAY) { goto error; }
  5042. /* is it prime? */
  5043. if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { goto error; }
  5044. }
  5045. } while (res == MP_NO);
  5046. if (flags & LTM_PRIME_SAFE) {
  5047. /* restore a to the original value */
  5048. if ((err = mp_mul_2(a, a)) != MP_OKAY) { goto error; }
  5049. if ((err = mp_add_d(a, 1, a)) != MP_OKAY) { goto error; }
  5050. }
  5051. err = MP_OKAY;
  5052. error:
  5053. XFREE(tmp);
  5054. return err;
  5055. }
  5056. #endif
  5057. /* End: bn_mp_prime_random_ex.c */
  5058. /* Start: bn_mp_radix_size.c */
  5059. #include <ltc_tommath.h>
  5060. #ifdef BN_MP_RADIX_SIZE_C
  5061. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  5062. *
  5063. * LibTomMath is a library that provides multiple-precision
  5064. * integer arithmetic as well as number theoretic functionality.
  5065. *
  5066. * The library was designed directly after the MPI library by
  5067. * Michael Fromberger but has been written from scratch with
  5068. * additional optimizations in place.
  5069. *
  5070. * The library is free for all purposes without any express
  5071. * guarantee it works.
  5072. *
  5073. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  5074. */
  5075. /* returns size of ASCII reprensentation */
  5076. int mp_radix_size (mp_int * a, int radix, int *size)
  5077. {
  5078. int res, digs;
  5079. mp_int t;
  5080. mp_digit d;
  5081. *size = 0;
  5082. /* special case for binary */
  5083. if (radix == 2) {
  5084. *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1;
  5085. return MP_OKAY;
  5086. }
  5087. /* make sure the radix is in range */
  5088. if (radix < 2 || radix > 64) {
  5089. return MP_VAL;
  5090. }
  5091. /* init a copy of the input */
  5092. if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
  5093. return res;
  5094. }
  5095. /* digs is the digit count */
  5096. digs = 0;
  5097. /* if it's negative add one for the sign */
  5098. if (t.sign == MP_NEG) {
  5099. ++digs;
  5100. t.sign = MP_ZPOS;
  5101. }
  5102. /* fetch out all of the digits */
  5103. while (mp_iszero (&t) == 0) {
  5104. if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
  5105. mp_clear (&t);
  5106. return res;
  5107. }
  5108. ++digs;
  5109. }
  5110. mp_clear (&t);
  5111. /* return digs + 1, the 1 is for the NULL byte that would be required. */
  5112. *size = digs + 1;
  5113. return MP_OKAY;
  5114. }
  5115. #endif
  5116. /* End: bn_mp_radix_size.c */
  5117. /* Start: bn_mp_radix_smap.c */
  5118. #include <ltc_tommath.h>
  5119. #ifdef BN_MP_RADIX_SMAP_C
  5120. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  5121. *
  5122. * LibTomMath is a library that provides multiple-precision
  5123. * integer arithmetic as well as number theoretic functionality.
  5124. *
  5125. * The library was designed directly after the MPI library by
  5126. * Michael Fromberger but has been written from scratch with
  5127. * additional optimizations in place.
  5128. *
  5129. * The library is free for all purposes without any express
  5130. * guarantee it works.
  5131. *
  5132. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  5133. */
  5134. /* chars used in radix conversions */
  5135. const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
  5136. #endif
  5137. /* End: bn_mp_radix_smap.c */
  5138. /* Start: bn_mp_rand.c */
  5139. #include <ltc_tommath.h>
  5140. #ifdef BN_MP_RAND_C
  5141. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  5142. *
  5143. * LibTomMath is a library that provides multiple-precision
  5144. * integer arithmetic as well as number theoretic functionality.
  5145. *
  5146. * The library was designed directly after the MPI library by
  5147. * Michael Fromberger but has been written from scratch with
  5148. * additional optimizations in place.
  5149. *
  5150. * The library is free for all purposes without any express
  5151. * guarantee it works.
  5152. *
  5153. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  5154. */
  5155. /* makes a pseudo-random int of a given size */
  5156. int
  5157. mp_rand (mp_int * a, int digits)
  5158. {
  5159. int res;
  5160. mp_digit d;
  5161. mp_zero (a);
  5162. if (digits <= 0) {
  5163. return MP_OKAY;
  5164. }
  5165. /* first place a random non-zero digit */
  5166. do {
  5167. d = ((mp_digit) abs (rand ()));
  5168. } while (d == 0);
  5169. if ((res = mp_add_d (a, d, a)) != MP_OKAY) {
  5170. return res;
  5171. }
  5172. while (digits-- > 0) {
  5173. if ((res = mp_lshd (a, 1)) != MP_OKAY) {
  5174. return res;
  5175. }
  5176. if ((res = mp_add_d (a, ((mp_digit) abs (rand ())), a)) != MP_OKAY) {
  5177. return res;
  5178. }
  5179. }
  5180. return MP_OKAY;
  5181. }
  5182. #endif
  5183. /* End: bn_mp_rand.c */
  5184. /* Start: bn_mp_read_radix.c */
  5185. #include <ltc_tommath.h>
  5186. #ifdef BN_MP_READ_RADIX_C
  5187. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  5188. *
  5189. * LibTomMath is a library that provides multiple-precision
  5190. * integer arithmetic as well as number theoretic functionality.
  5191. *
  5192. * The library was designed directly after the MPI library by
  5193. * Michael Fromberger but has been written from scratch with
  5194. * additional optimizations in place.
  5195. *
  5196. * The library is free for all purposes without any express
  5197. * guarantee it works.
  5198. *
  5199. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  5200. */
  5201. /* read a string [ASCII] in a given radix */
  5202. int mp_read_radix (mp_int * a, char *str, int radix)
  5203. {
  5204. int y, res, neg;
  5205. char ch;
  5206. /* make sure the radix is ok */
  5207. if (radix < 2 || radix > 64) {
  5208. return MP_VAL;
  5209. }
  5210. /* if the leading digit is a
  5211. * minus set the sign to negative.
  5212. */
  5213. if (*str == '-') {
  5214. ++str;
  5215. neg = MP_NEG;
  5216. } else {
  5217. neg = MP_ZPOS;
  5218. }
  5219. /* set the integer to the default of zero */
  5220. mp_zero (a);
  5221. /* process each digit of the string */
  5222. while (*str) {
  5223. /* if the radix < 36 the conversion is case insensitive
  5224. * this allows numbers like 1AB and 1ab to represent the same value
  5225. * [e.g. in hex]
  5226. */
  5227. ch = (char) ((radix < 36) ? toupper (*str) : *str);
  5228. for (y = 0; y < 64; y++) {
  5229. if (ch == mp_s_rmap[y]) {
  5230. break;
  5231. }
  5232. }
  5233. /* if the char was found in the map
  5234. * and is less than the given radix add it
  5235. * to the number, otherwise exit the loop.
  5236. */
  5237. if (y < radix) {
  5238. if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) {
  5239. return res;
  5240. }
  5241. if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) {
  5242. return res;
  5243. }
  5244. } else {
  5245. break;
  5246. }
  5247. ++str;
  5248. }
  5249. /* set the sign only if a != 0 */
  5250. if (mp_iszero(a) != 1) {
  5251. a->sign = neg;
  5252. }
  5253. return MP_OKAY;
  5254. }
  5255. #endif
  5256. /* End: bn_mp_read_radix.c */
  5257. /* Start: bn_mp_read_signed_bin.c */
  5258. #include <ltc_tommath.h>
  5259. #ifdef BN_MP_READ_SIGNED_BIN_C
  5260. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  5261. *
  5262. * LibTomMath is a library that provides multiple-precision
  5263. * integer arithmetic as well as number theoretic functionality.
  5264. *
  5265. * The library was designed directly after the MPI library by
  5266. * Michael Fromberger but has been written from scratch with
  5267. * additional optimizations in place.
  5268. *
  5269. * The library is free for all purposes without any express
  5270. * guarantee it works.
  5271. *
  5272. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  5273. */
  5274. /* read signed bin, big endian, first byte is 0==positive or 1==negative */
  5275. int
  5276. mp_read_signed_bin (mp_int * a, unsigned char *b, int c)
  5277. {
  5278. int res;
  5279. /* read magnitude */
  5280. if ((res = mp_read_unsigned_bin (a, b + 1, c - 1)) != MP_OKAY) {
  5281. return res;
  5282. }
  5283. /* first byte is 0 for positive, non-zero for negative */
  5284. if (b[0] == 0) {
  5285. a->sign = MP_ZPOS;
  5286. } else {
  5287. a->sign = MP_NEG;
  5288. }
  5289. return MP_OKAY;
  5290. }
  5291. #endif
  5292. /* End: bn_mp_read_signed_bin.c */
  5293. /* Start: bn_mp_read_unsigned_bin.c */
  5294. #include <ltc_tommath.h>
  5295. #ifdef BN_MP_READ_UNSIGNED_BIN_C
  5296. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  5297. *
  5298. * LibTomMath is a library that provides multiple-precision
  5299. * integer arithmetic as well as number theoretic functionality.
  5300. *
  5301. * The library was designed directly after the MPI library by
  5302. * Michael Fromberger but has been written from scratch with
  5303. * additional optimizations in place.
  5304. *
  5305. * The library is free for all purposes without any express
  5306. * guarantee it works.
  5307. *
  5308. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  5309. */
  5310. /* reads a unsigned char array, assumes the msb is stored first [big endian] */
  5311. int
  5312. mp_read_unsigned_bin (mp_int * a, unsigned char *b, int c)
  5313. {
  5314. int res;
  5315. /* make sure there are at least two digits */
  5316. if (a->alloc < 2) {
  5317. if ((res = mp_grow(a, 2)) != MP_OKAY) {
  5318. return res;
  5319. }
  5320. }
  5321. /* zero the int */
  5322. mp_zero (a);
  5323. /* read the bytes in */
  5324. while (c-- > 0) {
  5325. if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) {
  5326. return res;
  5327. }
  5328. #ifndef MP_8BIT
  5329. a->dp[0] |= *b++;
  5330. a->used += 1;
  5331. #else
  5332. a->dp[0] = (*b & MP_MASK);
  5333. a->dp[1] |= ((*b++ >> 7U) & 1);
  5334. a->used += 2;
  5335. #endif
  5336. }
  5337. mp_clamp (a);
  5338. return MP_OKAY;
  5339. }
  5340. #endif
  5341. /* End: bn_mp_read_unsigned_bin.c */
  5342. /* Start: bn_mp_reduce.c */
  5343. #include <ltc_tommath.h>
  5344. #ifdef BN_MP_REDUCE_C
  5345. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  5346. *
  5347. * LibTomMath is a library that provides multiple-precision
  5348. * integer arithmetic as well as number theoretic functionality.
  5349. *
  5350. * The library was designed directly after the MPI library by
  5351. * Michael Fromberger but has been written from scratch with
  5352. * additional optimizations in place.
  5353. *
  5354. * The library is free for all purposes without any express
  5355. * guarantee it works.
  5356. *
  5357. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  5358. */
  5359. /* reduces x mod m, assumes 0 < x < m**2, mu is
  5360. * precomputed via mp_reduce_setup.
  5361. * From HAC pp.604 Algorithm 14.42
  5362. */
  5363. int
  5364. mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
  5365. {
  5366. mp_int q;
  5367. int res, um = m->used;
  5368. /* q = x */
  5369. if ((res = mp_init_copy (&q, x)) != MP_OKAY) {
  5370. return res;
  5371. }
  5372. /* q1 = x / b**(k-1) */
  5373. mp_rshd (&q, um - 1);
  5374. /* according to HAC this optimization is ok */
  5375. if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {
  5376. if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) {
  5377. goto CLEANUP;
  5378. }
  5379. } else {
  5380. #ifdef BN_S_MP_MUL_HIGH_DIGS_C
  5381. if ((res = s_mp_mul_high_digs (&q, mu, &q, um - 1)) != MP_OKAY) {
  5382. goto CLEANUP;
  5383. }
  5384. #elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
  5385. if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um - 1)) != MP_OKAY) {
  5386. goto CLEANUP;
  5387. }
  5388. #else
  5389. {
  5390. res = MP_VAL;
  5391. goto CLEANUP;
  5392. }
  5393. #endif
  5394. }
  5395. /* q3 = q2 / b**(k+1) */
  5396. mp_rshd (&q, um + 1);
  5397. /* x = x mod b**(k+1), quick (no division) */
  5398. if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
  5399. goto CLEANUP;
  5400. }
  5401. /* q = q * m mod b**(k+1), quick (no division) */
  5402. if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {
  5403. goto CLEANUP;
  5404. }
  5405. /* x = x - q */
  5406. if ((res = mp_sub (x, &q, x)) != MP_OKAY) {
  5407. goto CLEANUP;
  5408. }
  5409. /* If x < 0, add b**(k+1) to it */
  5410. if (mp_cmp_d (x, 0) == MP_LT) {
  5411. mp_set (&q, 1);
  5412. if ((res = mp_lshd (&q, um + 1)) != MP_OKAY)
  5413. goto CLEANUP;
  5414. if ((res = mp_add (x, &q, x)) != MP_OKAY)
  5415. goto CLEANUP;
  5416. }
  5417. /* Back off if it's too big */
  5418. while (mp_cmp (x, m) != MP_LT) {
  5419. if ((res = s_mp_sub (x, m, x)) != MP_OKAY) {
  5420. goto CLEANUP;
  5421. }
  5422. }
  5423. CLEANUP:
  5424. mp_clear (&q);
  5425. return res;
  5426. }
  5427. #endif
  5428. /* End: bn_mp_reduce.c */
  5429. /* Start: bn_mp_reduce_2k.c */
  5430. #include <ltc_tommath.h>
  5431. #ifdef BN_MP_REDUCE_2K_C
  5432. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  5433. *
  5434. * LibTomMath is a library that provides multiple-precision
  5435. * integer arithmetic as well as number theoretic functionality.
  5436. *
  5437. * The library was designed directly after the MPI library by
  5438. * Michael Fromberger but has been written from scratch with
  5439. * additional optimizations in place.
  5440. *
  5441. * The library is free for all purposes without any express
  5442. * guarantee it works.
  5443. *
  5444. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  5445. */
  5446. /* reduces a modulo n where n is of the form 2**p - d */
  5447. int
  5448. mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d)
  5449. {
  5450. mp_int q;
  5451. int p, res;
  5452. if ((res = mp_init(&q)) != MP_OKAY) {
  5453. return res;
  5454. }
  5455. p = mp_count_bits(n);
  5456. top:
  5457. /* q = a/2**p, a = a mod 2**p */
  5458. if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
  5459. goto ERR;
  5460. }
  5461. if (d != 1) {
  5462. /* q = q * d */
  5463. if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) {
  5464. goto ERR;
  5465. }
  5466. }
  5467. /* a = a + q */
  5468. if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
  5469. goto ERR;
  5470. }
  5471. if (mp_cmp_mag(a, n) != MP_LT) {
  5472. s_mp_sub(a, n, a);
  5473. goto top;
  5474. }
  5475. ERR:
  5476. mp_clear(&q);
  5477. return res;
  5478. }
  5479. #endif
  5480. /* End: bn_mp_reduce_2k.c */
  5481. /* Start: bn_mp_reduce_2k_setup.c */
  5482. #include <ltc_tommath.h>
  5483. #ifdef BN_MP_REDUCE_2K_SETUP_C
  5484. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  5485. *
  5486. * LibTomMath is a library that provides multiple-precision
  5487. * integer arithmetic as well as number theoretic functionality.
  5488. *
  5489. * The library was designed directly after the MPI library by
  5490. * Michael Fromberger but has been written from scratch with
  5491. * additional optimizations in place.
  5492. *
  5493. * The library is free for all purposes without any express
  5494. * guarantee it works.
  5495. *
  5496. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  5497. */
  5498. /* determines the setup value */
  5499. int
  5500. mp_reduce_2k_setup(mp_int *a, mp_digit *d)
  5501. {
  5502. int res, p;
  5503. mp_int tmp;
  5504. if ((res = mp_init(&tmp)) != MP_OKAY) {
  5505. return res;
  5506. }
  5507. p = mp_count_bits(a);
  5508. if ((res = mp_2expt(&tmp, p)) != MP_OKAY) {
  5509. mp_clear(&tmp);
  5510. return res;
  5511. }
  5512. if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) {
  5513. mp_clear(&tmp);
  5514. return res;
  5515. }
  5516. *d = tmp.dp[0];
  5517. mp_clear(&tmp);
  5518. return MP_OKAY;
  5519. }
  5520. #endif
  5521. /* End: bn_mp_reduce_2k_setup.c */
  5522. /* Start: bn_mp_reduce_is_2k.c */
  5523. #include <ltc_tommath.h>
  5524. #ifdef BN_MP_REDUCE_IS_2K_C
  5525. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  5526. *
  5527. * LibTomMath is a library that provides multiple-precision
  5528. * integer arithmetic as well as number theoretic functionality.
  5529. *
  5530. * The library was designed directly after the MPI library by
  5531. * Michael Fromberger but has been written from scratch with
  5532. * additional optimizations in place.
  5533. *
  5534. * The library is free for all purposes without any express
  5535. * guarantee it works.
  5536. *
  5537. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  5538. */
  5539. /* determines if mp_reduce_2k can be used */
  5540. int mp_reduce_is_2k(mp_int *a)
  5541. {
  5542. int ix, iy, iw;
  5543. mp_digit iz;
  5544. if (a->used == 0) {
  5545. return 0;
  5546. } else if (a->used == 1) {
  5547. return 1;
  5548. } else if (a->used > 1) {
  5549. iy = mp_count_bits(a);
  5550. iz = 1;
  5551. iw = 1;
  5552. /* Test every bit from the second digit up, must be 1 */
  5553. for (ix = DIGIT_BIT; ix < iy; ix++) {
  5554. if ((a->dp[iw] & iz) == 0) {
  5555. return 0;
  5556. }
  5557. iz <<= 1;
  5558. if (iz > (mp_digit)MP_MASK) {
  5559. ++iw;
  5560. iz = 1;
  5561. }
  5562. }
  5563. }
  5564. return 1;
  5565. }
  5566. #endif
  5567. /* End: bn_mp_reduce_is_2k.c */
  5568. /* Start: bn_mp_reduce_setup.c */
  5569. #include <ltc_tommath.h>
  5570. #ifdef BN_MP_REDUCE_SETUP_C
  5571. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  5572. *
  5573. * LibTomMath is a library that provides multiple-precision
  5574. * integer arithmetic as well as number theoretic functionality.
  5575. *
  5576. * The library was designed directly after the MPI library by
  5577. * Michael Fromberger but has been written from scratch with
  5578. * additional optimizations in place.
  5579. *
  5580. * The library is free for all purposes without any express
  5581. * guarantee it works.
  5582. *
  5583. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  5584. */
  5585. /* pre-calculate the value required for Barrett reduction
  5586. * For a given modulus "b" it calulates the value required in "a"
  5587. */
  5588. int mp_reduce_setup (mp_int * a, mp_int * b)
  5589. {
  5590. int res;
  5591. if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) {
  5592. return res;
  5593. }
  5594. return mp_div (a, b, a, NULL);
  5595. }
  5596. #endif
  5597. /* End: bn_mp_reduce_setup.c */
  5598. /* Start: bn_mp_rshd.c */
  5599. #include <ltc_tommath.h>
  5600. #ifdef BN_MP_RSHD_C
  5601. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  5602. *
  5603. * LibTomMath is a library that provides multiple-precision
  5604. * integer arithmetic as well as number theoretic functionality.
  5605. *
  5606. * The library was designed directly after the MPI library by
  5607. * Michael Fromberger but has been written from scratch with
  5608. * additional optimizations in place.
  5609. *
  5610. * The library is free for all purposes without any express
  5611. * guarantee it works.
  5612. *
  5613. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  5614. */
  5615. /* shift right a certain amount of digits */
  5616. void mp_rshd (mp_int * a, int b)
  5617. {
  5618. int x;
  5619. /* if b <= 0 then ignore it */
  5620. if (b <= 0) {
  5621. return;
  5622. }
  5623. /* if b > used then simply zero it and return */
  5624. if (a->used <= b) {
  5625. mp_zero (a);
  5626. return;
  5627. }
  5628. {
  5629. register mp_digit *bottom, *top;
  5630. /* shift the digits down */
  5631. /* bottom */
  5632. bottom = a->dp;
  5633. /* top [offset into digits] */
  5634. top = a->dp + b;
  5635. /* this is implemented as a sliding window where
  5636. * the window is b-digits long and digits from
  5637. * the top of the window are copied to the bottom
  5638. *
  5639. * e.g.
  5640. b-2 | b-1 | b0 | b1 | b2 | ... | bb | ---->
  5641. /\ | ---->
  5642. \-------------------/ ---->
  5643. */
  5644. for (x = 0; x < (a->used - b); x++) {
  5645. *bottom++ = *top++;
  5646. }
  5647. /* zero the top digits */
  5648. for (; x < a->used; x++) {
  5649. *bottom++ = 0;
  5650. }
  5651. }
  5652. /* remove excess digits */
  5653. a->used -= b;
  5654. }
  5655. #endif
  5656. /* End: bn_mp_rshd.c */
  5657. /* Start: bn_mp_set.c */
  5658. #include <ltc_tommath.h>
  5659. #ifdef BN_MP_SET_C
  5660. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  5661. *
  5662. * LibTomMath is a library that provides multiple-precision
  5663. * integer arithmetic as well as number theoretic functionality.
  5664. *
  5665. * The library was designed directly after the MPI library by
  5666. * Michael Fromberger but has been written from scratch with
  5667. * additional optimizations in place.
  5668. *
  5669. * The library is free for all purposes without any express
  5670. * guarantee it works.
  5671. *
  5672. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  5673. */
  5674. /* set to a digit */
  5675. void mp_set (mp_int * a, mp_digit b)
  5676. {
  5677. mp_zero (a);
  5678. a->dp[0] = b & MP_MASK;
  5679. a->used = (a->dp[0] != 0) ? 1 : 0;
  5680. }
  5681. #endif
  5682. /* End: bn_mp_set.c */
  5683. /* Start: bn_mp_set_int.c */
  5684. #include <ltc_tommath.h>
  5685. #ifdef BN_MP_SET_INT_C
  5686. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  5687. *
  5688. * LibTomMath is a library that provides multiple-precision
  5689. * integer arithmetic as well as number theoretic functionality.
  5690. *
  5691. * The library was designed directly after the MPI library by
  5692. * Michael Fromberger but has been written from scratch with
  5693. * additional optimizations in place.
  5694. *
  5695. * The library is free for all purposes without any express
  5696. * guarantee it works.
  5697. *
  5698. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  5699. */
  5700. /* set a 32-bit const */
  5701. int mp_set_int (mp_int * a, unsigned long b)
  5702. {
  5703. int x, res;
  5704. mp_zero (a);
  5705. /* set four bits at a time */
  5706. for (x = 0; x < 8; x++) {
  5707. /* shift the number up four bits */
  5708. if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) {
  5709. return res;
  5710. }
  5711. /* OR in the top four bits of the source */
  5712. a->dp[0] |= (b >> 28) & 15;
  5713. /* shift the source up to the next four bits */
  5714. b <<= 4;
  5715. /* ensure that digits are not clamped off */
  5716. a->used += 1;
  5717. }
  5718. mp_clamp (a);
  5719. return MP_OKAY;
  5720. }
  5721. #endif
  5722. /* End: bn_mp_set_int.c */
  5723. /* Start: bn_mp_shrink.c */
  5724. #include <ltc_tommath.h>
  5725. #ifdef BN_MP_SHRINK_C
  5726. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  5727. *
  5728. * LibTomMath is a library that provides multiple-precision
  5729. * integer arithmetic as well as number theoretic functionality.
  5730. *
  5731. * The library was designed directly after the MPI library by
  5732. * Michael Fromberger but has been written from scratch with
  5733. * additional optimizations in place.
  5734. *
  5735. * The library is free for all purposes without any express
  5736. * guarantee it works.
  5737. *
  5738. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  5739. */
  5740. /* shrink a bignum */
  5741. int mp_shrink (mp_int * a)
  5742. {
  5743. mp_digit *tmp;
  5744. if (a->alloc != a->used && a->used > 0) {
  5745. if ((tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * a->used)) == NULL) {
  5746. return MP_MEM;
  5747. }
  5748. a->dp = tmp;
  5749. a->alloc = a->used;
  5750. }
  5751. return MP_OKAY;
  5752. }
  5753. #endif
  5754. /* End: bn_mp_shrink.c */
  5755. /* Start: bn_mp_signed_bin_size.c */
  5756. #include <ltc_tommath.h>
  5757. #ifdef BN_MP_SIGNED_BIN_SIZE_C
  5758. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  5759. *
  5760. * LibTomMath is a library that provides multiple-precision
  5761. * integer arithmetic as well as number theoretic functionality.
  5762. *
  5763. * The library was designed directly after the MPI library by
  5764. * Michael Fromberger but has been written from scratch with
  5765. * additional optimizations in place.
  5766. *
  5767. * The library is free for all purposes without any express
  5768. * guarantee it works.
  5769. *
  5770. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  5771. */
  5772. /* get the size for an signed equivalent */
  5773. int mp_signed_bin_size (mp_int * a)
  5774. {
  5775. return 1 + mp_unsigned_bin_size (a);
  5776. }
  5777. #endif
  5778. /* End: bn_mp_signed_bin_size.c */
  5779. /* Start: bn_mp_sqr.c */
  5780. #include <ltc_tommath.h>
  5781. #ifdef BN_MP_SQR_C
  5782. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  5783. *
  5784. * LibTomMath is a library that provides multiple-precision
  5785. * integer arithmetic as well as number theoretic functionality.
  5786. *
  5787. * The library was designed directly after the MPI library by
  5788. * Michael Fromberger but has been written from scratch with
  5789. * additional optimizations in place.
  5790. *
  5791. * The library is free for all purposes without any express
  5792. * guarantee it works.
  5793. *
  5794. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  5795. */
  5796. /* computes b = a*a */
  5797. int
  5798. mp_sqr (mp_int * a, mp_int * b)
  5799. {
  5800. int res;
  5801. #ifdef BN_MP_TOOM_SQR_C
  5802. /* use Toom-Cook? */
  5803. if (a->used >= TOOM_SQR_CUTOFF) {
  5804. res = mp_toom_sqr(a, b);
  5805. /* Karatsuba? */
  5806. } else
  5807. #endif
  5808. #ifdef BN_MP_KARATSUBA_SQR_C
  5809. if (a->used >= KARATSUBA_SQR_CUTOFF) {
  5810. res = mp_karatsuba_sqr (a, b);
  5811. } else
  5812. #endif
  5813. {
  5814. #ifdef BN_FAST_S_MP_SQR_C
  5815. /* can we use the fast comba multiplier? */
  5816. if ((a->used * 2 + 1) < MP_WARRAY &&
  5817. a->used <
  5818. (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) {
  5819. res = fast_s_mp_sqr (a, b);
  5820. } else
  5821. #endif
  5822. #ifdef BN_S_MP_SQR_C
  5823. res = s_mp_sqr (a, b);
  5824. #else
  5825. res = MP_VAL;
  5826. #endif
  5827. }
  5828. b->sign = MP_ZPOS;
  5829. return res;
  5830. }
  5831. #endif
  5832. /* End: bn_mp_sqr.c */
  5833. /* Start: bn_mp_sqrmod.c */
  5834. #include <ltc_tommath.h>
  5835. #ifdef BN_MP_SQRMOD_C
  5836. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  5837. *
  5838. * LibTomMath is a library that provides multiple-precision
  5839. * integer arithmetic as well as number theoretic functionality.
  5840. *
  5841. * The library was designed directly after the MPI library by
  5842. * Michael Fromberger but has been written from scratch with
  5843. * additional optimizations in place.
  5844. *
  5845. * The library is free for all purposes without any express
  5846. * guarantee it works.
  5847. *
  5848. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  5849. */
  5850. /* c = a * a (mod b) */
  5851. int
  5852. mp_sqrmod (mp_int * a, mp_int * b, mp_int * c)
  5853. {
  5854. int res;
  5855. mp_int t;
  5856. if ((res = mp_init (&t)) != MP_OKAY) {
  5857. return res;
  5858. }
  5859. if ((res = mp_sqr (a, &t)) != MP_OKAY) {
  5860. mp_clear (&t);
  5861. return res;
  5862. }
  5863. res = mp_mod (&t, b, c);
  5864. mp_clear (&t);
  5865. return res;
  5866. }
  5867. #endif
  5868. /* End: bn_mp_sqrmod.c */
  5869. /* Start: bn_mp_sqrt.c */
  5870. #include <ltc_tommath.h>
  5871. #ifdef BN_MP_SQRT_C
  5872. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  5873. *
  5874. * LibTomMath is a library that provides multiple-precision
  5875. * integer arithmetic as well as number theoretic functionality.
  5876. *
  5877. * The library was designed directly after the MPI library by
  5878. * Michael Fromberger but has been written from scratch with
  5879. * additional optimizations in place.
  5880. *
  5881. * The library is free for all purposes without any express
  5882. * guarantee it works.
  5883. *
  5884. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  5885. */
  5886. /* this function is less generic than mp_n_root, simpler and faster */
  5887. int mp_sqrt(mp_int *arg, mp_int *ret)
  5888. {
  5889. int res;
  5890. mp_int t1,t2;
  5891. /* must be positive */
  5892. if (arg->sign == MP_NEG) {
  5893. return MP_VAL;
  5894. }
  5895. /* easy out */
  5896. if (mp_iszero(arg) == MP_YES) {
  5897. mp_zero(ret);
  5898. return MP_OKAY;
  5899. }
  5900. if ((res = mp_init_copy(&t1, arg)) != MP_OKAY) {
  5901. return res;
  5902. }
  5903. if ((res = mp_init(&t2)) != MP_OKAY) {
  5904. goto E2;
  5905. }
  5906. /* First approx. (not very bad for large arg) */
  5907. mp_rshd (&t1,t1.used/2);
  5908. /* t1 > 0 */
  5909. if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
  5910. goto E1;
  5911. }
  5912. if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
  5913. goto E1;
  5914. }
  5915. if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
  5916. goto E1;
  5917. }
  5918. /* And now t1 > sqrt(arg) */
  5919. do {
  5920. if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
  5921. goto E1;
  5922. }
  5923. if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
  5924. goto E1;
  5925. }
  5926. if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
  5927. goto E1;
  5928. }
  5929. /* t1 >= sqrt(arg) >= t2 at this point */
  5930. } while (mp_cmp_mag(&t1,&t2) == MP_GT);
  5931. mp_exch(&t1,ret);
  5932. E1: mp_clear(&t2);
  5933. E2: mp_clear(&t1);
  5934. return res;
  5935. }
  5936. #endif
  5937. /* End: bn_mp_sqrt.c */
  5938. /* Start: bn_mp_sub.c */
  5939. #include <ltc_tommath.h>
  5940. #ifdef BN_MP_SUB_C
  5941. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  5942. *
  5943. * LibTomMath is a library that provides multiple-precision
  5944. * integer arithmetic as well as number theoretic functionality.
  5945. *
  5946. * The library was designed directly after the MPI library by
  5947. * Michael Fromberger but has been written from scratch with
  5948. * additional optimizations in place.
  5949. *
  5950. * The library is free for all purposes without any express
  5951. * guarantee it works.
  5952. *
  5953. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  5954. */
  5955. /* high level subtraction (handles signs) */
  5956. int
  5957. mp_sub (mp_int * a, mp_int * b, mp_int * c)
  5958. {
  5959. int sa, sb, res;
  5960. sa = a->sign;
  5961. sb = b->sign;
  5962. if (sa != sb) {
  5963. /* subtract a negative from a positive, OR */
  5964. /* subtract a positive from a negative. */
  5965. /* In either case, ADD their magnitudes, */
  5966. /* and use the sign of the first number. */
  5967. c->sign = sa;
  5968. res = s_mp_add (a, b, c);
  5969. } else {
  5970. /* subtract a positive from a positive, OR */
  5971. /* subtract a negative from a negative. */
  5972. /* First, take the difference between their */
  5973. /* magnitudes, then... */
  5974. if (mp_cmp_mag (a, b) != MP_LT) {
  5975. /* Copy the sign from the first */
  5976. c->sign = sa;
  5977. /* The first has a larger or equal magnitude */
  5978. res = s_mp_sub (a, b, c);
  5979. } else {
  5980. /* The result has the *opposite* sign from */
  5981. /* the first number. */
  5982. c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;
  5983. /* The second has a larger magnitude */
  5984. res = s_mp_sub (b, a, c);
  5985. }
  5986. }
  5987. return res;
  5988. }
  5989. #endif
  5990. /* End: bn_mp_sub.c */
  5991. /* Start: bn_mp_sub_d.c */
  5992. #include <ltc_tommath.h>
  5993. #ifdef BN_MP_SUB_D_C
  5994. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  5995. *
  5996. * LibTomMath is a library that provides multiple-precision
  5997. * integer arithmetic as well as number theoretic functionality.
  5998. *
  5999. * The library was designed directly after the MPI library by
  6000. * Michael Fromberger but has been written from scratch with
  6001. * additional optimizations in place.
  6002. *
  6003. * The library is free for all purposes without any express
  6004. * guarantee it works.
  6005. *
  6006. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  6007. */
  6008. /* single digit subtraction */
  6009. int
  6010. mp_sub_d (mp_int * a, mp_digit b, mp_int * c)
  6011. {
  6012. mp_digit *tmpa, *tmpc, mu;
  6013. int res, ix, oldused;
  6014. /* grow c as required */
  6015. if (c->alloc < a->used + 1) {
  6016. if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
  6017. return res;
  6018. }
  6019. }
  6020. /* if a is negative just do an unsigned
  6021. * addition [with fudged signs]
  6022. */
  6023. if (a->sign == MP_NEG) {
  6024. a->sign = MP_ZPOS;
  6025. res = mp_add_d(a, b, c);
  6026. a->sign = c->sign = MP_NEG;
  6027. return res;
  6028. }
  6029. /* setup regs */
  6030. oldused = c->used;
  6031. tmpa = a->dp;
  6032. tmpc = c->dp;
  6033. /* if a <= b simply fix the single digit */
  6034. if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) {
  6035. if (a->used == 1) {
  6036. *tmpc++ = b - *tmpa;
  6037. } else {
  6038. *tmpc++ = b;
  6039. }
  6040. ix = 1;
  6041. /* negative/1digit */
  6042. c->sign = MP_NEG;
  6043. c->used = 1;
  6044. } else {
  6045. /* positive/size */
  6046. c->sign = MP_ZPOS;
  6047. c->used = a->used;
  6048. /* subtract first digit */
  6049. *tmpc = *tmpa++ - b;
  6050. mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
  6051. *tmpc++ &= MP_MASK;
  6052. /* handle rest of the digits */
  6053. for (ix = 1; ix < a->used; ix++) {
  6054. *tmpc = *tmpa++ - mu;
  6055. mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
  6056. *tmpc++ &= MP_MASK;
  6057. }
  6058. }
  6059. /* zero excess digits */
  6060. while (ix++ < oldused) {
  6061. *tmpc++ = 0;
  6062. }
  6063. mp_clamp(c);
  6064. return MP_OKAY;
  6065. }
  6066. #endif
  6067. /* End: bn_mp_sub_d.c */
  6068. /* Start: bn_mp_submod.c */
  6069. #include <ltc_tommath.h>
  6070. #ifdef BN_MP_SUBMOD_C
  6071. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  6072. *
  6073. * LibTomMath is a library that provides multiple-precision
  6074. * integer arithmetic as well as number theoretic functionality.
  6075. *
  6076. * The library was designed directly after the MPI library by
  6077. * Michael Fromberger but has been written from scratch with
  6078. * additional optimizations in place.
  6079. *
  6080. * The library is free for all purposes without any express
  6081. * guarantee it works.
  6082. *
  6083. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  6084. */
  6085. /* d = a - b (mod c) */
  6086. int
  6087. mp_submod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
  6088. {
  6089. int res;
  6090. mp_int t;
  6091. if ((res = mp_init (&t)) != MP_OKAY) {
  6092. return res;
  6093. }
  6094. if ((res = mp_sub (a, b, &t)) != MP_OKAY) {
  6095. mp_clear (&t);
  6096. return res;
  6097. }
  6098. res = mp_mod (&t, c, d);
  6099. mp_clear (&t);
  6100. return res;
  6101. }
  6102. #endif
  6103. /* End: bn_mp_submod.c */
  6104. /* Start: bn_mp_to_signed_bin.c */
  6105. #include <ltc_tommath.h>
  6106. #ifdef BN_MP_TO_SIGNED_BIN_C
  6107. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  6108. *
  6109. * LibTomMath is a library that provides multiple-precision
  6110. * integer arithmetic as well as number theoretic functionality.
  6111. *
  6112. * The library was designed directly after the MPI library by
  6113. * Michael Fromberger but has been written from scratch with
  6114. * additional optimizations in place.
  6115. *
  6116. * The library is free for all purposes without any express
  6117. * guarantee it works.
  6118. *
  6119. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  6120. */
  6121. /* store in signed [big endian] format */
  6122. int
  6123. mp_to_signed_bin (mp_int * a, unsigned char *b)
  6124. {
  6125. int res;
  6126. if ((res = mp_to_unsigned_bin (a, b + 1)) != MP_OKAY) {
  6127. return res;
  6128. }
  6129. b[0] = (unsigned char) ((a->sign == MP_ZPOS) ? 0 : 1);
  6130. return MP_OKAY;
  6131. }
  6132. #endif
  6133. /* End: bn_mp_to_signed_bin.c */
  6134. /* Start: bn_mp_to_unsigned_bin.c */
  6135. #include <ltc_tommath.h>
  6136. #ifdef BN_MP_TO_UNSIGNED_BIN_C
  6137. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  6138. *
  6139. * LibTomMath is a library that provides multiple-precision
  6140. * integer arithmetic as well as number theoretic functionality.
  6141. *
  6142. * The library was designed directly after the MPI library by
  6143. * Michael Fromberger but has been written from scratch with
  6144. * additional optimizations in place.
  6145. *
  6146. * The library is free for all purposes without any express
  6147. * guarantee it works.
  6148. *
  6149. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  6150. */
  6151. /* store in unsigned [big endian] format */
  6152. int
  6153. mp_to_unsigned_bin (mp_int * a, unsigned char *b)
  6154. {
  6155. int x, res;
  6156. mp_int t;
  6157. if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
  6158. return res;
  6159. }
  6160. x = 0;
  6161. while (mp_iszero (&t) == 0) {
  6162. #ifndef MP_8BIT
  6163. b[x++] = (unsigned char) (t.dp[0] & 255);
  6164. #else
  6165. b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7));
  6166. #endif
  6167. if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) {
  6168. mp_clear (&t);
  6169. return res;
  6170. }
  6171. }
  6172. bn_reverse (b, x);
  6173. mp_clear (&t);
  6174. return MP_OKAY;
  6175. }
  6176. #endif
  6177. /* End: bn_mp_to_unsigned_bin.c */
  6178. /* Start: bn_mp_toom_mul.c */
  6179. #include <ltc_tommath.h>
  6180. #ifdef BN_MP_TOOM_MUL_C
  6181. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  6182. *
  6183. * LibTomMath is a library that provides multiple-precision
  6184. * integer arithmetic as well as number theoretic functionality.
  6185. *
  6186. * The library was designed directly after the MPI library by
  6187. * Michael Fromberger but has been written from scratch with
  6188. * additional optimizations in place.
  6189. *
  6190. * The library is free for all purposes without any express
  6191. * guarantee it works.
  6192. *
  6193. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  6194. */
  6195. /* multiplication using the Toom-Cook 3-way algorithm
  6196. *
  6197. * Much more complicated than Karatsuba but has a lower asymptotic running time of
  6198. * O(N**1.464). This algorithm is only particularly useful on VERY large
  6199. * inputs (we're talking 1000s of digits here...).
  6200. */
  6201. int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
  6202. {
  6203. mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2;
  6204. int res, B;
  6205. /* init temps */
  6206. if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4,
  6207. &a0, &a1, &a2, &b0, &b1,
  6208. &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) {
  6209. return res;
  6210. }
  6211. /* B */
  6212. B = MIN(a->used, b->used) / 3;
  6213. /* a = a2 * B**2 + a1 * B + a0 */
  6214. if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
  6215. goto ERR;
  6216. }
  6217. if ((res = mp_copy(a, &a1)) != MP_OKAY) {
  6218. goto ERR;
  6219. }
  6220. mp_rshd(&a1, B);
  6221. mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
  6222. if ((res = mp_copy(a, &a2)) != MP_OKAY) {
  6223. goto ERR;
  6224. }
  6225. mp_rshd(&a2, B*2);
  6226. /* b = b2 * B**2 + b1 * B + b0 */
  6227. if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) {
  6228. goto ERR;
  6229. }
  6230. if ((res = mp_copy(b, &b1)) != MP_OKAY) {
  6231. goto ERR;
  6232. }
  6233. mp_rshd(&b1, B);
  6234. mp_mod_2d(&b1, DIGIT_BIT * B, &b1);
  6235. if ((res = mp_copy(b, &b2)) != MP_OKAY) {
  6236. goto ERR;
  6237. }
  6238. mp_rshd(&b2, B*2);
  6239. /* w0 = a0*b0 */
  6240. if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) {
  6241. goto ERR;
  6242. }
  6243. /* w4 = a2 * b2 */
  6244. if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) {
  6245. goto ERR;
  6246. }
  6247. /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */
  6248. if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
  6249. goto ERR;
  6250. }
  6251. if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
  6252. goto ERR;
  6253. }
  6254. if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
  6255. goto ERR;
  6256. }
  6257. if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
  6258. goto ERR;
  6259. }
  6260. if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) {
  6261. goto ERR;
  6262. }
  6263. if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
  6264. goto ERR;
  6265. }
  6266. if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
  6267. goto ERR;
  6268. }
  6269. if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) {
  6270. goto ERR;
  6271. }
  6272. if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) {
  6273. goto ERR;
  6274. }
  6275. /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */
  6276. if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
  6277. goto ERR;
  6278. }
  6279. if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
  6280. goto ERR;
  6281. }
  6282. if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
  6283. goto ERR;
  6284. }
  6285. if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
  6286. goto ERR;
  6287. }
  6288. if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) {
  6289. goto ERR;
  6290. }
  6291. if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
  6292. goto ERR;
  6293. }
  6294. if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
  6295. goto ERR;
  6296. }
  6297. if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
  6298. goto ERR;
  6299. }
  6300. if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) {
  6301. goto ERR;
  6302. }
  6303. /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */
  6304. if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
  6305. goto ERR;
  6306. }
  6307. if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
  6308. goto ERR;
  6309. }
  6310. if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) {
  6311. goto ERR;
  6312. }
  6313. if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
  6314. goto ERR;
  6315. }
  6316. if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) {
  6317. goto ERR;
  6318. }
  6319. /* now solve the matrix
  6320. 0 0 0 0 1
  6321. 1 2 4 8 16
  6322. 1 1 1 1 1
  6323. 16 8 4 2 1
  6324. 1 0 0 0 0
  6325. using 12 subtractions, 4 shifts,
  6326. 2 small divisions and 1 small multiplication
  6327. */
  6328. /* r1 - r4 */
  6329. if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
  6330. goto ERR;
  6331. }
  6332. /* r3 - r0 */
  6333. if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
  6334. goto ERR;
  6335. }
  6336. /* r1/2 */
  6337. if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
  6338. goto ERR;
  6339. }
  6340. /* r3/2 */
  6341. if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
  6342. goto ERR;
  6343. }
  6344. /* r2 - r0 - r4 */
  6345. if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
  6346. goto ERR;
  6347. }
  6348. if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
  6349. goto ERR;
  6350. }
  6351. /* r1 - r2 */
  6352. if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
  6353. goto ERR;
  6354. }
  6355. /* r3 - r2 */
  6356. if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
  6357. goto ERR;
  6358. }
  6359. /* r1 - 8r0 */
  6360. if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
  6361. goto ERR;
  6362. }
  6363. if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
  6364. goto ERR;
  6365. }
  6366. /* r3 - 8r4 */
  6367. if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
  6368. goto ERR;
  6369. }
  6370. if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
  6371. goto ERR;
  6372. }
  6373. /* 3r2 - r1 - r3 */
  6374. if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
  6375. goto ERR;
  6376. }
  6377. if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
  6378. goto ERR;
  6379. }
  6380. if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
  6381. goto ERR;
  6382. }
  6383. /* r1 - r2 */
  6384. if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
  6385. goto ERR;
  6386. }
  6387. /* r3 - r2 */
  6388. if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
  6389. goto ERR;
  6390. }
  6391. /* r1/3 */
  6392. if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
  6393. goto ERR;
  6394. }
  6395. /* r3/3 */
  6396. if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
  6397. goto ERR;
  6398. }
  6399. /* at this point shift W[n] by B*n */
  6400. if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
  6401. goto ERR;
  6402. }
  6403. if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
  6404. goto ERR;
  6405. }
  6406. if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
  6407. goto ERR;
  6408. }
  6409. if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
  6410. goto ERR;
  6411. }
  6412. if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) {
  6413. goto ERR;
  6414. }
  6415. if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
  6416. goto ERR;
  6417. }
  6418. if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
  6419. goto ERR;
  6420. }
  6421. if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) {
  6422. goto ERR;
  6423. }
  6424. ERR:
  6425. mp_clear_multi(&w0, &w1, &w2, &w3, &w4,
  6426. &a0, &a1, &a2, &b0, &b1,
  6427. &b2, &tmp1, &tmp2, NULL);
  6428. return res;
  6429. }
  6430. #endif
  6431. /* End: bn_mp_toom_mul.c */
  6432. /* Start: bn_mp_toom_sqr.c */
  6433. #include <ltc_tommath.h>
  6434. #ifdef BN_MP_TOOM_SQR_C
  6435. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  6436. *
  6437. * LibTomMath is a library that provides multiple-precision
  6438. * integer arithmetic as well as number theoretic functionality.
  6439. *
  6440. * The library was designed directly after the MPI library by
  6441. * Michael Fromberger but has been written from scratch with
  6442. * additional optimizations in place.
  6443. *
  6444. * The library is free for all purposes without any express
  6445. * guarantee it works.
  6446. *
  6447. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  6448. */
  6449. /* squaring using Toom-Cook 3-way algorithm */
  6450. int
  6451. mp_toom_sqr(mp_int *a, mp_int *b)
  6452. {
  6453. mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2;
  6454. int res, B;
  6455. /* init temps */
  6456. if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) {
  6457. return res;
  6458. }
  6459. /* B */
  6460. B = a->used / 3;
  6461. /* a = a2 * B**2 + a1 * B + a0 */
  6462. if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
  6463. goto ERR;
  6464. }
  6465. if ((res = mp_copy(a, &a1)) != MP_OKAY) {
  6466. goto ERR;
  6467. }
  6468. mp_rshd(&a1, B);
  6469. mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
  6470. if ((res = mp_copy(a, &a2)) != MP_OKAY) {
  6471. goto ERR;
  6472. }
  6473. mp_rshd(&a2, B*2);
  6474. /* w0 = a0*a0 */
  6475. if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) {
  6476. goto ERR;
  6477. }
  6478. /* w4 = a2 * a2 */
  6479. if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) {
  6480. goto ERR;
  6481. }
  6482. /* w1 = (a2 + 2(a1 + 2a0))**2 */
  6483. if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
  6484. goto ERR;
  6485. }
  6486. if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
  6487. goto ERR;
  6488. }
  6489. if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
  6490. goto ERR;
  6491. }
  6492. if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
  6493. goto ERR;
  6494. }
  6495. if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) {
  6496. goto ERR;
  6497. }
  6498. /* w3 = (a0 + 2(a1 + 2a2))**2 */
  6499. if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
  6500. goto ERR;
  6501. }
  6502. if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
  6503. goto ERR;
  6504. }
  6505. if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
  6506. goto ERR;
  6507. }
  6508. if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
  6509. goto ERR;
  6510. }
  6511. if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) {
  6512. goto ERR;
  6513. }
  6514. /* w2 = (a2 + a1 + a0)**2 */
  6515. if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
  6516. goto ERR;
  6517. }
  6518. if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
  6519. goto ERR;
  6520. }
  6521. if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) {
  6522. goto ERR;
  6523. }
  6524. /* now solve the matrix
  6525. 0 0 0 0 1
  6526. 1 2 4 8 16
  6527. 1 1 1 1 1
  6528. 16 8 4 2 1
  6529. 1 0 0 0 0
  6530. using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication.
  6531. */
  6532. /* r1 - r4 */
  6533. if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
  6534. goto ERR;
  6535. }
  6536. /* r3 - r0 */
  6537. if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
  6538. goto ERR;
  6539. }
  6540. /* r1/2 */
  6541. if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
  6542. goto ERR;
  6543. }
  6544. /* r3/2 */
  6545. if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
  6546. goto ERR;
  6547. }
  6548. /* r2 - r0 - r4 */
  6549. if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
  6550. goto ERR;
  6551. }
  6552. if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
  6553. goto ERR;
  6554. }
  6555. /* r1 - r2 */
  6556. if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
  6557. goto ERR;
  6558. }
  6559. /* r3 - r2 */
  6560. if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
  6561. goto ERR;
  6562. }
  6563. /* r1 - 8r0 */
  6564. if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
  6565. goto ERR;
  6566. }
  6567. if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
  6568. goto ERR;
  6569. }
  6570. /* r3 - 8r4 */
  6571. if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
  6572. goto ERR;
  6573. }
  6574. if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
  6575. goto ERR;
  6576. }
  6577. /* 3r2 - r1 - r3 */
  6578. if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
  6579. goto ERR;
  6580. }
  6581. if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
  6582. goto ERR;
  6583. }
  6584. if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
  6585. goto ERR;
  6586. }
  6587. /* r1 - r2 */
  6588. if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
  6589. goto ERR;
  6590. }
  6591. /* r3 - r2 */
  6592. if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
  6593. goto ERR;
  6594. }
  6595. /* r1/3 */
  6596. if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
  6597. goto ERR;
  6598. }
  6599. /* r3/3 */
  6600. if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
  6601. goto ERR;
  6602. }
  6603. /* at this point shift W[n] by B*n */
  6604. if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
  6605. goto ERR;
  6606. }
  6607. if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
  6608. goto ERR;
  6609. }
  6610. if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
  6611. goto ERR;
  6612. }
  6613. if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
  6614. goto ERR;
  6615. }
  6616. if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) {
  6617. goto ERR;
  6618. }
  6619. if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
  6620. goto ERR;
  6621. }
  6622. if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
  6623. goto ERR;
  6624. }
  6625. if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) {
  6626. goto ERR;
  6627. }
  6628. ERR:
  6629. mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL);
  6630. return res;
  6631. }
  6632. #endif
  6633. /* End: bn_mp_toom_sqr.c */
  6634. /* Start: bn_mp_toradix.c */
  6635. #include <ltc_tommath.h>
  6636. #ifdef BN_MP_TORADIX_C
  6637. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  6638. *
  6639. * LibTomMath is a library that provides multiple-precision
  6640. * integer arithmetic as well as number theoretic functionality.
  6641. *
  6642. * The library was designed directly after the MPI library by
  6643. * Michael Fromberger but has been written from scratch with
  6644. * additional optimizations in place.
  6645. *
  6646. * The library is free for all purposes without any express
  6647. * guarantee it works.
  6648. *
  6649. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  6650. */
  6651. /* stores a bignum as a ASCII string in a given radix (2..64) */
  6652. int mp_toradix (mp_int * a, char *str, int radix)
  6653. {
  6654. int res, digs;
  6655. mp_int t;
  6656. mp_digit d;
  6657. char *_s = str;
  6658. /* check range of the radix */
  6659. if (radix < 2 || radix > 64) {
  6660. return MP_VAL;
  6661. }
  6662. /* quick out if its zero */
  6663. if (mp_iszero(a) == 1) {
  6664. *str++ = '0';
  6665. *str = '\0';
  6666. return MP_OKAY;
  6667. }
  6668. if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
  6669. return res;
  6670. }
  6671. /* if it is negative output a - */
  6672. if (t.sign == MP_NEG) {
  6673. ++_s;
  6674. *str++ = '-';
  6675. t.sign = MP_ZPOS;
  6676. }
  6677. digs = 0;
  6678. while (mp_iszero (&t) == 0) {
  6679. if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
  6680. mp_clear (&t);
  6681. return res;
  6682. }
  6683. *str++ = mp_s_rmap[d];
  6684. ++digs;
  6685. }
  6686. /* reverse the digits of the string. In this case _s points
  6687. * to the first digit [exluding the sign] of the number]
  6688. */
  6689. bn_reverse ((unsigned char *)_s, digs);
  6690. /* append a NULL so the string is properly terminated */
  6691. *str = '\0';
  6692. mp_clear (&t);
  6693. return MP_OKAY;
  6694. }
  6695. #endif
  6696. /* End: bn_mp_toradix.c */
  6697. /* Start: bn_mp_toradix_n.c */
  6698. #include <ltc_tommath.h>
  6699. #ifdef BN_MP_TORADIX_N_C
  6700. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  6701. *
  6702. * LibTomMath is a library that provides multiple-precision
  6703. * integer arithmetic as well as number theoretic functionality.
  6704. *
  6705. * The library was designed directly after the MPI library by
  6706. * Michael Fromberger but has been written from scratch with
  6707. * additional optimizations in place.
  6708. *
  6709. * The library is free for all purposes without any express
  6710. * guarantee it works.
  6711. *
  6712. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  6713. */
  6714. /* stores a bignum as a ASCII string in a given radix (2..64)
  6715. *
  6716. * Stores upto maxlen-1 chars and always a NULL byte
  6717. */
  6718. int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen)
  6719. {
  6720. int res, digs;
  6721. mp_int t;
  6722. mp_digit d;
  6723. char *_s = str;
  6724. /* check range of the maxlen, radix */
  6725. if (maxlen < 3 || radix < 2 || radix > 64) {
  6726. return MP_VAL;
  6727. }
  6728. /* quick out if its zero */
  6729. if (mp_iszero(a) == 1) {
  6730. *str++ = '0';
  6731. *str = '\0';
  6732. return MP_OKAY;
  6733. }
  6734. if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
  6735. return res;
  6736. }
  6737. /* if it is negative output a - */
  6738. if (t.sign == MP_NEG) {
  6739. /* we have to reverse our digits later... but not the - sign!! */
  6740. ++_s;
  6741. /* store the flag and mark the number as positive */
  6742. *str++ = '-';
  6743. t.sign = MP_ZPOS;
  6744. /* subtract a char */
  6745. --maxlen;
  6746. }
  6747. digs = 0;
  6748. while (mp_iszero (&t) == 0) {
  6749. if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
  6750. mp_clear (&t);
  6751. return res;
  6752. }
  6753. *str++ = mp_s_rmap[d];
  6754. ++digs;
  6755. if (--maxlen == 1) {
  6756. /* no more room */
  6757. break;
  6758. }
  6759. }
  6760. /* reverse the digits of the string. In this case _s points
  6761. * to the first digit [exluding the sign] of the number]
  6762. */
  6763. bn_reverse ((unsigned char *)_s, digs);
  6764. /* append a NULL so the string is properly terminated */
  6765. *str = '\0';
  6766. mp_clear (&t);
  6767. return MP_OKAY;
  6768. }
  6769. #endif
  6770. /* End: bn_mp_toradix_n.c */
  6771. /* Start: bn_mp_unsigned_bin_size.c */
  6772. #include <ltc_tommath.h>
  6773. #ifdef BN_MP_UNSIGNED_BIN_SIZE_C
  6774. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  6775. *
  6776. * LibTomMath is a library that provides multiple-precision
  6777. * integer arithmetic as well as number theoretic functionality.
  6778. *
  6779. * The library was designed directly after the MPI library by
  6780. * Michael Fromberger but has been written from scratch with
  6781. * additional optimizations in place.
  6782. *
  6783. * The library is free for all purposes without any express
  6784. * guarantee it works.
  6785. *
  6786. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  6787. */
  6788. /* get the size for an unsigned equivalent */
  6789. int
  6790. mp_unsigned_bin_size (mp_int * a)
  6791. {
  6792. int size = mp_count_bits (a);
  6793. return (size / 8 + ((size & 7) != 0 ? 1 : 0));
  6794. }
  6795. #endif
  6796. /* End: bn_mp_unsigned_bin_size.c */
  6797. /* Start: bn_mp_xor.c */
  6798. #include <ltc_tommath.h>
  6799. #ifdef BN_MP_XOR_C
  6800. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  6801. *
  6802. * LibTomMath is a library that provides multiple-precision
  6803. * integer arithmetic as well as number theoretic functionality.
  6804. *
  6805. * The library was designed directly after the MPI library by
  6806. * Michael Fromberger but has been written from scratch with
  6807. * additional optimizations in place.
  6808. *
  6809. * The library is free for all purposes without any express
  6810. * guarantee it works.
  6811. *
  6812. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  6813. */
  6814. /* XOR two ints together */
  6815. int
  6816. mp_xor (mp_int * a, mp_int * b, mp_int * c)
  6817. {
  6818. int res, ix, px;
  6819. mp_int t, *x;
  6820. if (a->used > b->used) {
  6821. if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
  6822. return res;
  6823. }
  6824. px = b->used;
  6825. x = b;
  6826. } else {
  6827. if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
  6828. return res;
  6829. }
  6830. px = a->used;
  6831. x = a;
  6832. }
  6833. for (ix = 0; ix < px; ix++) {
  6834. }
  6835. mp_clamp (&t);
  6836. mp_exch (c, &t);
  6837. mp_clear (&t);
  6838. return MP_OKAY;
  6839. }
  6840. #endif
  6841. /* End: bn_mp_xor.c */
  6842. /* Start: bn_mp_zero.c */
  6843. #include <ltc_tommath.h>
  6844. #ifdef BN_MP_ZERO_C
  6845. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  6846. *
  6847. * LibTomMath is a library that provides multiple-precision
  6848. * integer arithmetic as well as number theoretic functionality.
  6849. *
  6850. * The library was designed directly after the MPI library by
  6851. * Michael Fromberger but has been written from scratch with
  6852. * additional optimizations in place.
  6853. *
  6854. * The library is free for all purposes without any express
  6855. * guarantee it works.
  6856. *
  6857. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  6858. */
  6859. /* set to zero */
  6860. void
  6861. mp_zero (mp_int * a)
  6862. {
  6863. a->sign = MP_ZPOS;
  6864. a->used = 0;
  6865. memset (a->dp, 0, sizeof (mp_digit) * a->alloc);
  6866. }
  6867. #endif
  6868. /* End: bn_mp_zero.c */
  6869. /* Start: bn_prime_tab.c */
  6870. #include <ltc_tommath.h>
  6871. #ifdef BN_PRIME_TAB_C
  6872. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  6873. *
  6874. * LibTomMath is a library that provides multiple-precision
  6875. * integer arithmetic as well as number theoretic functionality.
  6876. *
  6877. * The library was designed directly after the MPI library by
  6878. * Michael Fromberger but has been written from scratch with
  6879. * additional optimizations in place.
  6880. *
  6881. * The library is free for all purposes without any express
  6882. * guarantee it works.
  6883. *
  6884. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  6885. */
  6886. const mp_digit __prime_tab[] = {
  6887. 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
  6888. 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
  6889. 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
  6890. 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F,
  6891. #ifndef MP_8BIT
  6892. 0x0083,
  6893. 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
  6894. 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
  6895. 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
  6896. 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
  6897. 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
  6898. 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
  6899. 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
  6900. 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
  6901. 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
  6902. 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
  6903. 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
  6904. 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
  6905. 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
  6906. 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
  6907. 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
  6908. 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
  6909. 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
  6910. 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
  6911. 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
  6912. 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
  6913. 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
  6914. 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
  6915. 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
  6916. 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
  6917. 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
  6918. 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
  6919. 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
  6920. 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
  6921. #endif
  6922. };
  6923. #endif
  6924. /* End: bn_prime_tab.c */
  6925. /* Start: bn_reverse.c */
  6926. #include <ltc_tommath.h>
  6927. #ifdef BN_REVERSE_C
  6928. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  6929. *
  6930. * LibTomMath is a library that provides multiple-precision
  6931. * integer arithmetic as well as number theoretic functionality.
  6932. *
  6933. * The library was designed directly after the MPI library by
  6934. * Michael Fromberger but has been written from scratch with
  6935. * additional optimizations in place.
  6936. *
  6937. * The library is free for all purposes without any express
  6938. * guarantee it works.
  6939. *
  6940. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  6941. */
  6942. /* reverse an array, used for radix code */
  6943. void
  6944. bn_reverse (unsigned char *s, int len)
  6945. {
  6946. int ix, iy;
  6947. unsigned char t;
  6948. ix = 0;
  6949. iy = len - 1;
  6950. while (ix < iy) {
  6951. t = s[ix];
  6952. s[ix] = s[iy];
  6953. s[iy] = t;
  6954. ++ix;
  6955. --iy;
  6956. }
  6957. }
  6958. #endif
  6959. /* End: bn_reverse.c */
  6960. /* Start: bn_s_mp_add.c */
  6961. #include <ltc_tommath.h>
  6962. #ifdef BN_S_MP_ADD_C
  6963. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  6964. *
  6965. * LibTomMath is a library that provides multiple-precision
  6966. * integer arithmetic as well as number theoretic functionality.
  6967. *
  6968. * The library was designed directly after the MPI library by
  6969. * Michael Fromberger but has been written from scratch with
  6970. * additional optimizations in place.
  6971. *
  6972. * The library is free for all purposes without any express
  6973. * guarantee it works.
  6974. *
  6975. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  6976. */
  6977. /* low level addition, based on HAC pp.594, Algorithm 14.7 */
  6978. int
  6979. s_mp_add (mp_int * a, mp_int * b, mp_int * c)
  6980. {
  6981. mp_int *x;
  6982. int olduse, res, min, max;
  6983. /* find sizes, we let |a| <= |b| which means we have to sort
  6984. * them. "x" will point to the input with the most digits
  6985. */
  6986. if (a->used > b->used) {
  6987. min = b->used;
  6988. max = a->used;
  6989. x = a;
  6990. } else {
  6991. min = a->used;
  6992. max = b->used;
  6993. x = b;
  6994. }
  6995. /* init result */
  6996. if (c->alloc < max + 1) {
  6997. if ((res = mp_grow (c, max + 1)) != MP_OKAY) {
  6998. return res;
  6999. }
  7000. }
  7001. /* get old used digit count and set new one */
  7002. olduse = c->used;
  7003. c->used = max + 1;
  7004. {
  7005. register mp_digit u, *tmpa, *tmpb, *tmpc;
  7006. register int i;
  7007. /* alias for digit pointers */
  7008. /* first input */
  7009. tmpa = a->dp;
  7010. /* second input */
  7011. tmpb = b->dp;
  7012. /* destination */
  7013. tmpc = c->dp;
  7014. /* zero the carry */
  7015. u = 0;
  7016. for (i = 0; i < min; i++) {
  7017. /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
  7018. *tmpc = *tmpa++ + *tmpb++ + u;
  7019. /* U = carry bit of T[i] */
  7020. u = *tmpc >> ((mp_digit)DIGIT_BIT);
  7021. /* take away carry bit from T[i] */
  7022. *tmpc++ &= MP_MASK;
  7023. }
  7024. /* now copy higher words if any, that is in A+B
  7025. * if A or B has more digits add those in
  7026. */
  7027. if (min != max) {
  7028. for (; i < max; i++) {
  7029. /* T[i] = X[i] + U */
  7030. *tmpc = x->dp[i] + u;
  7031. /* U = carry bit of T[i] */
  7032. u = *tmpc >> ((mp_digit)DIGIT_BIT);
  7033. /* take away carry bit from T[i] */
  7034. *tmpc++ &= MP_MASK;
  7035. }
  7036. }
  7037. /* add carry */
  7038. *tmpc++ = u;
  7039. /* clear digits above oldused */
  7040. for (i = c->used; i < olduse; i++) {
  7041. *tmpc++ = 0;
  7042. }
  7043. }
  7044. mp_clamp (c);
  7045. return MP_OKAY;
  7046. }
  7047. #endif
  7048. /* End: bn_s_mp_add.c */
  7049. /* Start: bn_s_mp_exptmod.c */
  7050. #include <ltc_tommath.h>
  7051. #ifdef BN_S_MP_EXPTMOD_C
  7052. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  7053. *
  7054. * LibTomMath is a library that provides multiple-precision
  7055. * integer arithmetic as well as number theoretic functionality.
  7056. *
  7057. * The library was designed directly after the MPI library by
  7058. * Michael Fromberger but has been written from scratch with
  7059. * additional optimizations in place.
  7060. *
  7061. * The library is free for all purposes without any express
  7062. * guarantee it works.
  7063. *
  7064. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  7065. */
  7066. #ifdef MP_LOW_MEM
  7067. #define TAB_SIZE 32
  7068. #else
  7069. #define TAB_SIZE 256
  7070. #endif
  7071. int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
  7072. {
  7073. mp_int M[TAB_SIZE], res, mu;
  7074. mp_digit buf;
  7075. int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
  7076. /* find window size */
  7077. x = mp_count_bits (X);
  7078. if (x <= 7) {
  7079. winsize = 2;
  7080. } else if (x <= 36) {
  7081. winsize = 3;
  7082. } else if (x <= 140) {
  7083. winsize = 4;
  7084. } else if (x <= 450) {
  7085. winsize = 5;
  7086. } else if (x <= 1303) {
  7087. winsize = 6;
  7088. } else if (x <= 3529) {
  7089. winsize = 7;
  7090. } else {
  7091. winsize = 8;
  7092. }
  7093. #ifdef MP_LOW_MEM
  7094. if (winsize > 5) {
  7095. winsize = 5;
  7096. }
  7097. #endif
  7098. /* init M array */
  7099. /* init first cell */
  7100. if ((err = mp_init(&M[1])) != MP_OKAY) {
  7101. return err;
  7102. }
  7103. /* now init the second half of the array */
  7104. for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
  7105. if ((err = mp_init(&M[x])) != MP_OKAY) {
  7106. for (y = 1<<(winsize-1); y < x; y++) {
  7107. mp_clear (&M[y]);
  7108. }
  7109. mp_clear(&M[1]);
  7110. return err;
  7111. }
  7112. }
  7113. /* create mu, used for Barrett reduction */
  7114. if ((err = mp_init (&mu)) != MP_OKAY) {
  7115. goto __M;
  7116. }
  7117. if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) {
  7118. goto __MU;
  7119. }
  7120. /* create M table
  7121. *
  7122. * The M table contains powers of the base,
  7123. * e.g. M[x] = G**x mod P
  7124. *
  7125. * The first half of the table is not
  7126. * computed though accept for M[0] and M[1]
  7127. */
  7128. if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) {
  7129. goto __MU;
  7130. }
  7131. /* compute the value at M[1<<(winsize-1)] by squaring
  7132. * M[1] (winsize-1) times
  7133. */
  7134. if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
  7135. goto __MU;
  7136. }
  7137. for (x = 0; x < (winsize - 1); x++) {
  7138. if ((err = mp_sqr (&M[1 << (winsize - 1)],
  7139. &M[1 << (winsize - 1)])) != MP_OKAY) {
  7140. goto __MU;
  7141. }
  7142. if ((err = mp_reduce (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) {
  7143. goto __MU;
  7144. }
  7145. }
  7146. /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
  7147. * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
  7148. */
  7149. for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
  7150. if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
  7151. goto __MU;
  7152. }
  7153. if ((err = mp_reduce (&M[x], P, &mu)) != MP_OKAY) {
  7154. goto __MU;
  7155. }
  7156. }
  7157. /* setup result */
  7158. if ((err = mp_init (&res)) != MP_OKAY) {
  7159. goto __MU;
  7160. }
  7161. mp_set (&res, 1);
  7162. /* set initial mode and bit cnt */
  7163. mode = 0;
  7164. bitcnt = 1;
  7165. buf = 0;
  7166. digidx = X->used - 1;
  7167. bitcpy = 0;
  7168. bitbuf = 0;
  7169. for (;;) {
  7170. /* grab next digit as required */
  7171. if (--bitcnt == 0) {
  7172. /* if digidx == -1 we are out of digits */
  7173. if (digidx == -1) {
  7174. break;
  7175. }
  7176. /* read next digit and reset the bitcnt */
  7177. buf = X->dp[digidx--];
  7178. bitcnt = (int) DIGIT_BIT;
  7179. }
  7180. /* grab the next msb from the exponent */
  7181. y = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;
  7182. buf <<= (mp_digit)1;
  7183. /* if the bit is zero and mode == 0 then we ignore it
  7184. * These represent the leading zero bits before the first 1 bit
  7185. * in the exponent. Technically this opt is not required but it
  7186. * does lower the # of trivial squaring/reductions used
  7187. */
  7188. if (mode == 0 && y == 0) {
  7189. continue;
  7190. }
  7191. /* if the bit is zero and mode == 1 then we square */
  7192. if (mode == 1 && y == 0) {
  7193. if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
  7194. goto __RES;
  7195. }
  7196. if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) {
  7197. goto __RES;
  7198. }
  7199. continue;
  7200. }
  7201. /* else we add it to the window */
  7202. bitbuf |= (y << (winsize - ++bitcpy));
  7203. mode = 2;
  7204. if (bitcpy == winsize) {
  7205. /* ok window is filled so square as required and multiply */
  7206. /* square first */
  7207. for (x = 0; x < winsize; x++) {
  7208. if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
  7209. goto __RES;
  7210. }
  7211. if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) {
  7212. goto __RES;
  7213. }
  7214. }
  7215. /* then multiply */
  7216. if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
  7217. goto __RES;
  7218. }
  7219. if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) {
  7220. goto __RES;
  7221. }
  7222. /* empty window and reset */
  7223. bitcpy = 0;
  7224. bitbuf = 0;
  7225. mode = 1;
  7226. }
  7227. }
  7228. /* if bits remain then square/multiply */
  7229. if (mode == 2 && bitcpy > 0) {
  7230. /* square then multiply if the bit is set */
  7231. for (x = 0; x < bitcpy; x++) {
  7232. if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
  7233. goto __RES;
  7234. }
  7235. if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) {
  7236. goto __RES;
  7237. }
  7238. bitbuf <<= 1;
  7239. if ((bitbuf & (1 << winsize)) != 0) {
  7240. /* then multiply */
  7241. if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
  7242. goto __RES;
  7243. }
  7244. if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) {
  7245. goto __RES;
  7246. }
  7247. }
  7248. }
  7249. }
  7250. mp_exch (&res, Y);
  7251. err = MP_OKAY;
  7252. __RES:mp_clear (&res);
  7253. __MU:mp_clear (&mu);
  7254. __M:
  7255. mp_clear(&M[1]);
  7256. for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
  7257. mp_clear (&M[x]);
  7258. }
  7259. return err;
  7260. }
  7261. #endif
  7262. /* End: bn_s_mp_exptmod.c */
  7263. /* Start: bn_s_mp_mul_digs.c */
  7264. #include <ltc_tommath.h>
  7265. #ifdef BN_S_MP_MUL_DIGS_C
  7266. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  7267. *
  7268. * LibTomMath is a library that provides multiple-precision
  7269. * integer arithmetic as well as number theoretic functionality.
  7270. *
  7271. * The library was designed directly after the MPI library by
  7272. * Michael Fromberger but has been written from scratch with
  7273. * additional optimizations in place.
  7274. *
  7275. * The library is free for all purposes without any express
  7276. * guarantee it works.
  7277. *
  7278. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  7279. */
  7280. /* multiplies |a| * |b| and only computes upto digs digits of result
  7281. * HAC pp. 595, Algorithm 14.12 Modified so you can control how
  7282. * many digits of output are created.
  7283. */
  7284. int
  7285. s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
  7286. {
  7287. mp_int t;
  7288. int res, pa, pb, ix, iy;
  7289. mp_digit u;
  7290. mp_word r;
  7291. mp_digit tmpx, *tmpt, *tmpy;
  7292. /* can we use the fast multiplier? */
  7293. if (((digs) < MP_WARRAY) &&
  7294. MIN (a->used, b->used) <
  7295. (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
  7296. return fast_s_mp_mul_digs (a, b, c, digs);
  7297. }
  7298. if ((res = mp_init_size (&t, digs)) != MP_OKAY) {
  7299. return res;
  7300. }
  7301. t.used = digs;
  7302. /* compute the digits of the product directly */
  7303. pa = a->used;
  7304. for (ix = 0; ix < pa; ix++) {
  7305. /* set the carry to zero */
  7306. u = 0;
  7307. /* limit ourselves to making digs digits of output */
  7308. pb = MIN (b->used, digs - ix);
  7309. /* setup some aliases */
  7310. /* copy of the digit from a used within the nested loop */
  7311. tmpx = a->dp[ix];
  7312. /* an alias for the destination shifted ix places */
  7313. tmpt = t.dp + ix;
  7314. /* an alias for the digits of b */
  7315. tmpy = b->dp;
  7316. /* compute the columns of the output and propagate the carry */
  7317. for (iy = 0; iy < pb; iy++) {
  7318. /* compute the column as a mp_word */
  7319. r = ((mp_word)*tmpt) +
  7320. ((mp_word)tmpx) * ((mp_word)*tmpy++) +
  7321. ((mp_word) u);
  7322. /* the new column is the lower part of the result */
  7323. *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
  7324. /* get the carry word from the result */
  7325. u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
  7326. }
  7327. /* set carry if it is placed below digs */
  7328. if (ix + iy < digs) {
  7329. *tmpt = u;
  7330. }
  7331. }
  7332. mp_clamp (&t);
  7333. mp_exch (&t, c);
  7334. mp_clear (&t);
  7335. return MP_OKAY;
  7336. }
  7337. #endif
  7338. /* End: bn_s_mp_mul_digs.c */
  7339. /* Start: bn_s_mp_mul_high_digs.c */
  7340. #include <ltc_tommath.h>
  7341. #ifdef BN_S_MP_MUL_HIGH_DIGS_C
  7342. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  7343. *
  7344. * LibTomMath is a library that provides multiple-precision
  7345. * integer arithmetic as well as number theoretic functionality.
  7346. *
  7347. * The library was designed directly after the MPI library by
  7348. * Michael Fromberger but has been written from scratch with
  7349. * additional optimizations in place.
  7350. *
  7351. * The library is free for all purposes without any express
  7352. * guarantee it works.
  7353. *
  7354. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  7355. */
  7356. /* multiplies |a| * |b| and does not compute the lower digs digits
  7357. * [meant to get the higher part of the product]
  7358. */
  7359. int
  7360. s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
  7361. {
  7362. mp_int t;
  7363. int res, pa, pb, ix, iy;
  7364. mp_digit u;
  7365. mp_word r;
  7366. mp_digit tmpx, *tmpt, *tmpy;
  7367. /* can we use the fast multiplier? */
  7368. #ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
  7369. if (((a->used + b->used + 1) < MP_WARRAY)
  7370. && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
  7371. return fast_s_mp_mul_high_digs (a, b, c, digs);
  7372. }
  7373. #endif
  7374. if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) {
  7375. return res;
  7376. }
  7377. t.used = a->used + b->used + 1;
  7378. pa = a->used;
  7379. pb = b->used;
  7380. for (ix = 0; ix < pa; ix++) {
  7381. /* clear the carry */
  7382. u = 0;
  7383. /* left hand side of A[ix] * B[iy] */
  7384. tmpx = a->dp[ix];
  7385. /* alias to the address of where the digits will be stored */
  7386. tmpt = &(t.dp[digs]);
  7387. /* alias for where to read the right hand side from */
  7388. tmpy = b->dp + (digs - ix);
  7389. for (iy = digs - ix; iy < pb; iy++) {
  7390. /* calculate the double precision result */
  7391. r = ((mp_word)*tmpt) +
  7392. ((mp_word)tmpx) * ((mp_word)*tmpy++) +
  7393. ((mp_word) u);
  7394. /* get the lower part */
  7395. *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
  7396. /* carry the carry */
  7397. u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
  7398. }
  7399. *tmpt = u;
  7400. }
  7401. mp_clamp (&t);
  7402. mp_exch (&t, c);
  7403. mp_clear (&t);
  7404. return MP_OKAY;
  7405. }
  7406. #endif
  7407. /* End: bn_s_mp_mul_high_digs.c */
  7408. /* Start: bn_s_mp_sqr.c */
  7409. #include <ltc_tommath.h>
  7410. #ifdef BN_S_MP_SQR_C
  7411. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  7412. *
  7413. * LibTomMath is a library that provides multiple-precision
  7414. * integer arithmetic as well as number theoretic functionality.
  7415. *
  7416. * The library was designed directly after the MPI library by
  7417. * Michael Fromberger but has been written from scratch with
  7418. * additional optimizations in place.
  7419. *
  7420. * The library is free for all purposes without any express
  7421. * guarantee it works.
  7422. *
  7423. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  7424. */
  7425. /* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
  7426. int
  7427. s_mp_sqr (mp_int * a, mp_int * b)
  7428. {
  7429. mp_int t;
  7430. int res, ix, iy, pa;
  7431. mp_word r;
  7432. mp_digit u, tmpx, *tmpt;
  7433. pa = a->used;
  7434. if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) {
  7435. return res;
  7436. }
  7437. /* default used is maximum possible size */
  7438. t.used = 2*pa + 1;
  7439. for (ix = 0; ix < pa; ix++) {
  7440. /* first calculate the digit at 2*ix */
  7441. /* calculate double precision result */
  7442. r = ((mp_word) t.dp[2*ix]) +
  7443. ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);
  7444. /* store lower part in result */
  7445. t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));
  7446. /* get the carry */
  7447. u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
  7448. /* left hand side of A[ix] * A[iy] */
  7449. tmpx = a->dp[ix];
  7450. /* alias for where to store the results */
  7451. tmpt = t.dp + (2*ix + 1);
  7452. for (iy = ix + 1; iy < pa; iy++) {
  7453. /* first calculate the product */
  7454. r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);
  7455. /* now calculate the double precision result, note we use
  7456. * addition instead of *2 since it's easier to optimize
  7457. */
  7458. r = ((mp_word) *tmpt) + r + r + ((mp_word) u);
  7459. /* store lower part */
  7460. *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
  7461. /* get carry */
  7462. u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
  7463. }
  7464. /* propagate upwards */
  7465. while (u != ((mp_digit) 0)) {
  7466. r = ((mp_word) *tmpt) + ((mp_word) u);
  7467. *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
  7468. u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
  7469. }
  7470. }
  7471. mp_clamp (&t);
  7472. mp_exch (&t, b);
  7473. mp_clear (&t);
  7474. return MP_OKAY;
  7475. }
  7476. #endif
  7477. /* End: bn_s_mp_sqr.c */
  7478. /* Start: bn_s_mp_sub.c */
  7479. #include <ltc_tommath.h>
  7480. #ifdef BN_S_MP_SUB_C
  7481. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  7482. *
  7483. * LibTomMath is a library that provides multiple-precision
  7484. * integer arithmetic as well as number theoretic functionality.
  7485. *
  7486. * The library was designed directly after the MPI library by
  7487. * Michael Fromberger but has been written from scratch with
  7488. * additional optimizations in place.
  7489. *
  7490. * The library is free for all purposes without any express
  7491. * guarantee it works.
  7492. *
  7493. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  7494. */
  7495. /* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
  7496. int
  7497. s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
  7498. {
  7499. int olduse, res, min, max;
  7500. /* find sizes */
  7501. min = b->used;
  7502. max = a->used;
  7503. /* init result */
  7504. if (c->alloc < max) {
  7505. if ((res = mp_grow (c, max)) != MP_OKAY) {
  7506. return res;
  7507. }
  7508. }
  7509. olduse = c->used;
  7510. c->used = max;
  7511. {
  7512. register mp_digit u, *tmpa, *tmpb, *tmpc;
  7513. register int i;
  7514. /* alias for digit pointers */
  7515. tmpa = a->dp;
  7516. tmpb = b->dp;
  7517. tmpc = c->dp;
  7518. /* set carry to zero */
  7519. u = 0;
  7520. for (i = 0; i < min; i++) {
  7521. /* T[i] = A[i] - B[i] - U */
  7522. *tmpc = *tmpa++ - *tmpb++ - u;
  7523. /* U = carry bit of T[i]
  7524. * Note this saves performing an AND operation since
  7525. * if a carry does occur it will propagate all the way to the
  7526. * MSB. As a result a single shift is enough to get the carry
  7527. */
  7528. u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
  7529. /* Clear carry from T[i] */
  7530. *tmpc++ &= MP_MASK;
  7531. }
  7532. /* now copy higher words if any, e.g. if A has more digits than B */
  7533. for (; i < max; i++) {
  7534. /* T[i] = A[i] - U */
  7535. *tmpc = *tmpa++ - u;
  7536. /* U = carry bit of T[i] */
  7537. u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
  7538. /* Clear carry from T[i] */
  7539. *tmpc++ &= MP_MASK;
  7540. }
  7541. /* clear digits above used (since we may not have grown result above) */
  7542. for (i = c->used; i < olduse; i++) {
  7543. *tmpc++ = 0;
  7544. }
  7545. }
  7546. mp_clamp (c);
  7547. return MP_OKAY;
  7548. }
  7549. #endif
  7550. /* End: bn_s_mp_sub.c */
  7551. /* Start: bncore.c */
  7552. #include <ltc_tommath.h>
  7553. #ifdef BNCORE_C
  7554. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  7555. *
  7556. * LibTomMath is a library that provides multiple-precision
  7557. * integer arithmetic as well as number theoretic functionality.
  7558. *
  7559. * The library was designed directly after the MPI library by
  7560. * Michael Fromberger but has been written from scratch with
  7561. * additional optimizations in place.
  7562. *
  7563. * The library is free for all purposes without any express
  7564. * guarantee it works.
  7565. *
  7566. * Tom St Denis, [email protected], http://math.libtomcrypt.org
  7567. */
  7568. /* Known optimal configurations
  7569. CPU /Compiler /MUL CUTOFF/SQR CUTOFF
  7570. -------------------------------------------------------------
  7571. Intel P4 Northwood /GCC v3.4.1 / 88/ 128/LTM 0.32 ;-)
  7572. */
  7573. int KARATSUBA_MUL_CUTOFF = 88, /* Min. number of digits before Karatsuba multiplication is used. */
  7574. KARATSUBA_SQR_CUTOFF = 128, /* Min. number of digits before Karatsuba squaring is used. */
  7575. TOOM_MUL_CUTOFF = 350, /* no optimal values of these are known yet so set em high */
  7576. TOOM_SQR_CUTOFF = 400;
  7577. #endif
  7578. /* End: bncore.c */
  7579. /* EOF */