1 /* mpiutil.ac - Utility functions for MPI
2 * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 #include "mpi-internal.h"
23 /* Constants allocated right away at startup. */
24 static MPI constants
[MPI_NUMBER_OF_CONSTANTS
];
26 /* Initialize the MPI subsystem. This is called early and allows to
27 * do some initialization without taking care of threading issues.
29 static int __init
mpi_init(void)
34 for (idx
= 0; idx
< MPI_NUMBER_OF_CONSTANTS
; idx
++) {
55 pr_err("MPI: invalid mpi_const selector %d\n", idx
);
58 constants
[idx
] = mpi_alloc_set_ui(value
);
59 constants
[idx
]->flags
= (16|32);
64 postcore_initcall(mpi_init
);
66 /* Return a constant MPI descripbed by NO which is one of the
67 * MPI_C_xxx macros. There is no need to copy this returned value; it
68 * may be used directly.
70 MPI
mpi_const(enum gcry_mpi_constants no
)
72 if ((int)no
< 0 || no
> MPI_NUMBER_OF_CONSTANTS
)
73 pr_err("MPI: invalid mpi_const selector %d\n", no
);
75 pr_err("MPI: MPI subsystem not initialized\n");
78 EXPORT_SYMBOL_GPL(mpi_const
);
81 * Note: It was a bad idea to use the number of limbs to allocate
82 * because on a alpha the limbs are large but we normally need
83 * integers of n bits - So we should chnage this to bits (or bytes).
85 * But mpi_alloc is used in a lot of places :-)
87 MPI
mpi_alloc(unsigned nlimbs
)
91 a
= kmalloc(sizeof *a
, GFP_KERNEL
);
96 a
->d
= mpi_alloc_limb_space(nlimbs
);
112 EXPORT_SYMBOL_GPL(mpi_alloc
);
114 mpi_ptr_t
mpi_alloc_limb_space(unsigned nlimbs
)
116 size_t len
= nlimbs
* sizeof(mpi_limb_t
);
121 return kmalloc(len
, GFP_KERNEL
);
124 void mpi_free_limb_space(mpi_ptr_t a
)
132 void mpi_assign_limb_space(MPI a
, mpi_ptr_t ap
, unsigned nlimbs
)
134 mpi_free_limb_space(a
->d
);
140 * Resize the array of A to NLIMBS. the additional space is cleared
141 * (set to 0) [done by m_realloc()]
143 int mpi_resize(MPI a
, unsigned nlimbs
)
147 if (nlimbs
<= a
->alloced
)
148 return 0; /* no need to do it */
151 p
= kmalloc_array(nlimbs
, sizeof(mpi_limb_t
), GFP_KERNEL
);
154 memcpy(p
, a
->d
, a
->alloced
* sizeof(mpi_limb_t
));
155 kfree_sensitive(a
->d
);
158 a
->d
= kcalloc(nlimbs
, sizeof(mpi_limb_t
), GFP_KERNEL
);
166 void mpi_clear(MPI a
)
173 EXPORT_SYMBOL_GPL(mpi_clear
);
181 kfree_sensitive(a
->d
);
183 mpi_free_limb_space(a
->d
);
186 pr_info("invalid flag value in mpi\n");
189 EXPORT_SYMBOL_GPL(mpi_free
);
192 * Note: This copy function should not interpret the MPI
193 * but copy it transparently.
201 b
= mpi_alloc(a
->nlimbs
);
202 b
->nlimbs
= a
->nlimbs
;
205 b
->flags
&= ~(16|32); /* Reset the immutable and constant flags. */
206 for (i
= 0; i
< b
->nlimbs
; i
++)
214 * This function allocates an MPI which is optimized to hold
215 * a value as large as the one given in the argument and allocates it
216 * with the same flags as A.
218 MPI
mpi_alloc_like(MPI a
)
223 b
= mpi_alloc(a
->nlimbs
);
234 /* Set U into W and release U. If W is NULL only U will be released. */
235 void mpi_snatch(MPI w
, MPI u
)
238 mpi_assign_limb_space(w
, u
->d
, u
->alloced
);
239 w
->nlimbs
= u
->nlimbs
;
250 MPI
mpi_set(MPI w
, MPI u
)
253 mpi_size_t usize
= u
->nlimbs
;
257 w
= mpi_alloc(mpi_get_nlimbs(u
));
258 RESIZE_IF_NEEDED(w
, usize
);
261 MPN_COPY(wp
, up
, usize
);
264 w
->flags
&= ~(16|32); /* Reset the immutable and constant flags. */
268 EXPORT_SYMBOL_GPL(mpi_set
);
270 MPI
mpi_set_ui(MPI w
, unsigned long u
)
274 /* FIXME: If U is 0 we have no need to resize and thus possible
275 * allocating the the limbs.
277 RESIZE_IF_NEEDED(w
, 1);
279 w
->nlimbs
= u
? 1 : 0;
284 EXPORT_SYMBOL_GPL(mpi_set_ui
);
286 MPI
mpi_alloc_set_ui(unsigned long u
)
288 MPI w
= mpi_alloc(1);
290 w
->nlimbs
= u
? 1 : 0;
296 * Swap the value of A and B, when SWAP is 1.
297 * Leave the value when SWAP is 0.
298 * This implementation should be constant-time regardless of SWAP.
300 void mpi_swap_cond(MPI a
, MPI b
, unsigned long swap
)
304 mpi_limb_t mask
= ((mpi_limb_t
)0) - swap
;
307 if (a
->alloced
> b
->alloced
)
311 if (a
->nlimbs
> nlimbs
|| b
->nlimbs
> nlimbs
)
314 for (i
= 0; i
< nlimbs
; i
++) {
315 x
= mask
& (a
->d
[i
] ^ b
->d
[i
]);
316 a
->d
[i
] = a
->d
[i
] ^ x
;
317 b
->d
[i
] = b
->d
[i
] ^ x
;
320 x
= mask
& (a
->nlimbs
^ b
->nlimbs
);
321 a
->nlimbs
= a
->nlimbs
^ x
;
322 b
->nlimbs
= b
->nlimbs
^ x
;
324 x
= mask
& (a
->sign
^ b
->sign
);
325 a
->sign
= a
->sign
^ x
;
326 b
->sign
= b
->sign
^ x
;
329 MODULE_DESCRIPTION("Multiprecision maths library");
330 MODULE_LICENSE("GPL");