/* mpiutil.ac - Utility functions for MPI1* Copyright (C) 1998, 1999 Free Software Foundation, Inc.2*3* This file is part of GnuPG.4*5* GnuPG is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License as published by7* the Free Software Foundation; either version 2 of the License, or8* (at your option) any later version.9*10* GnuPG is distributed in the hope that it will be useful,11* but WITHOUT ANY WARRANTY; without even the implied warranty of12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13* GNU General Public License for more details.14*15* You should have received a copy of the GNU General Public License16* along with this program; if not, write to the Free Software17* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA18*/1920#include <linux/export.h>2122#include "mpi-internal.h"2324/****************25* Note: It was a bad idea to use the number of limbs to allocate26* because on a alpha the limbs are large but we normally need27* integers of n bits - So we should change this to bits (or bytes).28*29* But mpi_alloc is used in a lot of places :-)30*/31MPI mpi_alloc(unsigned nlimbs)32{33MPI a;3435a = kmalloc(sizeof *a, GFP_KERNEL);36if (!a)37return a;3839if (nlimbs) {40a->d = mpi_alloc_limb_space(nlimbs);41if (!a->d) {42kfree(a);43return NULL;44}45} else {46a->d = NULL;47}4849a->alloced = nlimbs;50a->nlimbs = 0;51a->sign = 0;52a->flags = 0;53a->nbits = 0;54return a;55}56EXPORT_SYMBOL_GPL(mpi_alloc);5758mpi_ptr_t mpi_alloc_limb_space(unsigned nlimbs)59{60size_t len = nlimbs * sizeof(mpi_limb_t);6162if (!len)63return NULL;6465return kmalloc(len, GFP_KERNEL);66}6768void mpi_free_limb_space(mpi_ptr_t a)69{70if (!a)71return;7273kfree_sensitive(a);74}7576void mpi_assign_limb_space(MPI a, mpi_ptr_t ap, unsigned nlimbs)77{78mpi_free_limb_space(a->d);79a->d = ap;80a->alloced = nlimbs;81}8283/****************84* Resize the array of A to NLIMBS. the additional space is cleared85* (set to 0) [done by m_realloc()]86*/87int mpi_resize(MPI a, unsigned nlimbs)88{89void *p;9091if (nlimbs <= a->alloced)92return 0; /* no need to do it */9394if (a->d) {95p = kcalloc(nlimbs, sizeof(mpi_limb_t), GFP_KERNEL);96if (!p)97return -ENOMEM;98memcpy(p, a->d, a->alloced * sizeof(mpi_limb_t));99kfree_sensitive(a->d);100a->d = p;101} else {102a->d = kcalloc(nlimbs, sizeof(mpi_limb_t), GFP_KERNEL);103if (!a->d)104return -ENOMEM;105}106a->alloced = nlimbs;107return 0;108}109110void mpi_free(MPI a)111{112if (!a)113return;114115if (a->flags & 4)116kfree_sensitive(a->d);117else118mpi_free_limb_space(a->d);119120if (a->flags & ~7)121pr_info("invalid flag value in mpi\n");122kfree(a);123}124EXPORT_SYMBOL_GPL(mpi_free);125126/****************127* Note: This copy function should not interpret the MPI128* but copy it transparently.129*/130MPI mpi_copy(MPI a)131{132int i;133MPI b;134135if (a) {136b = mpi_alloc(a->nlimbs);137if (!b)138return NULL;139b->nlimbs = a->nlimbs;140b->sign = a->sign;141b->flags = a->flags;142b->flags &= ~(16|32); /* Reset the immutable and constant flags. */143for (i = 0; i < b->nlimbs; i++)144b->d[i] = a->d[i];145} else146b = NULL;147return b;148}149150MODULE_DESCRIPTION("Multiprecision maths library");151MODULE_LICENSE("GPL");152153154