bigint.c 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754
  1. /*++
  2. Copyright (c) 2015 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. bigint.c
  5. Abstract:
  6. This module implements support for large integer arithmetic.
  7. Author:
  8. Evan Green 14-Jul-2015
  9. Environment:
  10. Any
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include "../cryptop.h"
  16. //
  17. // --------------------------------------------------------------------- Macros
  18. //
  19. #define CypBiResidue(_Context, _Value) \
  20. CypBiPerformBarrettReduction((_Context), (_Value))
  21. #define CypBiModulo(_Context, _Value) \
  22. CypBiDivide((_Context), \
  23. (_Value), \
  24. (_Context)->Modulus[(_Context)->ModOffset], \
  25. TRUE)
  26. //
  27. // ---------------------------------------------------------------- Definitions
  28. //
  29. //
  30. // Define the special reference count that signifies reference counting is
  31. // not in use for this value.
  32. //
  33. #define BIG_INTEGER_PERMANENT_REFERENCE 0x7FFFFFF0
  34. //
  35. // Define the number of bits in a component.
  36. //
  37. #define BIG_INTEGER_COMPONENT_BITS \
  38. (sizeof(BIG_INTEGER_COMPONENT) * BITS_PER_BYTE)
  39. #define BIG_INTEGER_LONG_COMPONENT_MAX 0xFFFFFFFFFFFFFFFFULL
  40. //
  41. // ------------------------------------------------------ Data Type Definitions
  42. //
  43. //
  44. // ----------------------------------------------- Internal Function Prototypes
  45. //
  46. PBIG_INTEGER
  47. CypBiAdd (
  48. PBIG_INTEGER_CONTEXT Context,
  49. PBIG_INTEGER Left,
  50. PBIG_INTEGER Right
  51. );
  52. PBIG_INTEGER
  53. CypBiSubtract (
  54. PBIG_INTEGER_CONTEXT Context,
  55. PBIG_INTEGER Left,
  56. PBIG_INTEGER Right,
  57. PBOOL NegativeResult
  58. );
  59. PBIG_INTEGER
  60. CypBiMultiply (
  61. PBIG_INTEGER_CONTEXT Context,
  62. PBIG_INTEGER Left,
  63. PBIG_INTEGER Right
  64. );
  65. PBIG_INTEGER
  66. CypBiDivide (
  67. PBIG_INTEGER_CONTEXT Context,
  68. PBIG_INTEGER Numerator,
  69. PBIG_INTEGER Denominator,
  70. BOOL ModuloOperation
  71. );
  72. PBIG_INTEGER
  73. CypBiSquare (
  74. PBIG_INTEGER_CONTEXT Context,
  75. PBIG_INTEGER Value
  76. );
  77. INT
  78. CypBiCompare (
  79. PBIG_INTEGER Left,
  80. PBIG_INTEGER Right
  81. );
  82. PBIG_INTEGER
  83. CypBiMultiplyComponent (
  84. PBIG_INTEGER_CONTEXT Context,
  85. PBIG_INTEGER Left,
  86. BIG_INTEGER_COMPONENT RightComponent
  87. );
  88. PBIG_INTEGER
  89. CypBiMultiplyStandard (
  90. PBIG_INTEGER_CONTEXT Context,
  91. PBIG_INTEGER Left,
  92. PBIG_INTEGER Right,
  93. INTN InnerPartial,
  94. INTN OuterPartial
  95. );
  96. PBIG_INTEGER
  97. CypBiDivideComponent (
  98. PBIG_INTEGER_CONTEXT Context,
  99. PBIG_INTEGER Numerator,
  100. BIG_INTEGER_COMPONENT Denominator
  101. );
  102. PBIG_INTEGER
  103. CypBiRightShiftComponent (
  104. PBIG_INTEGER Value,
  105. UINTN ComponentCount
  106. );
  107. PBIG_INTEGER
  108. CypBiLeftShiftComponent (
  109. PBIG_INTEGER_CONTEXT Context,
  110. PBIG_INTEGER Value,
  111. UINTN ComponentCount
  112. );
  113. INTN
  114. CypBiFindLeadingBit (
  115. PBIG_INTEGER Value
  116. );
  117. BOOL
  118. CypBiTestBit (
  119. PBIG_INTEGER Value,
  120. UINTN BitIndex
  121. );
  122. PBIG_INTEGER
  123. CypBiPerformBarrettReduction (
  124. PBIG_INTEGER_CONTEXT Context,
  125. PBIG_INTEGER Value
  126. );
  127. KSTATUS
  128. CypBiComputeExponentTable (
  129. PBIG_INTEGER_CONTEXT Context,
  130. INTN CountExponent,
  131. PBIG_INTEGER Value
  132. );
  133. PBIG_INTEGER
  134. CypBiClone (
  135. PBIG_INTEGER_CONTEXT Context,
  136. PBIG_INTEGER Integer
  137. );
  138. PBIG_INTEGER
  139. CypBiCreateFromInteger (
  140. PBIG_INTEGER_CONTEXT Context,
  141. BIG_INTEGER_COMPONENT Value
  142. );
  143. PBIG_INTEGER
  144. CypBiCreate (
  145. PBIG_INTEGER_CONTEXT Context,
  146. UINTN ComponentCount
  147. );
  148. KSTATUS
  149. CypBiResize (
  150. PBIG_INTEGER_CONTEXT Context,
  151. PBIG_INTEGER Integer,
  152. UINTN ComponentCount
  153. );
  154. VOID
  155. CypBiTrim (
  156. PBIG_INTEGER Integer
  157. );
  158. //
  159. // -------------------------------------------------------------------- Globals
  160. //
  161. //
  162. // ------------------------------------------------------------------ Functions
  163. //
  164. KSTATUS
  165. CypBiInitializeContext (
  166. PBIG_INTEGER_CONTEXT Context
  167. )
  168. /*++
  169. Routine Description:
  170. This routine initializes a big integer context.
  171. Arguments:
  172. Context - Supplies a pointer to the context to initialize.
  173. Return Value:
  174. STATUS_SUCCESS on success.
  175. STATUS_INVALID_PARAMETER if the context was not partially filled
  176. in correctly.
  177. STATUS_INSUFFICIENT_RESOURCES if an allocation failed.
  178. --*/
  179. {
  180. UINTN DataSize;
  181. if ((Context->AllocateMemory == NULL) ||
  182. (Context->ReallocateMemory == NULL) ||
  183. (Context->FreeMemory == NULL)) {
  184. ASSERT(FALSE);
  185. return STATUS_INVALID_PARAMETER;
  186. }
  187. //
  188. // Zero everything but the functions.
  189. //
  190. DataSize = sizeof(BIG_INTEGER_CONTEXT) -
  191. FIELD_OFFSET(BIG_INTEGER_CONTEXT, ActiveList);
  192. RtlZeroMemory(&(Context->ActiveList), DataSize);
  193. Context->Radix = CypBiCreate(Context, 2);
  194. if (Context->Radix == NULL) {
  195. return STATUS_INSUFFICIENT_RESOURCES;
  196. }
  197. Context->Radix->Components[0] = 0;
  198. Context->Radix->Components[1] = 1;
  199. CypBiMakePermanent(Context->Radix);
  200. return STATUS_SUCCESS;
  201. }
  202. VOID
  203. CypBiDestroyContext (
  204. PBIG_INTEGER_CONTEXT Context
  205. )
  206. /*++
  207. Routine Description:
  208. This routine destroys a big integer context.
  209. Arguments:
  210. Context - Supplies a pointer to the context to tear down.
  211. Return Value:
  212. None.
  213. --*/
  214. {
  215. ASSERT((Context->ExponentTable == NULL) &&
  216. (Context->WindowSize == 0));
  217. CypBiMakeNonPermanent(Context->Radix);
  218. CypBiReleaseReference(Context, Context->Radix);
  219. ASSERT(Context->ActiveCount == 0);
  220. CypBiClearCache(Context);
  221. return;
  222. }
  223. VOID
  224. CypBiClearCache (
  225. PBIG_INTEGER_CONTEXT Context
  226. )
  227. /*++
  228. Routine Description:
  229. This routine destroys all big integers on the free list for the given
  230. context.
  231. Arguments:
  232. Context - Supplies a pointer to the context to clear.
  233. for.
  234. Return Value:
  235. None.
  236. --*/
  237. {
  238. PBIG_INTEGER Integer;
  239. PBIG_INTEGER Next;
  240. Integer = Context->FreeList;
  241. while (Integer != NULL) {
  242. Next = Integer->Next;
  243. //
  244. // Zero out the value itself to avoid leaking state.
  245. //
  246. RtlZeroMemory(Integer->Components,
  247. Integer->Capacity * sizeof(BIG_INTEGER_COMPONENT));
  248. Context->FreeMemory(Integer->Components);
  249. Context->FreeMemory(Integer);
  250. Integer = Next;
  251. }
  252. return;
  253. }
  254. KSTATUS
  255. CypBiCalculateModuli (
  256. PBIG_INTEGER_CONTEXT Context,
  257. PBIG_INTEGER Value,
  258. INTN ModOffset
  259. )
  260. /*++
  261. Routine Description:
  262. This routine performs some pre-calculations used in modulo reduction
  263. optimizations.
  264. Arguments:
  265. Context - Supplies a pointer to the big integer context.
  266. Value - Supplies a pointer to the modulus that will be used. This value
  267. will be made permanent.
  268. ModOffset - Supplies an offset to the moduli that can be used: the standard
  269. moduli, or the primes p and q.
  270. Return Value:
  271. STATUS_SUCCESS on success.
  272. STATUS_INSUFFICIENT_RESOURCES if an allocation failed.
  273. --*/
  274. {
  275. BIG_INTEGER_COMPONENT DValue;
  276. PBIG_INTEGER RadixCopy;
  277. PBIG_INTEGER ShiftedRadix;
  278. UINTN Size;
  279. KSTATUS Status;
  280. RadixCopy = NULL;
  281. Size = Value->Size;
  282. Status = STATUS_INSUFFICIENT_RESOURCES;
  283. DValue = BIG_INTEGER_RADIX / (Value->Components[Size - 1] + 1);
  284. ASSERT(Context->Modulus[ModOffset] == NULL);
  285. Context->Modulus[ModOffset] = Value;
  286. CypBiMakePermanent(Value);
  287. ASSERT(Context->NormalizedMod[ModOffset] == NULL);
  288. Context->NormalizedMod[ModOffset] = CypBiMultiplyComponent(Context,
  289. Value,
  290. DValue);
  291. if (Context->NormalizedMod[ModOffset] == NULL) {
  292. goto BiCalculateModuliEnd;
  293. }
  294. CypBiMakePermanent(Context->NormalizedMod[ModOffset]);
  295. //
  296. // Compute Mu for Barrett reduction.
  297. //
  298. RadixCopy = CypBiClone(Context, Context->Radix);
  299. if (RadixCopy == NULL) {
  300. goto BiCalculateModuliEnd;
  301. }
  302. ShiftedRadix = CypBiLeftShiftComponent(Context, RadixCopy, (Size * 2) - 1);
  303. if (ShiftedRadix == NULL) {
  304. goto BiCalculateModuliEnd;
  305. }
  306. ASSERT(Context->Mu[ModOffset] == NULL);
  307. Context->Mu[ModOffset] = CypBiDivide(Context,
  308. ShiftedRadix,
  309. Context->Modulus[ModOffset],
  310. FALSE);
  311. if (Context->Mu[ModOffset] == NULL) {
  312. goto BiCalculateModuliEnd;
  313. }
  314. CypBiMakePermanent(Context->Mu[ModOffset]);
  315. RadixCopy = NULL;
  316. Status = STATUS_SUCCESS;
  317. BiCalculateModuliEnd:
  318. if (RadixCopy != NULL) {
  319. CypBiReleaseReference(Context, RadixCopy);
  320. }
  321. return Status;
  322. }
  323. VOID
  324. CypBiReleaseModuli (
  325. PBIG_INTEGER_CONTEXT Context,
  326. INTN ModOffset
  327. )
  328. /*++
  329. Routine Description:
  330. This routine frees memory associated with moduli for the given offset.
  331. Arguments:
  332. Context - Supplies a pointer to the big integer context.
  333. ModOffset - Supplies the index of the moduli to free: the standard
  334. moduli, or the primes p and q.
  335. Return Value:
  336. None.
  337. --*/
  338. {
  339. PBIG_INTEGER *Pointer;
  340. Pointer = &(Context->Modulus[ModOffset]);
  341. if (*Pointer != NULL) {
  342. CypBiMakeNonPermanent(*Pointer);
  343. CypBiReleaseReference(Context, *Pointer);
  344. *Pointer = NULL;
  345. }
  346. Pointer = &(Context->Mu[ModOffset]);
  347. if (*Pointer != NULL) {
  348. CypBiMakeNonPermanent(*Pointer);
  349. CypBiReleaseReference(Context, *Pointer);
  350. *Pointer = NULL;
  351. }
  352. Pointer = &(Context->NormalizedMod[ModOffset]);
  353. if (*Pointer != NULL) {
  354. CypBiMakeNonPermanent(*Pointer);
  355. CypBiReleaseReference(Context, *Pointer);
  356. *Pointer = NULL;
  357. }
  358. return;
  359. }
  360. PBIG_INTEGER
  361. CypBiExponentiateModulo (
  362. PBIG_INTEGER_CONTEXT Context,
  363. PBIG_INTEGER Value,
  364. PBIG_INTEGER Exponent
  365. )
  366. /*++
  367. Routine Description:
  368. This routine performs exponentiation, modulo a value.
  369. Arguments:
  370. Context - Supplies a pointer to the big integer context.
  371. Value - Supplies a pointer to the value to reduce. A reference on this
  372. value will be released on success.
  373. Exponent - Supplies the exponent to raise the value to. A reference on this
  374. value will be released on success.
  375. Return Value:
  376. Returns a pointer to the exponentiated value on success.
  377. NULL on allocation failure.
  378. --*/
  379. {
  380. INTN BitIndex;
  381. UINTN Index;
  382. INTN LeadingBit;
  383. PBIG_INTEGER NewValue;
  384. INTN NextBit;
  385. INTN PartialExponent;
  386. PBIG_INTEGER Result;
  387. KSTATUS Status;
  388. INTN WindowSize;
  389. WindowSize = 1;
  390. LeadingBit = CypBiFindLeadingBit(Exponent);
  391. ASSERT(LeadingBit > 0);
  392. Result = CypBiCreateFromInteger(Context, 1);
  393. if (Result == NULL) {
  394. return NULL;
  395. }
  396. Status = STATUS_INSUFFICIENT_RESOURCES;
  397. //
  398. // Work out a reasonable window size.
  399. //
  400. for (BitIndex = LeadingBit; BitIndex > 32; BitIndex /= 5) {
  401. WindowSize += 1;
  402. }
  403. Status = CypBiComputeExponentTable(Context, WindowSize, Value);
  404. if (!KSUCCESS(Status)) {
  405. goto BiExponentiateModuloEnd;
  406. }
  407. //
  408. // Compute the exponentiated value, a bit at a time if the window size is
  409. // one, or a few bits at a time for a greater window.
  410. //
  411. Status = STATUS_INSUFFICIENT_RESOURCES;
  412. do {
  413. if (CypBiTestBit(Exponent, LeadingBit) != FALSE) {
  414. NextBit = LeadingBit - WindowSize + 1;
  415. //
  416. // The least significant bit of the exponent is always set.
  417. //
  418. if (NextBit < 0) {
  419. NextBit = 0;
  420. } else {
  421. while (CypBiTestBit(Exponent, NextBit) == FALSE) {
  422. NextBit += 1;
  423. }
  424. }
  425. PartialExponent = 0;
  426. //
  427. // Compute the portion of the exponent.
  428. //
  429. for (BitIndex = LeadingBit; BitIndex >= NextBit; BitIndex -= 1) {
  430. NewValue = CypBiSquare(Context, Result);
  431. if (NewValue == NULL) {
  432. goto BiExponentiateModuloEnd;
  433. }
  434. Result = NewValue;
  435. NewValue = CypBiResidue(Context, Result);
  436. if (NewValue == NULL) {
  437. goto BiExponentiateModuloEnd;
  438. }
  439. ASSERT(NewValue == Result);
  440. if (CypBiTestBit(Exponent, BitIndex) != FALSE) {
  441. PartialExponent += 1;
  442. }
  443. if (BitIndex != NextBit) {
  444. PartialExponent <<= 1;
  445. }
  446. }
  447. //
  448. // Adjust to the array indices.
  449. //
  450. PartialExponent = (PartialExponent - 1) / 2;
  451. ASSERT(PartialExponent < Context->WindowSize);
  452. NewValue = CypBiMultiply(Context,
  453. Result,
  454. Context->ExponentTable[PartialExponent]);
  455. if (NewValue == NULL) {
  456. goto BiExponentiateModuloEnd;
  457. }
  458. Result = NewValue;
  459. NewValue = CypBiResidue(Context, Result);
  460. if (NewValue == NULL) {
  461. goto BiExponentiateModuloEnd;
  462. }
  463. ASSERT(NewValue == Result);
  464. LeadingBit = NextBit - 1;
  465. //
  466. // Square the value.
  467. //
  468. } else {
  469. NewValue = CypBiSquare(Context, Result);
  470. if (NewValue == NULL) {
  471. goto BiExponentiateModuloEnd;
  472. }
  473. Result = NewValue;
  474. NewValue = CypBiResidue(Context, Result);
  475. if (NewValue == NULL) {
  476. goto BiExponentiateModuloEnd;
  477. }
  478. ASSERT(NewValue == Result);
  479. LeadingBit -= 1;
  480. }
  481. } while (LeadingBit >= 0);
  482. CypBiReleaseReference(Context, Value);
  483. CypBiReleaseReference(Context, Exponent);
  484. Status = STATUS_SUCCESS;
  485. BiExponentiateModuloEnd:
  486. //
  487. // Destroy the exponent table.
  488. //
  489. if (Context->ExponentTable != NULL) {
  490. for (Index = 0; Index < Context->WindowSize; Index += 1) {
  491. CypBiMakeNonPermanent(Context->ExponentTable[Index]);
  492. CypBiReleaseReference(Context, Context->ExponentTable[Index]);
  493. }
  494. Context->FreeMemory(Context->ExponentTable);
  495. Context->ExponentTable = NULL;
  496. Context->WindowSize = 0;
  497. }
  498. if (!KSUCCESS(Status)) {
  499. if (Result != NULL) {
  500. CypBiReleaseReference(Context, Result);
  501. Result = NULL;
  502. }
  503. }
  504. return Result;
  505. }
  506. PBIG_INTEGER
  507. CypBiChineseRemainderTheorem (
  508. PBIG_INTEGER_CONTEXT Context,
  509. PBIG_INTEGER Value,
  510. PBIG_INTEGER DpValue,
  511. PBIG_INTEGER DqValue,
  512. PBIG_INTEGER PValue,
  513. PBIG_INTEGER QValue,
  514. PBIG_INTEGER QInverse
  515. )
  516. /*++
  517. Routine Description:
  518. This routine uses the Chinese Remainder Theorem as an aide to quickly
  519. decrypting RSA values.
  520. Arguments:
  521. Context - Supplies a pointer to the big integer context.
  522. Value - Supplies a pointer to the value to perform the exponentiation on. A
  523. reference on this value will be released on success.
  524. DpValue - Supplies a pointer to the dP value. A reference on this will be
  525. released on success.
  526. DqValue - Supplies a pointer to the dQ value. A reference on this will be
  527. released on success.
  528. PValue - Supplies a pointer to the p prime. A reference on this value will
  529. be released on success.
  530. QValue - Supplies a pointer to the q prime. A reference on this value will
  531. be released on success.
  532. QInverse - Supplies a pointer to the Q inverse. A reference on this will be
  533. released on success.
  534. Return Value:
  535. Returns a pointer to the result of the Chinese Remainder Theorem on success.
  536. NULL on allocation failure.
  537. --*/
  538. {
  539. PBIG_INTEGER HValue;
  540. PBIG_INTEGER M1;
  541. PBIG_INTEGER M2;
  542. PBIG_INTEGER NewValue;
  543. UCHAR OriginalModOffset;
  544. PBIG_INTEGER Result;
  545. HValue = NULL;
  546. M1 = NULL;
  547. M2 = NULL;
  548. Result = NULL;
  549. OriginalModOffset = Context->ModOffset;
  550. Context->ModOffset = BIG_INTEGER_P_OFFSET;
  551. CypBiAddReference(Value);
  552. CypBiAddReference(DpValue);
  553. M1 = CypBiExponentiateModulo(Context, Value, DpValue);
  554. if (M1 == NULL) {
  555. CypBiReleaseReference(Context, Value);
  556. CypBiReleaseReference(Context, DpValue);
  557. goto BiChineseRemainderTheoremEnd;
  558. }
  559. Context->ModOffset = BIG_INTEGER_Q_OFFSET;
  560. CypBiAddReference(Value);
  561. CypBiAddReference(DqValue);
  562. M2 = CypBiExponentiateModulo(Context, Value, DqValue);
  563. if (M2 == NULL) {
  564. CypBiReleaseReference(Context, Value);
  565. CypBiReleaseReference(Context, DqValue);
  566. goto BiChineseRemainderTheoremEnd;
  567. }
  568. CypBiAddReference(PValue);
  569. HValue = CypBiAdd(Context, M1, PValue);
  570. if (HValue == NULL) {
  571. CypBiReleaseReference(Context, PValue);
  572. goto BiChineseRemainderTheoremEnd;
  573. }
  574. M1 = NULL;
  575. CypBiAddReference(M2);
  576. NewValue = CypBiSubtract(Context, HValue, M2, NULL);
  577. if (NewValue == NULL) {
  578. CypBiReleaseReference(Context, M2);
  579. goto BiChineseRemainderTheoremEnd;
  580. }
  581. ASSERT(HValue == NewValue);
  582. CypBiAddReference(QInverse);
  583. NewValue = CypBiMultiply(Context, HValue, QInverse);
  584. if (NewValue == NULL) {
  585. CypBiReleaseReference(Context, QInverse);
  586. goto BiChineseRemainderTheoremEnd;
  587. }
  588. HValue = NewValue;
  589. Context->ModOffset = BIG_INTEGER_P_OFFSET;
  590. NewValue = CypBiResidue(Context, HValue);
  591. if (NewValue == NULL) {
  592. goto BiChineseRemainderTheoremEnd;
  593. }
  594. ASSERT(NewValue == HValue);
  595. CypBiAddReference(QValue);
  596. NewValue = CypBiMultiply(Context, QValue, HValue);
  597. if (NewValue == NULL) {
  598. CypBiReleaseReference(Context, QValue);
  599. goto BiChineseRemainderTheoremEnd;
  600. }
  601. HValue = NULL;
  602. Result = CypBiAdd(Context, M2, NewValue);
  603. if (Result == NULL) {
  604. goto BiChineseRemainderTheoremEnd;
  605. }
  606. M2 = NULL;
  607. CypBiReleaseReference(Context, PValue);
  608. CypBiReleaseReference(Context, QValue);
  609. CypBiReleaseReference(Context, DpValue);
  610. CypBiReleaseReference(Context, DqValue);
  611. CypBiReleaseReference(Context, QInverse);
  612. CypBiReleaseReference(Context, Value);
  613. BiChineseRemainderTheoremEnd:
  614. Context->ModOffset = OriginalModOffset;
  615. if (M1 != NULL) {
  616. CypBiReleaseReference(Context, M1);
  617. }
  618. if (M2 != NULL) {
  619. CypBiReleaseReference(Context, M2);
  620. }
  621. if (HValue != NULL) {
  622. CypBiReleaseReference(Context, HValue);
  623. }
  624. return Result;
  625. }
  626. PBIG_INTEGER
  627. CypBiImport (
  628. PBIG_INTEGER_CONTEXT Context,
  629. PVOID Data,
  630. UINTN Size
  631. )
  632. /*++
  633. Routine Description:
  634. This routine creates a big integer from a set of raw binary bytes.
  635. Arguments:
  636. Context - Supplies a pointer to the big integer context.
  637. Data - Supplies a pointer to the data to import.
  638. Size - Supplies the number of bytes in the data.
  639. Return Value:
  640. Returns a pointer to the newly created value on success.
  641. NULL on allocation failure.
  642. --*/
  643. {
  644. UINTN ByteIndex;
  645. PUCHAR Bytes;
  646. UINTN ComponentCount;
  647. INTN Index;
  648. UINTN Offset;
  649. PBIG_INTEGER Value;
  650. Bytes = Data;
  651. ComponentCount = ALIGN_RANGE_UP(Size, sizeof(BIG_INTEGER_COMPONENT));
  652. Value = CypBiCreate(Context, ComponentCount);
  653. if (Value == NULL) {
  654. return NULL;
  655. }
  656. RtlZeroMemory(Value->Components,
  657. Value->Size * sizeof(BIG_INTEGER_COMPONENT));
  658. //
  659. // The data comes in as a sequence of bytes, most significant first.
  660. // Convert that to a series of components, least significant component
  661. // first.
  662. //
  663. ByteIndex = 0;
  664. Offset = 0;
  665. for (Index = Size - 1; Index >= 0; Index -= 1) {
  666. Value->Components[Offset] += Bytes[Index] <<
  667. (ByteIndex * BITS_PER_BYTE);
  668. ByteIndex += 1;
  669. if (ByteIndex == sizeof(BIG_INTEGER_COMPONENT)) {
  670. ByteIndex = 0;
  671. Offset += 1;
  672. }
  673. }
  674. CypBiTrim(Value);
  675. return Value;
  676. }
  677. KSTATUS
  678. CypBiExport (
  679. PBIG_INTEGER_CONTEXT Context,
  680. PBIG_INTEGER Value,
  681. PVOID Data,
  682. UINTN Size
  683. )
  684. /*++
  685. Routine Description:
  686. This routine exports a big integer to a byte stream.
  687. Arguments:
  688. Context - Supplies a pointer to the big integer context.
  689. Value - Supplies a pointer to the big integer to export. A reference is
  690. released on this value by this function on success.
  691. Data - Supplies a pointer to the data buffer.
  692. Size - Supplies the number of bytes in the data buffer.
  693. Return Value:
  694. STATUS_SUCCESS on success.
  695. STATUS_BUFFER_TOO_SMALL if the given buffer was not big enough to hold the
  696. entire integer.
  697. --*/
  698. {
  699. ULONG Byte;
  700. UINTN ByteIndex;
  701. PUCHAR DataBytes;
  702. UINTN DataIndex;
  703. INTN Index;
  704. UINTN IntegerSize;
  705. BIG_INTEGER_COMPONENT Mask;
  706. DataBytes = Data;
  707. IntegerSize = Value->Size * sizeof(BIG_INTEGER_COMPONENT);
  708. if (IntegerSize > Size) {
  709. return STATUS_BUFFER_TOO_SMALL;
  710. }
  711. DataIndex = IntegerSize - 1;
  712. for (Index = 0; Index < Value->Size; Index += 1) {
  713. for (ByteIndex = 0;
  714. ByteIndex < sizeof(BIG_INTEGER_COMPONENT);
  715. ByteIndex += 1) {
  716. Mask = 0xFF << (ByteIndex * BITS_PER_BYTE);
  717. Byte = (Value->Components[Index] & Mask) >>
  718. (ByteIndex * BITS_PER_BYTE);
  719. DataBytes[DataIndex] = Byte;
  720. DataIndex -= 1;
  721. }
  722. }
  723. CypBiReleaseReference(Context, Value);
  724. return STATUS_SUCCESS;
  725. }
  726. VOID
  727. CypBiDebugPrint (
  728. PBIG_INTEGER Value
  729. )
  730. /*++
  731. Routine Description:
  732. This routine debug prints the contents of a big integer.
  733. Arguments:
  734. Value - Supplies a pointer to the value to print.
  735. Return Value:
  736. None.
  737. --*/
  738. {
  739. PBIG_INTEGER_COMPONENT Components;
  740. ULONG FieldSize;
  741. INTN Index;
  742. //
  743. // Each hex digit prints 4 bits, hence the divide by 4.
  744. //
  745. FieldSize = BIG_INTEGER_COMPONENT_BITS / 4;
  746. Index = Value->Size - 1;
  747. Components = Value->Components;
  748. RtlDebugPrint("%x", Components[Index]);
  749. while (Index > 0) {
  750. RtlDebugPrint("%0*llx", FieldSize, (ULONGLONG)(Components[Index]));
  751. Index -= 1;
  752. }
  753. return;
  754. }
  755. VOID
  756. CypBiAddReference (
  757. PBIG_INTEGER Integer
  758. )
  759. /*++
  760. Routine Description:
  761. This routine adds a reference to the given big integer.
  762. Arguments:
  763. Integer - Supplies a pointer to the big integer.
  764. Return Value:
  765. None.
  766. --*/
  767. {
  768. if (Integer->ReferenceCount == BIG_INTEGER_PERMANENT_REFERENCE) {
  769. return;
  770. }
  771. ASSERT((Integer->ReferenceCount != 0) &&
  772. (Integer->ReferenceCount < 0x10000000));
  773. Integer->ReferenceCount += 1;
  774. return;
  775. }
  776. VOID
  777. CypBiReleaseReference (
  778. PBIG_INTEGER_CONTEXT Context,
  779. PBIG_INTEGER Integer
  780. )
  781. /*++
  782. Routine Description:
  783. This routine releases resources associated with a big integer.
  784. Arguments:
  785. Context - Supplies a pointer to the context that owns the integer.
  786. Integer - Supplies a pointer to the big integer.
  787. ComponentCount - Supplies the number of components to allocate
  788. for.
  789. Return Value:
  790. None.
  791. --*/
  792. {
  793. if (Integer->ReferenceCount == BIG_INTEGER_PERMANENT_REFERENCE) {
  794. return;
  795. }
  796. ASSERT((Integer->ReferenceCount != 0) &&
  797. (Integer->ReferenceCount < 0x10000000));
  798. Integer->ReferenceCount -= 1;
  799. if (Integer->ReferenceCount > 0) {
  800. return;
  801. }
  802. //
  803. // Move the integer to the free list.
  804. //
  805. Integer->Next = Context->FreeList;
  806. Context->FreeList = Integer;
  807. Context->FreeCount += 1;
  808. ASSERT(Context->ActiveCount > 0);
  809. Context->ActiveCount -= 1;
  810. return;
  811. }
  812. VOID
  813. CypBiMakePermanent (
  814. PBIG_INTEGER Integer
  815. )
  816. /*++
  817. Routine Description:
  818. This routine makes a big integer "permanent", causing add and release
  819. references to be ignored.
  820. Arguments:
  821. Integer - Supplies a pointer to the big integer.
  822. Return Value:
  823. None.
  824. --*/
  825. {
  826. ASSERT(Integer->ReferenceCount == 1);
  827. Integer->ReferenceCount = BIG_INTEGER_PERMANENT_REFERENCE;
  828. return;
  829. }
  830. VOID
  831. CypBiMakeNonPermanent (
  832. PBIG_INTEGER Integer
  833. )
  834. /*++
  835. Routine Description:
  836. This routine undoes the effects of making a big integer permanent,
  837. instead giving it a reference count of 1.
  838. Arguments:
  839. Integer - Supplies a pointer to the big integer.
  840. Return Value:
  841. None.
  842. --*/
  843. {
  844. ASSERT(Integer->ReferenceCount == BIG_INTEGER_PERMANENT_REFERENCE);
  845. Integer->ReferenceCount = 1;
  846. return;
  847. }
  848. //
  849. // --------------------------------------------------------- Internal Functions
  850. //
  851. PBIG_INTEGER
  852. CypBiAdd (
  853. PBIG_INTEGER_CONTEXT Context,
  854. PBIG_INTEGER Left,
  855. PBIG_INTEGER Right
  856. )
  857. /*++
  858. Routine Description:
  859. This routine adds two big integers together.
  860. Arguments:
  861. Context - Supplies a pointer to the big integer context.
  862. Left - Supplies the first value to add, as well as the destination.
  863. Right - Supplies the second value to add. A reference on this value will be
  864. released on success.
  865. Return Value:
  866. Returns a pointer to the left value, which will have accumulated
  867. the sum of the two.
  868. NULL on allocation failure.
  869. --*/
  870. {
  871. BIG_INTEGER_COMPONENT Carry;
  872. PBIG_INTEGER_COMPONENT LeftComponent;
  873. PBIG_INTEGER_COMPONENT RightComponent;
  874. KSTATUS Status;
  875. BIG_INTEGER_COMPONENT Sum;
  876. UINTN SumSize;
  877. BIG_INTEGER_COMPONENT SumWithCarry;
  878. //
  879. // The number of components in the sum is the maximum number of components
  880. // between then two, plus one for a potential carry.
  881. //
  882. SumSize = Left->Size;
  883. if (SumSize < Right->Size) {
  884. SumSize = Right->Size;
  885. }
  886. //
  887. // Resize the left for the final result, and resize the right to be the max
  888. // of the two to avoid annoying checks within the computation loop.
  889. //
  890. Status = CypBiResize(Context, Left, SumSize + 1);
  891. if (!KSUCCESS(Status)) {
  892. return NULL;
  893. }
  894. Status = CypBiResize(Context, Right, SumSize);
  895. if (!KSUCCESS(Status)) {
  896. return NULL;
  897. }
  898. LeftComponent = Left->Components;
  899. RightComponent = Right->Components;
  900. Carry = 0;
  901. do {
  902. Sum = *LeftComponent + *RightComponent;
  903. SumWithCarry = Sum + Carry;
  904. Carry = 0;
  905. if ((Sum < *LeftComponent) || (SumWithCarry < Sum)) {
  906. Carry = 1;
  907. }
  908. *LeftComponent = SumWithCarry;
  909. LeftComponent += 1;
  910. RightComponent += 1;
  911. SumSize -= 1;
  912. } while (SumSize != 0);
  913. *LeftComponent = Carry;
  914. CypBiReleaseReference(Context, Right);
  915. CypBiTrim(Left);
  916. return Left;
  917. }
  918. PBIG_INTEGER
  919. CypBiSubtract (
  920. PBIG_INTEGER_CONTEXT Context,
  921. PBIG_INTEGER Left,
  922. PBIG_INTEGER Right,
  923. PBOOL NegativeResult
  924. )
  925. /*++
  926. Routine Description:
  927. This routine subtracts two big integers from each other.
  928. Arguments:
  929. Context - Supplies a pointer to the big integer context.
  930. Left - Supplies the value to subtract from, as well as the destination.
  931. Right - Supplies the value to subtract. A reference on this value will be
  932. released on success.
  933. NegativeResult - Supplies an optional pointer where a boolean will be
  934. returned indicating whether the result was negative or not.
  935. Return Value:
  936. Returns a pointer to the left value, which will have subtracted
  937. value.
  938. NULL on allocation failure.
  939. --*/
  940. {
  941. BIG_INTEGER_COMPONENT Carry;
  942. PBIG_INTEGER_COMPONENT LeftComponent;
  943. PBIG_INTEGER_COMPONENT RightComponent;
  944. INTN Size;
  945. KSTATUS Status;
  946. BIG_INTEGER_COMPONENT Sum;
  947. BIG_INTEGER_COMPONENT SumWithCarry;
  948. Size = Left->Size;
  949. Status = CypBiResize(Context, Right, Size);
  950. if (!KSUCCESS(Status)) {
  951. return NULL;
  952. }
  953. LeftComponent = Left->Components;
  954. RightComponent = Right->Components;
  955. Carry = 0;
  956. do {
  957. Sum = *LeftComponent - *RightComponent;
  958. SumWithCarry = Sum - Carry;
  959. Carry = 0;
  960. if ((Sum > *LeftComponent) || (SumWithCarry > Sum)) {
  961. Carry = 1;
  962. }
  963. *LeftComponent = SumWithCarry;
  964. LeftComponent += 1;
  965. RightComponent += 1;
  966. Size -= 1;
  967. } while (Size != 0);
  968. if (NegativeResult != NULL) {
  969. *NegativeResult = Carry;
  970. }
  971. //
  972. // Put the right side back to what it was.
  973. //
  974. CypBiTrim(Right);
  975. CypBiReleaseReference(Context, Right);
  976. CypBiTrim(Left);
  977. return Left;
  978. }
  979. PBIG_INTEGER
  980. CypBiMultiply (
  981. PBIG_INTEGER_CONTEXT Context,
  982. PBIG_INTEGER Left,
  983. PBIG_INTEGER Right
  984. )
  985. /*++
  986. Routine Description:
  987. This routine multiplies two big integers together.
  988. Arguments:
  989. Context - Supplies a pointer to the big integer context.
  990. Left - Supplies the value to multiply. A reference on this value will be
  991. released on success.
  992. Right - Supplies the value to multiply by. A reference on this value will be
  993. released on success.
  994. Return Value:
  995. Returns a pointer to the new product.
  996. NULL on allocation failure.
  997. --*/
  998. {
  999. return CypBiMultiplyStandard(Context, Left, Right, 0, 0);
  1000. }
  1001. PBIG_INTEGER
  1002. CypBiDivide (
  1003. PBIG_INTEGER_CONTEXT Context,
  1004. PBIG_INTEGER Numerator,
  1005. PBIG_INTEGER Denominator,
  1006. BOOL ModuloOperation
  1007. )
  1008. /*++
  1009. Routine Description:
  1010. This routine divides two big integers.
  1011. Arguments:
  1012. Context - Supplies a pointer to the big integer context.
  1013. Numerator - Supplies a pointer to the numerator. This is also the
  1014. destination.
  1015. Denominator - Supplies a pointer to the denominator. A reference will be
  1016. released on this value on success.
  1017. ModuloOperation - Supplies a boolean indicating whether to return the
  1018. quotient (FALSE) or the modulo (TRUE).
  1019. Return Value:
  1020. Returns a pointer to the numerator (now quotient or modulo) on success.
  1021. NULL on allocation failure.
  1022. --*/
  1023. {
  1024. PBIG_INTEGER DenominatorTimesQDash;
  1025. UINTN Index;
  1026. BIG_INTEGER_COMPONENT Inner;
  1027. BOOL IsNegative;
  1028. BIG_INTEGER_COMPONENT Last;
  1029. BIG_INTEGER_COMPONENT LastDenominator;
  1030. BIG_INTEGER_COMPONENT LastWorking;
  1031. INTN ModOffset;
  1032. PBIG_INTEGER NewWorking;
  1033. INTN NumeratorIndex;
  1034. INTN OriginalNumeratorSize;
  1035. BIG_INTEGER_COMPONENT QPrime;
  1036. PBIG_INTEGER Quotient;
  1037. INTN QuotientSize;
  1038. BIG_INTEGER_COMPONENT SecondLastDenominator;
  1039. BIG_INTEGER_COMPONENT SecondLastWorking;
  1040. INTN Size;
  1041. KSTATUS Status;
  1042. PBIG_INTEGER Working;
  1043. Status = STATUS_INSUFFICIENT_RESOURCES;
  1044. DenominatorTimesQDash = NULL;
  1045. ModOffset = Context->ModOffset;
  1046. OriginalNumeratorSize = Numerator->Size;
  1047. Size = Denominator->Size;
  1048. QuotientSize = Numerator->Size - Size;
  1049. Working = NULL;
  1050. //
  1051. // Perform a quick exit: if the value is less than the modulo, then just
  1052. // return the value.
  1053. //
  1054. if ((ModuloOperation != FALSE) &&
  1055. (CypBiCompare(Denominator, Numerator) > 0)) {
  1056. CypBiReleaseReference(Context, Denominator);
  1057. return Numerator;
  1058. }
  1059. Quotient = CypBiCreate(Context, QuotientSize + 1);
  1060. if (Quotient == NULL) {
  1061. goto BiDivideEnd;
  1062. }
  1063. RtlZeroMemory(Quotient->Components,
  1064. Quotient->Size * sizeof(BIG_INTEGER_COMPONENT));
  1065. Working = CypBiCreate(Context, Size + 1);
  1066. if (Working == NULL) {
  1067. goto BiDivideEnd;
  1068. }
  1069. CypBiTrim(Denominator);
  1070. Last = BIG_INTEGER_RADIX /
  1071. (Denominator->Components[Denominator->Size - 1] + 1);
  1072. if (Last > 1) {
  1073. Numerator = CypBiMultiplyComponent(Context, Numerator, Last);
  1074. if (Numerator == NULL) {
  1075. goto BiDivideEnd;
  1076. }
  1077. if (ModuloOperation != FALSE) {
  1078. Denominator = Context->NormalizedMod[ModOffset];
  1079. } else {
  1080. Denominator = CypBiMultiplyComponent(Context, Denominator, Last);
  1081. }
  1082. }
  1083. if (OriginalNumeratorSize == Numerator->Size) {
  1084. CypBiResize(Context, Numerator, OriginalNumeratorSize + 1);
  1085. }
  1086. Index = 0;
  1087. do {
  1088. //
  1089. // Create a shorter version of the numerator.
  1090. //
  1091. NumeratorIndex = Numerator->Size - Size - 1 - Index;
  1092. RtlCopyMemory(Working->Components,
  1093. &(Numerator->Components[NumeratorIndex]),
  1094. (Size + 1) * sizeof(BIG_INTEGER_COMPONENT));
  1095. //
  1096. // Calculate q'.
  1097. //
  1098. LastWorking = Working->Components[Working->Size - 1];
  1099. LastDenominator = Denominator->Components[Denominator->Size - 1];
  1100. if (LastWorking == LastDenominator) {
  1101. QPrime = BIG_INTEGER_RADIX - 1;
  1102. } else {
  1103. SecondLastWorking = Working->Components[Working->Size - 2];
  1104. QPrime = (((BIG_INTEGER_LONG_COMPONENT)LastWorking *
  1105. BIG_INTEGER_RADIX) +
  1106. SecondLastWorking) / LastDenominator;
  1107. if (Denominator->Size > 1) {
  1108. SecondLastDenominator =
  1109. Denominator->Components[Denominator->Size - 2];
  1110. if (SecondLastDenominator != 0) {
  1111. Inner = (BIG_INTEGER_RADIX * LastWorking) +
  1112. SecondLastWorking -
  1113. ((BIG_INTEGER_LONG_COMPONENT)QPrime *
  1114. LastDenominator);
  1115. if (((BIG_INTEGER_LONG_COMPONENT)SecondLastDenominator *
  1116. QPrime) >
  1117. (((BIG_INTEGER_LONG_COMPONENT)Inner *
  1118. BIG_INTEGER_RADIX) + SecondLastWorking)) {
  1119. QPrime -= 1;
  1120. }
  1121. }
  1122. }
  1123. }
  1124. //
  1125. // Multiply and subtract the working value.
  1126. //
  1127. if (QPrime != 0) {
  1128. CypBiAddReference(Denominator);
  1129. DenominatorTimesQDash = CypBiMultiplyComponent(Context,
  1130. Denominator,
  1131. QPrime);
  1132. if (DenominatorTimesQDash == NULL) {
  1133. goto BiDivideEnd;
  1134. }
  1135. NewWorking = CypBiSubtract(Context,
  1136. Working,
  1137. DenominatorTimesQDash,
  1138. &IsNegative);
  1139. if (NewWorking == NULL) {
  1140. goto BiDivideEnd;
  1141. }
  1142. DenominatorTimesQDash = NULL;
  1143. Working = NewWorking;
  1144. Status = CypBiResize(Context, Working, Size + 1);
  1145. if (!KSUCCESS(Status)) {
  1146. goto BiDivideEnd;
  1147. }
  1148. if (IsNegative != FALSE) {
  1149. QPrime -= 1;
  1150. CypBiAddReference(Denominator);
  1151. NewWorking = CypBiAdd(Context, Working, Denominator);
  1152. if (NewWorking == NULL) {
  1153. goto BiDivideEnd;
  1154. }
  1155. Working = NewWorking;
  1156. Working->Size -= 1;
  1157. Denominator->Size -= 1;
  1158. }
  1159. }
  1160. Quotient->Components[Quotient->Size - Index - 1] = QPrime;
  1161. //
  1162. // Copy the result back.
  1163. //
  1164. NumeratorIndex = Numerator->Size - Size - 1 - Index;
  1165. RtlCopyMemory(&(Numerator->Components[NumeratorIndex]),
  1166. Working->Components,
  1167. (Size + 1) * sizeof(BIG_INTEGER_COMPONENT));
  1168. Index += 1;
  1169. } while (Index <= QuotientSize);
  1170. CypBiReleaseReference(Context, Working);
  1171. Working = NULL;
  1172. CypBiReleaseReference(Context, Denominator);
  1173. Denominator = NULL;
  1174. //
  1175. // If it's a modulo operation, get the remainder.
  1176. //
  1177. if (ModuloOperation != FALSE) {
  1178. CypBiReleaseReference(Context, Quotient);
  1179. CypBiTrim(Numerator);
  1180. Quotient = CypBiDivideComponent(Context, Numerator, Last);
  1181. if (Quotient == NULL) {
  1182. goto BiDivideEnd;
  1183. }
  1184. } else {
  1185. CypBiReleaseReference(Context, Numerator);
  1186. CypBiTrim(Quotient);
  1187. }
  1188. Status = STATUS_SUCCESS;
  1189. BiDivideEnd:
  1190. if (Working != NULL) {
  1191. CypBiReleaseReference(Context, Working);
  1192. }
  1193. if (DenominatorTimesQDash != NULL) {
  1194. CypBiReleaseReference(Context, DenominatorTimesQDash);
  1195. }
  1196. if (!KSUCCESS(Status)) {
  1197. if (Quotient != NULL) {
  1198. CypBiReleaseReference(Context, Quotient);
  1199. Quotient = NULL;
  1200. }
  1201. }
  1202. return Quotient;
  1203. }
  1204. PBIG_INTEGER
  1205. CypBiSquare (
  1206. PBIG_INTEGER_CONTEXT Context,
  1207. PBIG_INTEGER Value
  1208. )
  1209. /*++
  1210. Routine Description:
  1211. This routine squares a value, using half the multiplies of the standard
  1212. multiply method.
  1213. Arguments:
  1214. Context - Supplies a pointer to the big integer context.
  1215. Value - Supplies a pointer to the big integer to square. On success a
  1216. reference on this value is released.
  1217. Return Value:
  1218. Returns a pointer to the new square.
  1219. NULL on allocation failure.
  1220. --*/
  1221. {
  1222. BIG_INTEGER_LONG_COMPONENT Carry;
  1223. INTN Index;
  1224. INTN InnerCarry;
  1225. INTN InnerIndex;
  1226. BIG_INTEGER_LONG_COMPONENT InnerProduct;
  1227. BIG_INTEGER_LONG_COMPONENT Product;
  1228. PBIG_INTEGER Result;
  1229. PBIG_INTEGER_COMPONENT ResultComponents;
  1230. INTN Size;
  1231. PBIG_INTEGER_COMPONENT ValueComponents;
  1232. Index = 0;
  1233. Size = Value->Size;
  1234. Result = CypBiCreate(Context, (Size * 2) + 1);
  1235. if (Result == NULL) {
  1236. return NULL;
  1237. }
  1238. ResultComponents = Result->Components;
  1239. ValueComponents = Value->Components;
  1240. RtlZeroMemory(ResultComponents,
  1241. Result->Size * sizeof(BIG_INTEGER_COMPONENT));
  1242. do {
  1243. Product = ResultComponents[Index * 2] +
  1244. (BIG_INTEGER_LONG_COMPONENT)ValueComponents[Index] *
  1245. ValueComponents[Index];
  1246. ResultComponents[Index * 2] = (BIG_INTEGER_COMPONENT)Product;
  1247. Carry = Product >> BIG_INTEGER_COMPONENT_BITS;
  1248. for (InnerIndex = Index + 1; InnerIndex < Size; InnerIndex += 1) {
  1249. InnerCarry = 0;
  1250. InnerProduct = (BIG_INTEGER_LONG_COMPONENT)ValueComponents[Index] *
  1251. ValueComponents[InnerIndex];
  1252. if ((BIG_INTEGER_LONG_COMPONENT_MAX - InnerProduct) <
  1253. InnerProduct) {
  1254. InnerCarry = 1;
  1255. }
  1256. Product = InnerProduct << 1;
  1257. if ((BIG_INTEGER_LONG_COMPONENT_MAX - Product) <
  1258. ResultComponents[Index + InnerIndex]) {
  1259. InnerCarry = 1;
  1260. }
  1261. Product += ResultComponents[Index + InnerIndex];
  1262. if ((BIG_INTEGER_LONG_COMPONENT_MAX - Product) < Carry) {
  1263. InnerCarry = 1;
  1264. }
  1265. Product += Carry;
  1266. ResultComponents[Index + InnerIndex] =
  1267. (BIG_INTEGER_COMPONENT)Product;
  1268. Carry = Product >> BIG_INTEGER_COMPONENT_BITS;
  1269. if (InnerCarry != 0) {
  1270. Carry += BIG_INTEGER_RADIX;
  1271. }
  1272. }
  1273. Product = ResultComponents[Index + Size] + Carry;
  1274. ResultComponents[Index + Size] = Product;
  1275. ResultComponents[Index + Size + 1] =
  1276. Product >> BIG_INTEGER_COMPONENT_BITS;
  1277. Index += 1;
  1278. } while (Index < Size);
  1279. CypBiReleaseReference(Context, Value);
  1280. CypBiTrim(Result);
  1281. return Result;
  1282. }
  1283. INT
  1284. CypBiCompare (
  1285. PBIG_INTEGER Left,
  1286. PBIG_INTEGER Right
  1287. )
  1288. /*++
  1289. Routine Description:
  1290. This routine compares two big integers.
  1291. Arguments:
  1292. Left - Supplies a pointer to the left value to compare.
  1293. Right - Supplies a pointer to the right value to compare.
  1294. Return Value:
  1295. < 0 if Left < Right.
  1296. 0 if Left == Right.
  1297. > 0 if Left > Right.
  1298. --*/
  1299. {
  1300. INTN Index;
  1301. PBIG_INTEGER_COMPONENT LeftComponents;
  1302. INT Result;
  1303. PBIG_INTEGER_COMPONENT RightComponents;
  1304. if (Left->Size > Right->Size) {
  1305. Result = 1;
  1306. } else if (Left->Size < Right->Size) {
  1307. Result = -1;
  1308. } else {
  1309. LeftComponents = Left->Components;
  1310. RightComponents = Right->Components;
  1311. Result = 0;
  1312. Index = Left->Size - 1;
  1313. do {
  1314. if (LeftComponents[Index] > RightComponents[Index]) {
  1315. Result = 1;
  1316. break;
  1317. } else if (LeftComponents[Index] < RightComponents[Index]) {
  1318. Result = -1;
  1319. break;
  1320. }
  1321. Index -= 1;
  1322. } while (Index >= 0);
  1323. }
  1324. return Result;
  1325. }
  1326. PBIG_INTEGER
  1327. CypBiMultiplyComponent (
  1328. PBIG_INTEGER_CONTEXT Context,
  1329. PBIG_INTEGER Left,
  1330. BIG_INTEGER_COMPONENT RightComponent
  1331. )
  1332. /*++
  1333. Routine Description:
  1334. This routine multiplies a big integer by a big integer component.
  1335. Arguments:
  1336. Context - Supplies a pointer to the big integer context.
  1337. Left - Supplies the value to multiply. A reference on this value will be
  1338. released on success.
  1339. RightComponent - Supplies the value to multiply by.
  1340. Return Value:
  1341. Returns a pointer to the new result.
  1342. NULL on allocation failure.
  1343. --*/
  1344. {
  1345. BIG_INTEGER_COMPONENT Carry;
  1346. UINTN Index;
  1347. PBIG_INTEGER_COMPONENT LeftComponents;
  1348. PBIG_INTEGER Result;
  1349. BIG_INTEGER_LONG_COMPONENT ResultComponent;
  1350. PBIG_INTEGER_COMPONENT ResultComponents;
  1351. UINTN Size;
  1352. Size = Left->Size;
  1353. Result = CypBiCreate(Context, Size + 1);
  1354. if (Result == NULL) {
  1355. return NULL;
  1356. }
  1357. LeftComponents = Left->Components;
  1358. ResultComponents = Result->Components;
  1359. RtlZeroMemory(ResultComponents, (Size * 1) * sizeof(BIG_INTEGER_COMPONENT));
  1360. Carry = 0;
  1361. for (Index = 0; Index < Size; Index += 1) {
  1362. ResultComponent = ((BIG_INTEGER_LONG_COMPONENT)*LeftComponents *
  1363. RightComponent) + Carry;
  1364. *ResultComponents = ResultComponent;
  1365. Carry = ResultComponent >> BIG_INTEGER_COMPONENT_BITS;
  1366. ResultComponents += 1;
  1367. LeftComponents += 1;
  1368. }
  1369. *ResultComponents = Carry;
  1370. CypBiReleaseReference(Context, Left);
  1371. CypBiTrim(Result);
  1372. return Result;
  1373. }
  1374. PBIG_INTEGER
  1375. CypBiMultiplyStandard (
  1376. PBIG_INTEGER_CONTEXT Context,
  1377. PBIG_INTEGER Left,
  1378. PBIG_INTEGER Right,
  1379. INTN InnerPartial,
  1380. INTN OuterPartial
  1381. )
  1382. /*++
  1383. Routine Description:
  1384. This routine multiplies two big integers together.
  1385. Arguments:
  1386. Context - Supplies a pointer to the big integer context.
  1387. Left - Supplies the value to multiply. A reference on this value will be
  1388. released on success.
  1389. Right - Supplies the value to multiply by. A reference on this value will be
  1390. released on success.
  1391. InnerPartial - Supplies the inner partial product.
  1392. OuterPartial - Supplies the outer partial product.
  1393. Return Value:
  1394. Returns a pointer to the new product.
  1395. NULL on allocation failure.
  1396. --*/
  1397. {
  1398. BIG_INTEGER_COMPONENT Carry;
  1399. PBIG_INTEGER_COMPONENT LeftComponents;
  1400. INTN LeftIndex;
  1401. INTN LeftSize;
  1402. BIG_INTEGER_LONG_COMPONENT Product;
  1403. PBIG_INTEGER Result;
  1404. PBIG_INTEGER_COMPONENT ResultComponents;
  1405. INTN ResultIndex;
  1406. PBIG_INTEGER_COMPONENT RightComponents;
  1407. INTN RightIndex;
  1408. INTN RightSize;
  1409. LeftSize = Left->Size;
  1410. RightSize = Right->Size;
  1411. Result = CypBiCreate(Context, LeftSize + RightSize);
  1412. if (Result == NULL) {
  1413. return NULL;
  1414. }
  1415. LeftComponents = Left->Components;
  1416. RightComponents = Right->Components;
  1417. ResultComponents = Result->Components;
  1418. RtlZeroMemory(ResultComponents,
  1419. (LeftSize + RightSize) * sizeof(BIG_INTEGER_COMPONENT));
  1420. RightIndex = 0;
  1421. do {
  1422. Carry = 0;
  1423. ResultIndex = RightIndex;
  1424. LeftIndex = 0;
  1425. if ((OuterPartial != 0) && (OuterPartial - RightIndex > 0) &&
  1426. (OuterPartial < LeftSize)) {
  1427. ResultIndex = OuterPartial - 1;
  1428. LeftIndex = OuterPartial - RightIndex - 1;
  1429. }
  1430. do {
  1431. if ((InnerPartial != 0) && (ResultIndex >= InnerPartial)) {
  1432. break;
  1433. }
  1434. Product = ResultComponents[ResultIndex] +
  1435. (((BIG_INTEGER_LONG_COMPONENT)LeftComponents[LeftIndex]) *
  1436. RightComponents[RightIndex]) + Carry;
  1437. ResultComponents[ResultIndex] = Product;
  1438. ResultIndex += 1;
  1439. LeftIndex += 1;
  1440. Carry = Product >> BIG_INTEGER_COMPONENT_BITS;
  1441. } while (LeftIndex < LeftSize);
  1442. ResultComponents[ResultIndex] = Carry;
  1443. RightIndex += 1;
  1444. } while (RightIndex < RightSize);
  1445. CypBiReleaseReference(Context, Left);
  1446. CypBiReleaseReference(Context, Right);
  1447. CypBiTrim(Result);
  1448. return Result;
  1449. }
  1450. PBIG_INTEGER
  1451. CypBiDivideComponent (
  1452. PBIG_INTEGER_CONTEXT Context,
  1453. PBIG_INTEGER Numerator,
  1454. BIG_INTEGER_COMPONENT Denominator
  1455. )
  1456. /*++
  1457. Routine Description:
  1458. This routine divides a big integer by a big integer component.
  1459. Arguments:
  1460. Context - Supplies a pointer to the big integer context.
  1461. Numerator - Supplies a pointer to the numerator. This is also the
  1462. destination.
  1463. Denominator - Supplies the denominator value to divide by.
  1464. Return Value:
  1465. Returns a pointer to the numerator (now quotient) on success.
  1466. NULL on allocation failure.
  1467. --*/
  1468. {
  1469. INTN Index;
  1470. PBIG_INTEGER Result;
  1471. BIG_INTEGER_LONG_COMPONENT ResultComponent;
  1472. ASSERT(Numerator->Size != 0);
  1473. Result = Numerator;
  1474. ResultComponent = 0;
  1475. Index = Numerator->Size - 1;
  1476. do {
  1477. ResultComponent = (ResultComponent << BIG_INTEGER_COMPONENT_BITS) +
  1478. Numerator->Components[Index];
  1479. Result->Components[Index] =
  1480. (BIG_INTEGER_COMPONENT)(ResultComponent / Denominator);
  1481. ResultComponent = ResultComponent % Denominator;
  1482. Index -= 1;
  1483. } while (Index >= 0);
  1484. CypBiTrim(Result);
  1485. return Result;
  1486. }
  1487. PBIG_INTEGER
  1488. CypBiRightShiftComponent (
  1489. PBIG_INTEGER Value,
  1490. UINTN ComponentCount
  1491. )
  1492. /*++
  1493. Routine Description:
  1494. This routine performs a right shift of a given big integer.
  1495. Arguments:
  1496. Value - Supplies a pointer to the value to shift. This is also the
  1497. destination.
  1498. ComponentCount - Supplies the amount to shift, in components.
  1499. Return Value:
  1500. Returns a pointer to the value on success.
  1501. NULL on allocation failure.
  1502. --*/
  1503. {
  1504. PBIG_INTEGER_COMPONENT High;
  1505. INTN Index;
  1506. PBIG_INTEGER_COMPONENT Low;
  1507. Index = Value->Size - ComponentCount;
  1508. Low = Value->Components;
  1509. High = &(Value->Components[ComponentCount]);
  1510. if (Index <= 0) {
  1511. Value->Components[0] = 0;
  1512. Value->Size = 1;
  1513. return Value;
  1514. }
  1515. do {
  1516. *Low = *High;
  1517. Low += 1;
  1518. High += 1;
  1519. Index -= 1;
  1520. } while (Index > 0);
  1521. Value->Size -= ComponentCount;
  1522. return Value;
  1523. }
  1524. PBIG_INTEGER
  1525. CypBiLeftShiftComponent (
  1526. PBIG_INTEGER_CONTEXT Context,
  1527. PBIG_INTEGER Value,
  1528. UINTN ComponentCount
  1529. )
  1530. /*++
  1531. Routine Description:
  1532. This routine performs a left shift of a given big integer.
  1533. Arguments:
  1534. Context - Supplies a pointer to the big integer context.
  1535. Value - Supplies a pointer to the value to shift. This is also the
  1536. destination.
  1537. ComponentCount - Supplies the amount to shift, in components.
  1538. Return Value:
  1539. Returns a pointer to the value on success.
  1540. NULL on allocation failure.
  1541. --*/
  1542. {
  1543. PBIG_INTEGER_COMPONENT High;
  1544. INTN Index;
  1545. PBIG_INTEGER_COMPONENT Low;
  1546. KSTATUS Status;
  1547. Index = Value->Size - 1;
  1548. if (ComponentCount <= 0) {
  1549. return Value;
  1550. }
  1551. Status = CypBiResize(Context, Value, Value->Size + ComponentCount);
  1552. if (!KSUCCESS(Status)) {
  1553. return NULL;
  1554. }
  1555. High = &(Value->Components[Index + ComponentCount]);
  1556. Low = &(Value->Components[Index]);
  1557. do {
  1558. *High = *Low;
  1559. High += 1;
  1560. Low += 1;
  1561. Index -= 1;
  1562. } while (Index > 0);
  1563. RtlZeroMemory(Value->Components,
  1564. ComponentCount * sizeof(BIG_INTEGER_COMPONENT));
  1565. return Value;
  1566. }
  1567. INTN
  1568. CypBiFindLeadingBit (
  1569. PBIG_INTEGER Value
  1570. )
  1571. /*++
  1572. Routine Description:
  1573. This routine returns the bit index of the highest bit set in the given
  1574. value.
  1575. Arguments:
  1576. Value - Supplies a pointer to the value to find the leading bit index of.
  1577. Return Value:
  1578. Returns the index of the highest bit set in the value.
  1579. -1 if the value is zero.
  1580. --*/
  1581. {
  1582. BIG_INTEGER_COMPONENT Component;
  1583. BIG_INTEGER_COMPONENT Index;
  1584. BIG_INTEGER_COMPONENT Mask;
  1585. Component = Value->Components[Value->Size - 1];
  1586. Mask = BIG_INTEGER_RADIX / 2;
  1587. Index = BIG_INTEGER_COMPONENT_BITS - 1;
  1588. do {
  1589. if ((Component & Mask) != 0) {
  1590. return Index + ((Value->Size - 1) * BIG_INTEGER_COMPONENT_BITS);
  1591. }
  1592. Mask >>= 1;
  1593. Index -= 1;
  1594. } while (Index != 0);
  1595. return -1;
  1596. }
  1597. BOOL
  1598. CypBiTestBit (
  1599. PBIG_INTEGER Value,
  1600. UINTN BitIndex
  1601. )
  1602. /*++
  1603. Routine Description:
  1604. This routine tests to see if the bit at the given bit index is set in the
  1605. given value.
  1606. Arguments:
  1607. Value - Supplies a pointer to the value to test.
  1608. BitIndex - Supplies the zero-based bit index of the bit to test.
  1609. Return Value:
  1610. TRUE if the bit is set in the value.
  1611. FALSE if the bit is not set in the value.
  1612. --*/
  1613. {
  1614. BIG_INTEGER_COMPONENT Component;
  1615. UINTN ComponentIndex;
  1616. BIG_INTEGER_COMPONENT Mask;
  1617. ComponentIndex = BitIndex / BIG_INTEGER_COMPONENT_BITS;
  1618. ASSERT(ComponentIndex < Value->Size);
  1619. Component = Value->Components[ComponentIndex];
  1620. Mask = 1 << (BitIndex % BIG_INTEGER_COMPONENT_BITS);
  1621. if ((Component & Mask) != 0) {
  1622. return TRUE;
  1623. }
  1624. return FALSE;
  1625. }
  1626. PBIG_INTEGER
  1627. CypBiPerformBarrettReduction (
  1628. PBIG_INTEGER_CONTEXT Context,
  1629. PBIG_INTEGER Value
  1630. )
  1631. /*++
  1632. Routine Description:
  1633. This routine performs a single Barrett reduction.
  1634. Arguments:
  1635. Context - Supplies a pointer to the big integer context.
  1636. Value - Supplies a pointer to the value to reduce. This is also the
  1637. destination.
  1638. Return Value:
  1639. Returns a pointer to the reduced value on success.
  1640. NULL on allocation failure.
  1641. --*/
  1642. {
  1643. UINTN ModOffset;
  1644. PBIG_INTEGER Modulus;
  1645. UINTN ModulusSize;
  1646. PBIG_INTEGER NewValue;
  1647. PBIG_INTEGER QValue;
  1648. PBIG_INTEGER RValue;
  1649. ModOffset = Context->ModOffset;
  1650. Modulus = Context->Modulus[ModOffset];
  1651. ModulusSize = Modulus->Size;
  1652. RValue = NULL;
  1653. //
  1654. // Use the original method if Barrett cannot help.
  1655. //
  1656. if (Value->Size > ModulusSize * 2) {
  1657. return CypBiModulo(Context, Value);
  1658. }
  1659. QValue = CypBiClone(Context, Value);
  1660. if (QValue == NULL) {
  1661. return NULL;
  1662. }
  1663. NewValue = CypBiRightShiftComponent(QValue, ModulusSize - 1);
  1664. ASSERT(NewValue == QValue);
  1665. NewValue = CypBiMultiplyStandard(Context,
  1666. QValue,
  1667. Context->Mu[ModOffset],
  1668. 0,
  1669. ModulusSize - 1);
  1670. if (NewValue == NULL) {
  1671. CypBiReleaseReference(Context, QValue);
  1672. return NULL;
  1673. }
  1674. QValue = NewValue;
  1675. NewValue = CypBiRightShiftComponent(QValue, ModulusSize + 1);
  1676. ASSERT(NewValue == QValue);
  1677. //
  1678. // Perform an optimized modulo operation via truncation.
  1679. //
  1680. if (Value->Size > ModulusSize + 1) {
  1681. Value->Size = ModulusSize + 1;
  1682. }
  1683. RValue = CypBiMultiplyStandard(Context,
  1684. QValue,
  1685. Modulus,
  1686. ModulusSize + 1,
  1687. 0);
  1688. if (RValue == NULL) {
  1689. CypBiReleaseReference(Context, QValue);
  1690. return NULL;
  1691. }
  1692. QValue = NULL;
  1693. //
  1694. // Do another modulo truncation.
  1695. //
  1696. if (RValue->Size > ModulusSize + 1) {
  1697. RValue->Size = ModulusSize + 1;
  1698. }
  1699. NewValue = CypBiSubtract(Context, Value, RValue, NULL);
  1700. if (NewValue == NULL) {
  1701. CypBiReleaseReference(Context, RValue);
  1702. return NULL;
  1703. }
  1704. ASSERT(NewValue == Value);
  1705. if (CypBiCompare(Value, Modulus) >= 0) {
  1706. NewValue = CypBiSubtract(Context, Value, Modulus, NULL);
  1707. if (NewValue == NULL) {
  1708. return NULL;
  1709. }
  1710. ASSERT(NewValue == Value);
  1711. }
  1712. return Value;
  1713. }
  1714. KSTATUS
  1715. CypBiComputeExponentTable (
  1716. PBIG_INTEGER_CONTEXT Context,
  1717. INTN CountExponent,
  1718. PBIG_INTEGER Value
  1719. )
  1720. /*++
  1721. Routine Description:
  1722. This routine computes common exponents for a given value, used to reduce
  1723. the number of multiplies during exponentiation.
  1724. Arguments:
  1725. Context - Supplies a pointer to the context that owns the integer.
  1726. CountExponent - Supplies one greater than the power of two number of
  1727. elements to compute in the table.
  1728. Value - Supplies a pointer to the value to compute exponents for.
  1729. Return Value:
  1730. STATUS_SUCCESS on success.
  1731. STATUS_INSUFFICIENT_RESOURCES on allocation failure.
  1732. --*/
  1733. {
  1734. UINTN AllocationSize;
  1735. UINTN Count;
  1736. UINTN Index;
  1737. PBIG_INTEGER Next;
  1738. KSTATUS Status;
  1739. PBIG_INTEGER Value2;
  1740. Count = 1 << (CountExponent - 1);
  1741. Status = STATUS_INSUFFICIENT_RESOURCES;
  1742. Value2 = NULL;
  1743. ASSERT(Context->ExponentTable == NULL);
  1744. AllocationSize = Count * sizeof(PBIG_INTEGER);
  1745. Context->ExponentTable = Context->AllocateMemory(AllocationSize);
  1746. if (Context->ExponentTable == NULL) {
  1747. goto BiComputeExponentTableEnd;
  1748. }
  1749. RtlZeroMemory(Context->ExponentTable, AllocationSize);
  1750. Context->ExponentTable[0] = CypBiClone(Context, Value);
  1751. if (Context->ExponentTable[0] == NULL) {
  1752. goto BiComputeExponentTableEnd;
  1753. }
  1754. CypBiMakePermanent(Context->ExponentTable[0]);
  1755. Value2 = CypBiSquare(Context, Context->ExponentTable[0]);
  1756. if (Value2 == NULL) {
  1757. goto BiComputeExponentTableEnd;
  1758. }
  1759. Next = CypBiResidue(Context, Value2);
  1760. if (Next == NULL) {
  1761. goto BiComputeExponentTableEnd;
  1762. }
  1763. ASSERT(Next == Value2);
  1764. for (Index = 1; Index < Count; Index += 1) {
  1765. CypBiAddReference(Value2);
  1766. Next = CypBiMultiply(Context,
  1767. Context->ExponentTable[Index - 1],
  1768. Value2);
  1769. if (Next == NULL) {
  1770. CypBiReleaseReference(Context, Value2);
  1771. goto BiComputeExponentTableEnd;
  1772. }
  1773. Context->ExponentTable[Index] = CypBiResidue(Context, Next);
  1774. if (Context->ExponentTable[Index] == NULL) {
  1775. goto BiComputeExponentTableEnd;
  1776. }
  1777. ASSERT(Context->ExponentTable[Index] == Next);
  1778. CypBiMakePermanent(Context->ExponentTable[Index]);
  1779. }
  1780. Context->WindowSize = Count;
  1781. Status = STATUS_SUCCESS;
  1782. BiComputeExponentTableEnd:
  1783. if (Value2 != NULL) {
  1784. CypBiReleaseReference(Context, Value2);
  1785. }
  1786. if (!KSUCCESS(Status)) {
  1787. if (Context->ExponentTable != NULL) {
  1788. for (Index = 0; Index < Count; Index += 1) {
  1789. Next = Context->ExponentTable[Index];
  1790. if (Next != NULL) {
  1791. CypBiMakeNonPermanent(Next);
  1792. CypBiReleaseReference(Context, Next);
  1793. }
  1794. }
  1795. Context->FreeMemory(Context->ExponentTable);
  1796. Context->ExponentTable = NULL;
  1797. Context->WindowSize = 0;
  1798. }
  1799. }
  1800. return Status;
  1801. }
  1802. PBIG_INTEGER
  1803. CypBiClone (
  1804. PBIG_INTEGER_CONTEXT Context,
  1805. PBIG_INTEGER Integer
  1806. )
  1807. /*++
  1808. Routine Description:
  1809. This routine creates a new big integer and initializes it with the given
  1810. big integer value.
  1811. Arguments:
  1812. Context - Supplies a pointer to the context that owns the integer.
  1813. Integer - Supplies a pointer to an existing big integer to copy.
  1814. Return Value:
  1815. Returns a pointer to the integer on success.
  1816. NULL on allocation failure.
  1817. --*/
  1818. {
  1819. PBIG_INTEGER NewInteger;
  1820. NewInteger = CypBiCreate(Context, Integer->Size);
  1821. if (NewInteger == NULL) {
  1822. return NULL;
  1823. }
  1824. RtlCopyMemory(NewInteger->Components,
  1825. Integer->Components,
  1826. Integer->Size * sizeof(BIG_INTEGER_COMPONENT));
  1827. return NewInteger;
  1828. }
  1829. PBIG_INTEGER
  1830. CypBiCreateFromInteger (
  1831. PBIG_INTEGER_CONTEXT Context,
  1832. BIG_INTEGER_COMPONENT Value
  1833. )
  1834. /*++
  1835. Routine Description:
  1836. This routine creates a new big integer and initializes it with the given
  1837. value.
  1838. Arguments:
  1839. Context - Supplies a pointer to the context that owns the integer.
  1840. Value - Supplies the value to initialize the integer to.
  1841. Return Value:
  1842. Returns a pointer to the integer on success.
  1843. NULL on allocation failure.
  1844. --*/
  1845. {
  1846. PBIG_INTEGER Integer;
  1847. Integer = CypBiCreate(Context, 1);
  1848. if (Integer == NULL) {
  1849. return NULL;
  1850. }
  1851. Integer->Components[0] = Value;
  1852. return Integer;
  1853. }
  1854. PBIG_INTEGER
  1855. CypBiCreate (
  1856. PBIG_INTEGER_CONTEXT Context,
  1857. UINTN ComponentCount
  1858. )
  1859. /*++
  1860. Routine Description:
  1861. This routine creates a new big integer.
  1862. Arguments:
  1863. Context - Supplies a pointer to the context that owns the integer.
  1864. ComponentCount - Supplies the number of components to allocate
  1865. for.
  1866. Return Value:
  1867. Returns a pointer to the integer on success.
  1868. NULL on allocation failure.
  1869. --*/
  1870. {
  1871. PBIG_INTEGER Integer;
  1872. if (Context->FreeList != NULL) {
  1873. Integer = Context->FreeList;
  1874. Context->FreeList = Integer->Next;
  1875. Context->FreeCount -= 1;
  1876. ASSERT(Integer->ReferenceCount == 0);
  1877. CypBiResize(Context, Integer, ComponentCount);
  1878. } else {
  1879. Integer = Context->AllocateMemory(sizeof(BIG_INTEGER));
  1880. if (Integer == NULL) {
  1881. return NULL;
  1882. }
  1883. Integer->Components = Context->AllocateMemory(
  1884. ComponentCount * sizeof(BIG_INTEGER_COMPONENT));
  1885. if (Integer->Components == NULL) {
  1886. Context->FreeMemory(Integer);
  1887. return NULL;
  1888. }
  1889. Integer->Capacity = ComponentCount;
  1890. }
  1891. Integer->Size = ComponentCount;
  1892. Integer->ReferenceCount = 1;
  1893. Integer->Next = NULL;
  1894. Context->ActiveCount += 1;
  1895. return Integer;
  1896. }
  1897. KSTATUS
  1898. CypBiResize (
  1899. PBIG_INTEGER_CONTEXT Context,
  1900. PBIG_INTEGER Integer,
  1901. UINTN ComponentCount
  1902. )
  1903. /*++
  1904. Routine Description:
  1905. This routine resizes a big integer to ensure it has at least the given
  1906. number of components.
  1907. Arguments:
  1908. Context - Supplies a pointer to the context that owns the integer.
  1909. Integer - Supplies a pointer to the big integer.
  1910. ComponentCount - Supplies the number of components to allocate
  1911. for.
  1912. Return Value:
  1913. STATUS_SUCCESS on success.
  1914. STATUS_INSUFFICIENT_RESOURCES on allocation failure.
  1915. --*/
  1916. {
  1917. UINTN ExtraSize;
  1918. PVOID NewBuffer;
  1919. UINTN NewCapacity;
  1920. if (Integer->Capacity < ComponentCount) {
  1921. NewCapacity = Integer->Capacity * 2;
  1922. if (NewCapacity < ComponentCount) {
  1923. NewCapacity = ComponentCount;
  1924. }
  1925. NewBuffer = Context->ReallocateMemory(
  1926. Integer->Components,
  1927. NewCapacity * sizeof(BIG_INTEGER_COMPONENT));
  1928. if (NewBuffer == NULL) {
  1929. return STATUS_INSUFFICIENT_RESOURCES;
  1930. }
  1931. Integer->Components = NewBuffer;
  1932. Integer->Capacity = NewCapacity;
  1933. }
  1934. if (ComponentCount > Integer->Size) {
  1935. ExtraSize = (ComponentCount - Integer->Size) *
  1936. sizeof(BIG_INTEGER_COMPONENT);
  1937. RtlZeroMemory(&(Integer->Components[Integer->Size]), ExtraSize);
  1938. }
  1939. Integer->Size = ComponentCount;
  1940. return STATUS_SUCCESS;
  1941. }
  1942. VOID
  1943. CypBiTrim (
  1944. PBIG_INTEGER Integer
  1945. )
  1946. /*++
  1947. Routine Description:
  1948. This routine removes leading zero components from an integer.
  1949. Arguments:
  1950. Integer - Supplies a pointer to the big integer.
  1951. Return Value:
  1952. None.
  1953. --*/
  1954. {
  1955. while ((Integer->Size > 1) &&
  1956. (Integer->Components[Integer->Size - 1] == 0)) {
  1957. Integer->Size -= 1;
  1958. }
  1959. return;
  1960. }