1  /* SPDX-License-Identifier: GPL-2.0-or-later */
2  /* mpi-inline.h  -  Internal to the Multi Precision Integers
3   *	Copyright (C) 1994, 1996, 1998, 1999 Free Software Foundation, Inc.
4   *
5   * This file is part of GnuPG.
6   *
7   * Note: This code is heavily based on the GNU MP Library.
8   *	 Actually it's the same code with only minor changes in the
9   *	 way the data is stored; this is to support the abstraction
10   *	 of an optional secure memory allocation which may be used
11   *	 to avoid revealing of sensitive data due to paging etc.
12   *	 The GNU MP Library itself is published under the LGPL;
13   *	 however I decided to publish this code under the plain GPL.
14   */
15  
16  #ifndef G10_MPI_INLINE_H
17  #define G10_MPI_INLINE_H
18  
19  #ifndef G10_MPI_INLINE_DECL
20  #define G10_MPI_INLINE_DECL  static inline
21  #endif
22  
23  G10_MPI_INLINE_DECL mpi_limb_t
mpihelp_add_1(mpi_ptr_t res_ptr,mpi_ptr_t s1_ptr,mpi_size_t s1_size,mpi_limb_t s2_limb)24  mpihelp_add_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
25  	      mpi_size_t s1_size, mpi_limb_t s2_limb)
26  {
27  	mpi_limb_t x;
28  
29  	x = *s1_ptr++;
30  	s2_limb += x;
31  	*res_ptr++ = s2_limb;
32  	if (s2_limb < x) {	/* sum is less than the left operand: handle carry */
33  		while (--s1_size) {
34  			x = *s1_ptr++ + 1;	/* add carry */
35  			*res_ptr++ = x;	/* and store */
36  			if (x)	/* not 0 (no overflow): we can stop */
37  				goto leave;
38  		}
39  		return 1;	/* return carry (size of s1 to small) */
40  	}
41  
42  leave:
43  	if (res_ptr != s1_ptr) {	/* not the same variable */
44  		mpi_size_t i;	/* copy the rest */
45  		for (i = 0; i < s1_size - 1; i++)
46  			res_ptr[i] = s1_ptr[i];
47  	}
48  	return 0;		/* no carry */
49  }
50  
51  G10_MPI_INLINE_DECL mpi_limb_t
mpihelp_add(mpi_ptr_t res_ptr,mpi_ptr_t s1_ptr,mpi_size_t s1_size,mpi_ptr_t s2_ptr,mpi_size_t s2_size)52  mpihelp_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size,
53  	    mpi_ptr_t s2_ptr, mpi_size_t s2_size)
54  {
55  	mpi_limb_t cy = 0;
56  
57  	if (s2_size)
58  		cy = mpihelp_add_n(res_ptr, s1_ptr, s2_ptr, s2_size);
59  
60  	if (s1_size - s2_size)
61  		cy = mpihelp_add_1(res_ptr + s2_size, s1_ptr + s2_size,
62  				   s1_size - s2_size, cy);
63  	return cy;
64  }
65  
66  G10_MPI_INLINE_DECL mpi_limb_t
mpihelp_sub_1(mpi_ptr_t res_ptr,mpi_ptr_t s1_ptr,mpi_size_t s1_size,mpi_limb_t s2_limb)67  mpihelp_sub_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
68  	      mpi_size_t s1_size, mpi_limb_t s2_limb)
69  {
70  	mpi_limb_t x;
71  
72  	x = *s1_ptr++;
73  	s2_limb = x - s2_limb;
74  	*res_ptr++ = s2_limb;
75  	if (s2_limb > x) {
76  		while (--s1_size) {
77  			x = *s1_ptr++;
78  			*res_ptr++ = x - 1;
79  			if (x)
80  				goto leave;
81  		}
82  		return 1;
83  	}
84  
85  leave:
86  	if (res_ptr != s1_ptr) {
87  		mpi_size_t i;
88  		for (i = 0; i < s1_size - 1; i++)
89  			res_ptr[i] = s1_ptr[i];
90  	}
91  	return 0;
92  }
93  
94  G10_MPI_INLINE_DECL mpi_limb_t
mpihelp_sub(mpi_ptr_t res_ptr,mpi_ptr_t s1_ptr,mpi_size_t s1_size,mpi_ptr_t s2_ptr,mpi_size_t s2_size)95  mpihelp_sub(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size,
96  	    mpi_ptr_t s2_ptr, mpi_size_t s2_size)
97  {
98  	mpi_limb_t cy = 0;
99  
100  	if (s2_size)
101  		cy = mpihelp_sub_n(res_ptr, s1_ptr, s2_ptr, s2_size);
102  
103  	if (s1_size - s2_size)
104  		cy = mpihelp_sub_1(res_ptr + s2_size, s1_ptr + s2_size,
105  				   s1_size - s2_size, cy);
106  	return cy;
107  }
108  
109  #endif /*G10_MPI_INLINE_H */
110