123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754 |
- /*++
- Copyright (c) 2015 Minoca Corp. All Rights Reserved
- Module Name:
- bigint.c
- Abstract:
- This module implements support for large integer arithmetic.
- Author:
- Evan Green 14-Jul-2015
- Environment:
- Any
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include "../cryptop.h"
- //
- // --------------------------------------------------------------------- Macros
- //
- #define CypBiResidue(_Context, _Value) \
- CypBiPerformBarrettReduction((_Context), (_Value))
- #define CypBiModulo(_Context, _Value) \
- CypBiDivide((_Context), \
- (_Value), \
- (_Context)->Modulus[(_Context)->ModOffset], \
- TRUE)
- //
- // ---------------------------------------------------------------- Definitions
- //
- //
- // Define the special reference count that signifies reference counting is
- // not in use for this value.
- //
- #define BIG_INTEGER_PERMANENT_REFERENCE 0x7FFFFFF0
- //
- // Define the number of bits in a component.
- //
- #define BIG_INTEGER_COMPONENT_BITS \
- (sizeof(BIG_INTEGER_COMPONENT) * BITS_PER_BYTE)
- #define BIG_INTEGER_LONG_COMPONENT_MAX 0xFFFFFFFFFFFFFFFFULL
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- PBIG_INTEGER
- CypBiAdd (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Left,
- PBIG_INTEGER Right
- );
- PBIG_INTEGER
- CypBiSubtract (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Left,
- PBIG_INTEGER Right,
- PBOOL NegativeResult
- );
- PBIG_INTEGER
- CypBiMultiply (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Left,
- PBIG_INTEGER Right
- );
- PBIG_INTEGER
- CypBiDivide (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Numerator,
- PBIG_INTEGER Denominator,
- BOOL ModuloOperation
- );
- PBIG_INTEGER
- CypBiSquare (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Value
- );
- INT
- CypBiCompare (
- PBIG_INTEGER Left,
- PBIG_INTEGER Right
- );
- PBIG_INTEGER
- CypBiMultiplyComponent (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Left,
- BIG_INTEGER_COMPONENT RightComponent
- );
- PBIG_INTEGER
- CypBiMultiplyStandard (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Left,
- PBIG_INTEGER Right,
- INTN InnerPartial,
- INTN OuterPartial
- );
- PBIG_INTEGER
- CypBiDivideComponent (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Numerator,
- BIG_INTEGER_COMPONENT Denominator
- );
- PBIG_INTEGER
- CypBiRightShiftComponent (
- PBIG_INTEGER Value,
- UINTN ComponentCount
- );
- PBIG_INTEGER
- CypBiLeftShiftComponent (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Value,
- UINTN ComponentCount
- );
- INTN
- CypBiFindLeadingBit (
- PBIG_INTEGER Value
- );
- BOOL
- CypBiTestBit (
- PBIG_INTEGER Value,
- UINTN BitIndex
- );
- PBIG_INTEGER
- CypBiPerformBarrettReduction (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Value
- );
- KSTATUS
- CypBiComputeExponentTable (
- PBIG_INTEGER_CONTEXT Context,
- INTN CountExponent,
- PBIG_INTEGER Value
- );
- PBIG_INTEGER
- CypBiClone (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Integer
- );
- PBIG_INTEGER
- CypBiCreateFromInteger (
- PBIG_INTEGER_CONTEXT Context,
- BIG_INTEGER_COMPONENT Value
- );
- PBIG_INTEGER
- CypBiCreate (
- PBIG_INTEGER_CONTEXT Context,
- UINTN ComponentCount
- );
- KSTATUS
- CypBiResize (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Integer,
- UINTN ComponentCount
- );
- VOID
- CypBiTrim (
- PBIG_INTEGER Integer
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- //
- // ------------------------------------------------------------------ Functions
- //
- KSTATUS
- CypBiInitializeContext (
- PBIG_INTEGER_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine initializes a big integer context.
- Arguments:
- Context - Supplies a pointer to the context to initialize.
- Return Value:
- STATUS_SUCCESS on success.
- STATUS_INVALID_PARAMETER if the context was not partially filled
- in correctly.
- STATUS_INSUFFICIENT_RESOURCES if an allocation failed.
- --*/
- {
- UINTN DataSize;
- if ((Context->AllocateMemory == NULL) ||
- (Context->ReallocateMemory == NULL) ||
- (Context->FreeMemory == NULL)) {
- ASSERT(FALSE);
- return STATUS_INVALID_PARAMETER;
- }
- //
- // Zero everything but the functions.
- //
- DataSize = sizeof(BIG_INTEGER_CONTEXT) -
- FIELD_OFFSET(BIG_INTEGER_CONTEXT, ActiveList);
- RtlZeroMemory(&(Context->ActiveList), DataSize);
- Context->Radix = CypBiCreate(Context, 2);
- if (Context->Radix == NULL) {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
- Context->Radix->Components[0] = 0;
- Context->Radix->Components[1] = 1;
- CypBiMakePermanent(Context->Radix);
- return STATUS_SUCCESS;
- }
- VOID
- CypBiDestroyContext (
- PBIG_INTEGER_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine destroys a big integer context.
- Arguments:
- Context - Supplies a pointer to the context to tear down.
- Return Value:
- None.
- --*/
- {
- ASSERT((Context->ExponentTable == NULL) &&
- (Context->WindowSize == 0));
- CypBiMakeNonPermanent(Context->Radix);
- CypBiReleaseReference(Context, Context->Radix);
- ASSERT(Context->ActiveCount == 0);
- CypBiClearCache(Context);
- return;
- }
- VOID
- CypBiClearCache (
- PBIG_INTEGER_CONTEXT Context
- )
- /*++
- Routine Description:
- This routine destroys all big integers on the free list for the given
- context.
- Arguments:
- Context - Supplies a pointer to the context to clear.
- for.
- Return Value:
- None.
- --*/
- {
- PBIG_INTEGER Integer;
- PBIG_INTEGER Next;
- Integer = Context->FreeList;
- while (Integer != NULL) {
- Next = Integer->Next;
- //
- // Zero out the value itself to avoid leaking state.
- //
- RtlZeroMemory(Integer->Components,
- Integer->Capacity * sizeof(BIG_INTEGER_COMPONENT));
- Context->FreeMemory(Integer->Components);
- Context->FreeMemory(Integer);
- Integer = Next;
- }
- return;
- }
- KSTATUS
- CypBiCalculateModuli (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Value,
- INTN ModOffset
- )
- /*++
- Routine Description:
- This routine performs some pre-calculations used in modulo reduction
- optimizations.
- Arguments:
- Context - Supplies a pointer to the big integer context.
- Value - Supplies a pointer to the modulus that will be used. This value
- will be made permanent.
- ModOffset - Supplies an offset to the moduli that can be used: the standard
- moduli, or the primes p and q.
- Return Value:
- STATUS_SUCCESS on success.
- STATUS_INSUFFICIENT_RESOURCES if an allocation failed.
- --*/
- {
- BIG_INTEGER_COMPONENT DValue;
- PBIG_INTEGER RadixCopy;
- PBIG_INTEGER ShiftedRadix;
- UINTN Size;
- KSTATUS Status;
- RadixCopy = NULL;
- Size = Value->Size;
- Status = STATUS_INSUFFICIENT_RESOURCES;
- DValue = BIG_INTEGER_RADIX / (Value->Components[Size - 1] + 1);
- ASSERT(Context->Modulus[ModOffset] == NULL);
- Context->Modulus[ModOffset] = Value;
- CypBiMakePermanent(Value);
- ASSERT(Context->NormalizedMod[ModOffset] == NULL);
- Context->NormalizedMod[ModOffset] = CypBiMultiplyComponent(Context,
- Value,
- DValue);
- if (Context->NormalizedMod[ModOffset] == NULL) {
- goto BiCalculateModuliEnd;
- }
- CypBiMakePermanent(Context->NormalizedMod[ModOffset]);
- //
- // Compute Mu for Barrett reduction.
- //
- RadixCopy = CypBiClone(Context, Context->Radix);
- if (RadixCopy == NULL) {
- goto BiCalculateModuliEnd;
- }
- ShiftedRadix = CypBiLeftShiftComponent(Context, RadixCopy, (Size * 2) - 1);
- if (ShiftedRadix == NULL) {
- goto BiCalculateModuliEnd;
- }
- ASSERT(Context->Mu[ModOffset] == NULL);
- Context->Mu[ModOffset] = CypBiDivide(Context,
- ShiftedRadix,
- Context->Modulus[ModOffset],
- FALSE);
- if (Context->Mu[ModOffset] == NULL) {
- goto BiCalculateModuliEnd;
- }
- CypBiMakePermanent(Context->Mu[ModOffset]);
- RadixCopy = NULL;
- Status = STATUS_SUCCESS;
- BiCalculateModuliEnd:
- if (RadixCopy != NULL) {
- CypBiReleaseReference(Context, RadixCopy);
- }
- return Status;
- }
- VOID
- CypBiReleaseModuli (
- PBIG_INTEGER_CONTEXT Context,
- INTN ModOffset
- )
- /*++
- Routine Description:
- This routine frees memory associated with moduli for the given offset.
- Arguments:
- Context - Supplies a pointer to the big integer context.
- ModOffset - Supplies the index of the moduli to free: the standard
- moduli, or the primes p and q.
- Return Value:
- None.
- --*/
- {
- PBIG_INTEGER *Pointer;
- Pointer = &(Context->Modulus[ModOffset]);
- if (*Pointer != NULL) {
- CypBiMakeNonPermanent(*Pointer);
- CypBiReleaseReference(Context, *Pointer);
- *Pointer = NULL;
- }
- Pointer = &(Context->Mu[ModOffset]);
- if (*Pointer != NULL) {
- CypBiMakeNonPermanent(*Pointer);
- CypBiReleaseReference(Context, *Pointer);
- *Pointer = NULL;
- }
- Pointer = &(Context->NormalizedMod[ModOffset]);
- if (*Pointer != NULL) {
- CypBiMakeNonPermanent(*Pointer);
- CypBiReleaseReference(Context, *Pointer);
- *Pointer = NULL;
- }
- return;
- }
- PBIG_INTEGER
- CypBiExponentiateModulo (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Value,
- PBIG_INTEGER Exponent
- )
- /*++
- Routine Description:
- This routine performs exponentiation, modulo a value.
- Arguments:
- Context - Supplies a pointer to the big integer context.
- Value - Supplies a pointer to the value to reduce. A reference on this
- value will be released on success.
- Exponent - Supplies the exponent to raise the value to. A reference on this
- value will be released on success.
- Return Value:
- Returns a pointer to the exponentiated value on success.
- NULL on allocation failure.
- --*/
- {
- INTN BitIndex;
- UINTN Index;
- INTN LeadingBit;
- PBIG_INTEGER NewValue;
- INTN NextBit;
- INTN PartialExponent;
- PBIG_INTEGER Result;
- KSTATUS Status;
- INTN WindowSize;
- WindowSize = 1;
- LeadingBit = CypBiFindLeadingBit(Exponent);
- ASSERT(LeadingBit > 0);
- Result = CypBiCreateFromInteger(Context, 1);
- if (Result == NULL) {
- return NULL;
- }
- Status = STATUS_INSUFFICIENT_RESOURCES;
- //
- // Work out a reasonable window size.
- //
- for (BitIndex = LeadingBit; BitIndex > 32; BitIndex /= 5) {
- WindowSize += 1;
- }
- Status = CypBiComputeExponentTable(Context, WindowSize, Value);
- if (!KSUCCESS(Status)) {
- goto BiExponentiateModuloEnd;
- }
- //
- // Compute the exponentiated value, a bit at a time if the window size is
- // one, or a few bits at a time for a greater window.
- //
- Status = STATUS_INSUFFICIENT_RESOURCES;
- do {
- if (CypBiTestBit(Exponent, LeadingBit) != FALSE) {
- NextBit = LeadingBit - WindowSize + 1;
- //
- // The least significant bit of the exponent is always set.
- //
- if (NextBit < 0) {
- NextBit = 0;
- } else {
- while (CypBiTestBit(Exponent, NextBit) == FALSE) {
- NextBit += 1;
- }
- }
- PartialExponent = 0;
- //
- // Compute the portion of the exponent.
- //
- for (BitIndex = LeadingBit; BitIndex >= NextBit; BitIndex -= 1) {
- NewValue = CypBiSquare(Context, Result);
- if (NewValue == NULL) {
- goto BiExponentiateModuloEnd;
- }
- Result = NewValue;
- NewValue = CypBiResidue(Context, Result);
- if (NewValue == NULL) {
- goto BiExponentiateModuloEnd;
- }
- ASSERT(NewValue == Result);
- if (CypBiTestBit(Exponent, BitIndex) != FALSE) {
- PartialExponent += 1;
- }
- if (BitIndex != NextBit) {
- PartialExponent <<= 1;
- }
- }
- //
- // Adjust to the array indices.
- //
- PartialExponent = (PartialExponent - 1) / 2;
- ASSERT(PartialExponent < Context->WindowSize);
- NewValue = CypBiMultiply(Context,
- Result,
- Context->ExponentTable[PartialExponent]);
- if (NewValue == NULL) {
- goto BiExponentiateModuloEnd;
- }
- Result = NewValue;
- NewValue = CypBiResidue(Context, Result);
- if (NewValue == NULL) {
- goto BiExponentiateModuloEnd;
- }
- ASSERT(NewValue == Result);
- LeadingBit = NextBit - 1;
- //
- // Square the value.
- //
- } else {
- NewValue = CypBiSquare(Context, Result);
- if (NewValue == NULL) {
- goto BiExponentiateModuloEnd;
- }
- Result = NewValue;
- NewValue = CypBiResidue(Context, Result);
- if (NewValue == NULL) {
- goto BiExponentiateModuloEnd;
- }
- ASSERT(NewValue == Result);
- LeadingBit -= 1;
- }
- } while (LeadingBit >= 0);
- CypBiReleaseReference(Context, Value);
- CypBiReleaseReference(Context, Exponent);
- Status = STATUS_SUCCESS;
- BiExponentiateModuloEnd:
- //
- // Destroy the exponent table.
- //
- if (Context->ExponentTable != NULL) {
- for (Index = 0; Index < Context->WindowSize; Index += 1) {
- CypBiMakeNonPermanent(Context->ExponentTable[Index]);
- CypBiReleaseReference(Context, Context->ExponentTable[Index]);
- }
- Context->FreeMemory(Context->ExponentTable);
- Context->ExponentTable = NULL;
- Context->WindowSize = 0;
- }
- if (!KSUCCESS(Status)) {
- if (Result != NULL) {
- CypBiReleaseReference(Context, Result);
- Result = NULL;
- }
- }
- return Result;
- }
- PBIG_INTEGER
- CypBiChineseRemainderTheorem (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Value,
- PBIG_INTEGER DpValue,
- PBIG_INTEGER DqValue,
- PBIG_INTEGER PValue,
- PBIG_INTEGER QValue,
- PBIG_INTEGER QInverse
- )
- /*++
- Routine Description:
- This routine uses the Chinese Remainder Theorem as an aide to quickly
- decrypting RSA values.
- Arguments:
- Context - Supplies a pointer to the big integer context.
- Value - Supplies a pointer to the value to perform the exponentiation on. A
- reference on this value will be released on success.
- DpValue - Supplies a pointer to the dP value. A reference on this will be
- released on success.
- DqValue - Supplies a pointer to the dQ value. A reference on this will be
- released on success.
- PValue - Supplies a pointer to the p prime. A reference on this value will
- be released on success.
- QValue - Supplies a pointer to the q prime. A reference on this value will
- be released on success.
- QInverse - Supplies a pointer to the Q inverse. A reference on this will be
- released on success.
- Return Value:
- Returns a pointer to the result of the Chinese Remainder Theorem on success.
- NULL on allocation failure.
- --*/
- {
- PBIG_INTEGER HValue;
- PBIG_INTEGER M1;
- PBIG_INTEGER M2;
- PBIG_INTEGER NewValue;
- UCHAR OriginalModOffset;
- PBIG_INTEGER Result;
- HValue = NULL;
- M1 = NULL;
- M2 = NULL;
- Result = NULL;
- OriginalModOffset = Context->ModOffset;
- Context->ModOffset = BIG_INTEGER_P_OFFSET;
- CypBiAddReference(Value);
- CypBiAddReference(DpValue);
- M1 = CypBiExponentiateModulo(Context, Value, DpValue);
- if (M1 == NULL) {
- CypBiReleaseReference(Context, Value);
- CypBiReleaseReference(Context, DpValue);
- goto BiChineseRemainderTheoremEnd;
- }
- Context->ModOffset = BIG_INTEGER_Q_OFFSET;
- CypBiAddReference(Value);
- CypBiAddReference(DqValue);
- M2 = CypBiExponentiateModulo(Context, Value, DqValue);
- if (M2 == NULL) {
- CypBiReleaseReference(Context, Value);
- CypBiReleaseReference(Context, DqValue);
- goto BiChineseRemainderTheoremEnd;
- }
- CypBiAddReference(PValue);
- HValue = CypBiAdd(Context, M1, PValue);
- if (HValue == NULL) {
- CypBiReleaseReference(Context, PValue);
- goto BiChineseRemainderTheoremEnd;
- }
- M1 = NULL;
- CypBiAddReference(M2);
- NewValue = CypBiSubtract(Context, HValue, M2, NULL);
- if (NewValue == NULL) {
- CypBiReleaseReference(Context, M2);
- goto BiChineseRemainderTheoremEnd;
- }
- ASSERT(HValue == NewValue);
- CypBiAddReference(QInverse);
- NewValue = CypBiMultiply(Context, HValue, QInverse);
- if (NewValue == NULL) {
- CypBiReleaseReference(Context, QInverse);
- goto BiChineseRemainderTheoremEnd;
- }
- HValue = NewValue;
- Context->ModOffset = BIG_INTEGER_P_OFFSET;
- NewValue = CypBiResidue(Context, HValue);
- if (NewValue == NULL) {
- goto BiChineseRemainderTheoremEnd;
- }
- ASSERT(NewValue == HValue);
- CypBiAddReference(QValue);
- NewValue = CypBiMultiply(Context, QValue, HValue);
- if (NewValue == NULL) {
- CypBiReleaseReference(Context, QValue);
- goto BiChineseRemainderTheoremEnd;
- }
- HValue = NULL;
- Result = CypBiAdd(Context, M2, NewValue);
- if (Result == NULL) {
- goto BiChineseRemainderTheoremEnd;
- }
- M2 = NULL;
- CypBiReleaseReference(Context, PValue);
- CypBiReleaseReference(Context, QValue);
- CypBiReleaseReference(Context, DpValue);
- CypBiReleaseReference(Context, DqValue);
- CypBiReleaseReference(Context, QInverse);
- CypBiReleaseReference(Context, Value);
- BiChineseRemainderTheoremEnd:
- Context->ModOffset = OriginalModOffset;
- if (M1 != NULL) {
- CypBiReleaseReference(Context, M1);
- }
- if (M2 != NULL) {
- CypBiReleaseReference(Context, M2);
- }
- if (HValue != NULL) {
- CypBiReleaseReference(Context, HValue);
- }
- return Result;
- }
- PBIG_INTEGER
- CypBiImport (
- PBIG_INTEGER_CONTEXT Context,
- PVOID Data,
- UINTN Size
- )
- /*++
- Routine Description:
- This routine creates a big integer from a set of raw binary bytes.
- Arguments:
- Context - Supplies a pointer to the big integer context.
- Data - Supplies a pointer to the data to import.
- Size - Supplies the number of bytes in the data.
- Return Value:
- Returns a pointer to the newly created value on success.
- NULL on allocation failure.
- --*/
- {
- UINTN ByteIndex;
- PUCHAR Bytes;
- UINTN ComponentCount;
- INTN Index;
- UINTN Offset;
- PBIG_INTEGER Value;
- Bytes = Data;
- ComponentCount = ALIGN_RANGE_UP(Size, sizeof(BIG_INTEGER_COMPONENT));
- Value = CypBiCreate(Context, ComponentCount);
- if (Value == NULL) {
- return NULL;
- }
- RtlZeroMemory(Value->Components,
- Value->Size * sizeof(BIG_INTEGER_COMPONENT));
- //
- // The data comes in as a sequence of bytes, most significant first.
- // Convert that to a series of components, least significant component
- // first.
- //
- ByteIndex = 0;
- Offset = 0;
- for (Index = Size - 1; Index >= 0; Index -= 1) {
- Value->Components[Offset] += Bytes[Index] <<
- (ByteIndex * BITS_PER_BYTE);
- ByteIndex += 1;
- if (ByteIndex == sizeof(BIG_INTEGER_COMPONENT)) {
- ByteIndex = 0;
- Offset += 1;
- }
- }
- CypBiTrim(Value);
- return Value;
- }
- KSTATUS
- CypBiExport (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Value,
- PVOID Data,
- UINTN Size
- )
- /*++
- Routine Description:
- This routine exports a big integer to a byte stream.
- Arguments:
- Context - Supplies a pointer to the big integer context.
- Value - Supplies a pointer to the big integer to export. A reference is
- released on this value by this function on success.
- Data - Supplies a pointer to the data buffer.
- Size - Supplies the number of bytes in the data buffer.
- Return Value:
- STATUS_SUCCESS on success.
- STATUS_BUFFER_TOO_SMALL if the given buffer was not big enough to hold the
- entire integer.
- --*/
- {
- ULONG Byte;
- UINTN ByteIndex;
- PUCHAR DataBytes;
- UINTN DataIndex;
- INTN Index;
- UINTN IntegerSize;
- BIG_INTEGER_COMPONENT Mask;
- DataBytes = Data;
- IntegerSize = Value->Size * sizeof(BIG_INTEGER_COMPONENT);
- if (IntegerSize > Size) {
- return STATUS_BUFFER_TOO_SMALL;
- }
- DataIndex = IntegerSize - 1;
- for (Index = 0; Index < Value->Size; Index += 1) {
- for (ByteIndex = 0;
- ByteIndex < sizeof(BIG_INTEGER_COMPONENT);
- ByteIndex += 1) {
- Mask = 0xFF << (ByteIndex * BITS_PER_BYTE);
- Byte = (Value->Components[Index] & Mask) >>
- (ByteIndex * BITS_PER_BYTE);
- DataBytes[DataIndex] = Byte;
- DataIndex -= 1;
- }
- }
- CypBiReleaseReference(Context, Value);
- return STATUS_SUCCESS;
- }
- VOID
- CypBiDebugPrint (
- PBIG_INTEGER Value
- )
- /*++
- Routine Description:
- This routine debug prints the contents of a big integer.
- Arguments:
- Value - Supplies a pointer to the value to print.
- Return Value:
- None.
- --*/
- {
- PBIG_INTEGER_COMPONENT Components;
- ULONG FieldSize;
- INTN Index;
- //
- // Each hex digit prints 4 bits, hence the divide by 4.
- //
- FieldSize = BIG_INTEGER_COMPONENT_BITS / 4;
- Index = Value->Size - 1;
- Components = Value->Components;
- RtlDebugPrint("%x", Components[Index]);
- while (Index > 0) {
- RtlDebugPrint("%0*llx", FieldSize, (ULONGLONG)(Components[Index]));
- Index -= 1;
- }
- return;
- }
- VOID
- CypBiAddReference (
- PBIG_INTEGER Integer
- )
- /*++
- Routine Description:
- This routine adds a reference to the given big integer.
- Arguments:
- Integer - Supplies a pointer to the big integer.
- Return Value:
- None.
- --*/
- {
- if (Integer->ReferenceCount == BIG_INTEGER_PERMANENT_REFERENCE) {
- return;
- }
- ASSERT((Integer->ReferenceCount != 0) &&
- (Integer->ReferenceCount < 0x10000000));
- Integer->ReferenceCount += 1;
- return;
- }
- VOID
- CypBiReleaseReference (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Integer
- )
- /*++
- Routine Description:
- This routine releases resources associated with a big integer.
- Arguments:
- Context - Supplies a pointer to the context that owns the integer.
- Integer - Supplies a pointer to the big integer.
- ComponentCount - Supplies the number of components to allocate
- for.
- Return Value:
- None.
- --*/
- {
- if (Integer->ReferenceCount == BIG_INTEGER_PERMANENT_REFERENCE) {
- return;
- }
- ASSERT((Integer->ReferenceCount != 0) &&
- (Integer->ReferenceCount < 0x10000000));
- Integer->ReferenceCount -= 1;
- if (Integer->ReferenceCount > 0) {
- return;
- }
- //
- // Move the integer to the free list.
- //
- Integer->Next = Context->FreeList;
- Context->FreeList = Integer;
- Context->FreeCount += 1;
- ASSERT(Context->ActiveCount > 0);
- Context->ActiveCount -= 1;
- return;
- }
- VOID
- CypBiMakePermanent (
- PBIG_INTEGER Integer
- )
- /*++
- Routine Description:
- This routine makes a big integer "permanent", causing add and release
- references to be ignored.
- Arguments:
- Integer - Supplies a pointer to the big integer.
- Return Value:
- None.
- --*/
- {
- ASSERT(Integer->ReferenceCount == 1);
- Integer->ReferenceCount = BIG_INTEGER_PERMANENT_REFERENCE;
- return;
- }
- VOID
- CypBiMakeNonPermanent (
- PBIG_INTEGER Integer
- )
- /*++
- Routine Description:
- This routine undoes the effects of making a big integer permanent,
- instead giving it a reference count of 1.
- Arguments:
- Integer - Supplies a pointer to the big integer.
- Return Value:
- None.
- --*/
- {
- ASSERT(Integer->ReferenceCount == BIG_INTEGER_PERMANENT_REFERENCE);
- Integer->ReferenceCount = 1;
- return;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- PBIG_INTEGER
- CypBiAdd (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Left,
- PBIG_INTEGER Right
- )
- /*++
- Routine Description:
- This routine adds two big integers together.
- Arguments:
- Context - Supplies a pointer to the big integer context.
- Left - Supplies the first value to add, as well as the destination.
- Right - Supplies the second value to add. A reference on this value will be
- released on success.
- Return Value:
- Returns a pointer to the left value, which will have accumulated
- the sum of the two.
- NULL on allocation failure.
- --*/
- {
- BIG_INTEGER_COMPONENT Carry;
- PBIG_INTEGER_COMPONENT LeftComponent;
- PBIG_INTEGER_COMPONENT RightComponent;
- KSTATUS Status;
- BIG_INTEGER_COMPONENT Sum;
- UINTN SumSize;
- BIG_INTEGER_COMPONENT SumWithCarry;
- //
- // The number of components in the sum is the maximum number of components
- // between then two, plus one for a potential carry.
- //
- SumSize = Left->Size;
- if (SumSize < Right->Size) {
- SumSize = Right->Size;
- }
- //
- // Resize the left for the final result, and resize the right to be the max
- // of the two to avoid annoying checks within the computation loop.
- //
- Status = CypBiResize(Context, Left, SumSize + 1);
- if (!KSUCCESS(Status)) {
- return NULL;
- }
- Status = CypBiResize(Context, Right, SumSize);
- if (!KSUCCESS(Status)) {
- return NULL;
- }
- LeftComponent = Left->Components;
- RightComponent = Right->Components;
- Carry = 0;
- do {
- Sum = *LeftComponent + *RightComponent;
- SumWithCarry = Sum + Carry;
- Carry = 0;
- if ((Sum < *LeftComponent) || (SumWithCarry < Sum)) {
- Carry = 1;
- }
- *LeftComponent = SumWithCarry;
- LeftComponent += 1;
- RightComponent += 1;
- SumSize -= 1;
- } while (SumSize != 0);
- *LeftComponent = Carry;
- CypBiReleaseReference(Context, Right);
- CypBiTrim(Left);
- return Left;
- }
- PBIG_INTEGER
- CypBiSubtract (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Left,
- PBIG_INTEGER Right,
- PBOOL NegativeResult
- )
- /*++
- Routine Description:
- This routine subtracts two big integers from each other.
- Arguments:
- Context - Supplies a pointer to the big integer context.
- Left - Supplies the value to subtract from, as well as the destination.
- Right - Supplies the value to subtract. A reference on this value will be
- released on success.
- NegativeResult - Supplies an optional pointer where a boolean will be
- returned indicating whether the result was negative or not.
- Return Value:
- Returns a pointer to the left value, which will have subtracted
- value.
- NULL on allocation failure.
- --*/
- {
- BIG_INTEGER_COMPONENT Carry;
- PBIG_INTEGER_COMPONENT LeftComponent;
- PBIG_INTEGER_COMPONENT RightComponent;
- INTN Size;
- KSTATUS Status;
- BIG_INTEGER_COMPONENT Sum;
- BIG_INTEGER_COMPONENT SumWithCarry;
- Size = Left->Size;
- Status = CypBiResize(Context, Right, Size);
- if (!KSUCCESS(Status)) {
- return NULL;
- }
- LeftComponent = Left->Components;
- RightComponent = Right->Components;
- Carry = 0;
- do {
- Sum = *LeftComponent - *RightComponent;
- SumWithCarry = Sum - Carry;
- Carry = 0;
- if ((Sum > *LeftComponent) || (SumWithCarry > Sum)) {
- Carry = 1;
- }
- *LeftComponent = SumWithCarry;
- LeftComponent += 1;
- RightComponent += 1;
- Size -= 1;
- } while (Size != 0);
- if (NegativeResult != NULL) {
- *NegativeResult = Carry;
- }
- //
- // Put the right side back to what it was.
- //
- CypBiTrim(Right);
- CypBiReleaseReference(Context, Right);
- CypBiTrim(Left);
- return Left;
- }
- PBIG_INTEGER
- CypBiMultiply (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Left,
- PBIG_INTEGER Right
- )
- /*++
- Routine Description:
- This routine multiplies two big integers together.
- Arguments:
- Context - Supplies a pointer to the big integer context.
- Left - Supplies the value to multiply. A reference on this value will be
- released on success.
- Right - Supplies the value to multiply by. A reference on this value will be
- released on success.
- Return Value:
- Returns a pointer to the new product.
- NULL on allocation failure.
- --*/
- {
- return CypBiMultiplyStandard(Context, Left, Right, 0, 0);
- }
- PBIG_INTEGER
- CypBiDivide (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Numerator,
- PBIG_INTEGER Denominator,
- BOOL ModuloOperation
- )
- /*++
- Routine Description:
- This routine divides two big integers.
- Arguments:
- Context - Supplies a pointer to the big integer context.
- Numerator - Supplies a pointer to the numerator. This is also the
- destination.
- Denominator - Supplies a pointer to the denominator. A reference will be
- released on this value on success.
- ModuloOperation - Supplies a boolean indicating whether to return the
- quotient (FALSE) or the modulo (TRUE).
- Return Value:
- Returns a pointer to the numerator (now quotient or modulo) on success.
- NULL on allocation failure.
- --*/
- {
- PBIG_INTEGER DenominatorTimesQDash;
- UINTN Index;
- BIG_INTEGER_COMPONENT Inner;
- BOOL IsNegative;
- BIG_INTEGER_COMPONENT Last;
- BIG_INTEGER_COMPONENT LastDenominator;
- BIG_INTEGER_COMPONENT LastWorking;
- INTN ModOffset;
- PBIG_INTEGER NewWorking;
- INTN NumeratorIndex;
- INTN OriginalNumeratorSize;
- BIG_INTEGER_COMPONENT QPrime;
- PBIG_INTEGER Quotient;
- INTN QuotientSize;
- BIG_INTEGER_COMPONENT SecondLastDenominator;
- BIG_INTEGER_COMPONENT SecondLastWorking;
- INTN Size;
- KSTATUS Status;
- PBIG_INTEGER Working;
- Status = STATUS_INSUFFICIENT_RESOURCES;
- DenominatorTimesQDash = NULL;
- ModOffset = Context->ModOffset;
- OriginalNumeratorSize = Numerator->Size;
- Size = Denominator->Size;
- QuotientSize = Numerator->Size - Size;
- Working = NULL;
- //
- // Perform a quick exit: if the value is less than the modulo, then just
- // return the value.
- //
- if ((ModuloOperation != FALSE) &&
- (CypBiCompare(Denominator, Numerator) > 0)) {
- CypBiReleaseReference(Context, Denominator);
- return Numerator;
- }
- Quotient = CypBiCreate(Context, QuotientSize + 1);
- if (Quotient == NULL) {
- goto BiDivideEnd;
- }
- RtlZeroMemory(Quotient->Components,
- Quotient->Size * sizeof(BIG_INTEGER_COMPONENT));
- Working = CypBiCreate(Context, Size + 1);
- if (Working == NULL) {
- goto BiDivideEnd;
- }
- CypBiTrim(Denominator);
- Last = BIG_INTEGER_RADIX /
- (Denominator->Components[Denominator->Size - 1] + 1);
- if (Last > 1) {
- Numerator = CypBiMultiplyComponent(Context, Numerator, Last);
- if (Numerator == NULL) {
- goto BiDivideEnd;
- }
- if (ModuloOperation != FALSE) {
- Denominator = Context->NormalizedMod[ModOffset];
- } else {
- Denominator = CypBiMultiplyComponent(Context, Denominator, Last);
- }
- }
- if (OriginalNumeratorSize == Numerator->Size) {
- CypBiResize(Context, Numerator, OriginalNumeratorSize + 1);
- }
- Index = 0;
- do {
- //
- // Create a shorter version of the numerator.
- //
- NumeratorIndex = Numerator->Size - Size - 1 - Index;
- RtlCopyMemory(Working->Components,
- &(Numerator->Components[NumeratorIndex]),
- (Size + 1) * sizeof(BIG_INTEGER_COMPONENT));
- //
- // Calculate q'.
- //
- LastWorking = Working->Components[Working->Size - 1];
- LastDenominator = Denominator->Components[Denominator->Size - 1];
- if (LastWorking == LastDenominator) {
- QPrime = BIG_INTEGER_RADIX - 1;
- } else {
- SecondLastWorking = Working->Components[Working->Size - 2];
- QPrime = (((BIG_INTEGER_LONG_COMPONENT)LastWorking *
- BIG_INTEGER_RADIX) +
- SecondLastWorking) / LastDenominator;
- if (Denominator->Size > 1) {
- SecondLastDenominator =
- Denominator->Components[Denominator->Size - 2];
- if (SecondLastDenominator != 0) {
- Inner = (BIG_INTEGER_RADIX * LastWorking) +
- SecondLastWorking -
- ((BIG_INTEGER_LONG_COMPONENT)QPrime *
- LastDenominator);
- if (((BIG_INTEGER_LONG_COMPONENT)SecondLastDenominator *
- QPrime) >
- (((BIG_INTEGER_LONG_COMPONENT)Inner *
- BIG_INTEGER_RADIX) + SecondLastWorking)) {
- QPrime -= 1;
- }
- }
- }
- }
- //
- // Multiply and subtract the working value.
- //
- if (QPrime != 0) {
- CypBiAddReference(Denominator);
- DenominatorTimesQDash = CypBiMultiplyComponent(Context,
- Denominator,
- QPrime);
- if (DenominatorTimesQDash == NULL) {
- goto BiDivideEnd;
- }
- NewWorking = CypBiSubtract(Context,
- Working,
- DenominatorTimesQDash,
- &IsNegative);
- if (NewWorking == NULL) {
- goto BiDivideEnd;
- }
- DenominatorTimesQDash = NULL;
- Working = NewWorking;
- Status = CypBiResize(Context, Working, Size + 1);
- if (!KSUCCESS(Status)) {
- goto BiDivideEnd;
- }
- if (IsNegative != FALSE) {
- QPrime -= 1;
- CypBiAddReference(Denominator);
- NewWorking = CypBiAdd(Context, Working, Denominator);
- if (NewWorking == NULL) {
- goto BiDivideEnd;
- }
- Working = NewWorking;
- Working->Size -= 1;
- Denominator->Size -= 1;
- }
- }
- Quotient->Components[Quotient->Size - Index - 1] = QPrime;
- //
- // Copy the result back.
- //
- NumeratorIndex = Numerator->Size - Size - 1 - Index;
- RtlCopyMemory(&(Numerator->Components[NumeratorIndex]),
- Working->Components,
- (Size + 1) * sizeof(BIG_INTEGER_COMPONENT));
- Index += 1;
- } while (Index <= QuotientSize);
- CypBiReleaseReference(Context, Working);
- Working = NULL;
- CypBiReleaseReference(Context, Denominator);
- Denominator = NULL;
- //
- // If it's a modulo operation, get the remainder.
- //
- if (ModuloOperation != FALSE) {
- CypBiReleaseReference(Context, Quotient);
- CypBiTrim(Numerator);
- Quotient = CypBiDivideComponent(Context, Numerator, Last);
- if (Quotient == NULL) {
- goto BiDivideEnd;
- }
- } else {
- CypBiReleaseReference(Context, Numerator);
- CypBiTrim(Quotient);
- }
- Status = STATUS_SUCCESS;
- BiDivideEnd:
- if (Working != NULL) {
- CypBiReleaseReference(Context, Working);
- }
- if (DenominatorTimesQDash != NULL) {
- CypBiReleaseReference(Context, DenominatorTimesQDash);
- }
- if (!KSUCCESS(Status)) {
- if (Quotient != NULL) {
- CypBiReleaseReference(Context, Quotient);
- Quotient = NULL;
- }
- }
- return Quotient;
- }
- PBIG_INTEGER
- CypBiSquare (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Value
- )
- /*++
- Routine Description:
- This routine squares a value, using half the multiplies of the standard
- multiply method.
- Arguments:
- Context - Supplies a pointer to the big integer context.
- Value - Supplies a pointer to the big integer to square. On success a
- reference on this value is released.
- Return Value:
- Returns a pointer to the new square.
- NULL on allocation failure.
- --*/
- {
- BIG_INTEGER_LONG_COMPONENT Carry;
- INTN Index;
- INTN InnerCarry;
- INTN InnerIndex;
- BIG_INTEGER_LONG_COMPONENT InnerProduct;
- BIG_INTEGER_LONG_COMPONENT Product;
- PBIG_INTEGER Result;
- PBIG_INTEGER_COMPONENT ResultComponents;
- INTN Size;
- PBIG_INTEGER_COMPONENT ValueComponents;
- Index = 0;
- Size = Value->Size;
- Result = CypBiCreate(Context, (Size * 2) + 1);
- if (Result == NULL) {
- return NULL;
- }
- ResultComponents = Result->Components;
- ValueComponents = Value->Components;
- RtlZeroMemory(ResultComponents,
- Result->Size * sizeof(BIG_INTEGER_COMPONENT));
- do {
- Product = ResultComponents[Index * 2] +
- (BIG_INTEGER_LONG_COMPONENT)ValueComponents[Index] *
- ValueComponents[Index];
- ResultComponents[Index * 2] = (BIG_INTEGER_COMPONENT)Product;
- Carry = Product >> BIG_INTEGER_COMPONENT_BITS;
- for (InnerIndex = Index + 1; InnerIndex < Size; InnerIndex += 1) {
- InnerCarry = 0;
- InnerProduct = (BIG_INTEGER_LONG_COMPONENT)ValueComponents[Index] *
- ValueComponents[InnerIndex];
- if ((BIG_INTEGER_LONG_COMPONENT_MAX - InnerProduct) <
- InnerProduct) {
- InnerCarry = 1;
- }
- Product = InnerProduct << 1;
- if ((BIG_INTEGER_LONG_COMPONENT_MAX - Product) <
- ResultComponents[Index + InnerIndex]) {
- InnerCarry = 1;
- }
- Product += ResultComponents[Index + InnerIndex];
- if ((BIG_INTEGER_LONG_COMPONENT_MAX - Product) < Carry) {
- InnerCarry = 1;
- }
- Product += Carry;
- ResultComponents[Index + InnerIndex] =
- (BIG_INTEGER_COMPONENT)Product;
- Carry = Product >> BIG_INTEGER_COMPONENT_BITS;
- if (InnerCarry != 0) {
- Carry += BIG_INTEGER_RADIX;
- }
- }
- Product = ResultComponents[Index + Size] + Carry;
- ResultComponents[Index + Size] = Product;
- ResultComponents[Index + Size + 1] =
- Product >> BIG_INTEGER_COMPONENT_BITS;
- Index += 1;
- } while (Index < Size);
- CypBiReleaseReference(Context, Value);
- CypBiTrim(Result);
- return Result;
- }
- INT
- CypBiCompare (
- PBIG_INTEGER Left,
- PBIG_INTEGER Right
- )
- /*++
- Routine Description:
- This routine compares two big integers.
- Arguments:
- Left - Supplies a pointer to the left value to compare.
- Right - Supplies a pointer to the right value to compare.
- Return Value:
- < 0 if Left < Right.
- 0 if Left == Right.
- > 0 if Left > Right.
- --*/
- {
- INTN Index;
- PBIG_INTEGER_COMPONENT LeftComponents;
- INT Result;
- PBIG_INTEGER_COMPONENT RightComponents;
- if (Left->Size > Right->Size) {
- Result = 1;
- } else if (Left->Size < Right->Size) {
- Result = -1;
- } else {
- LeftComponents = Left->Components;
- RightComponents = Right->Components;
- Result = 0;
- Index = Left->Size - 1;
- do {
- if (LeftComponents[Index] > RightComponents[Index]) {
- Result = 1;
- break;
- } else if (LeftComponents[Index] < RightComponents[Index]) {
- Result = -1;
- break;
- }
- Index -= 1;
- } while (Index >= 0);
- }
- return Result;
- }
- PBIG_INTEGER
- CypBiMultiplyComponent (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Left,
- BIG_INTEGER_COMPONENT RightComponent
- )
- /*++
- Routine Description:
- This routine multiplies a big integer by a big integer component.
- Arguments:
- Context - Supplies a pointer to the big integer context.
- Left - Supplies the value to multiply. A reference on this value will be
- released on success.
- RightComponent - Supplies the value to multiply by.
- Return Value:
- Returns a pointer to the new result.
- NULL on allocation failure.
- --*/
- {
- BIG_INTEGER_COMPONENT Carry;
- UINTN Index;
- PBIG_INTEGER_COMPONENT LeftComponents;
- PBIG_INTEGER Result;
- BIG_INTEGER_LONG_COMPONENT ResultComponent;
- PBIG_INTEGER_COMPONENT ResultComponents;
- UINTN Size;
- Size = Left->Size;
- Result = CypBiCreate(Context, Size + 1);
- if (Result == NULL) {
- return NULL;
- }
- LeftComponents = Left->Components;
- ResultComponents = Result->Components;
- RtlZeroMemory(ResultComponents, (Size * 1) * sizeof(BIG_INTEGER_COMPONENT));
- Carry = 0;
- for (Index = 0; Index < Size; Index += 1) {
- ResultComponent = ((BIG_INTEGER_LONG_COMPONENT)*LeftComponents *
- RightComponent) + Carry;
- *ResultComponents = ResultComponent;
- Carry = ResultComponent >> BIG_INTEGER_COMPONENT_BITS;
- ResultComponents += 1;
- LeftComponents += 1;
- }
- *ResultComponents = Carry;
- CypBiReleaseReference(Context, Left);
- CypBiTrim(Result);
- return Result;
- }
- PBIG_INTEGER
- CypBiMultiplyStandard (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Left,
- PBIG_INTEGER Right,
- INTN InnerPartial,
- INTN OuterPartial
- )
- /*++
- Routine Description:
- This routine multiplies two big integers together.
- Arguments:
- Context - Supplies a pointer to the big integer context.
- Left - Supplies the value to multiply. A reference on this value will be
- released on success.
- Right - Supplies the value to multiply by. A reference on this value will be
- released on success.
- InnerPartial - Supplies the inner partial product.
- OuterPartial - Supplies the outer partial product.
- Return Value:
- Returns a pointer to the new product.
- NULL on allocation failure.
- --*/
- {
- BIG_INTEGER_COMPONENT Carry;
- PBIG_INTEGER_COMPONENT LeftComponents;
- INTN LeftIndex;
- INTN LeftSize;
- BIG_INTEGER_LONG_COMPONENT Product;
- PBIG_INTEGER Result;
- PBIG_INTEGER_COMPONENT ResultComponents;
- INTN ResultIndex;
- PBIG_INTEGER_COMPONENT RightComponents;
- INTN RightIndex;
- INTN RightSize;
- LeftSize = Left->Size;
- RightSize = Right->Size;
- Result = CypBiCreate(Context, LeftSize + RightSize);
- if (Result == NULL) {
- return NULL;
- }
- LeftComponents = Left->Components;
- RightComponents = Right->Components;
- ResultComponents = Result->Components;
- RtlZeroMemory(ResultComponents,
- (LeftSize + RightSize) * sizeof(BIG_INTEGER_COMPONENT));
- RightIndex = 0;
- do {
- Carry = 0;
- ResultIndex = RightIndex;
- LeftIndex = 0;
- if ((OuterPartial != 0) && (OuterPartial - RightIndex > 0) &&
- (OuterPartial < LeftSize)) {
- ResultIndex = OuterPartial - 1;
- LeftIndex = OuterPartial - RightIndex - 1;
- }
- do {
- if ((InnerPartial != 0) && (ResultIndex >= InnerPartial)) {
- break;
- }
- Product = ResultComponents[ResultIndex] +
- (((BIG_INTEGER_LONG_COMPONENT)LeftComponents[LeftIndex]) *
- RightComponents[RightIndex]) + Carry;
- ResultComponents[ResultIndex] = Product;
- ResultIndex += 1;
- LeftIndex += 1;
- Carry = Product >> BIG_INTEGER_COMPONENT_BITS;
- } while (LeftIndex < LeftSize);
- ResultComponents[ResultIndex] = Carry;
- RightIndex += 1;
- } while (RightIndex < RightSize);
- CypBiReleaseReference(Context, Left);
- CypBiReleaseReference(Context, Right);
- CypBiTrim(Result);
- return Result;
- }
- PBIG_INTEGER
- CypBiDivideComponent (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Numerator,
- BIG_INTEGER_COMPONENT Denominator
- )
- /*++
- Routine Description:
- This routine divides a big integer by a big integer component.
- Arguments:
- Context - Supplies a pointer to the big integer context.
- Numerator - Supplies a pointer to the numerator. This is also the
- destination.
- Denominator - Supplies the denominator value to divide by.
- Return Value:
- Returns a pointer to the numerator (now quotient) on success.
- NULL on allocation failure.
- --*/
- {
- INTN Index;
- PBIG_INTEGER Result;
- BIG_INTEGER_LONG_COMPONENT ResultComponent;
- ASSERT(Numerator->Size != 0);
- Result = Numerator;
- ResultComponent = 0;
- Index = Numerator->Size - 1;
- do {
- ResultComponent = (ResultComponent << BIG_INTEGER_COMPONENT_BITS) +
- Numerator->Components[Index];
- Result->Components[Index] =
- (BIG_INTEGER_COMPONENT)(ResultComponent / Denominator);
- ResultComponent = ResultComponent % Denominator;
- Index -= 1;
- } while (Index >= 0);
- CypBiTrim(Result);
- return Result;
- }
- PBIG_INTEGER
- CypBiRightShiftComponent (
- PBIG_INTEGER Value,
- UINTN ComponentCount
- )
- /*++
- Routine Description:
- This routine performs a right shift of a given big integer.
- Arguments:
- Value - Supplies a pointer to the value to shift. This is also the
- destination.
- ComponentCount - Supplies the amount to shift, in components.
- Return Value:
- Returns a pointer to the value on success.
- NULL on allocation failure.
- --*/
- {
- PBIG_INTEGER_COMPONENT High;
- INTN Index;
- PBIG_INTEGER_COMPONENT Low;
- Index = Value->Size - ComponentCount;
- Low = Value->Components;
- High = &(Value->Components[ComponentCount]);
- if (Index <= 0) {
- Value->Components[0] = 0;
- Value->Size = 1;
- return Value;
- }
- do {
- *Low = *High;
- Low += 1;
- High += 1;
- Index -= 1;
- } while (Index > 0);
- Value->Size -= ComponentCount;
- return Value;
- }
- PBIG_INTEGER
- CypBiLeftShiftComponent (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Value,
- UINTN ComponentCount
- )
- /*++
- Routine Description:
- This routine performs a left shift of a given big integer.
- Arguments:
- Context - Supplies a pointer to the big integer context.
- Value - Supplies a pointer to the value to shift. This is also the
- destination.
- ComponentCount - Supplies the amount to shift, in components.
- Return Value:
- Returns a pointer to the value on success.
- NULL on allocation failure.
- --*/
- {
- PBIG_INTEGER_COMPONENT High;
- INTN Index;
- PBIG_INTEGER_COMPONENT Low;
- KSTATUS Status;
- Index = Value->Size - 1;
- if (ComponentCount <= 0) {
- return Value;
- }
- Status = CypBiResize(Context, Value, Value->Size + ComponentCount);
- if (!KSUCCESS(Status)) {
- return NULL;
- }
- High = &(Value->Components[Index + ComponentCount]);
- Low = &(Value->Components[Index]);
- do {
- *High = *Low;
- High += 1;
- Low += 1;
- Index -= 1;
- } while (Index > 0);
- RtlZeroMemory(Value->Components,
- ComponentCount * sizeof(BIG_INTEGER_COMPONENT));
- return Value;
- }
- INTN
- CypBiFindLeadingBit (
- PBIG_INTEGER Value
- )
- /*++
- Routine Description:
- This routine returns the bit index of the highest bit set in the given
- value.
- Arguments:
- Value - Supplies a pointer to the value to find the leading bit index of.
- Return Value:
- Returns the index of the highest bit set in the value.
- -1 if the value is zero.
- --*/
- {
- BIG_INTEGER_COMPONENT Component;
- BIG_INTEGER_COMPONENT Index;
- BIG_INTEGER_COMPONENT Mask;
- Component = Value->Components[Value->Size - 1];
- Mask = BIG_INTEGER_RADIX / 2;
- Index = BIG_INTEGER_COMPONENT_BITS - 1;
- do {
- if ((Component & Mask) != 0) {
- return Index + ((Value->Size - 1) * BIG_INTEGER_COMPONENT_BITS);
- }
- Mask >>= 1;
- Index -= 1;
- } while (Index != 0);
- return -1;
- }
- BOOL
- CypBiTestBit (
- PBIG_INTEGER Value,
- UINTN BitIndex
- )
- /*++
- Routine Description:
- This routine tests to see if the bit at the given bit index is set in the
- given value.
- Arguments:
- Value - Supplies a pointer to the value to test.
- BitIndex - Supplies the zero-based bit index of the bit to test.
- Return Value:
- TRUE if the bit is set in the value.
- FALSE if the bit is not set in the value.
- --*/
- {
- BIG_INTEGER_COMPONENT Component;
- UINTN ComponentIndex;
- BIG_INTEGER_COMPONENT Mask;
- ComponentIndex = BitIndex / BIG_INTEGER_COMPONENT_BITS;
- ASSERT(ComponentIndex < Value->Size);
- Component = Value->Components[ComponentIndex];
- Mask = 1 << (BitIndex % BIG_INTEGER_COMPONENT_BITS);
- if ((Component & Mask) != 0) {
- return TRUE;
- }
- return FALSE;
- }
- PBIG_INTEGER
- CypBiPerformBarrettReduction (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Value
- )
- /*++
- Routine Description:
- This routine performs a single Barrett reduction.
- Arguments:
- Context - Supplies a pointer to the big integer context.
- Value - Supplies a pointer to the value to reduce. This is also the
- destination.
- Return Value:
- Returns a pointer to the reduced value on success.
- NULL on allocation failure.
- --*/
- {
- UINTN ModOffset;
- PBIG_INTEGER Modulus;
- UINTN ModulusSize;
- PBIG_INTEGER NewValue;
- PBIG_INTEGER QValue;
- PBIG_INTEGER RValue;
- ModOffset = Context->ModOffset;
- Modulus = Context->Modulus[ModOffset];
- ModulusSize = Modulus->Size;
- RValue = NULL;
- //
- // Use the original method if Barrett cannot help.
- //
- if (Value->Size > ModulusSize * 2) {
- return CypBiModulo(Context, Value);
- }
- QValue = CypBiClone(Context, Value);
- if (QValue == NULL) {
- return NULL;
- }
- NewValue = CypBiRightShiftComponent(QValue, ModulusSize - 1);
- ASSERT(NewValue == QValue);
- NewValue = CypBiMultiplyStandard(Context,
- QValue,
- Context->Mu[ModOffset],
- 0,
- ModulusSize - 1);
- if (NewValue == NULL) {
- CypBiReleaseReference(Context, QValue);
- return NULL;
- }
- QValue = NewValue;
- NewValue = CypBiRightShiftComponent(QValue, ModulusSize + 1);
- ASSERT(NewValue == QValue);
- //
- // Perform an optimized modulo operation via truncation.
- //
- if (Value->Size > ModulusSize + 1) {
- Value->Size = ModulusSize + 1;
- }
- RValue = CypBiMultiplyStandard(Context,
- QValue,
- Modulus,
- ModulusSize + 1,
- 0);
- if (RValue == NULL) {
- CypBiReleaseReference(Context, QValue);
- return NULL;
- }
- QValue = NULL;
- //
- // Do another modulo truncation.
- //
- if (RValue->Size > ModulusSize + 1) {
- RValue->Size = ModulusSize + 1;
- }
- NewValue = CypBiSubtract(Context, Value, RValue, NULL);
- if (NewValue == NULL) {
- CypBiReleaseReference(Context, RValue);
- return NULL;
- }
- ASSERT(NewValue == Value);
- if (CypBiCompare(Value, Modulus) >= 0) {
- NewValue = CypBiSubtract(Context, Value, Modulus, NULL);
- if (NewValue == NULL) {
- return NULL;
- }
- ASSERT(NewValue == Value);
- }
- return Value;
- }
- KSTATUS
- CypBiComputeExponentTable (
- PBIG_INTEGER_CONTEXT Context,
- INTN CountExponent,
- PBIG_INTEGER Value
- )
- /*++
- Routine Description:
- This routine computes common exponents for a given value, used to reduce
- the number of multiplies during exponentiation.
- Arguments:
- Context - Supplies a pointer to the context that owns the integer.
- CountExponent - Supplies one greater than the power of two number of
- elements to compute in the table.
- Value - Supplies a pointer to the value to compute exponents for.
- Return Value:
- STATUS_SUCCESS on success.
- STATUS_INSUFFICIENT_RESOURCES on allocation failure.
- --*/
- {
- UINTN AllocationSize;
- UINTN Count;
- UINTN Index;
- PBIG_INTEGER Next;
- KSTATUS Status;
- PBIG_INTEGER Value2;
- Count = 1 << (CountExponent - 1);
- Status = STATUS_INSUFFICIENT_RESOURCES;
- Value2 = NULL;
- ASSERT(Context->ExponentTable == NULL);
- AllocationSize = Count * sizeof(PBIG_INTEGER);
- Context->ExponentTable = Context->AllocateMemory(AllocationSize);
- if (Context->ExponentTable == NULL) {
- goto BiComputeExponentTableEnd;
- }
- RtlZeroMemory(Context->ExponentTable, AllocationSize);
- Context->ExponentTable[0] = CypBiClone(Context, Value);
- if (Context->ExponentTable[0] == NULL) {
- goto BiComputeExponentTableEnd;
- }
- CypBiMakePermanent(Context->ExponentTable[0]);
- Value2 = CypBiSquare(Context, Context->ExponentTable[0]);
- if (Value2 == NULL) {
- goto BiComputeExponentTableEnd;
- }
- Next = CypBiResidue(Context, Value2);
- if (Next == NULL) {
- goto BiComputeExponentTableEnd;
- }
- ASSERT(Next == Value2);
- for (Index = 1; Index < Count; Index += 1) {
- CypBiAddReference(Value2);
- Next = CypBiMultiply(Context,
- Context->ExponentTable[Index - 1],
- Value2);
- if (Next == NULL) {
- CypBiReleaseReference(Context, Value2);
- goto BiComputeExponentTableEnd;
- }
- Context->ExponentTable[Index] = CypBiResidue(Context, Next);
- if (Context->ExponentTable[Index] == NULL) {
- goto BiComputeExponentTableEnd;
- }
- ASSERT(Context->ExponentTable[Index] == Next);
- CypBiMakePermanent(Context->ExponentTable[Index]);
- }
- Context->WindowSize = Count;
- Status = STATUS_SUCCESS;
- BiComputeExponentTableEnd:
- if (Value2 != NULL) {
- CypBiReleaseReference(Context, Value2);
- }
- if (!KSUCCESS(Status)) {
- if (Context->ExponentTable != NULL) {
- for (Index = 0; Index < Count; Index += 1) {
- Next = Context->ExponentTable[Index];
- if (Next != NULL) {
- CypBiMakeNonPermanent(Next);
- CypBiReleaseReference(Context, Next);
- }
- }
- Context->FreeMemory(Context->ExponentTable);
- Context->ExponentTable = NULL;
- Context->WindowSize = 0;
- }
- }
- return Status;
- }
- PBIG_INTEGER
- CypBiClone (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Integer
- )
- /*++
- Routine Description:
- This routine creates a new big integer and initializes it with the given
- big integer value.
- Arguments:
- Context - Supplies a pointer to the context that owns the integer.
- Integer - Supplies a pointer to an existing big integer to copy.
- Return Value:
- Returns a pointer to the integer on success.
- NULL on allocation failure.
- --*/
- {
- PBIG_INTEGER NewInteger;
- NewInteger = CypBiCreate(Context, Integer->Size);
- if (NewInteger == NULL) {
- return NULL;
- }
- RtlCopyMemory(NewInteger->Components,
- Integer->Components,
- Integer->Size * sizeof(BIG_INTEGER_COMPONENT));
- return NewInteger;
- }
- PBIG_INTEGER
- CypBiCreateFromInteger (
- PBIG_INTEGER_CONTEXT Context,
- BIG_INTEGER_COMPONENT Value
- )
- /*++
- Routine Description:
- This routine creates a new big integer and initializes it with the given
- value.
- Arguments:
- Context - Supplies a pointer to the context that owns the integer.
- Value - Supplies the value to initialize the integer to.
- Return Value:
- Returns a pointer to the integer on success.
- NULL on allocation failure.
- --*/
- {
- PBIG_INTEGER Integer;
- Integer = CypBiCreate(Context, 1);
- if (Integer == NULL) {
- return NULL;
- }
- Integer->Components[0] = Value;
- return Integer;
- }
- PBIG_INTEGER
- CypBiCreate (
- PBIG_INTEGER_CONTEXT Context,
- UINTN ComponentCount
- )
- /*++
- Routine Description:
- This routine creates a new big integer.
- Arguments:
- Context - Supplies a pointer to the context that owns the integer.
- ComponentCount - Supplies the number of components to allocate
- for.
- Return Value:
- Returns a pointer to the integer on success.
- NULL on allocation failure.
- --*/
- {
- PBIG_INTEGER Integer;
- if (Context->FreeList != NULL) {
- Integer = Context->FreeList;
- Context->FreeList = Integer->Next;
- Context->FreeCount -= 1;
- ASSERT(Integer->ReferenceCount == 0);
- CypBiResize(Context, Integer, ComponentCount);
- } else {
- Integer = Context->AllocateMemory(sizeof(BIG_INTEGER));
- if (Integer == NULL) {
- return NULL;
- }
- Integer->Components = Context->AllocateMemory(
- ComponentCount * sizeof(BIG_INTEGER_COMPONENT));
- if (Integer->Components == NULL) {
- Context->FreeMemory(Integer);
- return NULL;
- }
- Integer->Capacity = ComponentCount;
- }
- Integer->Size = ComponentCount;
- Integer->ReferenceCount = 1;
- Integer->Next = NULL;
- Context->ActiveCount += 1;
- return Integer;
- }
- KSTATUS
- CypBiResize (
- PBIG_INTEGER_CONTEXT Context,
- PBIG_INTEGER Integer,
- UINTN ComponentCount
- )
- /*++
- Routine Description:
- This routine resizes a big integer to ensure it has at least the given
- number of components.
- Arguments:
- Context - Supplies a pointer to the context that owns the integer.
- Integer - Supplies a pointer to the big integer.
- ComponentCount - Supplies the number of components to allocate
- for.
- Return Value:
- STATUS_SUCCESS on success.
- STATUS_INSUFFICIENT_RESOURCES on allocation failure.
- --*/
- {
- UINTN ExtraSize;
- PVOID NewBuffer;
- UINTN NewCapacity;
- if (Integer->Capacity < ComponentCount) {
- NewCapacity = Integer->Capacity * 2;
- if (NewCapacity < ComponentCount) {
- NewCapacity = ComponentCount;
- }
- NewBuffer = Context->ReallocateMemory(
- Integer->Components,
- NewCapacity * sizeof(BIG_INTEGER_COMPONENT));
- if (NewBuffer == NULL) {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
- Integer->Components = NewBuffer;
- Integer->Capacity = NewCapacity;
- }
- if (ComponentCount > Integer->Size) {
- ExtraSize = (ComponentCount - Integer->Size) *
- sizeof(BIG_INTEGER_COMPONENT);
- RtlZeroMemory(&(Integer->Components[Integer->Size]), ExtraSize);
- }
- Integer->Size = ComponentCount;
- return STATUS_SUCCESS;
- }
- VOID
- CypBiTrim (
- PBIG_INTEGER Integer
- )
- /*++
- Routine Description:
- This routine removes leading zero components from an integer.
- Arguments:
- Integer - Supplies a pointer to the big integer.
- Return Value:
- None.
- --*/
- {
- while ((Integer->Size > 1) &&
- (Integer->Components[Integer->Size - 1] == 0)) {
- Integer->Size -= 1;
- }
- return;
- }
|