1 
2 /***************************************************************************
3                                                                            *
4 Copyright 2012 CertiVox IOM Ltd.                                           *
5                                                                            *
6 This file is part of CertiVox MIRACL Crypto SDK.                           *
7                                                                            *
8 The CertiVox MIRACL Crypto SDK provides developers with an                 *
9 extensive and efficient set of cryptographic functions.                    *
10 For further information about its features and functionalities please      *
11 refer to http://www.certivox.com                                           *
12                                                                            *
13 * The CertiVox MIRACL Crypto SDK is free software: you can                 *
14   redistribute it and/or modify it under the terms of the                  *
15   GNU Affero General Public License as published by the                    *
16   Free Software Foundation, either version 3 of the License,               *
17   or (at your option) any later version.                                   *
18                                                                            *
19 * The CertiVox MIRACL Crypto SDK is distributed in the hope                *
20   that it will be useful, but WITHOUT ANY WARRANTY; without even the       *
21   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
22   See the GNU Affero General Public License for more details.              *
23                                                                            *
24 * You should have received a copy of the GNU Affero General Public         *
25   License along with CertiVox MIRACL Crypto SDK.                           *
26   If not, see <http://www.gnu.org/licenses/>.                              *
27                                                                            *
28 You can be released from the requirements of the license by purchasing     *
29 a commercial license. Buying such a license is mandatory as soon as you    *
30 develop commercial activities involving the CertiVox MIRACL Crypto SDK     *
31 without disclosing the source code of your own applications, or shipping   *
32 the CertiVox MIRACL Crypto SDK with a closed source product.               *
33                                                                            *
34 ***************************************************************************/
35 /*
36  *   MIRACL arithmetic routines 0 - Add and subtract routines
37  *   mrarth0.c
38  *
39  */
40 #include "miracl.h"
41 
mr_padd(_MIPD_ big x,big y,big z)42 void mr_padd(_MIPD_ big x,big y,big z)
43 { /*  add two  big numbers, z=x+y where *
44    *  x and y are positive              */
45     int i,lx,ly,lz,la;
46     mr_small carry,psum;
47     mr_small *gx,*gy,*gz;
48 #ifdef MR_OS_THREADS
49     miracl *mr_mip=get_mip();
50 #endif
51     lx = (int)x->len;
52     ly = (int)y->len;
53 
54     if (ly>lx)
55     {
56         lz=ly;
57         la=lx;
58         if (x!=z) copy(y,z);
59         else la=ly;
60     }
61     else
62     {
63         lz=lx;
64         la=ly;
65         if (y!=z) copy(x,z);
66         else la=lx;
67     }
68     carry=0;
69     z->len=lz;
70     gx=x->w; gy=y->w; gz=z->w;
71     if (lz<mr_mip->nib || !mr_mip->check) z->len++;
72 #ifndef MR_SIMPLE_BASE
73     if (mr_mip->base==0)
74     {
75 #endif
76         for (i=0;i<la;i++)
77         { /* add by columns to length of the smaller number */
78             psum=gx[i]+gy[i]+carry;
79             if (psum>gx[i]) carry=0;
80             else if (psum<gx[i]) carry=1;
81             gz[i]=psum;
82         }
83         for (;i<lz && carry>0;i++ )
84         { /* add by columns to the length of larger number (if there is a carry) */
85             psum=gx[i]+gy[i]+carry;
86             if (psum>gx[i]) carry=0;
87             else if (psum<gx[i]) carry=1;
88             gz[i]=psum;
89         }
90         if (carry)
91         { /* carry left over - possible overflow */
92             if (mr_mip->check && i>=mr_mip->nib)
93             {
94                 mr_berror(_MIPP_ MR_ERR_OVERFLOW);
95                 return;
96             }
97             gz[i]=carry;
98         }
99 #ifndef MR_SIMPLE_BASE
100     }
101     else
102     {
103         for (i=0;i<la;i++)
104         { /* add by columns */
105             psum=gx[i]+gy[i]+carry;
106             carry=0;
107             if (psum>=mr_mip->base)
108             { /* set carry */
109                 carry=1;
110                 psum-=mr_mip->base;
111             }
112             gz[i]=psum;
113         }
114         for (;i<lz && carry>0;i++)
115         {
116             psum=gx[i]+gy[i]+carry;
117             carry=0;
118             if (psum>=mr_mip->base)
119             { /* set carry */
120                 carry=1;
121                 psum-=mr_mip->base;
122             }
123             gz[i]=psum;
124         }
125         if (carry)
126         { /* carry left over - possible overflow */
127             if (mr_mip->check && i>=mr_mip->nib)
128             {
129                 mr_berror(_MIPP_ MR_ERR_OVERFLOW);
130                 return;
131             }
132             gz[i]=carry;
133         }
134     }
135 #endif
136     if (gz[z->len-1]==0) z->len--;
137 
138 }
139 
mr_psub(_MIPD_ big x,big y,big z)140 void mr_psub(_MIPD_ big x,big y,big z)
141 {  /*  subtract two big numbers z=x-y      *
142     *  where x and y are positive and x>y  */
143     int i,lx,ly;
144     mr_small borrow,pdiff;
145     mr_small *gx,*gy,*gz;
146 #ifdef MR_OS_THREADS
147     miracl *mr_mip=get_mip();
148 #endif
149     lx = (int)x->len;
150     ly = (int)y->len;
151     if (ly>lx)
152     {
153         mr_berror(_MIPP_ MR_ERR_NEG_RESULT);
154         return;
155     }
156     if (y!=z) copy(x,z);
157     else ly=lx;
158     z->len=lx;
159     gx=x->w; gy=y->w; gz=z->w;
160     borrow=0;
161 #ifndef MR_SIMPLE_BASE
162     if (mr_mip->base==0)
163     {
164 #endif
165         for (i=0;i<ly || borrow>0;i++)
166         { /* subtract by columns */
167             if (i>lx)
168             {
169                 mr_berror(_MIPP_ MR_ERR_NEG_RESULT);
170                 return;
171             }
172             pdiff=gx[i]-gy[i]-borrow;
173             if (pdiff<gx[i]) borrow=0;
174             else if (pdiff>gx[i]) borrow=1;
175             gz[i]=pdiff;
176         }
177 #ifndef MR_SIMPLE_BASE
178     }
179     else for (i=0;i<ly || borrow>0;i++)
180     { /* subtract by columns */
181         if (i>lx)
182         {
183             mr_berror(_MIPP_ MR_ERR_NEG_RESULT);
184             return;
185         }
186         pdiff=gy[i]+borrow;
187         borrow=0;
188         if (gx[i]>=pdiff) pdiff=gx[i]-pdiff;
189         else
190         { /* set borrow */
191             pdiff=mr_mip->base+gx[i]-pdiff;
192             borrow=1;
193         }
194         gz[i]=pdiff;
195     }
196 #endif
197     mr_lzero(z);
198 }
199 
mr_select(_MIPD_ big x,int d,big y,big z)200 static void mr_select(_MIPD_ big x,int d,big y,big z)
201 { /* perform required add or subtract operation */
202     int sx,sy,sz,jf,xgty;
203 #ifdef MR_FLASH
204     if (mr_notint(x) || mr_notint(y))
205     {
206         mr_berror(_MIPP_ MR_ERR_INT_OP);
207         return;
208     }
209 #endif
210     sx=exsign(x);
211     sy=exsign(y);
212     sz=0;
213     x->len&=MR_OBITS;  /* force operands to be positive */
214     y->len&=MR_OBITS;
215     xgty=mr_compare(x,y);
216     jf=(1+sx)+(1+d*sy)/2;
217     switch (jf)
218     { /* branch according to signs of operands */
219     case 0:
220         if (xgty>=0)
221             mr_padd(_MIPP_ x,y,z);
222         else
223             mr_padd(_MIPP_ y,x,z);
224         sz=MINUS;
225         break;
226     case 1:
227         if (xgty<=0)
228         {
229             mr_psub(_MIPP_ y,x,z);
230             sz=PLUS;
231         }
232         else
233         {
234             mr_psub(_MIPP_ x,y,z);
235             sz=MINUS;
236         }
237         break;
238     case 2:
239         if (xgty>=0)
240         {
241             mr_psub(_MIPP_ x,y,z);
242             sz=PLUS;
243         }
244         else
245         {
246             mr_psub(_MIPP_ y,x,z);
247             sz=MINUS;
248         }
249         break;
250     case 3:
251         if (xgty>=0)
252             mr_padd(_MIPP_ x,y,z);
253         else
254             mr_padd(_MIPP_ y,x,z);
255         sz=PLUS;
256         break;
257     }
258     if (sz<0) z->len^=MR_MSBIT;         /* set sign of result         */
259     if (x!=z && sx<0) x->len^=MR_MSBIT; /* restore signs to operands  */
260     if (y!=z && y!=x && sy<0) y->len^=MR_MSBIT;
261 }
262 
add(_MIPD_ big x,big y,big z)263 void add(_MIPD_ big x,big y,big z)
264 {  /* add two signed big numbers together z=x+y */
265 #ifdef MR_OS_THREADS
266     miracl *mr_mip=get_mip();
267 #endif
268     if (mr_mip->ERNUM) return;
269 
270     MR_IN(27)
271 
272     mr_select(_MIPP_ x,PLUS,y,z);
273 
274     MR_OUT
275 }
276 
subtract(_MIPD_ big x,big y,big z)277 void subtract(_MIPD_ big x,big y,big z)
278 { /* subtract two big signed numbers z=x-y */
279 #ifdef MR_OS_THREADS
280     miracl *mr_mip=get_mip();
281 #endif
282     if (mr_mip->ERNUM) return;
283 
284     MR_IN(28)
285 
286     mr_select(_MIPP_ x,MINUS,y,z);
287 
288     MR_OUT
289 }
290 
incr(_MIPD_ big x,int n,big z)291 void incr(_MIPD_ big x,int n,big z)
292 {  /* add int to big number: z=x+n */
293 #ifdef MR_OS_THREADS
294     miracl *mr_mip=get_mip();
295 #endif
296     if (mr_mip->ERNUM) return;
297 
298     MR_IN(7)
299 
300     convert(_MIPP_ n,mr_mip->w0);
301     mr_select(_MIPP_ x,PLUS,mr_mip->w0,z);
302 
303     MR_OUT
304 }
305 
decr(_MIPD_ big x,int n,big z)306 void decr(_MIPD_ big x,int n,big z)
307 {  /* subtract int from big number: z=x-n */
308 #ifdef MR_OS_THREADS
309     miracl *mr_mip=get_mip();
310 #endif
311     if (mr_mip->ERNUM) return;
312 
313     MR_IN(8)
314 
315     convert(_MIPP_ n,mr_mip->w0);
316     mr_select(_MIPP_ x,MINUS,mr_mip->w0,z);
317 
318     MR_OUT
319 }
320 
321