-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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>
- Loading branch information
Dmitry Kasatkin
committed
Nov 9, 2011
1 parent
1ea6b8f
commit cdec9cb
Showing
14 changed files
with
2,681 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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; | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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; | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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; | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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; | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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; | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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; | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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; | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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; | ||
| } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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; | ||
| } |
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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; | ||
| } |