110 lines · c
1/* SPDX-License-Identifier: GPL-2.0-or-later */2/* mpi-inline.h - Internal to the Multi Precision Integers3 * 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 the9 * way the data is stored; this is to support the abstraction10 * of an optional secure memory allocation which may be used11 * 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_H17#define G10_MPI_INLINE_H18 19#ifndef G10_MPI_INLINE_DECL20#define G10_MPI_INLINE_DECL static inline21#endif22 23G10_MPI_INLINE_DECL mpi_limb_t24mpihelp_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 42leave: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 51G10_MPI_INLINE_DECL mpi_limb_t52mpihelp_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 66G10_MPI_INLINE_DECL mpi_limb_t67mpihelp_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 85leave: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 94G10_MPI_INLINE_DECL mpi_limb_t95mpihelp_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