Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /* mpi-internal.h  -  Internal to the Multi Precision Integers
0003  *  Copyright (C) 1994, 1996 Free Software Foundation, Inc.
0004  *  Copyright (C) 1998, 2000 Free Software Foundation, Inc.
0005  *
0006  * This file is part of GnuPG.
0007  *
0008  * Note: This code is heavily based on the GNU MP Library.
0009  *   Actually it's the same code with only minor changes in the
0010  *   way the data is stored; this is to support the abstraction
0011  *   of an optional secure memory allocation which may be used
0012  *   to avoid revealing of sensitive data due to paging etc.
0013  *   The GNU MP Library itself is published under the LGPL;
0014  *   however I decided to publish this code under the plain GPL.
0015  */
0016 
0017 #ifndef G10_MPI_INTERNAL_H
0018 #define G10_MPI_INTERNAL_H
0019 
0020 #include <linux/module.h>
0021 #include <linux/kernel.h>
0022 #include <linux/slab.h>
0023 #include <linux/string.h>
0024 #include <linux/mpi.h>
0025 #include <linux/errno.h>
0026 
0027 #define log_debug printk
0028 #define log_bug printk
0029 
0030 #define assert(x) \
0031     do { \
0032         if (!x) \
0033             log_bug("failed assertion\n"); \
0034     } while (0);
0035 
0036 /* If KARATSUBA_THRESHOLD is not already defined, define it to a
0037  * value which is good on most machines.  */
0038 
0039 /* tested 4, 16, 32 and 64, where 16 gave the best performance when
0040  * checking a 768 and a 1024 bit ElGamal signature.
0041  * (wk 22.12.97) */
0042 #ifndef KARATSUBA_THRESHOLD
0043 #define KARATSUBA_THRESHOLD 16
0044 #endif
0045 
0046 /* The code can't handle KARATSUBA_THRESHOLD smaller than 2.  */
0047 #if KARATSUBA_THRESHOLD < 2
0048 #undef KARATSUBA_THRESHOLD
0049 #define KARATSUBA_THRESHOLD 2
0050 #endif
0051 
0052 typedef mpi_limb_t *mpi_ptr_t;  /* pointer to a limb */
0053 typedef int mpi_size_t;     /* (must be a signed type) */
0054 
0055 #define RESIZE_IF_NEEDED(a, b)          \
0056     do {                    \
0057         if ((a)->alloced < (b))     \
0058             mpi_resize((a), (b));   \
0059     } while (0)
0060 
0061 /* Copy N limbs from S to D.  */
0062 #define MPN_COPY(d, s, n) \
0063     do {                    \
0064         mpi_size_t _i;          \
0065         for (_i = 0; _i < (n); _i++)    \
0066             (d)[_i] = (s)[_i];  \
0067     } while (0)
0068 
0069 #define MPN_COPY_INCR(d, s, n)      \
0070     do {                    \
0071         mpi_size_t _i;          \
0072         for (_i = 0; _i < (n); _i++)    \
0073             (d)[_i] = (s)[_i];  \
0074     } while (0)
0075 
0076 
0077 #define MPN_COPY_DECR(d, s, n) \
0078     do {                    \
0079         mpi_size_t _i;          \
0080         for (_i = (n)-1; _i >= 0; _i--) \
0081             (d)[_i] = (s)[_i];  \
0082     } while (0)
0083 
0084 /* Zero N limbs at D */
0085 #define MPN_ZERO(d, n) \
0086     do {                    \
0087         int  _i;            \
0088         for (_i = 0; _i < (n); _i++)    \
0089             (d)[_i] = 0;        \
0090     } while (0)
0091 
0092 #define MPN_NORMALIZE(d, n)  \
0093     do {                    \
0094         while ((n) > 0) {       \
0095             if ((d)[(n)-1])     \
0096                 break;      \
0097             (n)--;          \
0098         }               \
0099     } while (0)
0100 
0101 #define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \
0102     do {                            \
0103         if ((size) < KARATSUBA_THRESHOLD)       \
0104             mul_n_basecase(prodp, up, vp, size);    \
0105         else                        \
0106             mul_n(prodp, up, vp, size, tspace); \
0107     } while (0);
0108 
0109 /* Divide the two-limb number in (NH,,NL) by D, with DI being the largest
0110  * limb not larger than (2**(2*BITS_PER_MP_LIMB))/D - (2**BITS_PER_MP_LIMB).
0111  * If this would yield overflow, DI should be the largest possible number
0112  * (i.e., only ones).  For correct operation, the most significant bit of D
0113  * has to be set.  Put the quotient in Q and the remainder in R.
0114  */
0115 #define UDIV_QRNND_PREINV(q, r, nh, nl, d, di)              \
0116     do {                                \
0117         mpi_limb_t _ql __maybe_unused;              \
0118         mpi_limb_t _q, _r;                  \
0119         mpi_limb_t _xh, _xl;                    \
0120         umul_ppmm(_q, _ql, (nh), (di));             \
0121         _q += (nh); /* DI is 2**BITS_PER_MPI_LIMB too small */ \
0122         umul_ppmm(_xh, _xl, _q, (d));               \
0123         sub_ddmmss(_xh, _r, (nh), (nl), _xh, _xl);      \
0124         if (_xh) {                      \
0125             sub_ddmmss(_xh, _r, _xh, _r, 0, (d));       \
0126             _q++;                       \
0127             if (_xh) {                  \
0128                 sub_ddmmss(_xh, _r, _xh, _r, 0, (d));   \
0129                 _q++;                   \
0130             }                       \
0131         }                           \
0132         if (_r >= (d)) {                    \
0133             _r -= (d);                  \
0134             _q++;                       \
0135         }                           \
0136         (r) = _r;                       \
0137         (q) = _q;                       \
0138     } while (0)
0139 
0140 
0141 /*-- mpiutil.c --*/
0142 mpi_ptr_t mpi_alloc_limb_space(unsigned nlimbs);
0143 void mpi_free_limb_space(mpi_ptr_t a);
0144 void mpi_assign_limb_space(MPI a, mpi_ptr_t ap, unsigned nlimbs);
0145 
0146 static inline mpi_limb_t mpihelp_add_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
0147              mpi_size_t s1_size, mpi_limb_t s2_limb);
0148 mpi_limb_t mpihelp_add_n(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
0149              mpi_ptr_t s2_ptr, mpi_size_t size);
0150 static inline mpi_limb_t mpihelp_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size,
0151                mpi_ptr_t s2_ptr, mpi_size_t s2_size);
0152 
0153 static inline mpi_limb_t mpihelp_sub_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
0154              mpi_size_t s1_size, mpi_limb_t s2_limb);
0155 mpi_limb_t mpihelp_sub_n(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
0156              mpi_ptr_t s2_ptr, mpi_size_t size);
0157 static inline mpi_limb_t mpihelp_sub(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size,
0158                mpi_ptr_t s2_ptr, mpi_size_t s2_size);
0159 
0160 /*-- mpih-cmp.c --*/
0161 int mpihelp_cmp(mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size);
0162 
0163 /*-- mpih-mul.c --*/
0164 
0165 struct karatsuba_ctx {
0166     struct karatsuba_ctx *next;
0167     mpi_ptr_t tspace;
0168     mpi_size_t tspace_size;
0169     mpi_ptr_t tp;
0170     mpi_size_t tp_size;
0171 };
0172 
0173 void mpihelp_release_karatsuba_ctx(struct karatsuba_ctx *ctx);
0174 
0175 mpi_limb_t mpihelp_addmul_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
0176                 mpi_size_t s1_size, mpi_limb_t s2_limb);
0177 mpi_limb_t mpihelp_submul_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
0178                 mpi_size_t s1_size, mpi_limb_t s2_limb);
0179 int mpihelp_mul(mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t usize,
0180         mpi_ptr_t vp, mpi_size_t vsize, mpi_limb_t *_result);
0181 void mpih_sqr_n_basecase(mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size);
0182 void mpih_sqr_n(mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size,
0183         mpi_ptr_t tspace);
0184 void mpihelp_mul_n(mpi_ptr_t prodp,
0185         mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t size);
0186 
0187 int mpihelp_mul_karatsuba_case(mpi_ptr_t prodp,
0188                    mpi_ptr_t up, mpi_size_t usize,
0189                    mpi_ptr_t vp, mpi_size_t vsize,
0190                    struct karatsuba_ctx *ctx);
0191 
0192 /*-- generic_mpih-mul1.c --*/
0193 mpi_limb_t mpihelp_mul_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
0194              mpi_size_t s1_size, mpi_limb_t s2_limb);
0195 
0196 /*-- mpih-div.c --*/
0197 mpi_limb_t mpihelp_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size,
0198              mpi_limb_t divisor_limb);
0199 mpi_limb_t mpihelp_divrem(mpi_ptr_t qp, mpi_size_t qextra_limbs,
0200               mpi_ptr_t np, mpi_size_t nsize,
0201               mpi_ptr_t dp, mpi_size_t dsize);
0202 mpi_limb_t mpihelp_divmod_1(mpi_ptr_t quot_ptr,
0203                 mpi_ptr_t dividend_ptr, mpi_size_t dividend_size,
0204                 mpi_limb_t divisor_limb);
0205 
0206 /*-- generic_mpih-[lr]shift.c --*/
0207 mpi_limb_t mpihelp_lshift(mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize,
0208               unsigned cnt);
0209 mpi_limb_t mpihelp_rshift(mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize,
0210               unsigned cnt);
0211 
0212 /* Define stuff for longlong.h.  */
0213 #define W_TYPE_SIZE BITS_PER_MPI_LIMB
0214 typedef mpi_limb_t UWtype;
0215 typedef unsigned int UHWtype;
0216 #if defined(__GNUC__)
0217 typedef unsigned int UQItype __attribute__ ((mode(QI)));
0218 typedef int SItype __attribute__ ((mode(SI)));
0219 typedef unsigned int USItype __attribute__ ((mode(SI)));
0220 typedef int DItype __attribute__ ((mode(DI)));
0221 typedef unsigned int UDItype __attribute__ ((mode(DI)));
0222 #else
0223 typedef unsigned char UQItype;
0224 typedef long SItype;
0225 typedef unsigned long USItype;
0226 #endif
0227 
0228 #ifdef __GNUC__
0229 #include "mpi-inline.h"
0230 #endif
0231 
0232 #endif /*G10_MPI_INTERNAL_H */