mirror of
https://github.com/armbian/linux-cix.git
synced 2026-01-06 12:30:45 -08:00
crypto: GnuPG based MPI lib - source files (part 1)
Adds the multi-precision-integer maths library which was originally taken from GnuPG and ported to the kernel by (among others) David Howells. This version is taken from Fedora kernel 2.6.32-71.14.1.el6. The difference is that checkpatch reported errors and warnings have been fixed. This library is used to implemenet RSA digital signature verification used in IMA/EVM integrity protection subsystem. Due to patch size limitation, the patch is divided into 4 parts. Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
This commit is contained in:
61
lib/mpi/generic_mpih-add1.c
Normal file
61
lib/mpi/generic_mpih-add1.c
Normal file
@@ -0,0 +1,61 @@
|
||||
/* mpihelp-add_1.c - MPI helper functions
|
||||
* Copyright (C) 1994, 1996, 1997, 1998,
|
||||
* 2000 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
* Note: This code is heavily based on the GNU MP Library.
|
||||
* Actually it's the same code with only minor changes in the
|
||||
* way the data is stored; this is to support the abstraction
|
||||
* of an optional secure memory allocation which may be used
|
||||
* to avoid revealing of sensitive data due to paging etc.
|
||||
* The GNU MP Library itself is published under the LGPL;
|
||||
* however I decided to publish this code under the plain GPL.
|
||||
*/
|
||||
|
||||
#include "mpi-internal.h"
|
||||
#include "longlong.h"
|
||||
|
||||
mpi_limb_t
|
||||
mpihelp_add_n(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
|
||||
mpi_ptr_t s2_ptr, mpi_size_t size)
|
||||
{
|
||||
mpi_limb_t x, y, cy;
|
||||
mpi_size_t j;
|
||||
|
||||
/* The loop counter and index J goes from -SIZE to -1. This way
|
||||
the loop becomes faster. */
|
||||
j = -size;
|
||||
|
||||
/* Offset the base pointers to compensate for the negative indices. */
|
||||
s1_ptr -= j;
|
||||
s2_ptr -= j;
|
||||
res_ptr -= j;
|
||||
|
||||
cy = 0;
|
||||
do {
|
||||
y = s2_ptr[j];
|
||||
x = s1_ptr[j];
|
||||
y += cy; /* add previous carry to one addend */
|
||||
cy = y < cy; /* get out carry from that addition */
|
||||
y += x; /* add other addend */
|
||||
cy += y < x; /* get out carry from that add, combine */
|
||||
res_ptr[j] = y;
|
||||
} while (++j);
|
||||
|
||||
return cy;
|
||||
}
|
||||
63
lib/mpi/generic_mpih-lshift.c
Normal file
63
lib/mpi/generic_mpih-lshift.c
Normal file
@@ -0,0 +1,63 @@
|
||||
/* mpihelp-lshift.c - MPI helper functions
|
||||
* Copyright (C) 1994, 1996, 1998, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
* Note: This code is heavily based on the GNU MP Library.
|
||||
* Actually it's the same code with only minor changes in the
|
||||
* way the data is stored; this is to support the abstraction
|
||||
* of an optional secure memory allocation which may be used
|
||||
* to avoid revealing of sensitive data due to paging etc.
|
||||
* The GNU MP Library itself is published under the LGPL;
|
||||
* however I decided to publish this code under the plain GPL.
|
||||
*/
|
||||
|
||||
#include "mpi-internal.h"
|
||||
|
||||
/* Shift U (pointed to by UP and USIZE digits long) CNT bits to the left
|
||||
* and store the USIZE least significant digits of the result at WP.
|
||||
* Return the bits shifted out from the most significant digit.
|
||||
*
|
||||
* Argument constraints:
|
||||
* 1. 0 < CNT < BITS_PER_MP_LIMB
|
||||
* 2. If the result is to be written over the input, WP must be >= UP.
|
||||
*/
|
||||
|
||||
mpi_limb_t
|
||||
mpihelp_lshift(mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, unsigned int cnt)
|
||||
{
|
||||
mpi_limb_t high_limb, low_limb;
|
||||
unsigned sh_1, sh_2;
|
||||
mpi_size_t i;
|
||||
mpi_limb_t retval;
|
||||
|
||||
sh_1 = cnt;
|
||||
wp += 1;
|
||||
sh_2 = BITS_PER_MPI_LIMB - sh_1;
|
||||
i = usize - 1;
|
||||
low_limb = up[i];
|
||||
retval = low_limb >> sh_2;
|
||||
high_limb = low_limb;
|
||||
while (--i >= 0) {
|
||||
low_limb = up[i];
|
||||
wp[i] = (high_limb << sh_1) | (low_limb >> sh_2);
|
||||
high_limb = low_limb;
|
||||
}
|
||||
wp[i] = high_limb << sh_1;
|
||||
|
||||
return retval;
|
||||
}
|
||||
57
lib/mpi/generic_mpih-mul1.c
Normal file
57
lib/mpi/generic_mpih-mul1.c
Normal file
@@ -0,0 +1,57 @@
|
||||
/* mpihelp-mul_1.c - MPI helper functions
|
||||
* Copyright (C) 1994, 1996, 1997, 1998, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
* Note: This code is heavily based on the GNU MP Library.
|
||||
* Actually it's the same code with only minor changes in the
|
||||
* way the data is stored; this is to support the abstraction
|
||||
* of an optional secure memory allocation which may be used
|
||||
* to avoid revealing of sensitive data due to paging etc.
|
||||
* The GNU MP Library itself is published under the LGPL;
|
||||
* however I decided to publish this code under the plain GPL.
|
||||
*/
|
||||
|
||||
#include "mpi-internal.h"
|
||||
#include "longlong.h"
|
||||
|
||||
mpi_limb_t
|
||||
mpihelp_mul_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size,
|
||||
mpi_limb_t s2_limb)
|
||||
{
|
||||
mpi_limb_t cy_limb;
|
||||
mpi_size_t j;
|
||||
mpi_limb_t prod_high, prod_low;
|
||||
|
||||
/* The loop counter and index J goes from -S1_SIZE to -1. This way
|
||||
* the loop becomes faster. */
|
||||
j = -s1_size;
|
||||
|
||||
/* Offset the base pointers to compensate for the negative indices. */
|
||||
s1_ptr -= j;
|
||||
res_ptr -= j;
|
||||
|
||||
cy_limb = 0;
|
||||
do {
|
||||
umul_ppmm(prod_high, prod_low, s1_ptr[j], s2_limb);
|
||||
prod_low += cy_limb;
|
||||
cy_limb = (prod_low < cy_limb ? 1 : 0) + prod_high;
|
||||
res_ptr[j] = prod_low;
|
||||
} while (++j);
|
||||
|
||||
return cy_limb;
|
||||
}
|
||||
60
lib/mpi/generic_mpih-mul2.c
Normal file
60
lib/mpi/generic_mpih-mul2.c
Normal file
@@ -0,0 +1,60 @@
|
||||
/* mpihelp-mul_2.c - MPI helper functions
|
||||
* Copyright (C) 1994, 1996, 1997, 1998, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
* Note: This code is heavily based on the GNU MP Library.
|
||||
* Actually it's the same code with only minor changes in the
|
||||
* way the data is stored; this is to support the abstraction
|
||||
* of an optional secure memory allocation which may be used
|
||||
* to avoid revealing of sensitive data due to paging etc.
|
||||
* The GNU MP Library itself is published under the LGPL;
|
||||
* however I decided to publish this code under the plain GPL.
|
||||
*/
|
||||
|
||||
#include "mpi-internal.h"
|
||||
#include "longlong.h"
|
||||
|
||||
mpi_limb_t
|
||||
mpihelp_addmul_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
|
||||
mpi_size_t s1_size, mpi_limb_t s2_limb)
|
||||
{
|
||||
mpi_limb_t cy_limb;
|
||||
mpi_size_t j;
|
||||
mpi_limb_t prod_high, prod_low;
|
||||
mpi_limb_t x;
|
||||
|
||||
/* The loop counter and index J goes from -SIZE to -1. This way
|
||||
* the loop becomes faster. */
|
||||
j = -s1_size;
|
||||
res_ptr -= j;
|
||||
s1_ptr -= j;
|
||||
|
||||
cy_limb = 0;
|
||||
do {
|
||||
umul_ppmm(prod_high, prod_low, s1_ptr[j], s2_limb);
|
||||
|
||||
prod_low += cy_limb;
|
||||
cy_limb = (prod_low < cy_limb ? 1 : 0) + prod_high;
|
||||
|
||||
x = res_ptr[j];
|
||||
prod_low = x + prod_low;
|
||||
cy_limb += prod_low < x ? 1 : 0;
|
||||
res_ptr[j] = prod_low;
|
||||
} while (++j);
|
||||
return cy_limb;
|
||||
}
|
||||
61
lib/mpi/generic_mpih-mul3.c
Normal file
61
lib/mpi/generic_mpih-mul3.c
Normal file
@@ -0,0 +1,61 @@
|
||||
/* mpihelp-mul_3.c - MPI helper functions
|
||||
* Copyright (C) 1994, 1996, 1997, 1998, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
* Note: This code is heavily based on the GNU MP Library.
|
||||
* Actually it's the same code with only minor changes in the
|
||||
* way the data is stored; this is to support the abstraction
|
||||
* of an optional secure memory allocation which may be used
|
||||
* to avoid revealing of sensitive data due to paging etc.
|
||||
* The GNU MP Library itself is published under the LGPL;
|
||||
* however I decided to publish this code under the plain GPL.
|
||||
*/
|
||||
|
||||
#include "mpi-internal.h"
|
||||
#include "longlong.h"
|
||||
|
||||
mpi_limb_t
|
||||
mpihelp_submul_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
|
||||
mpi_size_t s1_size, mpi_limb_t s2_limb)
|
||||
{
|
||||
mpi_limb_t cy_limb;
|
||||
mpi_size_t j;
|
||||
mpi_limb_t prod_high, prod_low;
|
||||
mpi_limb_t x;
|
||||
|
||||
/* The loop counter and index J goes from -SIZE to -1. This way
|
||||
* the loop becomes faster. */
|
||||
j = -s1_size;
|
||||
res_ptr -= j;
|
||||
s1_ptr -= j;
|
||||
|
||||
cy_limb = 0;
|
||||
do {
|
||||
umul_ppmm(prod_high, prod_low, s1_ptr[j], s2_limb);
|
||||
|
||||
prod_low += cy_limb;
|
||||
cy_limb = (prod_low < cy_limb ? 1 : 0) + prod_high;
|
||||
|
||||
x = res_ptr[j];
|
||||
prod_low = x - prod_low;
|
||||
cy_limb += prod_low > x ? 1 : 0;
|
||||
res_ptr[j] = prod_low;
|
||||
} while (++j);
|
||||
|
||||
return cy_limb;
|
||||
}
|
||||
63
lib/mpi/generic_mpih-rshift.c
Normal file
63
lib/mpi/generic_mpih-rshift.c
Normal file
@@ -0,0 +1,63 @@
|
||||
/* mpih-rshift.c - MPI helper functions
|
||||
* Copyright (C) 1994, 1996, 1998, 1999,
|
||||
* 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNUPG
|
||||
*
|
||||
* GNUPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GNUPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
* Note: This code is heavily based on the GNU MP Library.
|
||||
* Actually it's the same code with only minor changes in the
|
||||
* way the data is stored; this is to support the abstraction
|
||||
* of an optional secure memory allocation which may be used
|
||||
* to avoid revealing of sensitive data due to paging etc.
|
||||
* The GNU MP Library itself is published under the LGPL;
|
||||
* however I decided to publish this code under the plain GPL.
|
||||
*/
|
||||
|
||||
#include "mpi-internal.h"
|
||||
|
||||
/* Shift U (pointed to by UP and USIZE limbs long) CNT bits to the right
|
||||
* and store the USIZE least significant limbs of the result at WP.
|
||||
* The bits shifted out to the right are returned.
|
||||
*
|
||||
* Argument constraints:
|
||||
* 1. 0 < CNT < BITS_PER_MP_LIMB
|
||||
* 2. If the result is to be written over the input, WP must be <= UP.
|
||||
*/
|
||||
|
||||
mpi_limb_t
|
||||
mpihelp_rshift(mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, unsigned cnt)
|
||||
{
|
||||
mpi_limb_t high_limb, low_limb;
|
||||
unsigned sh_1, sh_2;
|
||||
mpi_size_t i;
|
||||
mpi_limb_t retval;
|
||||
|
||||
sh_1 = cnt;
|
||||
wp -= 1;
|
||||
sh_2 = BITS_PER_MPI_LIMB - sh_1;
|
||||
high_limb = up[0];
|
||||
retval = high_limb << sh_2;
|
||||
low_limb = high_limb;
|
||||
for (i = 1; i < usize; i++) {
|
||||
high_limb = up[i];
|
||||
wp[i] = (low_limb >> sh_1) | (high_limb << sh_2);
|
||||
low_limb = high_limb;
|
||||
}
|
||||
wp[i] = low_limb >> sh_1;
|
||||
|
||||
return retval;
|
||||
}
|
||||
60
lib/mpi/generic_mpih-sub1.c
Normal file
60
lib/mpi/generic_mpih-sub1.c
Normal file
@@ -0,0 +1,60 @@
|
||||
/* mpihelp-add_2.c - MPI helper functions
|
||||
* Copyright (C) 1994, 1996, 1997, 1998, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
* Note: This code is heavily based on the GNU MP Library.
|
||||
* Actually it's the same code with only minor changes in the
|
||||
* way the data is stored; this is to support the abstraction
|
||||
* of an optional secure memory allocation which may be used
|
||||
* to avoid revealing of sensitive data due to paging etc.
|
||||
* The GNU MP Library itself is published under the LGPL;
|
||||
* however I decided to publish this code under the plain GPL.
|
||||
*/
|
||||
|
||||
#include "mpi-internal.h"
|
||||
#include "longlong.h"
|
||||
|
||||
mpi_limb_t
|
||||
mpihelp_sub_n(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
|
||||
mpi_ptr_t s2_ptr, mpi_size_t size)
|
||||
{
|
||||
mpi_limb_t x, y, cy;
|
||||
mpi_size_t j;
|
||||
|
||||
/* The loop counter and index J goes from -SIZE to -1. This way
|
||||
the loop becomes faster. */
|
||||
j = -size;
|
||||
|
||||
/* Offset the base pointers to compensate for the negative indices. */
|
||||
s1_ptr -= j;
|
||||
s2_ptr -= j;
|
||||
res_ptr -= j;
|
||||
|
||||
cy = 0;
|
||||
do {
|
||||
y = s2_ptr[j];
|
||||
x = s1_ptr[j];
|
||||
y += cy; /* add previous carry to subtrahend */
|
||||
cy = y < cy; /* get out carry from that addition */
|
||||
y = x - y; /* main subtract */
|
||||
cy += y > x; /* get out carry from the subtract, combine */
|
||||
res_ptr[j] = y;
|
||||
} while (++j);
|
||||
|
||||
return cy;
|
||||
}
|
||||
236
lib/mpi/mpi-bit.c
Normal file
236
lib/mpi/mpi-bit.c
Normal file
@@ -0,0 +1,236 @@
|
||||
/* mpi-bit.c - MPI bit level fucntions
|
||||
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include "mpi-internal.h"
|
||||
#include "longlong.h"
|
||||
|
||||
const unsigned char __clz_tab[] = {
|
||||
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8,
|
||||
};
|
||||
|
||||
#define A_LIMB_1 ((mpi_limb_t) 1)
|
||||
|
||||
/****************
|
||||
* Sometimes we have MSL (most significant limbs) which are 0;
|
||||
* this is for some reasons not good, so this function removes them.
|
||||
*/
|
||||
void mpi_normalize(MPI a)
|
||||
{
|
||||
for (; a->nlimbs && !a->d[a->nlimbs - 1]; a->nlimbs--)
|
||||
;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Return the number of bits in A.
|
||||
*/
|
||||
unsigned mpi_get_nbits(MPI a)
|
||||
{
|
||||
unsigned n;
|
||||
|
||||
mpi_normalize(a);
|
||||
|
||||
if (a->nlimbs) {
|
||||
mpi_limb_t alimb = a->d[a->nlimbs - 1];
|
||||
if (alimb)
|
||||
count_leading_zeros(n, alimb);
|
||||
else
|
||||
n = BITS_PER_MPI_LIMB;
|
||||
n = BITS_PER_MPI_LIMB - n + (a->nlimbs - 1) * BITS_PER_MPI_LIMB;
|
||||
} else
|
||||
n = 0;
|
||||
return n;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mpi_get_nbits);
|
||||
|
||||
/****************
|
||||
* Test whether bit N is set.
|
||||
*/
|
||||
int mpi_test_bit(MPI a, unsigned n)
|
||||
{
|
||||
unsigned limbno, bitno;
|
||||
mpi_limb_t limb;
|
||||
|
||||
limbno = n / BITS_PER_MPI_LIMB;
|
||||
bitno = n % BITS_PER_MPI_LIMB;
|
||||
|
||||
if (limbno >= a->nlimbs)
|
||||
return 0; /* too far left: this is a 0 */
|
||||
limb = a->d[limbno];
|
||||
return (limb & (A_LIMB_1 << bitno)) ? 1 : 0;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Set bit N of A.
|
||||
*/
|
||||
int mpi_set_bit(MPI a, unsigned n)
|
||||
{
|
||||
unsigned limbno, bitno;
|
||||
|
||||
limbno = n / BITS_PER_MPI_LIMB;
|
||||
bitno = n % BITS_PER_MPI_LIMB;
|
||||
|
||||
if (limbno >= a->nlimbs) { /* resize */
|
||||
if (a->alloced >= limbno)
|
||||
if (mpi_resize(a, limbno + 1) < 0)
|
||||
return -ENOMEM;
|
||||
a->nlimbs = limbno + 1;
|
||||
}
|
||||
a->d[limbno] |= (A_LIMB_1 << bitno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Set bit N of A. and clear all bits above
|
||||
*/
|
||||
int mpi_set_highbit(MPI a, unsigned n)
|
||||
{
|
||||
unsigned limbno, bitno;
|
||||
|
||||
limbno = n / BITS_PER_MPI_LIMB;
|
||||
bitno = n % BITS_PER_MPI_LIMB;
|
||||
|
||||
if (limbno >= a->nlimbs) { /* resize */
|
||||
if (a->alloced >= limbno)
|
||||
if (mpi_resize(a, limbno + 1) < 0)
|
||||
return -ENOMEM;
|
||||
a->nlimbs = limbno + 1;
|
||||
}
|
||||
a->d[limbno] |= (A_LIMB_1 << bitno);
|
||||
for (bitno++; bitno < BITS_PER_MPI_LIMB; bitno++)
|
||||
a->d[limbno] &= ~(A_LIMB_1 << bitno);
|
||||
a->nlimbs = limbno + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************
|
||||
* clear bit N of A and all bits above
|
||||
*/
|
||||
void mpi_clear_highbit(MPI a, unsigned n)
|
||||
{
|
||||
unsigned limbno, bitno;
|
||||
|
||||
limbno = n / BITS_PER_MPI_LIMB;
|
||||
bitno = n % BITS_PER_MPI_LIMB;
|
||||
|
||||
if (limbno >= a->nlimbs)
|
||||
return; /* not allocated, so need to clear bits :-) */
|
||||
|
||||
for (; bitno < BITS_PER_MPI_LIMB; bitno++)
|
||||
a->d[limbno] &= ~(A_LIMB_1 << bitno);
|
||||
a->nlimbs = limbno + 1;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Clear bit N of A.
|
||||
*/
|
||||
void mpi_clear_bit(MPI a, unsigned n)
|
||||
{
|
||||
unsigned limbno, bitno;
|
||||
|
||||
limbno = n / BITS_PER_MPI_LIMB;
|
||||
bitno = n % BITS_PER_MPI_LIMB;
|
||||
|
||||
if (limbno >= a->nlimbs)
|
||||
return; /* don't need to clear this bit, it's to far to left */
|
||||
a->d[limbno] &= ~(A_LIMB_1 << bitno);
|
||||
}
|
||||
|
||||
/****************
|
||||
* Shift A by N bits to the right
|
||||
* FIXME: should use alloc_limb if X and A are same.
|
||||
*/
|
||||
int mpi_rshift(MPI x, MPI a, unsigned n)
|
||||
{
|
||||
mpi_ptr_t xp;
|
||||
mpi_size_t xsize;
|
||||
|
||||
xsize = a->nlimbs;
|
||||
x->sign = a->sign;
|
||||
if (RESIZE_IF_NEEDED(x, (size_t) xsize) < 0)
|
||||
return -ENOMEM;
|
||||
xp = x->d;
|
||||
|
||||
if (xsize) {
|
||||
mpihelp_rshift(xp, a->d, xsize, n);
|
||||
MPN_NORMALIZE(xp, xsize);
|
||||
}
|
||||
x->nlimbs = xsize;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Shift A by COUNT limbs to the left
|
||||
* This is used only within the MPI library
|
||||
*/
|
||||
int mpi_lshift_limbs(MPI a, unsigned int count)
|
||||
{
|
||||
mpi_ptr_t ap = a->d;
|
||||
int n = a->nlimbs;
|
||||
int i;
|
||||
|
||||
if (!count || !n)
|
||||
return 0;
|
||||
|
||||
if (RESIZE_IF_NEEDED(a, n + count) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = n - 1; i >= 0; i--)
|
||||
ap[i + count] = ap[i];
|
||||
for (i = 0; i < count; i++)
|
||||
ap[i] = 0;
|
||||
a->nlimbs += count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Shift A by COUNT limbs to the right
|
||||
* This is used only within the MPI library
|
||||
*/
|
||||
void mpi_rshift_limbs(MPI a, unsigned int count)
|
||||
{
|
||||
mpi_ptr_t ap = a->d;
|
||||
mpi_size_t n = a->nlimbs;
|
||||
unsigned int i;
|
||||
|
||||
if (count >= n) {
|
||||
a->nlimbs = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < n - count; i++)
|
||||
ap[i] = ap[i + count];
|
||||
ap[i] = 0;
|
||||
a->nlimbs -= count;
|
||||
}
|
||||
323
lib/mpi/mpi-pow.c
Normal file
323
lib/mpi/mpi-pow.c
Normal file
@@ -0,0 +1,323 @@
|
||||
/* mpi-pow.c - MPI functions
|
||||
* Copyright (C) 1994, 1996, 1998, 2000 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
* Note: This code is heavily based on the GNU MP Library.
|
||||
* Actually it's the same code with only minor changes in the
|
||||
* way the data is stored; this is to support the abstraction
|
||||
* of an optional secure memory allocation which may be used
|
||||
* to avoid revealing of sensitive data due to paging etc.
|
||||
* The GNU MP Library itself is published under the LGPL;
|
||||
* however I decided to publish this code under the plain GPL.
|
||||
*/
|
||||
|
||||
#include <linux/string.h>
|
||||
#include "mpi-internal.h"
|
||||
#include "longlong.h"
|
||||
|
||||
/****************
|
||||
* RES = BASE ^ EXP mod MOD
|
||||
*/
|
||||
int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
|
||||
{
|
||||
mpi_ptr_t mp_marker = NULL, bp_marker = NULL, ep_marker = NULL;
|
||||
mpi_ptr_t xp_marker = NULL;
|
||||
mpi_ptr_t tspace = NULL;
|
||||
mpi_ptr_t rp, ep, mp, bp;
|
||||
mpi_size_t esize, msize, bsize, rsize;
|
||||
int esign, msign, bsign, rsign;
|
||||
mpi_size_t size;
|
||||
int mod_shift_cnt;
|
||||
int negative_result;
|
||||
int assign_rp = 0;
|
||||
mpi_size_t tsize = 0; /* to avoid compiler warning */
|
||||
/* fixme: we should check that the warning is void */
|
||||
int rc = -ENOMEM;
|
||||
|
||||
esize = exp->nlimbs;
|
||||
msize = mod->nlimbs;
|
||||
size = 2 * msize;
|
||||
esign = exp->sign;
|
||||
msign = mod->sign;
|
||||
|
||||
rp = res->d;
|
||||
ep = exp->d;
|
||||
|
||||
if (!msize)
|
||||
msize = 1 / msize; /* provoke a signal */
|
||||
|
||||
if (!esize) {
|
||||
/* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0
|
||||
* depending on if MOD equals 1. */
|
||||
rp[0] = 1;
|
||||
res->nlimbs = (msize == 1 && mod->d[0] == 1) ? 0 : 1;
|
||||
res->sign = 0;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Normalize MOD (i.e. make its most significant bit set) as required by
|
||||
* mpn_divrem. This will make the intermediate values in the calculation
|
||||
* slightly larger, but the correct result is obtained after a final
|
||||
* reduction using the original MOD value. */
|
||||
mp = mp_marker = mpi_alloc_limb_space(msize);
|
||||
if (!mp)
|
||||
goto enomem;
|
||||
count_leading_zeros(mod_shift_cnt, mod->d[msize - 1]);
|
||||
if (mod_shift_cnt)
|
||||
mpihelp_lshift(mp, mod->d, msize, mod_shift_cnt);
|
||||
else
|
||||
MPN_COPY(mp, mod->d, msize);
|
||||
|
||||
bsize = base->nlimbs;
|
||||
bsign = base->sign;
|
||||
if (bsize > msize) { /* The base is larger than the module. Reduce it. */
|
||||
/* Allocate (BSIZE + 1) with space for remainder and quotient.
|
||||
* (The quotient is (bsize - msize + 1) limbs.) */
|
||||
bp = bp_marker = mpi_alloc_limb_space(bsize + 1);
|
||||
if (!bp)
|
||||
goto enomem;
|
||||
MPN_COPY(bp, base->d, bsize);
|
||||
/* We don't care about the quotient, store it above the remainder,
|
||||
* at BP + MSIZE. */
|
||||
mpihelp_divrem(bp + msize, 0, bp, bsize, mp, msize);
|
||||
bsize = msize;
|
||||
/* Canonicalize the base, since we are going to multiply with it
|
||||
* quite a few times. */
|
||||
MPN_NORMALIZE(bp, bsize);
|
||||
} else
|
||||
bp = base->d;
|
||||
|
||||
if (!bsize) {
|
||||
res->nlimbs = 0;
|
||||
res->sign = 0;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (res->alloced < size) {
|
||||
/* We have to allocate more space for RES. If any of the input
|
||||
* parameters are identical to RES, defer deallocation of the old
|
||||
* space. */
|
||||
if (rp == ep || rp == mp || rp == bp) {
|
||||
rp = mpi_alloc_limb_space(size);
|
||||
if (!rp)
|
||||
goto enomem;
|
||||
assign_rp = 1;
|
||||
} else {
|
||||
if (mpi_resize(res, size) < 0)
|
||||
goto enomem;
|
||||
rp = res->d;
|
||||
}
|
||||
} else { /* Make BASE, EXP and MOD not overlap with RES. */
|
||||
if (rp == bp) {
|
||||
/* RES and BASE are identical. Allocate temp. space for BASE. */
|
||||
BUG_ON(bp_marker);
|
||||
bp = bp_marker = mpi_alloc_limb_space(bsize);
|
||||
if (!bp)
|
||||
goto enomem;
|
||||
MPN_COPY(bp, rp, bsize);
|
||||
}
|
||||
if (rp == ep) {
|
||||
/* RES and EXP are identical. Allocate temp. space for EXP. */
|
||||
ep = ep_marker = mpi_alloc_limb_space(esize);
|
||||
if (!ep)
|
||||
goto enomem;
|
||||
MPN_COPY(ep, rp, esize);
|
||||
}
|
||||
if (rp == mp) {
|
||||
/* RES and MOD are identical. Allocate temporary space for MOD. */
|
||||
BUG_ON(mp_marker);
|
||||
mp = mp_marker = mpi_alloc_limb_space(msize);
|
||||
if (!mp)
|
||||
goto enomem;
|
||||
MPN_COPY(mp, rp, msize);
|
||||
}
|
||||
}
|
||||
|
||||
MPN_COPY(rp, bp, bsize);
|
||||
rsize = bsize;
|
||||
rsign = bsign;
|
||||
|
||||
{
|
||||
mpi_size_t i;
|
||||
mpi_ptr_t xp;
|
||||
int c;
|
||||
mpi_limb_t e;
|
||||
mpi_limb_t carry_limb;
|
||||
struct karatsuba_ctx karactx;
|
||||
|
||||
xp = xp_marker = mpi_alloc_limb_space(2 * (msize + 1));
|
||||
if (!xp)
|
||||
goto enomem;
|
||||
|
||||
memset(&karactx, 0, sizeof karactx);
|
||||
negative_result = (ep[0] & 1) && base->sign;
|
||||
|
||||
i = esize - 1;
|
||||
e = ep[i];
|
||||
count_leading_zeros(c, e);
|
||||
e = (e << c) << 1; /* shift the exp bits to the left, lose msb */
|
||||
c = BITS_PER_MPI_LIMB - 1 - c;
|
||||
|
||||
/* Main loop.
|
||||
*
|
||||
* Make the result be pointed to alternately by XP and RP. This
|
||||
* helps us avoid block copying, which would otherwise be necessary
|
||||
* with the overlap restrictions of mpihelp_divmod. With 50% probability
|
||||
* the result after this loop will be in the area originally pointed
|
||||
* by RP (==RES->d), and with 50% probability in the area originally
|
||||
* pointed to by XP.
|
||||
*/
|
||||
|
||||
for (;;) {
|
||||
while (c) {
|
||||
mpi_ptr_t tp;
|
||||
mpi_size_t xsize;
|
||||
|
||||
/*if (mpihelp_mul_n(xp, rp, rp, rsize) < 0) goto enomem */
|
||||
if (rsize < KARATSUBA_THRESHOLD)
|
||||
mpih_sqr_n_basecase(xp, rp, rsize);
|
||||
else {
|
||||
if (!tspace) {
|
||||
tsize = 2 * rsize;
|
||||
tspace =
|
||||
mpi_alloc_limb_space(tsize);
|
||||
if (!tspace)
|
||||
goto enomem;
|
||||
} else if (tsize < (2 * rsize)) {
|
||||
mpi_free_limb_space(tspace);
|
||||
tsize = 2 * rsize;
|
||||
tspace =
|
||||
mpi_alloc_limb_space(tsize);
|
||||
if (!tspace)
|
||||
goto enomem;
|
||||
}
|
||||
mpih_sqr_n(xp, rp, rsize, tspace);
|
||||
}
|
||||
|
||||
xsize = 2 * rsize;
|
||||
if (xsize > msize) {
|
||||
mpihelp_divrem(xp + msize, 0, xp, xsize,
|
||||
mp, msize);
|
||||
xsize = msize;
|
||||
}
|
||||
|
||||
tp = rp;
|
||||
rp = xp;
|
||||
xp = tp;
|
||||
rsize = xsize;
|
||||
|
||||
if ((mpi_limb_signed_t) e < 0) {
|
||||
/*mpihelp_mul( xp, rp, rsize, bp, bsize ); */
|
||||
if (bsize < KARATSUBA_THRESHOLD) {
|
||||
mpi_limb_t tmp;
|
||||
if (mpihelp_mul
|
||||
(xp, rp, rsize, bp, bsize,
|
||||
&tmp) < 0)
|
||||
goto enomem;
|
||||
} else {
|
||||
if (mpihelp_mul_karatsuba_case
|
||||
(xp, rp, rsize, bp, bsize,
|
||||
&karactx) < 0)
|
||||
goto enomem;
|
||||
}
|
||||
|
||||
xsize = rsize + bsize;
|
||||
if (xsize > msize) {
|
||||
mpihelp_divrem(xp + msize, 0,
|
||||
xp, xsize, mp,
|
||||
msize);
|
||||
xsize = msize;
|
||||
}
|
||||
|
||||
tp = rp;
|
||||
rp = xp;
|
||||
xp = tp;
|
||||
rsize = xsize;
|
||||
}
|
||||
e <<= 1;
|
||||
c--;
|
||||
}
|
||||
|
||||
i--;
|
||||
if (i < 0)
|
||||
break;
|
||||
e = ep[i];
|
||||
c = BITS_PER_MPI_LIMB;
|
||||
}
|
||||
|
||||
/* We shifted MOD, the modulo reduction argument, left MOD_SHIFT_CNT
|
||||
* steps. Adjust the result by reducing it with the original MOD.
|
||||
*
|
||||
* Also make sure the result is put in RES->d (where it already
|
||||
* might be, see above).
|
||||
*/
|
||||
if (mod_shift_cnt) {
|
||||
carry_limb =
|
||||
mpihelp_lshift(res->d, rp, rsize, mod_shift_cnt);
|
||||
rp = res->d;
|
||||
if (carry_limb) {
|
||||
rp[rsize] = carry_limb;
|
||||
rsize++;
|
||||
}
|
||||
} else {
|
||||
MPN_COPY(res->d, rp, rsize);
|
||||
rp = res->d;
|
||||
}
|
||||
|
||||
if (rsize >= msize) {
|
||||
mpihelp_divrem(rp + msize, 0, rp, rsize, mp, msize);
|
||||
rsize = msize;
|
||||
}
|
||||
|
||||
/* Remove any leading zero words from the result. */
|
||||
if (mod_shift_cnt)
|
||||
mpihelp_rshift(rp, rp, rsize, mod_shift_cnt);
|
||||
MPN_NORMALIZE(rp, rsize);
|
||||
|
||||
mpihelp_release_karatsuba_ctx(&karactx);
|
||||
}
|
||||
|
||||
if (negative_result && rsize) {
|
||||
if (mod_shift_cnt)
|
||||
mpihelp_rshift(mp, mp, msize, mod_shift_cnt);
|
||||
mpihelp_sub(rp, mp, msize, rp, rsize);
|
||||
rsize = msize;
|
||||
rsign = msign;
|
||||
MPN_NORMALIZE(rp, rsize);
|
||||
}
|
||||
res->nlimbs = rsize;
|
||||
res->sign = rsign;
|
||||
|
||||
leave:
|
||||
rc = 0;
|
||||
enomem:
|
||||
if (assign_rp)
|
||||
mpi_assign_limb_space(res, rp, size);
|
||||
if (mp_marker)
|
||||
mpi_free_limb_space(mp_marker);
|
||||
if (bp_marker)
|
||||
mpi_free_limb_space(bp_marker);
|
||||
if (ep_marker)
|
||||
mpi_free_limb_space(ep_marker);
|
||||
if (xp_marker)
|
||||
mpi_free_limb_space(xp_marker);
|
||||
if (tspace)
|
||||
mpi_free_limb_space(tspace);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mpi_powm);
|
||||
365
lib/mpi/mpicoder.c
Normal file
365
lib/mpi/mpicoder.c
Normal file
@@ -0,0 +1,365 @@
|
||||
/* mpicoder.c - Coder for the external representation of MPIs
|
||||
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include "mpi-internal.h"
|
||||
|
||||
#define DIM(v) (sizeof(v)/sizeof((v)[0]))
|
||||
#define MAX_EXTERN_MPI_BITS 16384
|
||||
|
||||
static uint8_t asn[15] = /* Object ID is 1.3.14.3.2.26 */
|
||||
{ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
|
||||
0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
|
||||
};
|
||||
|
||||
MPI do_encode_md(const void *sha_buffer, unsigned nbits)
|
||||
{
|
||||
int nframe = (nbits + 7) / 8;
|
||||
uint8_t *frame, *fr_pt;
|
||||
int i = 0, n;
|
||||
size_t asnlen = DIM(asn);
|
||||
MPI a = MPI_NULL;
|
||||
|
||||
if (SHA1_DIGEST_LENGTH + asnlen + 4 > nframe)
|
||||
pr_info("MPI: can't encode a %d bit MD into a %d bits frame\n",
|
||||
(int)(SHA1_DIGEST_LENGTH * 8), (int)nbits);
|
||||
|
||||
/* We encode the MD in this way:
|
||||
*
|
||||
* 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes)
|
||||
*
|
||||
* PAD consists of FF bytes.
|
||||
*/
|
||||
frame = kmalloc(nframe, GFP_KERNEL);
|
||||
if (!frame)
|
||||
return MPI_NULL;
|
||||
n = 0;
|
||||
frame[n++] = 0;
|
||||
frame[n++] = 1; /* block type */
|
||||
i = nframe - SHA1_DIGEST_LENGTH - asnlen - 3;
|
||||
|
||||
if (i <= 1) {
|
||||
pr_info("MPI: message digest encoding failed\n");
|
||||
kfree(frame);
|
||||
return a;
|
||||
}
|
||||
|
||||
memset(frame + n, 0xff, i);
|
||||
n += i;
|
||||
frame[n++] = 0;
|
||||
memcpy(frame + n, &asn, asnlen);
|
||||
n += asnlen;
|
||||
memcpy(frame + n, sha_buffer, SHA1_DIGEST_LENGTH);
|
||||
n += SHA1_DIGEST_LENGTH;
|
||||
|
||||
i = nframe;
|
||||
fr_pt = frame;
|
||||
|
||||
if (n != nframe) {
|
||||
printk
|
||||
("MPI: message digest encoding failed, frame length is wrong\n");
|
||||
kfree(frame);
|
||||
return a;
|
||||
}
|
||||
|
||||
a = mpi_alloc((nframe + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB);
|
||||
mpi_set_buffer(a, frame, nframe, 0);
|
||||
kfree(frame);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread)
|
||||
{
|
||||
const uint8_t *buffer = xbuffer;
|
||||
int i, j;
|
||||
unsigned nbits, nbytes, nlimbs, nread = 0;
|
||||
mpi_limb_t a;
|
||||
MPI val = MPI_NULL;
|
||||
|
||||
if (*ret_nread < 2)
|
||||
goto leave;
|
||||
nbits = buffer[0] << 8 | buffer[1];
|
||||
|
||||
if (nbits > MAX_EXTERN_MPI_BITS) {
|
||||
pr_info("MPI: mpi too large (%u bits)\n", nbits);
|
||||
goto leave;
|
||||
}
|
||||
buffer += 2;
|
||||
nread = 2;
|
||||
|
||||
nbytes = (nbits + 7) / 8;
|
||||
nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
|
||||
val = mpi_alloc(nlimbs);
|
||||
if (!val)
|
||||
return MPI_NULL;
|
||||
i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
|
||||
i %= BYTES_PER_MPI_LIMB;
|
||||
val->nbits = nbits;
|
||||
j = val->nlimbs = nlimbs;
|
||||
val->sign = 0;
|
||||
for (; j > 0; j--) {
|
||||
a = 0;
|
||||
for (; i < BYTES_PER_MPI_LIMB; i++) {
|
||||
if (++nread > *ret_nread) {
|
||||
printk
|
||||
("MPI: mpi larger than buffer nread=%d ret_nread=%d\n",
|
||||
nread, *ret_nread);
|
||||
goto leave;
|
||||
}
|
||||
a <<= 8;
|
||||
a |= *buffer++;
|
||||
}
|
||||
i = 0;
|
||||
val->d[j - 1] = a;
|
||||
}
|
||||
|
||||
leave:
|
||||
*ret_nread = nread;
|
||||
return val;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mpi_read_from_buffer);
|
||||
|
||||
/****************
|
||||
* Make an mpi from a character string.
|
||||
*/
|
||||
int mpi_fromstr(MPI val, const char *str)
|
||||
{
|
||||
int hexmode = 0, sign = 0, prepend_zero = 0, i, j, c, c1, c2;
|
||||
unsigned nbits, nbytes, nlimbs;
|
||||
mpi_limb_t a;
|
||||
|
||||
if (*str == '-') {
|
||||
sign = 1;
|
||||
str++;
|
||||
}
|
||||
if (*str == '0' && str[1] == 'x')
|
||||
hexmode = 1;
|
||||
else
|
||||
return -EINVAL; /* other bases are not yet supported */
|
||||
str += 2;
|
||||
|
||||
nbits = strlen(str) * 4;
|
||||
if (nbits % 8)
|
||||
prepend_zero = 1;
|
||||
nbytes = (nbits + 7) / 8;
|
||||
nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
|
||||
if (val->alloced < nlimbs)
|
||||
if (!mpi_resize(val, nlimbs))
|
||||
return -ENOMEM;
|
||||
i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
|
||||
i %= BYTES_PER_MPI_LIMB;
|
||||
j = val->nlimbs = nlimbs;
|
||||
val->sign = sign;
|
||||
for (; j > 0; j--) {
|
||||
a = 0;
|
||||
for (; i < BYTES_PER_MPI_LIMB; i++) {
|
||||
if (prepend_zero) {
|
||||
c1 = '0';
|
||||
prepend_zero = 0;
|
||||
} else
|
||||
c1 = *str++;
|
||||
assert(c1);
|
||||
c2 = *str++;
|
||||
assert(c2);
|
||||
if (c1 >= '0' && c1 <= '9')
|
||||
c = c1 - '0';
|
||||
else if (c1 >= 'a' && c1 <= 'f')
|
||||
c = c1 - 'a' + 10;
|
||||
else if (c1 >= 'A' && c1 <= 'F')
|
||||
c = c1 - 'A' + 10;
|
||||
else {
|
||||
mpi_clear(val);
|
||||
return 1;
|
||||
}
|
||||
c <<= 4;
|
||||
if (c2 >= '0' && c2 <= '9')
|
||||
c |= c2 - '0';
|
||||
else if (c2 >= 'a' && c2 <= 'f')
|
||||
c |= c2 - 'a' + 10;
|
||||
else if (c2 >= 'A' && c2 <= 'F')
|
||||
c |= c2 - 'A' + 10;
|
||||
else {
|
||||
mpi_clear(val);
|
||||
return 1;
|
||||
}
|
||||
a <<= 8;
|
||||
a |= c;
|
||||
}
|
||||
i = 0;
|
||||
|
||||
val->d[j - 1] = a;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mpi_fromstr);
|
||||
|
||||
/****************
|
||||
* Special function to get the low 8 bytes from an mpi.
|
||||
* This can be used as a keyid; KEYID is an 2 element array.
|
||||
* Return the low 4 bytes.
|
||||
*/
|
||||
u32 mpi_get_keyid(const MPI a, u32 *keyid)
|
||||
{
|
||||
#if BYTES_PER_MPI_LIMB == 4
|
||||
if (keyid) {
|
||||
keyid[0] = a->nlimbs >= 2 ? a->d[1] : 0;
|
||||
keyid[1] = a->nlimbs >= 1 ? a->d[0] : 0;
|
||||
}
|
||||
return a->nlimbs >= 1 ? a->d[0] : 0;
|
||||
#elif BYTES_PER_MPI_LIMB == 8
|
||||
if (keyid) {
|
||||
keyid[0] = a->nlimbs ? (u32) (a->d[0] >> 32) : 0;
|
||||
keyid[1] = a->nlimbs ? (u32) (a->d[0] & 0xffffffff) : 0;
|
||||
}
|
||||
return a->nlimbs ? (u32) (a->d[0] & 0xffffffff) : 0;
|
||||
#else
|
||||
#error Make this function work with other LIMB sizes
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************
|
||||
* Return an allocated buffer with the MPI (msb first).
|
||||
* NBYTES receives the length of this buffer. Caller must free the
|
||||
* return string (This function does return a 0 byte buffer with NBYTES
|
||||
* set to zero if the value of A is zero. If sign is not NULL, it will
|
||||
* be set to the sign of the A.
|
||||
*/
|
||||
void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign)
|
||||
{
|
||||
uint8_t *p, *buffer;
|
||||
mpi_limb_t alimb;
|
||||
int i;
|
||||
unsigned int n;
|
||||
|
||||
if (sign)
|
||||
*sign = a->sign;
|
||||
*nbytes = n = a->nlimbs * BYTES_PER_MPI_LIMB;
|
||||
if (!n)
|
||||
n++; /* avoid zero length allocation */
|
||||
p = buffer = kmalloc(n, GFP_KERNEL);
|
||||
|
||||
for (i = a->nlimbs - 1; i >= 0; i--) {
|
||||
alimb = a->d[i];
|
||||
#if BYTES_PER_MPI_LIMB == 4
|
||||
*p++ = alimb >> 24;
|
||||
*p++ = alimb >> 16;
|
||||
*p++ = alimb >> 8;
|
||||
*p++ = alimb;
|
||||
#elif BYTES_PER_MPI_LIMB == 8
|
||||
*p++ = alimb >> 56;
|
||||
*p++ = alimb >> 48;
|
||||
*p++ = alimb >> 40;
|
||||
*p++ = alimb >> 32;
|
||||
*p++ = alimb >> 24;
|
||||
*p++ = alimb >> 16;
|
||||
*p++ = alimb >> 8;
|
||||
*p++ = alimb;
|
||||
#else
|
||||
#error please implement for this limb size.
|
||||
#endif
|
||||
}
|
||||
|
||||
/* this is sub-optimal but we need to do the shift operation
|
||||
* because the caller has to free the returned buffer */
|
||||
for (p = buffer; !*p && *nbytes; p++, --*nbytes)
|
||||
;
|
||||
if (p != buffer)
|
||||
memmove(buffer, p, *nbytes);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mpi_get_buffer);
|
||||
|
||||
/****************
|
||||
* Use BUFFER to update MPI.
|
||||
*/
|
||||
int mpi_set_buffer(MPI a, const void *xbuffer, unsigned nbytes, int sign)
|
||||
{
|
||||
const uint8_t *buffer = xbuffer, *p;
|
||||
mpi_limb_t alimb;
|
||||
int nlimbs;
|
||||
int i;
|
||||
|
||||
nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
|
||||
if (RESIZE_IF_NEEDED(a, nlimbs) < 0)
|
||||
return -ENOMEM;
|
||||
a->sign = sign;
|
||||
|
||||
for (i = 0, p = buffer + nbytes - 1; p >= buffer + BYTES_PER_MPI_LIMB;) {
|
||||
#if BYTES_PER_MPI_LIMB == 4
|
||||
alimb = (mpi_limb_t) *p--;
|
||||
alimb |= (mpi_limb_t) *p-- << 8;
|
||||
alimb |= (mpi_limb_t) *p-- << 16;
|
||||
alimb |= (mpi_limb_t) *p-- << 24;
|
||||
#elif BYTES_PER_MPI_LIMB == 8
|
||||
alimb = (mpi_limb_t) *p--;
|
||||
alimb |= (mpi_limb_t) *p-- << 8;
|
||||
alimb |= (mpi_limb_t) *p-- << 16;
|
||||
alimb |= (mpi_limb_t) *p-- << 24;
|
||||
alimb |= (mpi_limb_t) *p-- << 32;
|
||||
alimb |= (mpi_limb_t) *p-- << 40;
|
||||
alimb |= (mpi_limb_t) *p-- << 48;
|
||||
alimb |= (mpi_limb_t) *p-- << 56;
|
||||
#else
|
||||
#error please implement for this limb size.
|
||||
#endif
|
||||
a->d[i++] = alimb;
|
||||
}
|
||||
if (p >= buffer) {
|
||||
#if BYTES_PER_MPI_LIMB == 4
|
||||
alimb = *p--;
|
||||
if (p >= buffer)
|
||||
alimb |= (mpi_limb_t) *p-- << 8;
|
||||
if (p >= buffer)
|
||||
alimb |= (mpi_limb_t) *p-- << 16;
|
||||
if (p >= buffer)
|
||||
alimb |= (mpi_limb_t) *p-- << 24;
|
||||
#elif BYTES_PER_MPI_LIMB == 8
|
||||
alimb = (mpi_limb_t) *p--;
|
||||
if (p >= buffer)
|
||||
alimb |= (mpi_limb_t) *p-- << 8;
|
||||
if (p >= buffer)
|
||||
alimb |= (mpi_limb_t) *p-- << 16;
|
||||
if (p >= buffer)
|
||||
alimb |= (mpi_limb_t) *p-- << 24;
|
||||
if (p >= buffer)
|
||||
alimb |= (mpi_limb_t) *p-- << 32;
|
||||
if (p >= buffer)
|
||||
alimb |= (mpi_limb_t) *p-- << 40;
|
||||
if (p >= buffer)
|
||||
alimb |= (mpi_limb_t) *p-- << 48;
|
||||
if (p >= buffer)
|
||||
alimb |= (mpi_limb_t) *p-- << 56;
|
||||
#else
|
||||
#error please implement for this limb size.
|
||||
#endif
|
||||
a->d[i++] = alimb;
|
||||
}
|
||||
a->nlimbs = i;
|
||||
|
||||
if (i != nlimbs) {
|
||||
pr_emerg("MPI: mpi_set_buffer: Assertion failed (%d != %d)", i,
|
||||
nlimbs);
|
||||
BUG();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mpi_set_buffer);
|
||||
56
lib/mpi/mpih-cmp.c
Normal file
56
lib/mpi/mpih-cmp.c
Normal file
@@ -0,0 +1,56 @@
|
||||
/* mpihelp-sub.c - MPI helper functions
|
||||
* Copyright (C) 1994, 1996 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
* Note: This code is heavily based on the GNU MP Library.
|
||||
* Actually it's the same code with only minor changes in the
|
||||
* way the data is stored; this is to support the abstraction
|
||||
* of an optional secure memory allocation which may be used
|
||||
* to avoid revealing of sensitive data due to paging etc.
|
||||
* The GNU MP Library itself is published under the LGPL;
|
||||
* however I decided to publish this code under the plain GPL.
|
||||
*/
|
||||
|
||||
#include "mpi-internal.h"
|
||||
|
||||
/****************
|
||||
* Compare OP1_PTR/OP1_SIZE with OP2_PTR/OP2_SIZE.
|
||||
* There are no restrictions on the relative sizes of
|
||||
* the two arguments.
|
||||
* Return 1 if OP1 > OP2, 0 if they are equal, and -1 if OP1 < OP2.
|
||||
*/
|
||||
int mpihelp_cmp(mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size)
|
||||
{
|
||||
mpi_size_t i;
|
||||
mpi_limb_t op1_word, op2_word;
|
||||
|
||||
for (i = size - 1; i >= 0; i--) {
|
||||
op1_word = op1_ptr[i];
|
||||
op2_word = op2_ptr[i];
|
||||
if (op1_word != op2_word)
|
||||
goto diff;
|
||||
}
|
||||
return 0;
|
||||
|
||||
diff:
|
||||
/* This can *not* be simplified to
|
||||
* op2_word - op2_word
|
||||
* since that expression might give signed overflow. */
|
||||
return (op1_word > op2_word) ? 1 : -1;
|
||||
}
|
||||
541
lib/mpi/mpih-div.c
Normal file
541
lib/mpi/mpih-div.c
Normal file
File diff suppressed because it is too large
Load Diff
527
lib/mpi/mpih-mul.c
Normal file
527
lib/mpi/mpih-mul.c
Normal file
File diff suppressed because it is too large
Load Diff
208
lib/mpi/mpiutil.c
Normal file
208
lib/mpi/mpiutil.c
Normal file
@@ -0,0 +1,208 @@
|
||||
/* mpiutil.ac - Utility functions for MPI
|
||||
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include "mpi-internal.h"
|
||||
|
||||
/****************
|
||||
* Note: It was a bad idea to use the number of limbs to allocate
|
||||
* because on a alpha the limbs are large but we normally need
|
||||
* integers of n bits - So we should chnage this to bits (or bytes).
|
||||
*
|
||||
* But mpi_alloc is used in a lot of places :-)
|
||||
*/
|
||||
MPI mpi_alloc(unsigned nlimbs)
|
||||
{
|
||||
MPI a;
|
||||
|
||||
a = kmalloc(sizeof *a, GFP_KERNEL);
|
||||
if (!a)
|
||||
return a;
|
||||
|
||||
if (nlimbs) {
|
||||
a->d = mpi_alloc_limb_space(nlimbs);
|
||||
if (!a->d) {
|
||||
kfree(a);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
a->d = NULL;
|
||||
}
|
||||
|
||||
a->alloced = nlimbs;
|
||||
a->nlimbs = 0;
|
||||
a->sign = 0;
|
||||
a->flags = 0;
|
||||
a->nbits = 0;
|
||||
return a;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mpi_alloc);
|
||||
|
||||
mpi_ptr_t mpi_alloc_limb_space(unsigned nlimbs)
|
||||
{
|
||||
size_t len = nlimbs * sizeof(mpi_limb_t);
|
||||
|
||||
return kmalloc(len, GFP_KERNEL);
|
||||
}
|
||||
|
||||
void mpi_free_limb_space(mpi_ptr_t a)
|
||||
{
|
||||
if (!a)
|
||||
return;
|
||||
|
||||
kfree(a);
|
||||
}
|
||||
|
||||
void mpi_assign_limb_space(MPI a, mpi_ptr_t ap, unsigned nlimbs)
|
||||
{
|
||||
mpi_free_limb_space(a->d);
|
||||
a->d = ap;
|
||||
a->alloced = nlimbs;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Resize the array of A to NLIMBS. the additional space is cleared
|
||||
* (set to 0) [done by m_realloc()]
|
||||
*/
|
||||
int mpi_resize(MPI a, unsigned nlimbs)
|
||||
{
|
||||
void *p;
|
||||
|
||||
if (nlimbs <= a->alloced)
|
||||
return 0; /* no need to do it */
|
||||
|
||||
if (a->d) {
|
||||
p = kmalloc(nlimbs * sizeof(mpi_limb_t), GFP_KERNEL);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
memcpy(p, a->d, a->alloced * sizeof(mpi_limb_t));
|
||||
kfree(a->d);
|
||||
a->d = p;
|
||||
} else {
|
||||
a->d = kzalloc(nlimbs * sizeof(mpi_limb_t), GFP_KERNEL);
|
||||
if (!a->d)
|
||||
return -ENOMEM;
|
||||
}
|
||||
a->alloced = nlimbs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mpi_clear(MPI a)
|
||||
{
|
||||
a->nlimbs = 0;
|
||||
a->nbits = 0;
|
||||
a->flags = 0;
|
||||
}
|
||||
|
||||
void mpi_free(MPI a)
|
||||
{
|
||||
if (!a)
|
||||
return;
|
||||
|
||||
if (a->flags & 4)
|
||||
kfree(a->d);
|
||||
else
|
||||
mpi_free_limb_space(a->d);
|
||||
|
||||
if (a->flags & ~7)
|
||||
pr_info("invalid flag value in mpi\n");
|
||||
kfree(a);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mpi_free);
|
||||
|
||||
/****************
|
||||
* Note: This copy function should not interpret the MPI
|
||||
* but copy it transparently.
|
||||
*/
|
||||
int mpi_copy(MPI *copied, const MPI a)
|
||||
{
|
||||
size_t i;
|
||||
MPI b;
|
||||
|
||||
*copied = MPI_NULL;
|
||||
|
||||
if (a) {
|
||||
b = mpi_alloc(a->nlimbs);
|
||||
if (!b)
|
||||
return -ENOMEM;
|
||||
|
||||
b->nlimbs = a->nlimbs;
|
||||
b->sign = a->sign;
|
||||
b->flags = a->flags;
|
||||
b->nbits = a->nbits;
|
||||
|
||||
for (i = 0; i < b->nlimbs; i++)
|
||||
b->d[i] = a->d[i];
|
||||
|
||||
*copied = b;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mpi_set(MPI w, const MPI u)
|
||||
{
|
||||
mpi_ptr_t wp, up;
|
||||
mpi_size_t usize = u->nlimbs;
|
||||
int usign = u->sign;
|
||||
|
||||
if (RESIZE_IF_NEEDED(w, (size_t) usize) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
wp = w->d;
|
||||
up = u->d;
|
||||
MPN_COPY(wp, up, usize);
|
||||
w->nlimbs = usize;
|
||||
w->nbits = u->nbits;
|
||||
w->flags = u->flags;
|
||||
w->sign = usign;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mpi_set_ui(MPI w, unsigned long u)
|
||||
{
|
||||
if (RESIZE_IF_NEEDED(w, 1) < 0)
|
||||
return -ENOMEM;
|
||||
w->d[0] = u;
|
||||
w->nlimbs = u ? 1 : 0;
|
||||
w->sign = 0;
|
||||
w->nbits = 0;
|
||||
w->flags = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
MPI mpi_alloc_set_ui(unsigned long u)
|
||||
{
|
||||
MPI w = mpi_alloc(1);
|
||||
if (!w)
|
||||
return w;
|
||||
w->d[0] = u;
|
||||
w->nlimbs = u ? 1 : 0;
|
||||
w->sign = 0;
|
||||
return w;
|
||||
}
|
||||
|
||||
void mpi_swap(MPI a, MPI b)
|
||||
{
|
||||
struct gcry_mpi tmp;
|
||||
|
||||
tmp = *a;
|
||||
*a = *b;
|
||||
*b = tmp;
|
||||
}
|
||||
Reference in New Issue
Block a user