diff options
Diffstat (limited to 'src/lib/libcrypto/bn/bn_word.c')
-rw-r--r-- | src/lib/libcrypto/bn/bn_word.c | 65 |
1 files changed, 55 insertions, 10 deletions
diff --git a/src/lib/libcrypto/bn/bn_word.c b/src/lib/libcrypto/bn/bn_word.c index 988e0ca7b3..ee7b87c45c 100644 --- a/src/lib/libcrypto/bn/bn_word.c +++ b/src/lib/libcrypto/bn/bn_word.c | |||
@@ -69,6 +69,10 @@ BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) | |||
69 | #endif | 69 | #endif |
70 | int i; | 70 | int i; |
71 | 71 | ||
72 | if (w == 0) | ||
73 | return (BN_ULONG)-1; | ||
74 | |||
75 | bn_check_top(a); | ||
72 | w&=BN_MASK2; | 76 | w&=BN_MASK2; |
73 | for (i=a->top-1; i>=0; i--) | 77 | for (i=a->top-1; i>=0; i--) |
74 | { | 78 | { |
@@ -85,12 +89,24 @@ BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) | |||
85 | 89 | ||
86 | BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) | 90 | BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) |
87 | { | 91 | { |
88 | BN_ULONG ret; | 92 | BN_ULONG ret = 0; |
89 | int i; | 93 | int i, j; |
94 | |||
95 | bn_check_top(a); | ||
96 | w &= BN_MASK2; | ||
97 | |||
98 | if (!w) | ||
99 | /* actually this an error (division by zero) */ | ||
100 | return (BN_ULONG)-1; | ||
101 | if (a->top == 0) | ||
102 | return 0; | ||
103 | |||
104 | /* normalize input (so bn_div_words doesn't complain) */ | ||
105 | j = BN_BITS2 - BN_num_bits_word(w); | ||
106 | w <<= j; | ||
107 | if (!BN_lshift(a, a, j)) | ||
108 | return (BN_ULONG)-1; | ||
90 | 109 | ||
91 | if (a->top == 0) return(0); | ||
92 | ret=0; | ||
93 | w&=BN_MASK2; | ||
94 | for (i=a->top-1; i>=0; i--) | 110 | for (i=a->top-1; i>=0; i--) |
95 | { | 111 | { |
96 | BN_ULONG l,d; | 112 | BN_ULONG l,d; |
@@ -102,6 +118,8 @@ BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) | |||
102 | } | 118 | } |
103 | if ((a->top > 0) && (a->d[a->top-1] == 0)) | 119 | if ((a->top > 0) && (a->d[a->top-1] == 0)) |
104 | a->top--; | 120 | a->top--; |
121 | ret >>= j; | ||
122 | bn_check_top(a); | ||
105 | return(ret); | 123 | return(ret); |
106 | } | 124 | } |
107 | 125 | ||
@@ -110,6 +128,14 @@ int BN_add_word(BIGNUM *a, BN_ULONG w) | |||
110 | BN_ULONG l; | 128 | BN_ULONG l; |
111 | int i; | 129 | int i; |
112 | 130 | ||
131 | bn_check_top(a); | ||
132 | w &= BN_MASK2; | ||
133 | |||
134 | /* degenerate case: w is zero */ | ||
135 | if (!w) return 1; | ||
136 | /* degenerate case: a is zero */ | ||
137 | if(BN_is_zero(a)) return BN_set_word(a, w); | ||
138 | /* handle 'a' when negative */ | ||
113 | if (a->neg) | 139 | if (a->neg) |
114 | { | 140 | { |
115 | a->neg=0; | 141 | a->neg=0; |
@@ -118,15 +144,17 @@ int BN_add_word(BIGNUM *a, BN_ULONG w) | |||
118 | a->neg=!(a->neg); | 144 | a->neg=!(a->neg); |
119 | return(i); | 145 | return(i); |
120 | } | 146 | } |
121 | w&=BN_MASK2; | 147 | /* Only expand (and risk failing) if it's possibly necessary */ |
122 | if (bn_wexpand(a,a->top+1) == NULL) return(0); | 148 | if (((BN_ULONG)(a->d[a->top - 1] + 1) == 0) && |
149 | (bn_wexpand(a,a->top+1) == NULL)) | ||
150 | return(0); | ||
123 | i=0; | 151 | i=0; |
124 | for (;;) | 152 | for (;;) |
125 | { | 153 | { |
126 | if (i >= a->top) | 154 | if (i >= a->top) |
127 | l=w; | 155 | l=w; |
128 | else | 156 | else |
129 | l=(a->d[i]+(BN_ULONG)w)&BN_MASK2; | 157 | l=(a->d[i]+w)&BN_MASK2; |
130 | a->d[i]=l; | 158 | a->d[i]=l; |
131 | if (w > l) | 159 | if (w > l) |
132 | w=1; | 160 | w=1; |
@@ -136,6 +164,7 @@ int BN_add_word(BIGNUM *a, BN_ULONG w) | |||
136 | } | 164 | } |
137 | if (i >= a->top) | 165 | if (i >= a->top) |
138 | a->top++; | 166 | a->top++; |
167 | bn_check_top(a); | ||
139 | return(1); | 168 | return(1); |
140 | } | 169 | } |
141 | 170 | ||
@@ -143,7 +172,21 @@ int BN_sub_word(BIGNUM *a, BN_ULONG w) | |||
143 | { | 172 | { |
144 | int i; | 173 | int i; |
145 | 174 | ||
146 | if (BN_is_zero(a) || a->neg) | 175 | bn_check_top(a); |
176 | w &= BN_MASK2; | ||
177 | |||
178 | /* degenerate case: w is zero */ | ||
179 | if (!w) return 1; | ||
180 | /* degenerate case: a is zero */ | ||
181 | if(BN_is_zero(a)) | ||
182 | { | ||
183 | i = BN_set_word(a,w); | ||
184 | if (i != 0) | ||
185 | BN_set_negative(a, 1); | ||
186 | return i; | ||
187 | } | ||
188 | /* handle 'a' when negative */ | ||
189 | if (a->neg) | ||
147 | { | 190 | { |
148 | a->neg=0; | 191 | a->neg=0; |
149 | i=BN_add_word(a,w); | 192 | i=BN_add_word(a,w); |
@@ -151,7 +194,6 @@ int BN_sub_word(BIGNUM *a, BN_ULONG w) | |||
151 | return(i); | 194 | return(i); |
152 | } | 195 | } |
153 | 196 | ||
154 | w&=BN_MASK2; | ||
155 | if ((a->top == 1) && (a->d[0] < w)) | 197 | if ((a->top == 1) && (a->d[0] < w)) |
156 | { | 198 | { |
157 | a->d[0]=w-a->d[0]; | 199 | a->d[0]=w-a->d[0]; |
@@ -175,6 +217,7 @@ int BN_sub_word(BIGNUM *a, BN_ULONG w) | |||
175 | } | 217 | } |
176 | if ((a->d[i] == 0) && (i == (a->top-1))) | 218 | if ((a->d[i] == 0) && (i == (a->top-1))) |
177 | a->top--; | 219 | a->top--; |
220 | bn_check_top(a); | ||
178 | return(1); | 221 | return(1); |
179 | } | 222 | } |
180 | 223 | ||
@@ -182,6 +225,7 @@ int BN_mul_word(BIGNUM *a, BN_ULONG w) | |||
182 | { | 225 | { |
183 | BN_ULONG ll; | 226 | BN_ULONG ll; |
184 | 227 | ||
228 | bn_check_top(a); | ||
185 | w&=BN_MASK2; | 229 | w&=BN_MASK2; |
186 | if (a->top) | 230 | if (a->top) |
187 | { | 231 | { |
@@ -197,6 +241,7 @@ int BN_mul_word(BIGNUM *a, BN_ULONG w) | |||
197 | } | 241 | } |
198 | } | 242 | } |
199 | } | 243 | } |
244 | bn_check_top(a); | ||
200 | return(1); | 245 | return(1); |
201 | } | 246 | } |
202 | 247 | ||