xref: /linux/lib/crypto/mpi/generic_mpih-lshift.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* mpihelp-lshift.c  -	MPI helper functions
3  * Copyright (C) 1994, 1996, 1998, 2001 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 #include "mpi-internal.h"
17 
18 /* Shift U (pointed to by UP and USIZE digits long) CNT bits to the left
19  * and store the USIZE least significant digits of the result at WP.
20  * Return the bits shifted out from the most significant digit.
21  *
22  * Argument constraints:
23  * 1. 0 < CNT < BITS_PER_MP_LIMB
24  * 2. If the result is to be written over the input, WP must be >= UP.
25  */
26 
27 mpi_limb_t
28 mpihelp_lshift(mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, unsigned int cnt)
29 {
30 	mpi_limb_t high_limb, low_limb;
31 	unsigned sh_1, sh_2;
32 	mpi_size_t i;
33 	mpi_limb_t retval;
34 
35 	sh_1 = cnt;
36 	wp += 1;
37 	sh_2 = BITS_PER_MPI_LIMB - sh_1;
38 	i = usize - 1;
39 	low_limb = up[i];
40 	retval = low_limb >> sh_2;
41 	high_limb = low_limb;
42 	while (--i >= 0) {
43 		low_limb = up[i];
44 		wp[i] = (high_limb << sh_1) | (low_limb >> sh_2);
45 		high_limb = low_limb;
46 	}
47 	wp[i] = high_limb << sh_1;
48 
49 	return retval;
50 }
51