15b37fcf3Sryker /* crypto/bn/bn_word.c */ 25b37fcf3Sryker /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 35b37fcf3Sryker * All rights reserved. 45b37fcf3Sryker * 55b37fcf3Sryker * This package is an SSL implementation written 65b37fcf3Sryker * by Eric Young (eay@cryptsoft.com). 75b37fcf3Sryker * The implementation was written so as to conform with Netscapes SSL. 85b37fcf3Sryker * 95b37fcf3Sryker * This library is free for commercial and non-commercial use as long as 105b37fcf3Sryker * the following conditions are aheared to. The following conditions 115b37fcf3Sryker * apply to all code found in this distribution, be it the RC4, RSA, 125b37fcf3Sryker * lhash, DES, etc., code; not just the SSL code. The SSL documentation 135b37fcf3Sryker * included with this distribution is covered by the same copyright terms 145b37fcf3Sryker * except that the holder is Tim Hudson (tjh@cryptsoft.com). 155b37fcf3Sryker * 165b37fcf3Sryker * Copyright remains Eric Young's, and as such any Copyright notices in 175b37fcf3Sryker * the code are not to be removed. 185b37fcf3Sryker * If this package is used in a product, Eric Young should be given attribution 195b37fcf3Sryker * as the author of the parts of the library used. 205b37fcf3Sryker * This can be in the form of a textual message at program startup or 215b37fcf3Sryker * in documentation (online or textual) provided with the package. 225b37fcf3Sryker * 235b37fcf3Sryker * Redistribution and use in source and binary forms, with or without 245b37fcf3Sryker * modification, are permitted provided that the following conditions 255b37fcf3Sryker * are met: 265b37fcf3Sryker * 1. Redistributions of source code must retain the copyright 275b37fcf3Sryker * notice, this list of conditions and the following disclaimer. 285b37fcf3Sryker * 2. Redistributions in binary form must reproduce the above copyright 295b37fcf3Sryker * notice, this list of conditions and the following disclaimer in the 305b37fcf3Sryker * documentation and/or other materials provided with the distribution. 315b37fcf3Sryker * 3. All advertising materials mentioning features or use of this software 325b37fcf3Sryker * must display the following acknowledgement: 335b37fcf3Sryker * "This product includes cryptographic software written by 345b37fcf3Sryker * Eric Young (eay@cryptsoft.com)" 355b37fcf3Sryker * The word 'cryptographic' can be left out if the rouines from the library 365b37fcf3Sryker * being used are not cryptographic related :-). 375b37fcf3Sryker * 4. If you include any Windows specific code (or a derivative thereof) from 385b37fcf3Sryker * the apps directory (application code) you must include an acknowledgement: 395b37fcf3Sryker * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 405b37fcf3Sryker * 415b37fcf3Sryker * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 425b37fcf3Sryker * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 435b37fcf3Sryker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 445b37fcf3Sryker * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 455b37fcf3Sryker * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 465b37fcf3Sryker * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 475b37fcf3Sryker * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 485b37fcf3Sryker * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 495b37fcf3Sryker * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 505b37fcf3Sryker * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 515b37fcf3Sryker * SUCH DAMAGE. 525b37fcf3Sryker * 535b37fcf3Sryker * The licence and distribution terms for any publically available version or 545b37fcf3Sryker * derivative of this code cannot be changed. i.e. this code cannot simply be 555b37fcf3Sryker * copied and put under another distribution licence 565b37fcf3Sryker * [including the GNU Public Licence.] 575b37fcf3Sryker */ 585b37fcf3Sryker 595b37fcf3Sryker #include <stdio.h> 605b37fcf3Sryker #include "cryptlib.h" 615b37fcf3Sryker #include "bn_lcl.h" 625b37fcf3Sryker 63ba5406e9Sbeck BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) 645b37fcf3Sryker { 655b37fcf3Sryker #ifndef BN_LLONG 665b37fcf3Sryker BN_ULONG ret=0; 675b37fcf3Sryker #else 685b37fcf3Sryker BN_ULLONG ret=0; 695b37fcf3Sryker #endif 705b37fcf3Sryker int i; 715b37fcf3Sryker 72*4fcf65c5Sdjm if (w == 0) 73*4fcf65c5Sdjm return (BN_ULONG)-1; 74*4fcf65c5Sdjm 75*4fcf65c5Sdjm bn_check_top(a); 765b37fcf3Sryker w&=BN_MASK2; 775b37fcf3Sryker for (i=a->top-1; i>=0; i--) 785b37fcf3Sryker { 795b37fcf3Sryker #ifndef BN_LLONG 80913ec974Sbeck ret=((ret<<BN_BITS4)|((a->d[i]>>BN_BITS4)&BN_MASK2l))%w; 81913ec974Sbeck ret=((ret<<BN_BITS4)|(a->d[i]&BN_MASK2l))%w; 825b37fcf3Sryker #else 835b37fcf3Sryker ret=(BN_ULLONG)(((ret<<(BN_ULLONG)BN_BITS2)|a->d[i])% 845b37fcf3Sryker (BN_ULLONG)w); 855b37fcf3Sryker #endif 865b37fcf3Sryker } 875b37fcf3Sryker return((BN_ULONG)ret); 885b37fcf3Sryker } 895b37fcf3Sryker 90913ec974Sbeck BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) 915b37fcf3Sryker { 92*4fcf65c5Sdjm BN_ULONG ret = 0; 93*4fcf65c5Sdjm int i, j; 945b37fcf3Sryker 95*4fcf65c5Sdjm bn_check_top(a); 965b37fcf3Sryker w &= BN_MASK2; 97*4fcf65c5Sdjm 98*4fcf65c5Sdjm if (!w) 99*4fcf65c5Sdjm /* actually this an error (division by zero) */ 100*4fcf65c5Sdjm return (BN_ULONG)-1; 101*4fcf65c5Sdjm if (a->top == 0) 102*4fcf65c5Sdjm return 0; 103*4fcf65c5Sdjm 104*4fcf65c5Sdjm /* normalize input (so bn_div_words doesn't complain) */ 105*4fcf65c5Sdjm j = BN_BITS2 - BN_num_bits_word(w); 106*4fcf65c5Sdjm w <<= j; 107*4fcf65c5Sdjm if (!BN_lshift(a, a, j)) 108*4fcf65c5Sdjm return (BN_ULONG)-1; 109*4fcf65c5Sdjm 1105b37fcf3Sryker for (i=a->top-1; i>=0; i--) 1115b37fcf3Sryker { 1125b37fcf3Sryker BN_ULONG l,d; 1135b37fcf3Sryker 1145b37fcf3Sryker l=a->d[i]; 115913ec974Sbeck d=bn_div_words(ret,l,w); 1165b37fcf3Sryker ret=(l-((d*w)&BN_MASK2))&BN_MASK2; 1175b37fcf3Sryker a->d[i]=d; 1185b37fcf3Sryker } 119913ec974Sbeck if ((a->top > 0) && (a->d[a->top-1] == 0)) 1205b37fcf3Sryker a->top--; 121*4fcf65c5Sdjm ret >>= j; 122*4fcf65c5Sdjm bn_check_top(a); 1235b37fcf3Sryker return(ret); 1245b37fcf3Sryker } 1255b37fcf3Sryker 126913ec974Sbeck int BN_add_word(BIGNUM *a, BN_ULONG w) 1275b37fcf3Sryker { 1285b37fcf3Sryker BN_ULONG l; 1295b37fcf3Sryker int i; 1305b37fcf3Sryker 131*4fcf65c5Sdjm bn_check_top(a); 132*4fcf65c5Sdjm w &= BN_MASK2; 133370d1fc7Sotto 134*4fcf65c5Sdjm /* degenerate case: w is zero */ 135*4fcf65c5Sdjm if (!w) return 1; 136*4fcf65c5Sdjm /* degenerate case: a is zero */ 137*4fcf65c5Sdjm if(BN_is_zero(a)) return BN_set_word(a, w); 138*4fcf65c5Sdjm /* handle 'a' when negative */ 1395b37fcf3Sryker if (a->neg) 1405b37fcf3Sryker { 1415b37fcf3Sryker a->neg=0; 1425b37fcf3Sryker i=BN_sub_word(a,w); 1435b37fcf3Sryker if (!BN_is_zero(a)) 144c109e398Sbeck a->neg=!(a->neg); 1455b37fcf3Sryker return(i); 1465b37fcf3Sryker } 147*4fcf65c5Sdjm /* Only expand (and risk failing) if it's possibly necessary */ 148*4fcf65c5Sdjm if (((BN_ULONG)(a->d[a->top - 1] + 1) == 0) && 149*4fcf65c5Sdjm (bn_wexpand(a,a->top+1) == NULL)) 150*4fcf65c5Sdjm return(0); 1515b37fcf3Sryker i=0; 1525b37fcf3Sryker for (;;) 1535b37fcf3Sryker { 154767fe2ffSmarkus if (i >= a->top) 155767fe2ffSmarkus l=w; 156767fe2ffSmarkus else 157*4fcf65c5Sdjm l=(a->d[i]+w)&BN_MASK2; 1585b37fcf3Sryker a->d[i]=l; 1595b37fcf3Sryker if (w > l) 1605b37fcf3Sryker w=1; 1615b37fcf3Sryker else 1625b37fcf3Sryker break; 1635b37fcf3Sryker i++; 1645b37fcf3Sryker } 1655b37fcf3Sryker if (i >= a->top) 1665b37fcf3Sryker a->top++; 167*4fcf65c5Sdjm bn_check_top(a); 1685b37fcf3Sryker return(1); 1695b37fcf3Sryker } 1705b37fcf3Sryker 171913ec974Sbeck int BN_sub_word(BIGNUM *a, BN_ULONG w) 1725b37fcf3Sryker { 1735b37fcf3Sryker int i; 1745b37fcf3Sryker 175*4fcf65c5Sdjm bn_check_top(a); 176*4fcf65c5Sdjm w &= BN_MASK2; 1773b996182Sotto 178*4fcf65c5Sdjm /* degenerate case: w is zero */ 179*4fcf65c5Sdjm if (!w) return 1; 180*4fcf65c5Sdjm /* degenerate case: a is zero */ 181*4fcf65c5Sdjm if(BN_is_zero(a)) 182*4fcf65c5Sdjm { 183*4fcf65c5Sdjm i = BN_set_word(a,w); 184*4fcf65c5Sdjm if (i != 0) 185*4fcf65c5Sdjm BN_set_negative(a, 1); 186*4fcf65c5Sdjm return i; 187*4fcf65c5Sdjm } 188*4fcf65c5Sdjm /* handle 'a' when negative */ 189*4fcf65c5Sdjm if (a->neg) 1905b37fcf3Sryker { 1915b37fcf3Sryker a->neg=0; 1925b37fcf3Sryker i=BN_add_word(a,w); 1935b37fcf3Sryker a->neg=1; 1945b37fcf3Sryker return(i); 1955b37fcf3Sryker } 1965b37fcf3Sryker 1975b37fcf3Sryker if ((a->top == 1) && (a->d[0] < w)) 1985b37fcf3Sryker { 1995b37fcf3Sryker a->d[0]=w-a->d[0]; 2005b37fcf3Sryker a->neg=1; 2015b37fcf3Sryker return(1); 2025b37fcf3Sryker } 2035b37fcf3Sryker i=0; 2045b37fcf3Sryker for (;;) 2055b37fcf3Sryker { 2065b37fcf3Sryker if (a->d[i] >= w) 2075b37fcf3Sryker { 2085b37fcf3Sryker a->d[i]-=w; 2095b37fcf3Sryker break; 2105b37fcf3Sryker } 2115b37fcf3Sryker else 2125b37fcf3Sryker { 2135b37fcf3Sryker a->d[i]=(a->d[i]-w)&BN_MASK2; 2145b37fcf3Sryker i++; 2155b37fcf3Sryker w=1; 2165b37fcf3Sryker } 2175b37fcf3Sryker } 2185b37fcf3Sryker if ((a->d[i] == 0) && (i == (a->top-1))) 2195b37fcf3Sryker a->top--; 220*4fcf65c5Sdjm bn_check_top(a); 2215b37fcf3Sryker return(1); 2225b37fcf3Sryker } 2235b37fcf3Sryker 224913ec974Sbeck int BN_mul_word(BIGNUM *a, BN_ULONG w) 2255b37fcf3Sryker { 2265b37fcf3Sryker BN_ULONG ll; 2275b37fcf3Sryker 228*4fcf65c5Sdjm bn_check_top(a); 2295b37fcf3Sryker w&=BN_MASK2; 2305b37fcf3Sryker if (a->top) 2315b37fcf3Sryker { 232c109e398Sbeck if (w == 0) 233c109e398Sbeck BN_zero(a); 234c109e398Sbeck else 235c109e398Sbeck { 2365b37fcf3Sryker ll=bn_mul_words(a->d,a->d,a->top,w); 2375b37fcf3Sryker if (ll) 2385b37fcf3Sryker { 2395b37fcf3Sryker if (bn_wexpand(a,a->top+1) == NULL) return(0); 2405b37fcf3Sryker a->d[a->top++]=ll; 2415b37fcf3Sryker } 2425b37fcf3Sryker } 243c109e398Sbeck } 244*4fcf65c5Sdjm bn_check_top(a); 245913ec974Sbeck return(1); 2465b37fcf3Sryker } 2475b37fcf3Sryker 248