diff options
-rw-r--r-- | lib/mpi/generic_mpih-add1.c | 61 | ||||
-rw-r--r-- | lib/mpi/generic_mpih-lshift.c | 63 | ||||
-rw-r--r-- | lib/mpi/generic_mpih-mul1.c | 57 | ||||
-rw-r--r-- | lib/mpi/generic_mpih-mul2.c | 60 | ||||
-rw-r--r-- | lib/mpi/generic_mpih-mul3.c | 61 | ||||
-rw-r--r-- | lib/mpi/generic_mpih-rshift.c | 63 | ||||
-rw-r--r-- | lib/mpi/generic_mpih-sub1.c | 60 | ||||
-rw-r--r-- | lib/mpi/mpi-bit.c | 236 | ||||
-rw-r--r-- | lib/mpi/mpi-pow.c | 323 | ||||
-rw-r--r-- | lib/mpi/mpicoder.c | 365 | ||||
-rw-r--r-- | lib/mpi/mpih-cmp.c | 56 | ||||
-rw-r--r-- | lib/mpi/mpih-div.c | 541 | ||||
-rw-r--r-- | lib/mpi/mpih-mul.c | 527 | ||||
-rw-r--r-- | lib/mpi/mpiutil.c | 208 |
14 files changed, 2681 insertions, 0 deletions
diff --git a/lib/mpi/generic_mpih-add1.c b/lib/mpi/generic_mpih-add1.c new file mode 100644 index 000000000000..c94c7dd344b3 --- /dev/null +++ b/lib/mpi/generic_mpih-add1.c | |||
@@ -0,0 +1,61 @@ | |||
1 | /* mpihelp-add_1.c - MPI helper functions | ||
2 | * Copyright (C) 1994, 1996, 1997, 1998, | ||
3 | * 2000 Free Software Foundation, Inc. | ||
4 | * | ||
5 | * This file is part of GnuPG. | ||
6 | * | ||
7 | * GnuPG is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * GnuPG is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | ||
20 | * | ||
21 | * Note: This code is heavily based on the GNU MP Library. | ||
22 | * Actually it's the same code with only minor changes in the | ||
23 | * way the data is stored; this is to support the abstraction | ||
24 | * of an optional secure memory allocation which may be used | ||
25 | * to avoid revealing of sensitive data due to paging etc. | ||
26 | * The GNU MP Library itself is published under the LGPL; | ||
27 | * however I decided to publish this code under the plain GPL. | ||
28 | */ | ||
29 | |||
30 | #include "mpi-internal.h" | ||
31 | #include "longlong.h" | ||
32 | |||
33 | mpi_limb_t | ||
34 | mpihelp_add_n(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, | ||
35 | mpi_ptr_t s2_ptr, mpi_size_t size) | ||
36 | { | ||
37 | mpi_limb_t x, y, cy; | ||
38 | mpi_size_t j; | ||
39 | |||
40 | /* The loop counter and index J goes from -SIZE to -1. This way | ||
41 | the loop becomes faster. */ | ||
42 | j = -size; | ||
43 | |||
44 | /* Offset the base pointers to compensate for the negative indices. */ | ||
45 | s1_ptr -= j; | ||
46 | s2_ptr -= j; | ||
47 | res_ptr -= j; | ||
48 | |||
49 | cy = 0; | ||
50 | do { | ||
51 | y = s2_ptr[j]; | ||
52 | x = s1_ptr[j]; | ||
53 | y += cy; /* add previous carry to one addend */ | ||
54 | cy = y < cy; /* get out carry from that addition */ | ||
55 | y += x; /* add other addend */ | ||
56 | cy += y < x; /* get out carry from that add, combine */ | ||
57 | res_ptr[j] = y; | ||
58 | } while (++j); | ||
59 | |||
60 | return cy; | ||
61 | } | ||
diff --git a/lib/mpi/generic_mpih-lshift.c b/lib/mpi/generic_mpih-lshift.c new file mode 100644 index 000000000000..86318927231a --- /dev/null +++ b/lib/mpi/generic_mpih-lshift.c | |||
@@ -0,0 +1,63 @@ | |||
1 | /* mpihelp-lshift.c - MPI helper functions | ||
2 | * Copyright (C) 1994, 1996, 1998, 2001 Free Software Foundation, Inc. | ||
3 | * | ||
4 | * This file is part of GnuPG. | ||
5 | * | ||
6 | * GnuPG is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * GnuPG is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | ||
19 | * | ||
20 | * Note: This code is heavily based on the GNU MP Library. | ||
21 | * Actually it's the same code with only minor changes in the | ||
22 | * way the data is stored; this is to support the abstraction | ||
23 | * of an optional secure memory allocation which may be used | ||
24 | * to avoid revealing of sensitive data due to paging etc. | ||
25 | * The GNU MP Library itself is published under the LGPL; | ||
26 | * however I decided to publish this code under the plain GPL. | ||
27 | */ | ||
28 | |||
29 | #include "mpi-internal.h" | ||
30 | |||
31 | /* Shift U (pointed to by UP and USIZE digits long) CNT bits to the left | ||
32 | * and store the USIZE least significant digits of the result at WP. | ||
33 | * Return the bits shifted out from the most significant digit. | ||
34 | * | ||
35 | * Argument constraints: | ||
36 | * 1. 0 < CNT < BITS_PER_MP_LIMB | ||
37 | * 2. If the result is to be written over the input, WP must be >= UP. | ||
38 | */ | ||
39 | |||
40 | mpi_limb_t | ||
41 | mpihelp_lshift(mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, unsigned int cnt) | ||
42 | { | ||
43 | mpi_limb_t high_limb, low_limb; | ||
44 | unsigned sh_1, sh_2; | ||
45 | mpi_size_t i; | ||
46 | mpi_limb_t retval; | ||
47 | |||
48 | sh_1 = cnt; | ||
49 | wp += 1; | ||
50 | sh_2 = BITS_PER_MPI_LIMB - sh_1; | ||
51 | i = usize - 1; | ||
52 | low_limb = up[i]; | ||
53 | retval = low_limb >> sh_2; | ||
54 | high_limb = low_limb; | ||
55 | while (--i >= 0) { | ||
56 | low_limb = up[i]; | ||
57 | wp[i] = (high_limb << sh_1) | (low_limb >> sh_2); | ||
58 | high_limb = low_limb; | ||
59 | } | ||
60 | wp[i] = high_limb << sh_1; | ||
61 | |||
62 | return retval; | ||
63 | } | ||
diff --git a/lib/mpi/generic_mpih-mul1.c b/lib/mpi/generic_mpih-mul1.c new file mode 100644 index 000000000000..1668dfd9092c --- /dev/null +++ b/lib/mpi/generic_mpih-mul1.c | |||
@@ -0,0 +1,57 @@ | |||
1 | /* mpihelp-mul_1.c - MPI helper functions | ||
2 | * Copyright (C) 1994, 1996, 1997, 1998, 2001 Free Software Foundation, Inc. | ||
3 | * | ||
4 | * This file is part of GnuPG. | ||
5 | * | ||
6 | * GnuPG is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * GnuPG is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | ||
19 | * | ||
20 | * Note: This code is heavily based on the GNU MP Library. | ||
21 | * Actually it's the same code with only minor changes in the | ||
22 | * way the data is stored; this is to support the abstraction | ||
23 | * of an optional secure memory allocation which may be used | ||
24 | * to avoid revealing of sensitive data due to paging etc. | ||
25 | * The GNU MP Library itself is published under the LGPL; | ||
26 | * however I decided to publish this code under the plain GPL. | ||
27 | */ | ||
28 | |||
29 | #include "mpi-internal.h" | ||
30 | #include "longlong.h" | ||
31 | |||
32 | mpi_limb_t | ||
33 | mpihelp_mul_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, | ||
34 | mpi_limb_t s2_limb) | ||
35 | { | ||
36 | mpi_limb_t cy_limb; | ||
37 | mpi_size_t j; | ||
38 | mpi_limb_t prod_high, prod_low; | ||
39 | |||
40 | /* The loop counter and index J goes from -S1_SIZE to -1. This way | ||
41 | * the loop becomes faster. */ | ||
42 | j = -s1_size; | ||
43 | |||
44 | /* Offset the base pointers to compensate for the negative indices. */ | ||
45 | s1_ptr -= j; | ||
46 | res_ptr -= j; | ||
47 | |||
48 | cy_limb = 0; | ||
49 | do { | ||
50 | umul_ppmm(prod_high, prod_low, s1_ptr[j], s2_limb); | ||
51 | prod_low += cy_limb; | ||
52 | cy_limb = (prod_low < cy_limb ? 1 : 0) + prod_high; | ||
53 | res_ptr[j] = prod_low; | ||
54 | } while (++j); | ||
55 | |||
56 | return cy_limb; | ||
57 | } | ||
diff --git a/lib/mpi/generic_mpih-mul2.c b/lib/mpi/generic_mpih-mul2.c new file mode 100644 index 000000000000..8a7b29ee1740 --- /dev/null +++ b/lib/mpi/generic_mpih-mul2.c | |||
@@ -0,0 +1,60 @@ | |||
1 | /* mpihelp-mul_2.c - MPI helper functions | ||
2 | * Copyright (C) 1994, 1996, 1997, 1998, 2001 Free Software Foundation, Inc. | ||
3 | * | ||
4 | * This file is part of GnuPG. | ||
5 | * | ||
6 | * GnuPG is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * GnuPG is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | ||
19 | * | ||
20 | * Note: This code is heavily based on the GNU MP Library. | ||
21 | * Actually it's the same code with only minor changes in the | ||
22 | * way the data is stored; this is to support the abstraction | ||
23 | * of an optional secure memory allocation which may be used | ||
24 | * to avoid revealing of sensitive data due to paging etc. | ||
25 | * The GNU MP Library itself is published under the LGPL; | ||
26 | * however I decided to publish this code under the plain GPL. | ||
27 | */ | ||
28 | |||
29 | #include "mpi-internal.h" | ||
30 | #include "longlong.h" | ||
31 | |||
32 | mpi_limb_t | ||
33 | mpihelp_addmul_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, | ||
34 | mpi_size_t s1_size, mpi_limb_t s2_limb) | ||
35 | { | ||
36 | mpi_limb_t cy_limb; | ||
37 | mpi_size_t j; | ||
38 | mpi_limb_t prod_high, prod_low; | ||
39 | mpi_limb_t x; | ||
40 | |||
41 | /* The loop counter and index J goes from -SIZE to -1. This way | ||
42 | * the loop becomes faster. */ | ||
43 | j = -s1_size; | ||
44 | res_ptr -= j; | ||
45 | s1_ptr -= j; | ||
46 | |||
47 | cy_limb = 0; | ||
48 | do { | ||
49 | umul_ppmm(prod_high, prod_low, s1_ptr[j], s2_limb); | ||
50 | |||
51 | prod_low += cy_limb; | ||
52 | cy_limb = (prod_low < cy_limb ? 1 : 0) + prod_high; | ||
53 | |||
54 | x = res_ptr[j]; | ||
55 | prod_low = x + prod_low; | ||
56 | cy_limb += prod_low < x ? 1 : 0; | ||
57 | res_ptr[j] = prod_low; | ||
58 | } while (++j); | ||
59 | return cy_limb; | ||
60 | } | ||
diff --git a/lib/mpi/generic_mpih-mul3.c b/lib/mpi/generic_mpih-mul3.c new file mode 100644 index 000000000000..f96df327be63 --- /dev/null +++ b/lib/mpi/generic_mpih-mul3.c | |||
@@ -0,0 +1,61 @@ | |||
1 | /* mpihelp-mul_3.c - MPI helper functions | ||
2 | * Copyright (C) 1994, 1996, 1997, 1998, 2001 Free Software Foundation, Inc. | ||
3 | * | ||
4 | * This file is part of GnuPG. | ||
5 | * | ||
6 | * GnuPG is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * GnuPG is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | ||
19 | * | ||
20 | * Note: This code is heavily based on the GNU MP Library. | ||
21 | * Actually it's the same code with only minor changes in the | ||
22 | * way the data is stored; this is to support the abstraction | ||
23 | * of an optional secure memory allocation which may be used | ||
24 | * to avoid revealing of sensitive data due to paging etc. | ||
25 | * The GNU MP Library itself is published under the LGPL; | ||
26 | * however I decided to publish this code under the plain GPL. | ||
27 | */ | ||
28 | |||
29 | #include "mpi-internal.h" | ||
30 | #include "longlong.h" | ||
31 | |||
32 | mpi_limb_t | ||
33 | mpihelp_submul_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, | ||
34 | mpi_size_t s1_size, mpi_limb_t s2_limb) | ||
35 | { | ||
36 | mpi_limb_t cy_limb; | ||
37 | mpi_size_t j; | ||
38 | mpi_limb_t prod_high, prod_low; | ||
39 | mpi_limb_t x; | ||
40 | |||
41 | /* The loop counter and index J goes from -SIZE to -1. This way | ||
42 | * the loop becomes faster. */ | ||
43 | j = -s1_size; | ||
44 | res_ptr -= j; | ||
45 | s1_ptr -= j; | ||
46 | |||
47 | cy_limb = 0; | ||
48 | do { | ||
49 | umul_ppmm(prod_high, prod_low, s1_ptr[j], s2_limb); | ||
50 | |||
51 | prod_low += cy_limb; | ||
52 | cy_limb = (prod_low < cy_limb ? 1 : 0) + prod_high; | ||
53 | |||
54 | x = res_ptr[j]; | ||
55 | prod_low = x - prod_low; | ||
56 | cy_limb += prod_low > x ? 1 : 0; | ||
57 | res_ptr[j] = prod_low; | ||
58 | } while (++j); | ||
59 | |||
60 | return cy_limb; | ||
61 | } | ||
diff --git a/lib/mpi/generic_mpih-rshift.c b/lib/mpi/generic_mpih-rshift.c new file mode 100644 index 000000000000..ffa328818ca6 --- /dev/null +++ b/lib/mpi/generic_mpih-rshift.c | |||
@@ -0,0 +1,63 @@ | |||
1 | /* mpih-rshift.c - MPI helper functions | ||
2 | * Copyright (C) 1994, 1996, 1998, 1999, | ||
3 | * 2000, 2001 Free Software Foundation, Inc. | ||
4 | * | ||
5 | * This file is part of GNUPG | ||
6 | * | ||
7 | * GNUPG is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * GNUPG is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | ||
20 | * | ||
21 | * Note: This code is heavily based on the GNU MP Library. | ||
22 | * Actually it's the same code with only minor changes in the | ||
23 | * way the data is stored; this is to support the abstraction | ||
24 | * of an optional secure memory allocation which may be used | ||
25 | * to avoid revealing of sensitive data due to paging etc. | ||
26 | * The GNU MP Library itself is published under the LGPL; | ||
27 | * however I decided to publish this code under the plain GPL. | ||
28 | */ | ||
29 | |||
30 | #include "mpi-internal.h" | ||
31 | |||
32 | /* Shift U (pointed to by UP and USIZE limbs long) CNT bits to the right | ||
33 | * and store the USIZE least significant limbs of the result at WP. | ||
34 | * The bits shifted out to the right are returned. | ||
35 | * | ||
36 | * Argument constraints: | ||
37 | * 1. 0 < CNT < BITS_PER_MP_LIMB | ||
38 | * 2. If the result is to be written over the input, WP must be <= UP. | ||
39 | */ | ||
40 | |||
41 | mpi_limb_t | ||
42 | mpihelp_rshift(mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, unsigned cnt) | ||
43 | { | ||
44 | mpi_limb_t high_limb, low_limb; | ||
45 | unsigned sh_1, sh_2; | ||
46 | mpi_size_t i; | ||
47 | mpi_limb_t retval; | ||
48 | |||
49 | sh_1 = cnt; | ||
50 | wp -= 1; | ||
51 | sh_2 = BITS_PER_MPI_LIMB - sh_1; | ||
52 | high_limb = up[0]; | ||
53 | retval = high_limb << sh_2; | ||
54 | low_limb = high_limb; | ||
55 | for (i = 1; i < usize; i++) { | ||
56 | high_limb = up[i]; | ||
57 | wp[i] = (low_limb >> sh_1) | (high_limb << sh_2); | ||
58 | low_limb = high_limb; | ||
59 | } | ||
60 | wp[i] = low_limb >> sh_1; | ||
61 | |||
62 | return retval; | ||
63 | } | ||
diff --git a/lib/mpi/generic_mpih-sub1.c b/lib/mpi/generic_mpih-sub1.c new file mode 100644 index 000000000000..5d98ab7d6853 --- /dev/null +++ b/lib/mpi/generic_mpih-sub1.c | |||
@@ -0,0 +1,60 @@ | |||
1 | /* mpihelp-add_2.c - MPI helper functions | ||
2 | * Copyright (C) 1994, 1996, 1997, 1998, 2001 Free Software Foundation, Inc. | ||
3 | * | ||
4 | * This file is part of GnuPG. | ||
5 | * | ||
6 | * GnuPG is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * GnuPG is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | ||
19 | * | ||
20 | * Note: This code is heavily based on the GNU MP Library. | ||
21 | * Actually it's the same code with only minor changes in the | ||
22 | * way the data is stored; this is to support the abstraction | ||
23 | * of an optional secure memory allocation which may be used | ||
24 | * to avoid revealing of sensitive data due to paging etc. | ||
25 | * The GNU MP Library itself is published under the LGPL; | ||
26 | * however I decided to publish this code under the plain GPL. | ||
27 | */ | ||
28 | |||
29 | #include "mpi-internal.h" | ||
30 | #include "longlong.h" | ||
31 | |||
32 | mpi_limb_t | ||
33 | mpihelp_sub_n(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, | ||
34 | mpi_ptr_t s2_ptr, mpi_size_t size) | ||
35 | { | ||
36 | mpi_limb_t x, y, cy; | ||
37 | mpi_size_t j; | ||
38 | |||
39 | /* The loop counter and index J goes from -SIZE to -1. This way | ||
40 | the loop becomes faster. */ | ||
41 | j = -size; | ||
42 | |||
43 | /* Offset the base pointers to compensate for the negative indices. */ | ||
44 | s1_ptr -= j; | ||
45 | s2_ptr -= j; | ||
46 | res_ptr -= j; | ||
47 | |||
48 | cy = 0; | ||
49 | do { | ||
50 | y = s2_ptr[j]; | ||
51 | x = s1_ptr[j]; | ||
52 | y += cy; /* add previous carry to subtrahend */ | ||
53 | cy = y < cy; /* get out carry from that addition */ | ||
54 | y = x - y; /* main subtract */ | ||
55 | cy += y > x; /* get out carry from the subtract, combine */ | ||
56 | res_ptr[j] = y; | ||
57 | } while (++j); | ||
58 | |||
59 | return cy; | ||
60 | } | ||
diff --git a/lib/mpi/mpi-bit.c b/lib/mpi/mpi-bit.c new file mode 100644 index 000000000000..854c9c6da025 --- /dev/null +++ b/lib/mpi/mpi-bit.c | |||
@@ -0,0 +1,236 @@ | |||
1 | /* mpi-bit.c - MPI bit level fucntions | ||
2 | * Copyright (C) 1998, 1999 Free Software Foundation, Inc. | ||
3 | * | ||
4 | * This file is part of GnuPG. | ||
5 | * | ||
6 | * GnuPG is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * GnuPG is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | ||
19 | */ | ||
20 | |||
21 | #include "mpi-internal.h" | ||
22 | #include "longlong.h" | ||
23 | |||
24 | const unsigned char __clz_tab[] = { | ||
25 | 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, | ||
26 | 5, 5, 5, 5, 5, 5, 5, 5, | ||
27 | 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, | ||
28 | 6, 6, 6, 6, 6, 6, 6, 6, | ||
29 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
30 | 7, 7, 7, 7, 7, 7, 7, 7, | ||
31 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
32 | 7, 7, 7, 7, 7, 7, 7, 7, | ||
33 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, | ||
34 | 8, 8, 8, 8, 8, 8, 8, 8, | ||
35 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, | ||
36 | 8, 8, 8, 8, 8, 8, 8, 8, | ||
37 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, | ||
38 | 8, 8, 8, 8, 8, 8, 8, 8, | ||
39 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, | ||
40 | 8, 8, 8, 8, 8, 8, 8, 8, | ||
41 | }; | ||
42 | |||
43 | #define A_LIMB_1 ((mpi_limb_t) 1) | ||
44 | |||
45 | /**************** | ||
46 | * Sometimes we have MSL (most significant limbs) which are 0; | ||
47 | * this is for some reasons not good, so this function removes them. | ||
48 | */ | ||
49 | void mpi_normalize(MPI a) | ||
50 | { | ||
51 | for (; a->nlimbs && !a->d[a->nlimbs - 1]; a->nlimbs--) | ||
52 | ; | ||
53 | } | ||
54 | |||
55 | /**************** | ||
56 | * Return the number of bits in A. | ||
57 | */ | ||
58 | unsigned mpi_get_nbits(MPI a) | ||
59 | { | ||
60 | unsigned n; | ||
61 | |||
62 | mpi_normalize(a); | ||
63 | |||
64 | if (a->nlimbs) { | ||
65 | mpi_limb_t alimb = a->d[a->nlimbs - 1]; | ||
66 | if (alimb) | ||
67 | count_leading_zeros(n, alimb); | ||
68 | else | ||
69 | n = BITS_PER_MPI_LIMB; | ||
70 | n = BITS_PER_MPI_LIMB - n + (a->nlimbs - 1) * BITS_PER_MPI_LIMB; | ||
71 | } else | ||
72 | n = 0; | ||
73 | return n; | ||
74 | } | ||
75 | EXPORT_SYMBOL_GPL(mpi_get_nbits); | ||
76 | |||
77 | /**************** | ||
78 | * Test whether bit N is set. | ||
79 | */ | ||
80 | int mpi_test_bit(MPI a, unsigned n) | ||
81 | { | ||
82 | unsigned limbno, bitno; | ||
83 | mpi_limb_t limb; | ||
84 | |||
85 | limbno = n / BITS_PER_MPI_LIMB; | ||
86 | bitno = n % BITS_PER_MPI_LIMB; | ||
87 | |||
88 | if (limbno >= a->nlimbs) | ||
89 | return 0; /* too far left: this is a 0 */ | ||
90 | limb = a->d[limbno]; | ||
91 | return (limb & (A_LIMB_1 << bitno)) ? 1 : 0; | ||
92 | } | ||
93 | |||
94 | /**************** | ||
95 | * Set bit N of A. | ||
96 | */ | ||
97 | int mpi_set_bit(MPI a, unsigned n) | ||
98 | { | ||
99 | unsigned limbno, bitno; | ||
100 | |||
101 | limbno = n / BITS_PER_MPI_LIMB; | ||
102 | bitno = n % BITS_PER_MPI_LIMB; | ||
103 | |||
104 | if (limbno >= a->nlimbs) { /* resize */ | ||
105 | if (a->alloced >= limbno) | ||
106 | if (mpi_resize(a, limbno + 1) < 0) | ||
107 | return -ENOMEM; | ||
108 | a->nlimbs = limbno + 1; | ||
109 | } | ||
110 | a->d[limbno] |= (A_LIMB_1 << bitno); | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | /**************** | ||
115 | * Set bit N of A. and clear all bits above | ||
116 | */ | ||
117 | int mpi_set_highbit(MPI a, unsigned n) | ||
118 | { | ||
119 | unsigned limbno, bitno; | ||
120 | |||
121 | limbno = n / BITS_PER_MPI_LIMB; | ||
122 | bitno = n % BITS_PER_MPI_LIMB; | ||
123 | |||
124 | if (limbno >= a->nlimbs) { /* resize */ | ||
125 | if (a->alloced >= limbno) | ||
126 | if (mpi_resize(a, limbno + 1) < 0) | ||
127 | return -ENOMEM; | ||
128 | a->nlimbs = limbno + 1; | ||
129 | } | ||
130 | a->d[limbno] |= (A_LIMB_1 << bitno); | ||
131 | for (bitno++; bitno < BITS_PER_MPI_LIMB; bitno++) | ||
132 | a->d[limbno] &= ~(A_LIMB_1 << bitno); | ||
133 | a->nlimbs = limbno + 1; | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | /**************** | ||
138 | * clear bit N of A and all bits above | ||
139 | */ | ||
140 | void mpi_clear_highbit(MPI a, unsigned n) | ||
141 | { | ||
142 | unsigned limbno, bitno; | ||
143 | |||
144 | limbno = n / BITS_PER_MPI_LIMB; | ||
145 | bitno = n % BITS_PER_MPI_LIMB; | ||
146 | |||
147 | if (limbno >= a->nlimbs) | ||
148 | return; /* not allocated, so need to clear bits :-) */ | ||
149 | |||
150 | for (; bitno < BITS_PER_MPI_LIMB; bitno++) | ||
151 | a->d[limbno] &= ~(A_LIMB_1 << bitno); | ||
152 | a->nlimbs = limbno + 1; | ||
153 | } | ||
154 | |||
155 | /**************** | ||
156 | * Clear bit N of A. | ||
157 | */ | ||
158 | void mpi_clear_bit(MPI a, unsigned n) | ||
159 | { | ||
160 | unsigned limbno, bitno; | ||
161 | |||
162 | limbno = n / BITS_PER_MPI_LIMB; | ||
163 | bitno = n % BITS_PER_MPI_LIMB; | ||
164 | |||
165 | if (limbno >= a->nlimbs) | ||
166 | return; /* don't need to clear this bit, it's to far to left */ | ||
167 | a->d[limbno] &= ~(A_LIMB_1 << bitno); | ||
168 | } | ||
169 | |||
170 | /**************** | ||
171 | * Shift A by N bits to the right | ||
172 | * FIXME: should use alloc_limb if X and A are same. | ||
173 | */ | ||
174 | int mpi_rshift(MPI x, MPI a, unsigned n) | ||
175 | { | ||
176 | mpi_ptr_t xp; | ||
177 | mpi_size_t xsize; | ||
178 | |||
179 | xsize = a->nlimbs; | ||
180 | x->sign = a->sign; | ||
181 | if (RESIZE_IF_NEEDED(x, (size_t) xsize) < 0) | ||
182 | return -ENOMEM; | ||
183 | xp = x->d; | ||
184 | |||
185 | if (xsize) { | ||
186 | mpihelp_rshift(xp, a->d, xsize, n); | ||
187 | MPN_NORMALIZE(xp, xsize); | ||
188 | } | ||
189 | x->nlimbs = xsize; | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | /**************** | ||
194 | * Shift A by COUNT limbs to the left | ||
195 | * This is used only within the MPI library | ||
196 | */ | ||
197 | int mpi_lshift_limbs(MPI a, unsigned int count) | ||
198 | { | ||
199 | mpi_ptr_t ap = a->d; | ||
200 | int n = a->nlimbs; | ||
201 | int i; | ||
202 | |||
203 | if (!count || !n) | ||
204 | return 0; | ||
205 | |||
206 | if (RESIZE_IF_NEEDED(a, n + count) < 0) | ||
207 | return -ENOMEM; | ||
208 | |||
209 | for (i = n - 1; i >= 0; i--) | ||
210 | ap[i + count] = ap[i]; | ||
211 | for (i = 0; i < count; i++) | ||
212 | ap[i] = 0; | ||
213 | a->nlimbs += count; | ||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | /**************** | ||
218 | * Shift A by COUNT limbs to the right | ||
219 | * This is used only within the MPI library | ||
220 | */ | ||
221 | void mpi_rshift_limbs(MPI a, unsigned int count) | ||
222 | { | ||
223 | mpi_ptr_t ap = a->d; | ||
224 | mpi_size_t n = a->nlimbs; | ||
225 | unsigned int i; | ||
226 | |||
227 | if (count >= n) { | ||
228 | a->nlimbs = 0; | ||
229 | return; | ||
230 | } | ||
231 | |||
232 | for (i = 0; i < n - count; i++) | ||
233 | ap[i] = ap[i + count]; | ||
234 | ap[i] = 0; | ||
235 | a->nlimbs -= count; | ||
236 | } | ||
diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c new file mode 100644 index 000000000000..b04a3cf80080 --- /dev/null +++ b/lib/mpi/mpi-pow.c | |||
@@ -0,0 +1,323 @@ | |||
1 | /* mpi-pow.c - MPI functions | ||
2 | * Copyright (C) 1994, 1996, 1998, 2000 Free Software Foundation, Inc. | ||
3 | * | ||
4 | * This file is part of GnuPG. | ||
5 | * | ||
6 | * GnuPG is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * GnuPG is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | ||
19 | * | ||
20 | * Note: This code is heavily based on the GNU MP Library. | ||
21 | * Actually it's the same code with only minor changes in the | ||
22 | * way the data is stored; this is to support the abstraction | ||
23 | * of an optional secure memory allocation which may be used | ||
24 | * to avoid revealing of sensitive data due to paging etc. | ||
25 | * The GNU MP Library itself is published under the LGPL; | ||
26 | * however I decided to publish this code under the plain GPL. | ||
27 | */ | ||
28 | |||
29 | #include <linux/string.h> | ||
30 | #include "mpi-internal.h" | ||
31 | #include "longlong.h" | ||
32 | |||
33 | /**************** | ||
34 | * RES = BASE ^ EXP mod MOD | ||
35 | */ | ||
36 | int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) | ||
37 | { | ||
38 | mpi_ptr_t mp_marker = NULL, bp_marker = NULL, ep_marker = NULL; | ||
39 | mpi_ptr_t xp_marker = NULL; | ||
40 | mpi_ptr_t tspace = NULL; | ||
41 | mpi_ptr_t rp, ep, mp, bp; | ||
42 | mpi_size_t esize, msize, bsize, rsize; | ||
43 | int esign, msign, bsign, rsign; | ||
44 | mpi_size_t size; | ||
45 | int mod_shift_cnt; | ||
46 | int negative_result; | ||
47 | int assign_rp = 0; | ||
48 | mpi_size_t tsize = 0; /* to avoid compiler warning */ | ||
49 | /* fixme: we should check that the warning is void */ | ||
50 | int rc = -ENOMEM; | ||
51 | |||
52 | esize = exp->nlimbs; | ||
53 | msize = mod->nlimbs; | ||
54 | size = 2 * msize; | ||
55 | esign = exp->sign; | ||
56 | msign = mod->sign; | ||
57 | |||
58 | rp = res->d; | ||
59 | ep = exp->d; | ||
60 | |||
61 | if (!msize) | ||
62 | msize = 1 / msize; /* provoke a signal */ | ||
63 | |||
64 | if (!esize) { | ||
65 | /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0 | ||
66 | * depending on if MOD equals 1. */ | ||
67 | rp[0] = 1; | ||
68 | res->nlimbs = (msize == 1 && mod->d[0] == 1) ? 0 : 1; | ||
69 | res->sign = 0; | ||
70 | goto leave; | ||
71 | } | ||
72 | |||
73 | /* Normalize MOD (i.e. make its most significant bit set) as required by | ||
74 | * mpn_divrem. This will make the intermediate values in the calculation | ||
75 | * slightly larger, but the correct result is obtained after a final | ||
76 | * reduction using the original MOD value. */ | ||
77 | mp = mp_marker = mpi_alloc_limb_space(msize); | ||
78 | if (!mp) | ||
79 | goto enomem; | ||
80 | count_leading_zeros(mod_shift_cnt, mod->d[msize - 1]); | ||
81 | if (mod_shift_cnt) | ||
82 | mpihelp_lshift(mp, mod->d, msize, mod_shift_cnt); | ||
83 | else | ||
84 | MPN_COPY(mp, mod->d, msize); | ||
85 | |||
86 | bsize = base->nlimbs; | ||
87 | bsign = base->sign; | ||
88 | if (bsize > msize) { /* The base is larger than the module. Reduce it. */ | ||
89 | /* Allocate (BSIZE + 1) with space for remainder and quotient. | ||
90 | * (The quotient is (bsize - msize + 1) limbs.) */ | ||
91 | bp = bp_marker = mpi_alloc_limb_space(bsize + 1); | ||
92 | if (!bp) | ||
93 | goto enomem; | ||
94 | MPN_COPY(bp, base->d, bsize); | ||
95 | /* We don't care about the quotient, store it above the remainder, | ||
96 | * at BP + MSIZE. */ | ||
97 | mpihelp_divrem(bp + msize, 0, bp, bsize, mp, msize); | ||
98 | bsize = msize; | ||
99 | /* Canonicalize the base, since we are going to multiply with it | ||
100 | * quite a few times. */ | ||
101 | MPN_NORMALIZE(bp, bsize); | ||
102 | } else | ||
103 | bp = base->d; | ||
104 | |||
105 | if (!bsize) { | ||
106 | res->nlimbs = 0; | ||
107 | res->sign = 0; | ||
108 | goto leave; | ||
109 | } | ||
110 | |||
111 | if (res->alloced < size) { | ||
112 | /* We have to allocate more space for RES. If any of the input | ||
113 | * parameters are identical to RES, defer deallocation of the old | ||
114 | * space. */ | ||
115 | if (rp == ep || rp == mp || rp == bp) { | ||
116 | rp = mpi_alloc_limb_space(size); | ||
117 | if (!rp) | ||
118 | goto enomem; | ||
119 | assign_rp = 1; | ||
120 | } else { | ||
121 | if (mpi_resize(res, size) < 0) | ||
122 | goto enomem; | ||
123 | rp = res->d; | ||
124 | } | ||
125 | } else { /* Make BASE, EXP and MOD not overlap with RES. */ | ||
126 | if (rp == bp) { | ||
127 | /* RES and BASE are identical. Allocate temp. space for BASE. */ | ||
128 | BUG_ON(bp_marker); | ||
129 | bp = bp_marker = mpi_alloc_limb_space(bsize); | ||
130 | if (!bp) | ||
131 | goto enomem; | ||
132 | MPN_COPY(bp, rp, bsize); | ||
133 | } | ||
134 | if (rp == ep) { | ||
135 | /* RES and EXP are identical. Allocate temp. space for EXP. */ | ||
136 | ep = ep_marker = mpi_alloc_limb_space(esize); | ||
137 | if (!ep) | ||
138 | goto enomem; | ||
139 | MPN_COPY(ep, rp, esize); | ||
140 | } | ||
141 | if (rp == mp) { | ||
142 | /* RES and MOD are identical. Allocate temporary space for MOD. */ | ||
143 | BUG_ON(mp_marker); | ||
144 | mp = mp_marker = mpi_alloc_limb_space(msize); | ||
145 | if (!mp) | ||
146 | goto enomem; | ||
147 | MPN_COPY(mp, rp, msize); | ||
148 | } | ||
149 | } | ||
150 | |||
151 | MPN_COPY(rp, bp, bsize); | ||
152 | rsize = bsize; | ||
153 | rsign = bsign; | ||
154 | |||
155 | { | ||
156 | mpi_size_t i; | ||
157 | mpi_ptr_t xp; | ||
158 | int c; | ||
159 | mpi_limb_t e; | ||
160 | mpi_limb_t carry_limb; | ||
161 | struct karatsuba_ctx karactx; | ||
162 | |||
163 | xp = xp_marker = mpi_alloc_limb_space(2 * (msize + 1)); | ||
164 | if (!xp) | ||
165 | goto enomem; | ||
166 | |||
167 | memset(&karactx, 0, sizeof karactx); | ||
168 | negative_result = (ep[0] & 1) && base->sign; | ||
169 | |||
170 | i = esize - 1; | ||
171 | e = ep[i]; | ||
172 | count_leading_zeros(c, e); | ||
173 | e = (e << c) << 1; /* shift the exp bits to the left, lose msb */ | ||
174 | c = BITS_PER_MPI_LIMB - 1 - c; | ||
175 | |||
176 | /* Main loop. | ||
177 | * | ||
178 | * Make the result be pointed to alternately by XP and RP. This | ||
179 | * helps us avoid block copying, which would otherwise be necessary | ||
180 | * with the overlap restrictions of mpihelp_divmod. With 50% probability | ||
181 | * the result after this loop will be in the area originally pointed | ||
182 | * by RP (==RES->d), and with 50% probability in the area originally | ||
183 | * pointed to by XP. | ||
184 | */ | ||
185 | |||
186 | for (;;) { | ||
187 | while (c) { | ||
188 | mpi_ptr_t tp; | ||
189 | mpi_size_t xsize; | ||
190 | |||
191 | /*if (mpihelp_mul_n(xp, rp, rp, rsize) < 0) goto enomem */ | ||
192 | if (rsize < KARATSUBA_THRESHOLD) | ||
193 | mpih_sqr_n_basecase(xp, rp, rsize); | ||
194 | else { | ||
195 | if (!tspace) { | ||
196 | tsize = 2 * rsize; | ||
197 | tspace = | ||
198 | mpi_alloc_limb_space(tsize); | ||
199 | if (!tspace) | ||
200 | goto enomem; | ||
201 | } else if (tsize < (2 * rsize)) { | ||
202 | mpi_free_limb_space(tspace); | ||
203 | tsize = 2 * rsize; | ||
204 | tspace = | ||
205 | mpi_alloc_limb_space(tsize); | ||
206 | if (!tspace) | ||
207 | goto enomem; | ||
208 | } | ||
209 | mpih_sqr_n(xp, rp, rsize, tspace); | ||
210 | } | ||
211 | |||
212 | xsize = 2 * rsize; | ||
213 | if (xsize > msize) { | ||
214 | mpihelp_divrem(xp + msize, 0, xp, xsize, | ||
215 | mp, msize); | ||
216 | xsize = msize; | ||
217 | } | ||
218 | |||
219 | tp = rp; | ||
220 | rp = xp; | ||
221 | xp = tp; | ||
222 | rsize = xsize; | ||
223 | |||
224 | if ((mpi_limb_signed_t) e < 0) { | ||
225 | /*mpihelp_mul( xp, rp, rsize, bp, bsize ); */ | ||
226 | if (bsize < KARATSUBA_THRESHOLD) { | ||
227 | mpi_limb_t tmp; | ||
228 | if (mpihelp_mul | ||
229 | (xp, rp, rsize, bp, bsize, | ||
230 | &tmp) < 0) | ||
231 | goto enomem; | ||
232 | } else { | ||
233 | if (mpihelp_mul_karatsuba_case | ||
234 | (xp, rp, rsize, bp, bsize, | ||
235 | &karactx) < 0) | ||
236 | goto enomem; | ||
237 | } | ||
238 | |||
239 | xsize = rsize + bsize; | ||
240 | if (xsize > msize) { | ||
241 | mpihelp_divrem(xp + msize, 0, | ||
242 | xp, xsize, mp, | ||
243 | msize); | ||
244 | xsize = msize; | ||
245 | } | ||
246 | |||
247 | tp = rp; | ||
248 | rp = xp; | ||
249 | xp = tp; | ||
250 | rsize = xsize; | ||
251 | } | ||
252 | e <<= 1; | ||
253 | c--; | ||
254 | } | ||
255 | |||
256 | i--; | ||
257 | if (i < 0) | ||
258 | break; | ||
259 | e = ep[i]; | ||
260 | c = BITS_PER_MPI_LIMB; | ||
261 | } | ||
262 | |||
263 | /* We shifted MOD, the modulo reduction argument, left MOD_SHIFT_CNT | ||
264 | * steps. Adjust the result by reducing it with the original MOD. | ||
265 | * | ||
266 | * Also make sure the result is put in RES->d (where it already | ||
267 | * might be, see above). | ||
268 | */ | ||
269 | if (mod_shift_cnt) { | ||
270 | carry_limb = | ||
271 | mpihelp_lshift(res->d, rp, rsize, mod_shift_cnt); | ||
272 | rp = res->d; | ||
273 | if (carry_limb) { | ||
274 | rp[rsize] = carry_limb; | ||
275 | rsize++; | ||
276 | } | ||
277 | } else { | ||
278 | MPN_COPY(res->d, rp, rsize); | ||
279 | rp = res->d; | ||
280 | } | ||
281 | |||
282 | if (rsize >= msize) { | ||
283 | mpihelp_divrem(rp + msize, 0, rp, rsize, mp, msize); | ||
284 | rsize = msize; | ||
285 | } | ||
286 | |||
287 | /* Remove any leading zero words from the result. */ | ||
288 | if (mod_shift_cnt) | ||
289 | mpihelp_rshift(rp, rp, rsize, mod_shift_cnt); | ||
290 | MPN_NORMALIZE(rp, rsize); | ||
291 | |||
292 | mpihelp_release_karatsuba_ctx(&karactx); | ||
293 | } | ||
294 | |||
295 | if (negative_result && rsize) { | ||
296 | if (mod_shift_cnt) | ||
297 | mpihelp_rshift(mp, mp, msize, mod_shift_cnt); | ||
298 | mpihelp_sub(rp, mp, msize, rp, rsize); | ||
299 | rsize = msize; | ||
300 | rsign = msign; | ||
301 | MPN_NORMALIZE(rp, rsize); | ||
302 | } | ||
303 | res->nlimbs = rsize; | ||
304 | res->sign = rsign; | ||
305 | |||
306 | leave: | ||
307 | rc = 0; | ||
308 | enomem: | ||
309 | if (assign_rp) | ||
310 | mpi_assign_limb_space(res, rp, size); | ||
311 | if (mp_marker) | ||
312 | mpi_free_limb_space(mp_marker); | ||
313 | if (bp_marker) | ||
314 | mpi_free_limb_space(bp_marker); | ||
315 | if (ep_marker) | ||
316 | mpi_free_limb_space(ep_marker); | ||
317 | if (xp_marker) | ||
318 | mpi_free_limb_space(xp_marker); | ||
319 | if (tspace) | ||
320 | mpi_free_limb_space(tspace); | ||
321 | return rc; | ||
322 | } | ||
323 | EXPORT_SYMBOL_GPL(mpi_powm); | ||
diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c new file mode 100644 index 000000000000..fe84bb978e3b --- /dev/null +++ b/lib/mpi/mpicoder.c | |||
@@ -0,0 +1,365 @@ | |||
1 | /* mpicoder.c - Coder for the external representation of MPIs | ||
2 | * Copyright (C) 1998, 1999 Free Software Foundation, Inc. | ||
3 | * | ||
4 | * This file is part of GnuPG. | ||
5 | * | ||
6 | * GnuPG is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * GnuPG is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | ||
19 | */ | ||
20 | |||
21 | #include "mpi-internal.h" | ||
22 | |||
23 | #define DIM(v) (sizeof(v)/sizeof((v)[0])) | ||
24 | #define MAX_EXTERN_MPI_BITS 16384 | ||
25 | |||
26 | static uint8_t asn[15] = /* Object ID is 1.3.14.3.2.26 */ | ||
27 | { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, | ||
28 | 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 | ||
29 | }; | ||
30 | |||
31 | MPI do_encode_md(const void *sha_buffer, unsigned nbits) | ||
32 | { | ||
33 | int nframe = (nbits + 7) / 8; | ||
34 | uint8_t *frame, *fr_pt; | ||
35 | int i = 0, n; | ||
36 | size_t asnlen = DIM(asn); | ||
37 | MPI a = MPI_NULL; | ||
38 | |||
39 | if (SHA1_DIGEST_LENGTH + asnlen + 4 > nframe) | ||
40 | pr_info("MPI: can't encode a %d bit MD into a %d bits frame\n", | ||
41 | (int)(SHA1_DIGEST_LENGTH * 8), (int)nbits); | ||
42 | |||
43 | /* We encode the MD in this way: | ||
44 | * | ||
45 | * 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) | ||
46 | * | ||
47 | * PAD consists of FF bytes. | ||
48 | */ | ||
49 | frame = kmalloc(nframe, GFP_KERNEL); | ||
50 | if (!frame) | ||
51 | return MPI_NULL; | ||
52 | n = 0; | ||
53 | frame[n++] = 0; | ||
54 | frame[n++] = 1; /* block type */ | ||
55 | i = nframe - SHA1_DIGEST_LENGTH - asnlen - 3; | ||
56 | |||
57 | if (i <= 1) { | ||
58 | pr_info("MPI: message digest encoding failed\n"); | ||
59 | kfree(frame); | ||
60 | return a; | ||
61 | } | ||
62 | |||
63 | memset(frame + n, 0xff, i); | ||
64 | n += i; | ||
65 | frame[n++] = 0; | ||
66 | memcpy(frame + n, &asn, asnlen); | ||
67 | n += asnlen; | ||
68 | memcpy(frame + n, sha_buffer, SHA1_DIGEST_LENGTH); | ||
69 | n += SHA1_DIGEST_LENGTH; | ||
70 | |||
71 | i = nframe; | ||
72 | fr_pt = frame; | ||
73 | |||
74 | if (n != nframe) { | ||
75 | printk | ||
76 | ("MPI: message digest encoding failed, frame length is wrong\n"); | ||
77 | kfree(frame); | ||
78 | return a; | ||
79 | } | ||
80 | |||
81 | a = mpi_alloc((nframe + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB); | ||
82 | mpi_set_buffer(a, frame, nframe, 0); | ||
83 | kfree(frame); | ||
84 | |||
85 | return a; | ||
86 | } | ||
87 | |||
88 | MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread) | ||
89 | { | ||
90 | const uint8_t *buffer = xbuffer; | ||
91 | int i, j; | ||
92 | unsigned nbits, nbytes, nlimbs, nread = 0; | ||
93 | mpi_limb_t a; | ||
94 | MPI val = MPI_NULL; | ||
95 | |||
96 | if (*ret_nread < 2) | ||
97 | goto leave; | ||
98 | nbits = buffer[0] << 8 | buffer[1]; | ||
99 | |||
100 | if (nbits > MAX_EXTERN_MPI_BITS) { | ||
101 | pr_info("MPI: mpi too large (%u bits)\n", nbits); | ||
102 | goto leave; | ||
103 | } | ||
104 | buffer += 2; | ||
105 | nread = 2; | ||
106 | |||
107 | nbytes = (nbits + 7) / 8; | ||
108 | nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB; | ||
109 | val = mpi_alloc(nlimbs); | ||
110 | if (!val) | ||
111 | return MPI_NULL; | ||
112 | i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; | ||
113 | i %= BYTES_PER_MPI_LIMB; | ||
114 | val->nbits = nbits; | ||
115 | j = val->nlimbs = nlimbs; | ||
116 | val->sign = 0; | ||
117 | for (; j > 0; j--) { | ||
118 | a = 0; | ||
119 | for (; i < BYTES_PER_MPI_LIMB; i++) { | ||
120 | if (++nread > *ret_nread) { | ||
121 | printk | ||
122 | ("MPI: mpi larger than buffer nread=%d ret_nread=%d\n", | ||
123 | nread, *ret_nread); | ||
124 | goto leave; | ||
125 | } | ||
126 | a <<= 8; | ||
127 | a |= *buffer++; | ||
128 | } | ||
129 | i = 0; | ||
130 | val->d[j - 1] = a; | ||
131 | } | ||
132 | |||
133 | leave: | ||
134 | *ret_nread = nread; | ||
135 | return val; | ||
136 | } | ||
137 | EXPORT_SYMBOL_GPL(mpi_read_from_buffer); | ||
138 | |||
139 | /**************** | ||
140 | * Make an mpi from a character string. | ||
141 | */ | ||
142 | int mpi_fromstr(MPI val, const char *str) | ||
143 | { | ||
144 | int hexmode = 0, sign = 0, prepend_zero = 0, i, j, c, c1, c2; | ||
145 | unsigned nbits, nbytes, nlimbs; | ||
146 | mpi_limb_t a; | ||
147 | |||
148 | if (*str == '-') { | ||
149 | sign = 1; | ||
150 | str++; | ||
151 | } | ||
152 | if (*str == '0' && str[1] == 'x') | ||
153 | hexmode = 1; | ||
154 | else | ||
155 | return -EINVAL; /* other bases are not yet supported */ | ||
156 | str += 2; | ||
157 | |||
158 | nbits = strlen(str) * 4; | ||
159 | if (nbits % 8) | ||
160 | prepend_zero = 1; | ||
161 | nbytes = (nbits + 7) / 8; | ||
162 | nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB; | ||
163 | if (val->alloced < nlimbs) | ||
164 | if (!mpi_resize(val, nlimbs)) | ||
165 | return -ENOMEM; | ||
166 | i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; | ||
167 | i %= BYTES_PER_MPI_LIMB; | ||
168 | j = val->nlimbs = nlimbs; | ||
169 | val->sign = sign; | ||
170 | for (; j > 0; j--) { | ||
171 | a = 0; | ||
172 | for (; i < BYTES_PER_MPI_LIMB; i++) { | ||
173 | if (prepend_zero) { | ||
174 | c1 = '0'; | ||
175 | prepend_zero = 0; | ||
176 | } else | ||
177 | c1 = *str++; | ||
178 | assert(c1); | ||
179 | c2 = *str++; | ||
180 | assert(c2); | ||
181 | if (c1 >= '0' && c1 <= '9') | ||
182 | c = c1 - '0'; | ||
183 | else if (c1 >= 'a' && c1 <= 'f') | ||
184 | c = c1 - 'a' + 10; | ||
185 | else if (c1 >= 'A' && c1 <= 'F') | ||
186 | c = c1 - 'A' + 10; | ||
187 | else { | ||
188 | mpi_clear(val); | ||
189 | return 1; | ||
190 | } | ||
191 | c <<= 4; | ||
192 | if (c2 >= '0' && c2 <= '9') | ||
193 | c |= c2 - '0'; | ||
194 | else if (c2 >= 'a' && c2 <= 'f') | ||
195 | c |= c2 - 'a' + 10; | ||
196 | else if (c2 >= 'A' && c2 <= 'F') | ||
197 | c |= c2 - 'A' + 10; | ||
198 | else { | ||
199 | mpi_clear(val); | ||
200 | return 1; | ||
201 | } | ||
202 | a <<= 8; | ||
203 | a |= c; | ||
204 | } | ||
205 | i = 0; | ||
206 | |||
207 | val->d[j - 1] = a; | ||
208 | } | ||
209 | |||
210 | return 0; | ||
211 | } | ||
212 | EXPORT_SYMBOL_GPL(mpi_fromstr); | ||
213 | |||
214 | /**************** | ||
215 | * Special function to get the low 8 bytes from an mpi. | ||
216 | * This can be used as a keyid; KEYID is an 2 element array. | ||
217 | * Return the low 4 bytes. | ||
218 | */ | ||
219 | u32 mpi_get_keyid(const MPI a, u32 *keyid) | ||
220 | { | ||
221 | #if BYTES_PER_MPI_LIMB == 4 | ||
222 | if (keyid) { | ||
223 | keyid[0] = a->nlimbs >= 2 ? a->d[1] : 0; | ||
224 | keyid[1] = a->nlimbs >= 1 ? a->d[0] : 0; | ||
225 | } | ||
226 | return a->nlimbs >= 1 ? a->d[0] : 0; | ||
227 | #elif BYTES_PER_MPI_LIMB == 8 | ||
228 | if (keyid) { | ||
229 | keyid[0] = a->nlimbs ? (u32) (a->d[0] >> 32) : 0; | ||
230 | keyid[1] = a->nlimbs ? (u32) (a->d[0] & 0xffffffff) : 0; | ||
231 | } | ||
232 | return a->nlimbs ? (u32) (a->d[0] & 0xffffffff) : 0; | ||
233 | #else | ||
234 | #error Make this function work with other LIMB sizes | ||
235 | #endif | ||
236 | } | ||
237 | |||
238 | /**************** | ||
239 | * Return an allocated buffer with the MPI (msb first). | ||
240 | * NBYTES receives the length of this buffer. Caller must free the | ||
241 | * return string (This function does return a 0 byte buffer with NBYTES | ||
242 | * set to zero if the value of A is zero. If sign is not NULL, it will | ||
243 | * be set to the sign of the A. | ||
244 | */ | ||
245 | void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign) | ||
246 | { | ||
247 | uint8_t *p, *buffer; | ||
248 | mpi_limb_t alimb; | ||
249 | int i; | ||
250 | unsigned int n; | ||
251 | |||
252 | if (sign) | ||
253 | *sign = a->sign; | ||
254 | *nbytes = n = a->nlimbs * BYTES_PER_MPI_LIMB; | ||
255 | if (!n) | ||
256 | n++; /* avoid zero length allocation */ | ||
257 | p = buffer = kmalloc(n, GFP_KERNEL); | ||
258 | |||
259 | for (i = a->nlimbs - 1; i >= 0; i--) { | ||
260 | alimb = a->d[i]; | ||
261 | #if BYTES_PER_MPI_LIMB == 4 | ||
262 | *p++ = alimb >> 24; | ||
263 | *p++ = alimb >> 16; | ||
264 | *p++ = alimb >> 8; | ||
265 | *p++ = alimb; | ||
266 | #elif BYTES_PER_MPI_LIMB == 8 | ||
267 | *p++ = alimb >> 56; | ||
268 | *p++ = alimb >> 48; | ||
269 | *p++ = alimb >> 40; | ||
270 | *p++ = alimb >> 32; | ||
271 | *p++ = alimb >> 24; | ||
272 | *p++ = alimb >> 16; | ||
273 | *p++ = alimb >> 8; | ||
274 | *p++ = alimb; | ||
275 | #else | ||
276 | #error please implement for this limb size. | ||
277 | #endif | ||
278 | } | ||
279 | |||
280 | /* this is sub-optimal but we need to do the shift operation | ||
281 | * because the caller has to free the returned buffer */ | ||
282 | for (p = buffer; !*p && *nbytes; p++, --*nbytes) | ||
283 | ; | ||
284 | if (p != buffer) | ||
285 | memmove(buffer, p, *nbytes); | ||
286 | |||
287 | return buffer; | ||
288 | } | ||
289 | EXPORT_SYMBOL_GPL(mpi_get_buffer); | ||
290 | |||
291 | /**************** | ||
292 | * Use BUFFER to update MPI. | ||
293 | */ | ||
294 | int mpi_set_buffer(MPI a, const void *xbuffer, unsigned nbytes, int sign) | ||
295 | { | ||
296 | const uint8_t *buffer = xbuffer, *p; | ||
297 | mpi_limb_t alimb; | ||
298 | int nlimbs; | ||
299 | int i; | ||
300 | |||
301 | nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB; | ||
302 | if (RESIZE_IF_NEEDED(a, nlimbs) < 0) | ||
303 | return -ENOMEM; | ||
304 | a->sign = sign; | ||
305 | |||
306 | for (i = 0, p = buffer + nbytes - 1; p >= buffer + BYTES_PER_MPI_LIMB;) { | ||
307 | #if BYTES_PER_MPI_LIMB == 4 | ||
308 | alimb = (mpi_limb_t) *p--; | ||
309 | alimb |= (mpi_limb_t) *p-- << 8; | ||
310 | alimb |= (mpi_limb_t) *p-- << 16; | ||
311 | alimb |= (mpi_limb_t) *p-- << 24; | ||
312 | #elif BYTES_PER_MPI_LIMB == 8 | ||
313 | alimb = (mpi_limb_t) *p--; | ||
314 | alimb |= (mpi_limb_t) *p-- << 8; | ||
315 | alimb |= (mpi_limb_t) *p-- << 16; | ||
316 | alimb |= (mpi_limb_t) *p-- << 24; | ||
317 | alimb |= (mpi_limb_t) *p-- << 32; | ||
318 | alimb |= (mpi_limb_t) *p-- << 40; | ||
319 | alimb |= (mpi_limb_t) *p-- << 48; | ||
320 | alimb |= (mpi_limb_t) *p-- << 56; | ||
321 | #else | ||
322 | #error please implement for this limb size. | ||
323 | #endif | ||
324 | a->d[i++] = alimb; | ||
325 | } | ||
326 | if (p >= buffer) { | ||
327 | #if BYTES_PER_MPI_LIMB == 4 | ||
328 | alimb = *p--; | ||
329 | if (p >= buffer) | ||
330 | alimb |= (mpi_limb_t) *p-- << 8; | ||
331 | if (p >= buffer) | ||
332 | alimb |= (mpi_limb_t) *p-- << 16; | ||
333 | if (p >= buffer) | ||
334 | alimb |= (mpi_limb_t) *p-- << 24; | ||
335 | #elif BYTES_PER_MPI_LIMB == 8 | ||
336 | alimb = (mpi_limb_t) *p--; | ||
337 | if (p >= buffer) | ||
338 | alimb |= (mpi_limb_t) *p-- << 8; | ||
339 | if (p >= buffer) | ||
340 | alimb |= (mpi_limb_t) *p-- << 16; | ||
341 | if (p >= buffer) | ||
342 | alimb |= (mpi_limb_t) *p-- << 24; | ||
343 | if (p >= buffer) | ||
344 | alimb |= (mpi_limb_t) *p-- << 32; | ||
345 | if (p >= buffer) | ||
346 | alimb |= (mpi_limb_t) *p-- << 40; | ||
347 | if (p >= buffer) | ||
348 | alimb |= (mpi_limb_t) *p-- << 48; | ||
349 | if (p >= buffer) | ||
350 | alimb |= (mpi_limb_t) *p-- << 56; | ||
351 | #else | ||
352 | #error please implement for this limb size. | ||
353 | #endif | ||
354 | a->d[i++] = alimb; | ||
355 | } | ||
356 | a->nlimbs = i; | ||
357 | |||
358 | if (i != nlimbs) { | ||
359 | pr_emerg("MPI: mpi_set_buffer: Assertion failed (%d != %d)", i, | ||
360 | nlimbs); | ||
361 | BUG(); | ||
362 | } | ||
363 | return 0; | ||
364 | } | ||
365 | EXPORT_SYMBOL_GPL(mpi_set_buffer); | ||
diff --git a/lib/mpi/mpih-cmp.c b/lib/mpi/mpih-cmp.c new file mode 100644 index 000000000000..b2fd39677f1b --- /dev/null +++ b/lib/mpi/mpih-cmp.c | |||
@@ -0,0 +1,56 @@ | |||
1 | /* mpihelp-sub.c - MPI helper functions | ||
2 | * Copyright (C) 1994, 1996 Free Software Foundation, Inc. | ||
3 | * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. | ||
4 | * | ||
5 | * This file is part of GnuPG. | ||
6 | * | ||
7 | * GnuPG is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * GnuPG is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | ||
20 | * | ||
21 | * Note: This code is heavily based on the GNU MP Library. | ||
22 | * Actually it's the same code with only minor changes in the | ||
23 | * way the data is stored; this is to support the abstraction | ||
24 | * of an optional secure memory allocation which may be used | ||
25 | * to avoid revealing of sensitive data due to paging etc. | ||
26 | * The GNU MP Library itself is published under the LGPL; | ||
27 | * however I decided to publish this code under the plain GPL. | ||
28 | */ | ||
29 | |||
30 | #include "mpi-internal.h" | ||
31 | |||
32 | /**************** | ||
33 | * Compare OP1_PTR/OP1_SIZE with OP2_PTR/OP2_SIZE. | ||
34 | * There are no restrictions on the relative sizes of | ||
35 | * the two arguments. | ||
36 | * Return 1 if OP1 > OP2, 0 if they are equal, and -1 if OP1 < OP2. | ||
37 | */ | ||
38 | int mpihelp_cmp(mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size) | ||
39 | { | ||
40 | mpi_size_t i; | ||
41 | mpi_limb_t op1_word, op2_word; | ||
42 | |||
43 | for (i = size - 1; i >= 0; i--) { | ||
44 | op1_word = op1_ptr[i]; | ||
45 | op2_word = op2_ptr[i]; | ||
46 | if (op1_word != op2_word) | ||
47 | goto diff; | ||
48 | } | ||
49 | return 0; | ||
50 | |||
51 | diff: | ||
52 | /* This can *not* be simplified to | ||
53 | * op2_word - op2_word | ||
54 | * since that expression might give signed overflow. */ | ||
55 | return (op1_word > op2_word) ? 1 : -1; | ||
56 | } | ||
diff --git a/lib/mpi/mpih-div.c b/lib/mpi/mpih-div.c new file mode 100644 index 000000000000..87ede162dfab --- /dev/null +++ b/lib/mpi/mpih-div.c | |||
@@ -0,0 +1,541 @@ | |||
1 | /* mpihelp-div.c - MPI helper functions | ||
2 | * Copyright (C) 1994, 1996 Free Software Foundation, Inc. | ||
3 | * Copyright (C) 1998, 1999 Free Software Foundation, Inc. | ||
4 | * | ||
5 | * This file is part of GnuPG. | ||
6 | * | ||
7 | * GnuPG is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * GnuPG is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | ||
20 | * | ||
21 | * Note: This code is heavily based on the GNU MP Library. | ||
22 | * Actually it's the same code with only minor changes in the | ||
23 | * way the data is stored; this is to support the abstraction | ||
24 | * of an optional secure memory allocation which may be used | ||
25 | * to avoid revealing of sensitive data due to paging etc. | ||
26 | * The GNU MP Library itself is published under the LGPL; | ||
27 | * however I decided to publish this code under the plain GPL. | ||
28 | */ | ||
29 | |||
30 | #include "mpi-internal.h" | ||
31 | #include "longlong.h" | ||
32 | |||
33 | #ifndef UMUL_TIME | ||
34 | #define UMUL_TIME 1 | ||
35 | #endif | ||
36 | #ifndef UDIV_TIME | ||
37 | #define UDIV_TIME UMUL_TIME | ||
38 | #endif | ||
39 | |||
40 | /* FIXME: We should be using invert_limb (or invert_normalized_limb) | ||
41 | * here (not udiv_qrnnd). | ||
42 | */ | ||
43 | |||
44 | mpi_limb_t | ||
45 | mpihelp_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, | ||
46 | mpi_limb_t divisor_limb) | ||
47 | { | ||
48 | mpi_size_t i; | ||
49 | mpi_limb_t n1, n0, r; | ||
50 | int dummy; | ||
51 | |||
52 | /* Botch: Should this be handled at all? Rely on callers? */ | ||
53 | if (!dividend_size) | ||
54 | return 0; | ||
55 | |||
56 | /* If multiplication is much faster than division, and the | ||
57 | * dividend is large, pre-invert the divisor, and use | ||
58 | * only multiplications in the inner loop. | ||
59 | * | ||
60 | * This test should be read: | ||
61 | * Does it ever help to use udiv_qrnnd_preinv? | ||
62 | * && Does what we save compensate for the inversion overhead? | ||
63 | */ | ||
64 | if (UDIV_TIME > (2 * UMUL_TIME + 6) | ||
65 | && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME) { | ||
66 | int normalization_steps; | ||
67 | |||
68 | count_leading_zeros(normalization_steps, divisor_limb); | ||
69 | if (normalization_steps) { | ||
70 | mpi_limb_t divisor_limb_inverted; | ||
71 | |||
72 | divisor_limb <<= normalization_steps; | ||
73 | |||
74 | /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The | ||
75 | * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the | ||
76 | * most significant bit (with weight 2**N) implicit. | ||
77 | * | ||
78 | * Special case for DIVISOR_LIMB == 100...000. | ||
79 | */ | ||
80 | if (!(divisor_limb << 1)) | ||
81 | divisor_limb_inverted = ~(mpi_limb_t) 0; | ||
82 | else | ||
83 | udiv_qrnnd(divisor_limb_inverted, dummy, | ||
84 | -divisor_limb, 0, divisor_limb); | ||
85 | |||
86 | n1 = dividend_ptr[dividend_size - 1]; | ||
87 | r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); | ||
88 | |||
89 | /* Possible optimization: | ||
90 | * if (r == 0 | ||
91 | * && divisor_limb > ((n1 << normalization_steps) | ||
92 | * | (dividend_ptr[dividend_size - 2] >> ...))) | ||
93 | * ...one division less... | ||
94 | */ | ||
95 | for (i = dividend_size - 2; i >= 0; i--) { | ||
96 | n0 = dividend_ptr[i]; | ||
97 | UDIV_QRNND_PREINV(dummy, r, r, | ||
98 | ((n1 << normalization_steps) | ||
99 | | (n0 >> | ||
100 | (BITS_PER_MPI_LIMB - | ||
101 | normalization_steps))), | ||
102 | divisor_limb, | ||
103 | divisor_limb_inverted); | ||
104 | n1 = n0; | ||
105 | } | ||
106 | UDIV_QRNND_PREINV(dummy, r, r, | ||
107 | n1 << normalization_steps, | ||
108 | divisor_limb, divisor_limb_inverted); | ||
109 | return r >> normalization_steps; | ||
110 | } else { | ||
111 | mpi_limb_t divisor_limb_inverted; | ||
112 | |||
113 | /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The | ||
114 | * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the | ||
115 | * most significant bit (with weight 2**N) implicit. | ||
116 | * | ||
117 | * Special case for DIVISOR_LIMB == 100...000. | ||
118 | */ | ||
119 | if (!(divisor_limb << 1)) | ||
120 | divisor_limb_inverted = ~(mpi_limb_t) 0; | ||
121 | else | ||
122 | udiv_qrnnd(divisor_limb_inverted, dummy, | ||
123 | -divisor_limb, 0, divisor_limb); | ||
124 | |||
125 | i = dividend_size - 1; | ||
126 | r = dividend_ptr[i]; | ||
127 | |||
128 | if (r >= divisor_limb) | ||
129 | r = 0; | ||
130 | else | ||
131 | i--; | ||
132 | |||
133 | for (; i >= 0; i--) { | ||
134 | n0 = dividend_ptr[i]; | ||
135 | UDIV_QRNND_PREINV(dummy, r, r, | ||
136 | n0, divisor_limb, | ||
137 | divisor_limb_inverted); | ||
138 | } | ||
139 | return r; | ||
140 | } | ||
141 | } else { | ||
142 | if (UDIV_NEEDS_NORMALIZATION) { | ||
143 | int normalization_steps; | ||
144 | |||
145 | count_leading_zeros(normalization_steps, divisor_limb); | ||
146 | if (normalization_steps) { | ||
147 | divisor_limb <<= normalization_steps; | ||
148 | |||
149 | n1 = dividend_ptr[dividend_size - 1]; | ||
150 | r = n1 >> (BITS_PER_MPI_LIMB - | ||
151 | normalization_steps); | ||
152 | |||
153 | /* Possible optimization: | ||
154 | * if (r == 0 | ||
155 | * && divisor_limb > ((n1 << normalization_steps) | ||
156 | * | (dividend_ptr[dividend_size - 2] >> ...))) | ||
157 | * ...one division less... | ||
158 | */ | ||
159 | for (i = dividend_size - 2; i >= 0; i--) { | ||
160 | n0 = dividend_ptr[i]; | ||
161 | udiv_qrnnd(dummy, r, r, | ||
162 | ((n1 << normalization_steps) | ||
163 | | (n0 >> | ||
164 | (BITS_PER_MPI_LIMB - | ||
165 | normalization_steps))), | ||
166 | divisor_limb); | ||
167 | n1 = n0; | ||
168 | } | ||
169 | udiv_qrnnd(dummy, r, r, | ||
170 | n1 << normalization_steps, | ||
171 | divisor_limb); | ||
172 | return r >> normalization_steps; | ||
173 | } | ||
174 | } | ||
175 | /* No normalization needed, either because udiv_qrnnd doesn't require | ||
176 | * it, or because DIVISOR_LIMB is already normalized. */ | ||
177 | i = dividend_size - 1; | ||
178 | r = dividend_ptr[i]; | ||
179 | |||
180 | if (r >= divisor_limb) | ||
181 | r = 0; | ||
182 | else | ||
183 | i--; | ||
184 | |||
185 | for (; i >= 0; i--) { | ||
186 | n0 = dividend_ptr[i]; | ||
187 | udiv_qrnnd(dummy, r, r, n0, divisor_limb); | ||
188 | } | ||
189 | return r; | ||
190 | } | ||
191 | } | ||
192 | |||
193 | /* Divide num (NP/NSIZE) by den (DP/DSIZE) and write | ||
194 | * the NSIZE-DSIZE least significant quotient limbs at QP | ||
195 | * and the DSIZE long remainder at NP. If QEXTRA_LIMBS is | ||
196 | * non-zero, generate that many fraction bits and append them after the | ||
197 | * other quotient limbs. | ||
198 | * Return the most significant limb of the quotient, this is always 0 or 1. | ||
199 | * | ||
200 | * Preconditions: | ||
201 | * 0. NSIZE >= DSIZE. | ||
202 | * 1. The most significant bit of the divisor must be set. | ||
203 | * 2. QP must either not overlap with the input operands at all, or | ||
204 | * QP + DSIZE >= NP must hold true. (This means that it's | ||
205 | * possible to put the quotient in the high part of NUM, right after the | ||
206 | * remainder in NUM. | ||
207 | * 3. NSIZE >= DSIZE, even if QEXTRA_LIMBS is non-zero. | ||
208 | */ | ||
209 | |||
210 | mpi_limb_t | ||
211 | mpihelp_divrem(mpi_ptr_t qp, mpi_size_t qextra_limbs, | ||
212 | mpi_ptr_t np, mpi_size_t nsize, mpi_ptr_t dp, mpi_size_t dsize) | ||
213 | { | ||
214 | mpi_limb_t most_significant_q_limb = 0; | ||
215 | |||
216 | switch (dsize) { | ||
217 | case 0: | ||
218 | /* We are asked to divide by zero, so go ahead and do it! (To make | ||
219 | the compiler not remove this statement, return the value.) */ | ||
220 | return 1 / dsize; | ||
221 | |||
222 | case 1: | ||
223 | { | ||
224 | mpi_size_t i; | ||
225 | mpi_limb_t n1; | ||
226 | mpi_limb_t d; | ||
227 | |||
228 | d = dp[0]; | ||
229 | n1 = np[nsize - 1]; | ||
230 | |||
231 | if (n1 >= d) { | ||
232 | n1 -= d; | ||
233 | most_significant_q_limb = 1; | ||
234 | } | ||
235 | |||
236 | qp += qextra_limbs; | ||
237 | for (i = nsize - 2; i >= 0; i--) | ||
238 | udiv_qrnnd(qp[i], n1, n1, np[i], d); | ||
239 | qp -= qextra_limbs; | ||
240 | |||
241 | for (i = qextra_limbs - 1; i >= 0; i--) | ||
242 | udiv_qrnnd(qp[i], n1, n1, 0, d); | ||
243 | |||
244 | np[0] = n1; | ||
245 | } | ||
246 | break; | ||
247 | |||
248 | case 2: | ||
249 | { | ||
250 | mpi_size_t i; | ||
251 | mpi_limb_t n1, n0, n2; | ||
252 | mpi_limb_t d1, d0; | ||
253 | |||
254 | np += nsize - 2; | ||
255 | d1 = dp[1]; | ||
256 | d0 = dp[0]; | ||
257 | n1 = np[1]; | ||
258 | n0 = np[0]; | ||
259 | |||
260 | if (n1 >= d1 && (n1 > d1 || n0 >= d0)) { | ||
261 | sub_ddmmss(n1, n0, n1, n0, d1, d0); | ||
262 | most_significant_q_limb = 1; | ||
263 | } | ||
264 | |||
265 | for (i = qextra_limbs + nsize - 2 - 1; i >= 0; i--) { | ||
266 | mpi_limb_t q; | ||
267 | mpi_limb_t r; | ||
268 | |||
269 | if (i >= qextra_limbs) | ||
270 | np--; | ||
271 | else | ||
272 | np[0] = 0; | ||
273 | |||
274 | if (n1 == d1) { | ||
275 | /* Q should be either 111..111 or 111..110. Need special | ||
276 | * treatment of this rare case as normal division would | ||
277 | * give overflow. */ | ||
278 | q = ~(mpi_limb_t) 0; | ||
279 | |||
280 | r = n0 + d1; | ||
281 | if (r < d1) { /* Carry in the addition? */ | ||
282 | add_ssaaaa(n1, n0, r - d0, | ||
283 | np[0], 0, d0); | ||
284 | qp[i] = q; | ||
285 | continue; | ||
286 | } | ||
287 | n1 = d0 - (d0 != 0 ? 1 : 0); | ||
288 | n0 = -d0; | ||
289 | } else { | ||
290 | udiv_qrnnd(q, r, n1, n0, d1); | ||
291 | umul_ppmm(n1, n0, d0, q); | ||
292 | } | ||
293 | |||
294 | n2 = np[0]; | ||
295 | q_test: | ||
296 | if (n1 > r || (n1 == r && n0 > n2)) { | ||
297 | /* The estimated Q was too large. */ | ||
298 | q--; | ||
299 | sub_ddmmss(n1, n0, n1, n0, 0, d0); | ||
300 | r += d1; | ||
301 | if (r >= d1) /* If not carry, test Q again. */ | ||
302 | goto q_test; | ||
303 | } | ||
304 | |||
305 | qp[i] = q; | ||
306 | sub_ddmmss(n1, n0, r, n2, n1, n0); | ||
307 | } | ||
308 | np[1] = n1; | ||
309 | np[0] = n0; | ||
310 | } | ||
311 | break; | ||
312 | |||
313 | default: | ||
314 | { | ||
315 | mpi_size_t i; | ||
316 | mpi_limb_t dX, d1, n0; | ||
317 | |||
318 | np += nsize - dsize; | ||
319 | dX = dp[dsize - 1]; | ||
320 | d1 = dp[dsize - 2]; | ||
321 | n0 = np[dsize - 1]; | ||
322 | |||
323 | if (n0 >= dX) { | ||
324 | if (n0 > dX | ||
325 | || mpihelp_cmp(np, dp, dsize - 1) >= 0) { | ||
326 | mpihelp_sub_n(np, np, dp, dsize); | ||
327 | n0 = np[dsize - 1]; | ||
328 | most_significant_q_limb = 1; | ||
329 | } | ||
330 | } | ||
331 | |||
332 | for (i = qextra_limbs + nsize - dsize - 1; i >= 0; i--) { | ||
333 | mpi_limb_t q; | ||
334 | mpi_limb_t n1, n2; | ||
335 | mpi_limb_t cy_limb; | ||
336 | |||
337 | if (i >= qextra_limbs) { | ||
338 | np--; | ||
339 | n2 = np[dsize]; | ||
340 | } else { | ||
341 | n2 = np[dsize - 1]; | ||
342 | MPN_COPY_DECR(np + 1, np, dsize - 1); | ||
343 | np[0] = 0; | ||
344 | } | ||
345 | |||
346 | if (n0 == dX) { | ||
347 | /* This might over-estimate q, but it's probably not worth | ||
348 | * the extra code here to find out. */ | ||
349 | q = ~(mpi_limb_t) 0; | ||
350 | } else { | ||
351 | mpi_limb_t r; | ||
352 | |||
353 | udiv_qrnnd(q, r, n0, np[dsize - 1], dX); | ||
354 | umul_ppmm(n1, n0, d1, q); | ||
355 | |||
356 | while (n1 > r | ||
357 | || (n1 == r | ||
358 | && n0 > np[dsize - 2])) { | ||
359 | q--; | ||
360 | r += dX; | ||
361 | if (r < dX) /* I.e. "carry in previous addition?" */ | ||
362 | break; | ||
363 | n1 -= n0 < d1; | ||
364 | n0 -= d1; | ||
365 | } | ||
366 | } | ||
367 | |||
368 | /* Possible optimization: We already have (q * n0) and (1 * n1) | ||
369 | * after the calculation of q. Taking advantage of that, we | ||
370 | * could make this loop make two iterations less. */ | ||
371 | cy_limb = mpihelp_submul_1(np, dp, dsize, q); | ||
372 | |||
373 | if (n2 != cy_limb) { | ||
374 | mpihelp_add_n(np, np, dp, dsize); | ||
375 | q--; | ||
376 | } | ||
377 | |||
378 | qp[i] = q; | ||
379 | n0 = np[dsize - 1]; | ||
380 | } | ||
381 | } | ||
382 | } | ||
383 | |||
384 | return most_significant_q_limb; | ||
385 | } | ||
386 | |||
387 | /**************** | ||
388 | * Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by DIVISOR_LIMB. | ||
389 | * Write DIVIDEND_SIZE limbs of quotient at QUOT_PTR. | ||
390 | * Return the single-limb remainder. | ||
391 | * There are no constraints on the value of the divisor. | ||
392 | * | ||
393 | * QUOT_PTR and DIVIDEND_PTR might point to the same limb. | ||
394 | */ | ||
395 | |||
396 | mpi_limb_t | ||
397 | mpihelp_divmod_1(mpi_ptr_t quot_ptr, | ||
398 | mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, | ||
399 | mpi_limb_t divisor_limb) | ||
400 | { | ||
401 | mpi_size_t i; | ||
402 | mpi_limb_t n1, n0, r; | ||
403 | int dummy; | ||
404 | |||
405 | if (!dividend_size) | ||
406 | return 0; | ||
407 | |||
408 | /* If multiplication is much faster than division, and the | ||
409 | * dividend is large, pre-invert the divisor, and use | ||
410 | * only multiplications in the inner loop. | ||
411 | * | ||
412 | * This test should be read: | ||
413 | * Does it ever help to use udiv_qrnnd_preinv? | ||
414 | * && Does what we save compensate for the inversion overhead? | ||
415 | */ | ||
416 | if (UDIV_TIME > (2 * UMUL_TIME + 6) | ||
417 | && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME) { | ||
418 | int normalization_steps; | ||
419 | |||
420 | count_leading_zeros(normalization_steps, divisor_limb); | ||
421 | if (normalization_steps) { | ||
422 | mpi_limb_t divisor_limb_inverted; | ||
423 | |||
424 | divisor_limb <<= normalization_steps; | ||
425 | |||
426 | /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The | ||
427 | * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the | ||
428 | * most significant bit (with weight 2**N) implicit. | ||
429 | */ | ||
430 | /* Special case for DIVISOR_LIMB == 100...000. */ | ||
431 | if (!(divisor_limb << 1)) | ||
432 | divisor_limb_inverted = ~(mpi_limb_t) 0; | ||
433 | else | ||
434 | udiv_qrnnd(divisor_limb_inverted, dummy, | ||
435 | -divisor_limb, 0, divisor_limb); | ||
436 | |||
437 | n1 = dividend_ptr[dividend_size - 1]; | ||
438 | r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); | ||
439 | |||
440 | /* Possible optimization: | ||
441 | * if (r == 0 | ||
442 | * && divisor_limb > ((n1 << normalization_steps) | ||
443 | * | (dividend_ptr[dividend_size - 2] >> ...))) | ||
444 | * ...one division less... | ||
445 | */ | ||
446 | for (i = dividend_size - 2; i >= 0; i--) { | ||
447 | n0 = dividend_ptr[i]; | ||
448 | UDIV_QRNND_PREINV(quot_ptr[i + 1], r, r, | ||
449 | ((n1 << normalization_steps) | ||
450 | | (n0 >> | ||
451 | (BITS_PER_MPI_LIMB - | ||
452 | normalization_steps))), | ||
453 | divisor_limb, | ||
454 | divisor_limb_inverted); | ||
455 | n1 = n0; | ||
456 | } | ||
457 | UDIV_QRNND_PREINV(quot_ptr[0], r, r, | ||
458 | n1 << normalization_steps, | ||
459 | divisor_limb, divisor_limb_inverted); | ||
460 | return r >> normalization_steps; | ||
461 | } else { | ||
462 | mpi_limb_t divisor_limb_inverted; | ||
463 | |||
464 | /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The | ||
465 | * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the | ||
466 | * most significant bit (with weight 2**N) implicit. | ||
467 | */ | ||
468 | /* Special case for DIVISOR_LIMB == 100...000. */ | ||
469 | if (!(divisor_limb << 1)) | ||
470 | divisor_limb_inverted = ~(mpi_limb_t) 0; | ||
471 | else | ||
472 | udiv_qrnnd(divisor_limb_inverted, dummy, | ||
473 | -divisor_limb, 0, divisor_limb); | ||
474 | |||
475 | i = dividend_size - 1; | ||
476 | r = dividend_ptr[i]; | ||
477 | |||
478 | if (r >= divisor_limb) | ||
479 | r = 0; | ||
480 | else | ||
481 | quot_ptr[i--] = 0; | ||
482 | |||
483 | for (; i >= 0; i--) { | ||
484 | n0 = dividend_ptr[i]; | ||
485 | UDIV_QRNND_PREINV(quot_ptr[i], r, r, | ||
486 | n0, divisor_limb, | ||
487 | divisor_limb_inverted); | ||
488 | } | ||
489 | return r; | ||
490 | } | ||
491 | } else { | ||
492 | if (UDIV_NEEDS_NORMALIZATION) { | ||
493 | int normalization_steps; | ||
494 | |||
495 | count_leading_zeros(normalization_steps, divisor_limb); | ||
496 | if (normalization_steps) { | ||
497 | divisor_limb <<= normalization_steps; | ||
498 | |||
499 | n1 = dividend_ptr[dividend_size - 1]; | ||
500 | r = n1 >> (BITS_PER_MPI_LIMB - | ||
501 | normalization_steps); | ||
502 | |||
503 | /* Possible optimization: | ||
504 | * if (r == 0 | ||
505 | * && divisor_limb > ((n1 << normalization_steps) | ||
506 | * | (dividend_ptr[dividend_size - 2] >> ...))) | ||
507 | * ...one division less... | ||
508 | */ | ||
509 | for (i = dividend_size - 2; i >= 0; i--) { | ||
510 | n0 = dividend_ptr[i]; | ||
511 | udiv_qrnnd(quot_ptr[i + 1], r, r, | ||
512 | ((n1 << normalization_steps) | ||
513 | | (n0 >> | ||
514 | (BITS_PER_MPI_LIMB - | ||
515 | normalization_steps))), | ||
516 | divisor_limb); | ||
517 | n1 = n0; | ||
518 | } | ||
519 | udiv_qrnnd(quot_ptr[0], r, r, | ||
520 | n1 << normalization_steps, | ||
521 | divisor_limb); | ||
522 | return r >> normalization_steps; | ||
523 | } | ||
524 | } | ||
525 | /* No normalization needed, either because udiv_qrnnd doesn't require | ||
526 | * it, or because DIVISOR_LIMB is already normalized. */ | ||
527 | i = dividend_size - 1; | ||
528 | r = dividend_ptr[i]; | ||
529 | |||
530 | if (r >= divisor_limb) | ||
531 | r = 0; | ||
532 | else | ||
533 | quot_ptr[i--] = 0; | ||
534 | |||
535 | for (; i >= 0; i--) { | ||
536 | n0 = dividend_ptr[i]; | ||
537 | udiv_qrnnd(quot_ptr[i], r, r, n0, divisor_limb); | ||
538 | } | ||
539 | return r; | ||
540 | } | ||
541 | } | ||
diff --git a/lib/mpi/mpih-mul.c b/lib/mpi/mpih-mul.c new file mode 100644 index 000000000000..c69c5eef233b --- /dev/null +++ b/lib/mpi/mpih-mul.c | |||
@@ -0,0 +1,527 @@ | |||
1 | /* mpihelp-mul.c - MPI helper functions | ||
2 | * Copyright (C) 1994, 1996, 1998, 1999, | ||
3 | * 2000 Free Software Foundation, Inc. | ||
4 | * | ||
5 | * This file is part of GnuPG. | ||
6 | * | ||
7 | * GnuPG is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * GnuPG is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | ||
20 | * | ||
21 | * Note: This code is heavily based on the GNU MP Library. | ||
22 | * Actually it's the same code with only minor changes in the | ||
23 | * way the data is stored; this is to support the abstraction | ||
24 | * of an optional secure memory allocation which may be used | ||
25 | * to avoid revealing of sensitive data due to paging etc. | ||
26 | * The GNU MP Library itself is published under the LGPL; | ||
27 | * however I decided to publish this code under the plain GPL. | ||
28 | */ | ||
29 | |||
30 | #include <linux/string.h> | ||
31 | #include "mpi-internal.h" | ||
32 | #include "longlong.h" | ||
33 | |||
34 | #define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \ | ||
35 | do { \ | ||
36 | if ((size) < KARATSUBA_THRESHOLD) \ | ||
37 | mul_n_basecase(prodp, up, vp, size); \ | ||
38 | else \ | ||
39 | mul_n(prodp, up, vp, size, tspace); \ | ||
40 | } while (0); | ||
41 | |||
42 | #define MPN_SQR_N_RECURSE(prodp, up, size, tspace) \ | ||
43 | do { \ | ||
44 | if ((size) < KARATSUBA_THRESHOLD) \ | ||
45 | mpih_sqr_n_basecase(prodp, up, size); \ | ||
46 | else \ | ||
47 | mpih_sqr_n(prodp, up, size, tspace); \ | ||
48 | } while (0); | ||
49 | |||
50 | /* Multiply the natural numbers u (pointed to by UP) and v (pointed to by VP), | ||
51 | * both with SIZE limbs, and store the result at PRODP. 2 * SIZE limbs are | ||
52 | * always stored. Return the most significant limb. | ||
53 | * | ||
54 | * Argument constraints: | ||
55 | * 1. PRODP != UP and PRODP != VP, i.e. the destination | ||
56 | * must be distinct from the multiplier and the multiplicand. | ||
57 | * | ||
58 | * | ||
59 | * Handle simple cases with traditional multiplication. | ||
60 | * | ||
61 | * This is the most critical code of multiplication. All multiplies rely | ||
62 | * on this, both small and huge. Small ones arrive here immediately. Huge | ||
63 | * ones arrive here as this is the base case for Karatsuba's recursive | ||
64 | * algorithm below. | ||
65 | */ | ||
66 | |||
67 | static mpi_limb_t | ||
68 | mul_n_basecase(mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t size) | ||
69 | { | ||
70 | mpi_size_t i; | ||
71 | mpi_limb_t cy; | ||
72 | mpi_limb_t v_limb; | ||
73 | |||
74 | /* Multiply by the first limb in V separately, as the result can be | ||
75 | * stored (not added) to PROD. We also avoid a loop for zeroing. */ | ||
76 | v_limb = vp[0]; | ||
77 | if (v_limb <= 1) { | ||
78 | if (v_limb == 1) | ||
79 | MPN_COPY(prodp, up, size); | ||
80 | else | ||
81 | MPN_ZERO(prodp, size); | ||
82 | cy = 0; | ||
83 | } else | ||
84 | cy = mpihelp_mul_1(prodp, up, size, v_limb); | ||
85 | |||
86 | prodp[size] = cy; | ||
87 | prodp++; | ||
88 | |||
89 | /* For each iteration in the outer loop, multiply one limb from | ||
90 | * U with one limb from V, and add it to PROD. */ | ||
91 | for (i = 1; i < size; i++) { | ||
92 | v_limb = vp[i]; | ||
93 | if (v_limb <= 1) { | ||
94 | cy = 0; | ||
95 | if (v_limb == 1) | ||
96 | cy = mpihelp_add_n(prodp, prodp, up, size); | ||
97 | } else | ||
98 | cy = mpihelp_addmul_1(prodp, up, size, v_limb); | ||
99 | |||
100 | prodp[size] = cy; | ||
101 | prodp++; | ||
102 | } | ||
103 | |||
104 | return cy; | ||
105 | } | ||
106 | |||
107 | static void | ||
108 | mul_n(mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, | ||
109 | mpi_size_t size, mpi_ptr_t tspace) | ||
110 | { | ||
111 | if (size & 1) { | ||
112 | /* The size is odd, and the code below doesn't handle that. | ||
113 | * Multiply the least significant (size - 1) limbs with a recursive | ||
114 | * call, and handle the most significant limb of S1 and S2 | ||
115 | * separately. | ||
116 | * A slightly faster way to do this would be to make the Karatsuba | ||
117 | * code below behave as if the size were even, and let it check for | ||
118 | * odd size in the end. I.e., in essence move this code to the end. | ||
119 | * Doing so would save us a recursive call, and potentially make the | ||
120 | * stack grow a lot less. | ||
121 | */ | ||
122 | mpi_size_t esize = size - 1; /* even size */ | ||
123 | mpi_limb_t cy_limb; | ||
124 | |||
125 | MPN_MUL_N_RECURSE(prodp, up, vp, esize, tspace); | ||
126 | cy_limb = mpihelp_addmul_1(prodp + esize, up, esize, vp[esize]); | ||
127 | prodp[esize + esize] = cy_limb; | ||
128 | cy_limb = mpihelp_addmul_1(prodp + esize, vp, size, up[esize]); | ||
129 | prodp[esize + size] = cy_limb; | ||
130 | } else { | ||
131 | /* Anatolij Alekseevich Karatsuba's divide-and-conquer algorithm. | ||
132 | * | ||
133 | * Split U in two pieces, U1 and U0, such that | ||
134 | * U = U0 + U1*(B**n), | ||
135 | * and V in V1 and V0, such that | ||
136 | * V = V0 + V1*(B**n). | ||
137 | * | ||
138 | * UV is then computed recursively using the identity | ||
139 | * | ||
140 | * 2n n n n | ||
141 | * UV = (B + B )U V + B (U -U )(V -V ) + (B + 1)U V | ||
142 | * 1 1 1 0 0 1 0 0 | ||
143 | * | ||
144 | * Where B = 2**BITS_PER_MP_LIMB. | ||
145 | */ | ||
146 | mpi_size_t hsize = size >> 1; | ||
147 | mpi_limb_t cy; | ||
148 | int negflg; | ||
149 | |||
150 | /* Product H. ________________ ________________ | ||
151 | * |_____U1 x V1____||____U0 x V0_____| | ||
152 | * Put result in upper part of PROD and pass low part of TSPACE | ||
153 | * as new TSPACE. | ||
154 | */ | ||
155 | MPN_MUL_N_RECURSE(prodp + size, up + hsize, vp + hsize, hsize, | ||
156 | tspace); | ||
157 | |||
158 | /* Product M. ________________ | ||
159 | * |_(U1-U0)(V0-V1)_| | ||
160 | */ | ||
161 | if (mpihelp_cmp(up + hsize, up, hsize) >= 0) { | ||
162 | mpihelp_sub_n(prodp, up + hsize, up, hsize); | ||
163 | negflg = 0; | ||
164 | } else { | ||
165 | mpihelp_sub_n(prodp, up, up + hsize, hsize); | ||
166 | negflg = 1; | ||
167 | } | ||
168 | if (mpihelp_cmp(vp + hsize, vp, hsize) >= 0) { | ||
169 | mpihelp_sub_n(prodp + hsize, vp + hsize, vp, hsize); | ||
170 | negflg ^= 1; | ||
171 | } else { | ||
172 | mpihelp_sub_n(prodp + hsize, vp, vp + hsize, hsize); | ||
173 | /* No change of NEGFLG. */ | ||
174 | } | ||
175 | /* Read temporary operands from low part of PROD. | ||
176 | * Put result in low part of TSPACE using upper part of TSPACE | ||
177 | * as new TSPACE. | ||
178 | */ | ||
179 | MPN_MUL_N_RECURSE(tspace, prodp, prodp + hsize, hsize, | ||
180 | tspace + size); | ||
181 | |||
182 | /* Add/copy product H. */ | ||
183 | MPN_COPY(prodp + hsize, prodp + size, hsize); | ||
184 | cy = mpihelp_add_n(prodp + size, prodp + size, | ||
185 | prodp + size + hsize, hsize); | ||
186 | |||
187 | /* Add product M (if NEGFLG M is a negative number) */ | ||
188 | if (negflg) | ||
189 | cy -= | ||
190 | mpihelp_sub_n(prodp + hsize, prodp + hsize, tspace, | ||
191 | size); | ||
192 | else | ||
193 | cy += | ||
194 | mpihelp_add_n(prodp + hsize, prodp + hsize, tspace, | ||
195 | size); | ||
196 | |||
197 | /* Product L. ________________ ________________ | ||
198 | * |________________||____U0 x V0_____| | ||
199 | * Read temporary operands from low part of PROD. | ||
200 | * Put result in low part of TSPACE using upper part of TSPACE | ||
201 | * as new TSPACE. | ||
202 | */ | ||
203 | MPN_MUL_N_RECURSE(tspace, up, vp, hsize, tspace + size); | ||
204 | |||
205 | /* Add/copy Product L (twice) */ | ||
206 | |||
207 | cy += mpihelp_add_n(prodp + hsize, prodp + hsize, tspace, size); | ||
208 | if (cy) | ||
209 | mpihelp_add_1(prodp + hsize + size, | ||
210 | prodp + hsize + size, hsize, cy); | ||
211 | |||
212 | MPN_COPY(prodp, tspace, hsize); | ||
213 | cy = mpihelp_add_n(prodp + hsize, prodp + hsize, tspace + hsize, | ||
214 | hsize); | ||
215 | if (cy) | ||
216 | mpihelp_add_1(prodp + size, prodp + size, size, 1); | ||
217 | } | ||
218 | } | ||
219 | |||
220 | void mpih_sqr_n_basecase(mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size) | ||
221 | { | ||
222 | mpi_size_t i; | ||
223 | mpi_limb_t cy_limb; | ||
224 | mpi_limb_t v_limb; | ||
225 | |||
226 | /* Multiply by the first limb in V separately, as the result can be | ||
227 | * stored (not added) to PROD. We also avoid a loop for zeroing. */ | ||
228 | v_limb = up[0]; | ||
229 | if (v_limb <= 1) { | ||
230 | if (v_limb == 1) | ||
231 | MPN_COPY(prodp, up, size); | ||
232 | else | ||
233 | MPN_ZERO(prodp, size); | ||
234 | cy_limb = 0; | ||
235 | } else | ||
236 | cy_limb = mpihelp_mul_1(prodp, up, size, v_limb); | ||
237 | |||
238 | prodp[size] = cy_limb; | ||
239 | prodp++; | ||
240 | |||
241 | /* For each iteration in the outer loop, multiply one limb from | ||
242 | * U with one limb from V, and add it to PROD. */ | ||
243 | for (i = 1; i < size; i++) { | ||
244 | v_limb = up[i]; | ||
245 | if (v_limb <= 1) { | ||
246 | cy_limb = 0; | ||
247 | if (v_limb == 1) | ||
248 | cy_limb = mpihelp_add_n(prodp, prodp, up, size); | ||
249 | } else | ||
250 | cy_limb = mpihelp_addmul_1(prodp, up, size, v_limb); | ||
251 | |||
252 | prodp[size] = cy_limb; | ||
253 | prodp++; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | void | ||
258 | mpih_sqr_n(mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size, mpi_ptr_t tspace) | ||
259 | { | ||
260 | if (size & 1) { | ||
261 | /* The size is odd, and the code below doesn't handle that. | ||
262 | * Multiply the least significant (size - 1) limbs with a recursive | ||
263 | * call, and handle the most significant limb of S1 and S2 | ||
264 | * separately. | ||
265 | * A slightly faster way to do this would be to make the Karatsuba | ||
266 | * code below behave as if the size were even, and let it check for | ||
267 | * odd size in the end. I.e., in essence move this code to the end. | ||
268 | * Doing so would save us a recursive call, and potentially make the | ||
269 | * stack grow a lot less. | ||
270 | */ | ||
271 | mpi_size_t esize = size - 1; /* even size */ | ||
272 | mpi_limb_t cy_limb; | ||
273 | |||
274 | MPN_SQR_N_RECURSE(prodp, up, esize, tspace); | ||
275 | cy_limb = mpihelp_addmul_1(prodp + esize, up, esize, up[esize]); | ||
276 | prodp[esize + esize] = cy_limb; | ||
277 | cy_limb = mpihelp_addmul_1(prodp + esize, up, size, up[esize]); | ||
278 | |||
279 | prodp[esize + size] = cy_limb; | ||
280 | } else { | ||
281 | mpi_size_t hsize = size >> 1; | ||
282 | mpi_limb_t cy; | ||
283 | |||
284 | /* Product H. ________________ ________________ | ||
285 | * |_____U1 x U1____||____U0 x U0_____| | ||
286 | * Put result in upper part of PROD and pass low part of TSPACE | ||
287 | * as new TSPACE. | ||
288 | */ | ||
289 | MPN_SQR_N_RECURSE(prodp + size, up + hsize, hsize, tspace); | ||
290 | |||
291 | /* Product M. ________________ | ||
292 | * |_(U1-U0)(U0-U1)_| | ||
293 | */ | ||
294 | if (mpihelp_cmp(up + hsize, up, hsize) >= 0) | ||
295 | mpihelp_sub_n(prodp, up + hsize, up, hsize); | ||
296 | else | ||
297 | mpihelp_sub_n(prodp, up, up + hsize, hsize); | ||
298 | |||
299 | /* Read temporary operands from low part of PROD. | ||
300 | * Put result in low part of TSPACE using upper part of TSPACE | ||
301 | * as new TSPACE. */ | ||
302 | MPN_SQR_N_RECURSE(tspace, prodp, hsize, tspace + size); | ||
303 | |||
304 | /* Add/copy product H */ | ||
305 | MPN_COPY(prodp + hsize, prodp + size, hsize); | ||
306 | cy = mpihelp_add_n(prodp + size, prodp + size, | ||
307 | prodp + size + hsize, hsize); | ||
308 | |||
309 | /* Add product M (if NEGFLG M is a negative number). */ | ||
310 | cy -= mpihelp_sub_n(prodp + hsize, prodp + hsize, tspace, size); | ||
311 | |||
312 | /* Product L. ________________ ________________ | ||
313 | * |________________||____U0 x U0_____| | ||
314 | * Read temporary operands from low part of PROD. | ||
315 | * Put result in low part of TSPACE using upper part of TSPACE | ||
316 | * as new TSPACE. */ | ||
317 | MPN_SQR_N_RECURSE(tspace, up, hsize, tspace + size); | ||
318 | |||
319 | /* Add/copy Product L (twice). */ | ||
320 | cy += mpihelp_add_n(prodp + hsize, prodp + hsize, tspace, size); | ||
321 | if (cy) | ||
322 | mpihelp_add_1(prodp + hsize + size, | ||
323 | prodp + hsize + size, hsize, cy); | ||
324 | |||
325 | MPN_COPY(prodp, tspace, hsize); | ||
326 | cy = mpihelp_add_n(prodp + hsize, prodp + hsize, tspace + hsize, | ||
327 | hsize); | ||
328 | if (cy) | ||
329 | mpihelp_add_1(prodp + size, prodp + size, size, 1); | ||
330 | } | ||
331 | } | ||
332 | |||
333 | /* This should be made into an inline function in gmp.h. */ | ||
334 | int mpihelp_mul_n(mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t size) | ||
335 | { | ||
336 | if (up == vp) { | ||
337 | if (size < KARATSUBA_THRESHOLD) | ||
338 | mpih_sqr_n_basecase(prodp, up, size); | ||
339 | else { | ||
340 | mpi_ptr_t tspace; | ||
341 | tspace = mpi_alloc_limb_space(2 * size); | ||
342 | if (!tspace) | ||
343 | return -ENOMEM; | ||
344 | mpih_sqr_n(prodp, up, size, tspace); | ||
345 | mpi_free_limb_space(tspace); | ||
346 | } | ||
347 | } else { | ||
348 | if (size < KARATSUBA_THRESHOLD) | ||
349 | mul_n_basecase(prodp, up, vp, size); | ||
350 | else { | ||
351 | mpi_ptr_t tspace; | ||
352 | tspace = mpi_alloc_limb_space(2 * size); | ||
353 | if (!tspace) | ||
354 | return -ENOMEM; | ||
355 | mul_n(prodp, up, vp, size, tspace); | ||
356 | mpi_free_limb_space(tspace); | ||
357 | } | ||
358 | } | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | int | ||
364 | mpihelp_mul_karatsuba_case(mpi_ptr_t prodp, | ||
365 | mpi_ptr_t up, mpi_size_t usize, | ||
366 | mpi_ptr_t vp, mpi_size_t vsize, | ||
367 | struct karatsuba_ctx *ctx) | ||
368 | { | ||
369 | mpi_limb_t cy; | ||
370 | |||
371 | if (!ctx->tspace || ctx->tspace_size < vsize) { | ||
372 | if (ctx->tspace) | ||
373 | mpi_free_limb_space(ctx->tspace); | ||
374 | ctx->tspace = mpi_alloc_limb_space(2 * vsize); | ||
375 | if (!ctx->tspace) | ||
376 | return -ENOMEM; | ||
377 | ctx->tspace_size = vsize; | ||
378 | } | ||
379 | |||
380 | MPN_MUL_N_RECURSE(prodp, up, vp, vsize, ctx->tspace); | ||
381 | |||
382 | prodp += vsize; | ||
383 | up += vsize; | ||
384 | usize -= vsize; | ||
385 | if (usize >= vsize) { | ||
386 | if (!ctx->tp || ctx->tp_size < vsize) { | ||
387 | if (ctx->tp) | ||
388 | mpi_free_limb_space(ctx->tp); | ||
389 | ctx->tp = mpi_alloc_limb_space(2 * vsize); | ||
390 | if (!ctx->tp) { | ||
391 | if (ctx->tspace) | ||
392 | mpi_free_limb_space(ctx->tspace); | ||
393 | ctx->tspace = NULL; | ||
394 | return -ENOMEM; | ||
395 | } | ||
396 | ctx->tp_size = vsize; | ||
397 | } | ||
398 | |||
399 | do { | ||
400 | MPN_MUL_N_RECURSE(ctx->tp, up, vp, vsize, ctx->tspace); | ||
401 | cy = mpihelp_add_n(prodp, prodp, ctx->tp, vsize); | ||
402 | mpihelp_add_1(prodp + vsize, ctx->tp + vsize, vsize, | ||
403 | cy); | ||
404 | prodp += vsize; | ||
405 | up += vsize; | ||
406 | usize -= vsize; | ||
407 | } while (usize >= vsize); | ||
408 | } | ||
409 | |||
410 | if (usize) { | ||
411 | if (usize < KARATSUBA_THRESHOLD) { | ||
412 | mpi_limb_t tmp; | ||
413 | if (mpihelp_mul(ctx->tspace, vp, vsize, up, usize, &tmp) | ||
414 | < 0) | ||
415 | return -ENOMEM; | ||
416 | } else { | ||
417 | if (!ctx->next) { | ||
418 | ctx->next = kzalloc(sizeof *ctx, GFP_KERNEL); | ||
419 | if (!ctx->next) | ||
420 | return -ENOMEM; | ||
421 | } | ||
422 | if (mpihelp_mul_karatsuba_case(ctx->tspace, | ||
423 | vp, vsize, | ||
424 | up, usize, | ||
425 | ctx->next) < 0) | ||
426 | return -ENOMEM; | ||
427 | } | ||
428 | |||
429 | cy = mpihelp_add_n(prodp, prodp, ctx->tspace, vsize); | ||
430 | mpihelp_add_1(prodp + vsize, ctx->tspace + vsize, usize, cy); | ||
431 | } | ||
432 | |||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | void mpihelp_release_karatsuba_ctx(struct karatsuba_ctx *ctx) | ||
437 | { | ||
438 | struct karatsuba_ctx *ctx2; | ||
439 | |||
440 | if (ctx->tp) | ||
441 | mpi_free_limb_space(ctx->tp); | ||
442 | if (ctx->tspace) | ||
443 | mpi_free_limb_space(ctx->tspace); | ||
444 | for (ctx = ctx->next; ctx; ctx = ctx2) { | ||
445 | ctx2 = ctx->next; | ||
446 | if (ctx->tp) | ||
447 | mpi_free_limb_space(ctx->tp); | ||
448 | if (ctx->tspace) | ||
449 | mpi_free_limb_space(ctx->tspace); | ||
450 | kfree(ctx); | ||
451 | } | ||
452 | } | ||
453 | |||
454 | /* Multiply the natural numbers u (pointed to by UP, with USIZE limbs) | ||
455 | * and v (pointed to by VP, with VSIZE limbs), and store the result at | ||
456 | * PRODP. USIZE + VSIZE limbs are always stored, but if the input | ||
457 | * operands are normalized. Return the most significant limb of the | ||
458 | * result. | ||
459 | * | ||
460 | * NOTE: The space pointed to by PRODP is overwritten before finished | ||
461 | * with U and V, so overlap is an error. | ||
462 | * | ||
463 | * Argument constraints: | ||
464 | * 1. USIZE >= VSIZE. | ||
465 | * 2. PRODP != UP and PRODP != VP, i.e. the destination | ||
466 | * must be distinct from the multiplier and the multiplicand. | ||
467 | */ | ||
468 | |||
469 | int | ||
470 | mpihelp_mul(mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t usize, | ||
471 | mpi_ptr_t vp, mpi_size_t vsize, mpi_limb_t *_result) | ||
472 | { | ||
473 | mpi_ptr_t prod_endp = prodp + usize + vsize - 1; | ||
474 | mpi_limb_t cy; | ||
475 | struct karatsuba_ctx ctx; | ||
476 | |||
477 | if (vsize < KARATSUBA_THRESHOLD) { | ||
478 | mpi_size_t i; | ||
479 | mpi_limb_t v_limb; | ||
480 | |||
481 | if (!vsize) { | ||
482 | *_result = 0; | ||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | /* Multiply by the first limb in V separately, as the result can be | ||
487 | * stored (not added) to PROD. We also avoid a loop for zeroing. */ | ||
488 | v_limb = vp[0]; | ||
489 | if (v_limb <= 1) { | ||
490 | if (v_limb == 1) | ||
491 | MPN_COPY(prodp, up, usize); | ||
492 | else | ||
493 | MPN_ZERO(prodp, usize); | ||
494 | cy = 0; | ||
495 | } else | ||
496 | cy = mpihelp_mul_1(prodp, up, usize, v_limb); | ||
497 | |||
498 | prodp[usize] = cy; | ||
499 | prodp++; | ||
500 | |||
501 | /* For each iteration in the outer loop, multiply one limb from | ||
502 | * U with one limb from V, and add it to PROD. */ | ||
503 | for (i = 1; i < vsize; i++) { | ||
504 | v_limb = vp[i]; | ||
505 | if (v_limb <= 1) { | ||
506 | cy = 0; | ||
507 | if (v_limb == 1) | ||
508 | cy = mpihelp_add_n(prodp, prodp, up, | ||
509 | usize); | ||
510 | } else | ||
511 | cy = mpihelp_addmul_1(prodp, up, usize, v_limb); | ||
512 | |||
513 | prodp[usize] = cy; | ||
514 | prodp++; | ||
515 | } | ||
516 | |||
517 | *_result = cy; | ||
518 | return 0; | ||
519 | } | ||
520 | |||
521 | memset(&ctx, 0, sizeof ctx); | ||
522 | if (mpihelp_mul_karatsuba_case(prodp, up, usize, vp, vsize, &ctx) < 0) | ||
523 | return -ENOMEM; | ||
524 | mpihelp_release_karatsuba_ctx(&ctx); | ||
525 | *_result = *prod_endp; | ||
526 | return 0; | ||
527 | } | ||
diff --git a/lib/mpi/mpiutil.c b/lib/mpi/mpiutil.c new file mode 100644 index 000000000000..eefc55d6b7f5 --- /dev/null +++ b/lib/mpi/mpiutil.c | |||
@@ -0,0 +1,208 @@ | |||
1 | /* mpiutil.ac - Utility functions for MPI | ||
2 | * Copyright (C) 1998, 1999 Free Software Foundation, Inc. | ||
3 | * | ||
4 | * This file is part of GnuPG. | ||
5 | * | ||
6 | * GnuPG is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * GnuPG is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | ||
19 | */ | ||
20 | |||
21 | #include "mpi-internal.h" | ||
22 | |||
23 | /**************** | ||
24 | * Note: It was a bad idea to use the number of limbs to allocate | ||
25 | * because on a alpha the limbs are large but we normally need | ||
26 | * integers of n bits - So we should chnage this to bits (or bytes). | ||
27 | * | ||
28 | * But mpi_alloc is used in a lot of places :-) | ||
29 | */ | ||
30 | MPI mpi_alloc(unsigned nlimbs) | ||
31 | { | ||
32 | MPI a; | ||
33 | |||
34 | a = kmalloc(sizeof *a, GFP_KERNEL); | ||
35 | if (!a) | ||
36 | return a; | ||
37 | |||
38 | if (nlimbs) { | ||
39 | a->d = mpi_alloc_limb_space(nlimbs); | ||
40 | if (!a->d) { | ||
41 | kfree(a); | ||
42 | return NULL; | ||
43 | } | ||
44 | } else { | ||
45 | a->d = NULL; | ||
46 | } | ||
47 | |||
48 | a->alloced = nlimbs; | ||
49 | a->nlimbs = 0; | ||
50 | a->sign = 0; | ||
51 | a->flags = 0; | ||
52 | a->nbits = 0; | ||
53 | return a; | ||
54 | } | ||
55 | EXPORT_SYMBOL_GPL(mpi_alloc); | ||
56 | |||
57 | mpi_ptr_t mpi_alloc_limb_space(unsigned nlimbs) | ||
58 | { | ||
59 | size_t len = nlimbs * sizeof(mpi_limb_t); | ||
60 | |||
61 | return kmalloc(len, GFP_KERNEL); | ||
62 | } | ||
63 | |||
64 | void mpi_free_limb_space(mpi_ptr_t a) | ||
65 | { | ||
66 | if (!a) | ||
67 | return; | ||
68 | |||
69 | kfree(a); | ||
70 | } | ||
71 | |||
72 | void mpi_assign_limb_space(MPI a, mpi_ptr_t ap, unsigned nlimbs) | ||
73 | { | ||
74 | mpi_free_limb_space(a->d); | ||
75 | a->d = ap; | ||
76 | a->alloced = nlimbs; | ||
77 | } | ||
78 | |||
79 | /**************** | ||
80 | * Resize the array of A to NLIMBS. the additional space is cleared | ||
81 | * (set to 0) [done by m_realloc()] | ||
82 | */ | ||
83 | int mpi_resize(MPI a, unsigned nlimbs) | ||
84 | { | ||
85 | void *p; | ||
86 | |||
87 | if (nlimbs <= a->alloced) | ||
88 | return 0; /* no need to do it */ | ||
89 | |||
90 | if (a->d) { | ||
91 | p = kmalloc(nlimbs * sizeof(mpi_limb_t), GFP_KERNEL); | ||
92 | if (!p) | ||
93 | return -ENOMEM; | ||
94 | memcpy(p, a->d, a->alloced * sizeof(mpi_limb_t)); | ||
95 | kfree(a->d); | ||
96 | a->d = p; | ||
97 | } else { | ||
98 | a->d = kzalloc(nlimbs * sizeof(mpi_limb_t), GFP_KERNEL); | ||
99 | if (!a->d) | ||
100 | return -ENOMEM; | ||
101 | } | ||
102 | a->alloced = nlimbs; | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | void mpi_clear(MPI a) | ||
107 | { | ||
108 | a->nlimbs = 0; | ||
109 | a->nbits = 0; | ||
110 | a->flags = 0; | ||
111 | } | ||
112 | |||
113 | void mpi_free(MPI a) | ||
114 | { | ||
115 | if (!a) | ||
116 | return; | ||
117 | |||
118 | if (a->flags & 4) | ||
119 | kfree(a->d); | ||
120 | else | ||
121 | mpi_free_limb_space(a->d); | ||
122 | |||
123 | if (a->flags & ~7) | ||
124 | pr_info("invalid flag value in mpi\n"); | ||
125 | kfree(a); | ||
126 | } | ||
127 | EXPORT_SYMBOL_GPL(mpi_free); | ||
128 | |||
129 | /**************** | ||
130 | * Note: This copy function should not interpret the MPI | ||
131 | * but copy it transparently. | ||
132 | */ | ||
133 | int mpi_copy(MPI *copied, const MPI a) | ||
134 | { | ||
135 | size_t i; | ||
136 | MPI b; | ||
137 | |||
138 | *copied = MPI_NULL; | ||
139 | |||
140 | if (a) { | ||
141 | b = mpi_alloc(a->nlimbs); | ||
142 | if (!b) | ||
143 | return -ENOMEM; | ||
144 | |||
145 | b->nlimbs = a->nlimbs; | ||
146 | b->sign = a->sign; | ||
147 | b->flags = a->flags; | ||
148 | b->nbits = a->nbits; | ||
149 | |||
150 | for (i = 0; i < b->nlimbs; i++) | ||
151 | b->d[i] = a->d[i]; | ||
152 | |||
153 | *copied = b; | ||
154 | } | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | int mpi_set(MPI w, const MPI u) | ||
160 | { | ||
161 | mpi_ptr_t wp, up; | ||
162 | mpi_size_t usize = u->nlimbs; | ||
163 | int usign = u->sign; | ||
164 | |||
165 | if (RESIZE_IF_NEEDED(w, (size_t) usize) < 0) | ||
166 | return -ENOMEM; | ||
167 | |||
168 | wp = w->d; | ||
169 | up = u->d; | ||
170 | MPN_COPY(wp, up, usize); | ||
171 | w->nlimbs = usize; | ||
172 | w->nbits = u->nbits; | ||
173 | w->flags = u->flags; | ||
174 | w->sign = usign; | ||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | int mpi_set_ui(MPI w, unsigned long u) | ||
179 | { | ||
180 | if (RESIZE_IF_NEEDED(w, 1) < 0) | ||
181 | return -ENOMEM; | ||
182 | w->d[0] = u; | ||
183 | w->nlimbs = u ? 1 : 0; | ||
184 | w->sign = 0; | ||
185 | w->nbits = 0; | ||
186 | w->flags = 0; | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | MPI mpi_alloc_set_ui(unsigned long u) | ||
191 | { | ||
192 | MPI w = mpi_alloc(1); | ||
193 | if (!w) | ||
194 | return w; | ||
195 | w->d[0] = u; | ||
196 | w->nlimbs = u ? 1 : 0; | ||
197 | w->sign = 0; | ||
198 | return w; | ||
199 | } | ||
200 | |||
201 | void mpi_swap(MPI a, MPI b) | ||
202 | { | ||
203 | struct gcry_mpi tmp; | ||
204 | |||
205 | tmp = *a; | ||
206 | *a = *b; | ||
207 | *b = tmp; | ||
208 | } | ||