1  /* SPDX-License-Identifier: GPL-2.0-or-later */
2  /* mpi-internal.h  -  Internal to the Multi Precision Integers
3   *	Copyright (C) 1994, 1996 Free Software Foundation, Inc.
4   *	Copyright (C) 1998, 2000 Free Software Foundation, Inc.
5   *
6   * This file is part of GnuPG.
7   *
8   * Note: This code is heavily based on the GNU MP Library.
9   *	 Actually it's the same code with only minor changes in the
10   *	 way the data is stored; this is to support the abstraction
11   *	 of an optional secure memory allocation which may be used
12   *	 to avoid revealing of sensitive data due to paging etc.
13   *	 The GNU MP Library itself is published under the LGPL;
14   *	 however I decided to publish this code under the plain GPL.
15   */
16  
17  #ifndef G10_MPI_INTERNAL_H
18  #define G10_MPI_INTERNAL_H
19  
20  #include <linux/module.h>
21  #include <linux/kernel.h>
22  #include <linux/slab.h>
23  #include <linux/string.h>
24  #include <linux/mpi.h>
25  #include <linux/errno.h>
26  
27  #define log_debug printk
28  #define log_bug printk
29  
30  #define assert(x) \
31  	do { \
32  		if (!x) \
33  			log_bug("failed assertion\n"); \
34  	} while (0);
35  
36  /* If KARATSUBA_THRESHOLD is not already defined, define it to a
37   * value which is good on most machines.  */
38  
39  /* tested 4, 16, 32 and 64, where 16 gave the best performance when
40   * checking a 768 and a 1024 bit ElGamal signature.
41   * (wk 22.12.97) */
42  #ifndef KARATSUBA_THRESHOLD
43  #define KARATSUBA_THRESHOLD 16
44  #endif
45  
46  /* The code can't handle KARATSUBA_THRESHOLD smaller than 2.  */
47  #if KARATSUBA_THRESHOLD < 2
48  #undef KARATSUBA_THRESHOLD
49  #define KARATSUBA_THRESHOLD 2
50  #endif
51  
52  typedef mpi_limb_t *mpi_ptr_t;	/* pointer to a limb */
53  typedef int mpi_size_t;		/* (must be a signed type) */
54  
RESIZE_IF_NEEDED(MPI a,unsigned b)55  static inline int RESIZE_IF_NEEDED(MPI a, unsigned b)
56  {
57  	if (a->alloced < b)
58  		return mpi_resize(a, b);
59  	return 0;
60  }
61  
62  /* Copy N limbs from S to D.  */
63  #define MPN_COPY(d, s, n) \
64  	do {					\
65  		mpi_size_t _i;			\
66  		for (_i = 0; _i < (n); _i++)	\
67  			(d)[_i] = (s)[_i];	\
68  	} while (0)
69  
70  #define MPN_COPY_DECR(d, s, n) \
71  	do {					\
72  		mpi_size_t _i;			\
73  		for (_i = (n)-1; _i >= 0; _i--) \
74  			(d)[_i] = (s)[_i];	\
75  	} while (0)
76  
77  /* Zero N limbs at D */
78  #define MPN_ZERO(d, n) \
79  	do {					\
80  		int  _i;			\
81  		for (_i = 0; _i < (n); _i++)	\
82  			(d)[_i] = 0;		\
83  	} while (0)
84  
85  #define MPN_NORMALIZE(d, n)  \
86  	do {					\
87  		while ((n) > 0) {		\
88  			if ((d)[(n)-1])		\
89  				break;		\
90  			(n)--;			\
91  		}				\
92  	} while (0)
93  
94  #define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \
95  	do {							\
96  		if ((size) < KARATSUBA_THRESHOLD)		\
97  			mul_n_basecase(prodp, up, vp, size);	\
98  		else						\
99  			mul_n(prodp, up, vp, size, tspace);	\
100  	} while (0);
101  
102  /* Divide the two-limb number in (NH,,NL) by D, with DI being the largest
103   * limb not larger than (2**(2*BITS_PER_MP_LIMB))/D - (2**BITS_PER_MP_LIMB).
104   * If this would yield overflow, DI should be the largest possible number
105   * (i.e., only ones).  For correct operation, the most significant bit of D
106   * has to be set.  Put the quotient in Q and the remainder in R.
107   */
108  #define UDIV_QRNND_PREINV(q, r, nh, nl, d, di)				\
109  	do {								\
110  		mpi_limb_t _ql __maybe_unused;				\
111  		mpi_limb_t _q, _r;					\
112  		mpi_limb_t _xh, _xl;					\
113  		umul_ppmm(_q, _ql, (nh), (di));				\
114  		_q += (nh);	/* DI is 2**BITS_PER_MPI_LIMB too small */ \
115  		umul_ppmm(_xh, _xl, _q, (d));				\
116  		sub_ddmmss(_xh, _r, (nh), (nl), _xh, _xl);		\
117  		if (_xh) {						\
118  			sub_ddmmss(_xh, _r, _xh, _r, 0, (d));		\
119  			_q++;						\
120  			if (_xh) {					\
121  				sub_ddmmss(_xh, _r, _xh, _r, 0, (d));	\
122  				_q++;					\
123  			}						\
124  		}							\
125  		if (_r >= (d)) {					\
126  			_r -= (d);					\
127  			_q++;						\
128  		}							\
129  		(r) = _r;						\
130  		(q) = _q;						\
131  	} while (0)
132  
133  
134  /*-- mpiutil.c --*/
135  mpi_ptr_t mpi_alloc_limb_space(unsigned nlimbs);
136  void mpi_free_limb_space(mpi_ptr_t a);
137  void mpi_assign_limb_space(MPI a, mpi_ptr_t ap, unsigned nlimbs);
138  
139  static inline mpi_limb_t mpihelp_add_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
140  			 mpi_size_t s1_size, mpi_limb_t s2_limb);
141  mpi_limb_t mpihelp_add_n(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
142  			 mpi_ptr_t s2_ptr, mpi_size_t size);
143  static inline mpi_limb_t mpihelp_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size,
144  		       mpi_ptr_t s2_ptr, mpi_size_t s2_size);
145  
146  static inline mpi_limb_t mpihelp_sub_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
147  			 mpi_size_t s1_size, mpi_limb_t s2_limb);
148  mpi_limb_t mpihelp_sub_n(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
149  			 mpi_ptr_t s2_ptr, mpi_size_t size);
150  static inline mpi_limb_t mpihelp_sub(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size,
151  		       mpi_ptr_t s2_ptr, mpi_size_t s2_size);
152  
153  /*-- mpih-cmp.c --*/
154  int mpihelp_cmp(mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size);
155  
156  /*-- mpih-mul.c --*/
157  
158  struct karatsuba_ctx {
159  	struct karatsuba_ctx *next;
160  	mpi_ptr_t tspace;
161  	mpi_size_t tspace_size;
162  	mpi_ptr_t tp;
163  	mpi_size_t tp_size;
164  };
165  
166  void mpihelp_release_karatsuba_ctx(struct karatsuba_ctx *ctx);
167  
168  mpi_limb_t mpihelp_addmul_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
169  			    mpi_size_t s1_size, mpi_limb_t s2_limb);
170  mpi_limb_t mpihelp_submul_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
171  			    mpi_size_t s1_size, mpi_limb_t s2_limb);
172  int mpihelp_mul(mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t usize,
173  		mpi_ptr_t vp, mpi_size_t vsize, mpi_limb_t *_result);
174  void mpih_sqr_n_basecase(mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size);
175  void mpih_sqr_n(mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size,
176  		mpi_ptr_t tspace);
177  
178  int mpihelp_mul_karatsuba_case(mpi_ptr_t prodp,
179  			       mpi_ptr_t up, mpi_size_t usize,
180  			       mpi_ptr_t vp, mpi_size_t vsize,
181  			       struct karatsuba_ctx *ctx);
182  
183  /*-- generic_mpih-mul1.c --*/
184  mpi_limb_t mpihelp_mul_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
185  			 mpi_size_t s1_size, mpi_limb_t s2_limb);
186  
187  /*-- mpih-div.c --*/
188  mpi_limb_t mpihelp_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size,
189  			 mpi_limb_t divisor_limb);
190  mpi_limb_t mpihelp_divrem(mpi_ptr_t qp, mpi_size_t qextra_limbs,
191  			  mpi_ptr_t np, mpi_size_t nsize,
192  			  mpi_ptr_t dp, mpi_size_t dsize);
193  mpi_limb_t mpihelp_divmod_1(mpi_ptr_t quot_ptr,
194  			    mpi_ptr_t dividend_ptr, mpi_size_t dividend_size,
195  			    mpi_limb_t divisor_limb);
196  
197  /*-- generic_mpih-[lr]shift.c --*/
198  mpi_limb_t mpihelp_lshift(mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize,
199  			  unsigned cnt);
200  mpi_limb_t mpihelp_rshift(mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize,
201  			  unsigned cnt);
202  
203  /* Define stuff for longlong.h.  */
204  #define W_TYPE_SIZE BITS_PER_MPI_LIMB
205  typedef mpi_limb_t UWtype;
206  typedef unsigned int UHWtype;
207  #if defined(__GNUC__)
208  typedef unsigned int UQItype __attribute__ ((mode(QI)));
209  typedef int SItype __attribute__ ((mode(SI)));
210  typedef unsigned int USItype __attribute__ ((mode(SI)));
211  typedef int DItype __attribute__ ((mode(DI)));
212  typedef unsigned int UDItype __attribute__ ((mode(DI)));
213  #else
214  typedef unsigned char UQItype;
215  typedef long SItype;
216  typedef unsigned long USItype;
217  #endif
218  
219  #ifdef __GNUC__
220  #include "mpi-inline.h"
221  #endif
222  
223  #endif /*G10_MPI_INTERNAL_H */
224