1 /* mpiutil.ac - Utility functions for MPI 2 * Copyright (C) 1998, 1999 Free Software Foundation, Inc. 3 * 4 * This file is part of GnuPG. 5 * 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. 10 * 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. 15 * 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 19 */ 20 21 #include "mpi-internal.h" 22 23 /**************** 24 * Note: It was a bad idea to use the number of limbs to allocate 25 * because on a alpha the limbs are large but we normally need 26 * integers of n bits - So we should change this to bits (or bytes). 27 * 28 * But mpi_alloc is used in a lot of places :-) 29 */ 30 MPI mpi_alloc(unsigned nlimbs) 31 { 32 MPI a; 33 34 a = kmalloc(sizeof *a, GFP_KERNEL); 35 if (!a) 36 return a; 37 38 if (nlimbs) { 39 a->d = mpi_alloc_limb_space(nlimbs); 40 if (!a->d) { 41 kfree(a); 42 return NULL; 43 } 44 } else { 45 a->d = NULL; 46 } 47 48 a->alloced = nlimbs; 49 a->nlimbs = 0; 50 a->sign = 0; 51 a->flags = 0; 52 a->nbits = 0; 53 return a; 54 } 55 EXPORT_SYMBOL_GPL(mpi_alloc); 56 57 mpi_ptr_t mpi_alloc_limb_space(unsigned nlimbs) 58 { 59 size_t len = nlimbs * sizeof(mpi_limb_t); 60 61 if (!len) 62 return NULL; 63 64 return kmalloc(len, GFP_KERNEL); 65 } 66 67 void mpi_free_limb_space(mpi_ptr_t a) 68 { 69 if (!a) 70 return; 71 72 kfree_sensitive(a); 73 } 74 75 void mpi_assign_limb_space(MPI a, mpi_ptr_t ap, unsigned nlimbs) 76 { 77 mpi_free_limb_space(a->d); 78 a->d = ap; 79 a->alloced = nlimbs; 80 } 81 82 /**************** 83 * Resize the array of A to NLIMBS. the additional space is cleared 84 * (set to 0) [done by m_realloc()] 85 */ 86 int mpi_resize(MPI a, unsigned nlimbs) 87 { 88 void *p; 89 90 if (nlimbs <= a->alloced) 91 return 0; /* no need to do it */ 92 93 if (a->d) { 94 p = kcalloc(nlimbs, sizeof(mpi_limb_t), GFP_KERNEL); 95 if (!p) 96 return -ENOMEM; 97 memcpy(p, a->d, a->alloced * sizeof(mpi_limb_t)); 98 kfree_sensitive(a->d); 99 a->d = p; 100 } else { 101 a->d = kcalloc(nlimbs, sizeof(mpi_limb_t), GFP_KERNEL); 102 if (!a->d) 103 return -ENOMEM; 104 } 105 a->alloced = nlimbs; 106 return 0; 107 } 108 109 void mpi_free(MPI a) 110 { 111 if (!a) 112 return; 113 114 if (a->flags & 4) 115 kfree_sensitive(a->d); 116 else 117 mpi_free_limb_space(a->d); 118 119 if (a->flags & ~7) 120 pr_info("invalid flag value in mpi\n"); 121 kfree(a); 122 } 123 EXPORT_SYMBOL_GPL(mpi_free); 124 125 /**************** 126 * Note: This copy function should not interpret the MPI 127 * but copy it transparently. 128 */ 129 MPI mpi_copy(MPI a) 130 { 131 int i; 132 MPI b; 133 134 if (a) { 135 b = mpi_alloc(a->nlimbs); 136 if (!b) 137 return NULL; 138 b->nlimbs = a->nlimbs; 139 b->sign = a->sign; 140 b->flags = a->flags; 141 b->flags &= ~(16|32); /* Reset the immutable and constant flags. */ 142 for (i = 0; i < b->nlimbs; i++) 143 b->d[i] = a->d[i]; 144 } else 145 b = NULL; 146 return b; 147 } 148 149 MODULE_DESCRIPTION("Multiprecision maths library"); 150 MODULE_LICENSE("GPL"); 151