mpi.c 233 KB

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