at v3.4 211 lines 3.9 kB view raw
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 chnage this to bits (or bytes). 27 * 28 * But mpi_alloc is used in a lot of places :-) 29 */ 30MPI 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} 55EXPORT_SYMBOL_GPL(mpi_alloc); 56 57mpi_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 67void mpi_free_limb_space(mpi_ptr_t a) 68{ 69 if (!a) 70 return; 71 72 kfree(a); 73} 74 75void 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 */ 86int 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 = kmalloc(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(a->d); 99 a->d = p; 100 } else { 101 a->d = kzalloc(nlimbs * sizeof(mpi_limb_t), GFP_KERNEL); 102 if (!a->d) 103 return -ENOMEM; 104 } 105 a->alloced = nlimbs; 106 return 0; 107} 108 109void mpi_clear(MPI a) 110{ 111 a->nlimbs = 0; 112 a->nbits = 0; 113 a->flags = 0; 114} 115 116void mpi_free(MPI a) 117{ 118 if (!a) 119 return; 120 121 if (a->flags & 4) 122 kfree(a->d); 123 else 124 mpi_free_limb_space(a->d); 125 126 if (a->flags & ~7) 127 pr_info("invalid flag value in mpi\n"); 128 kfree(a); 129} 130EXPORT_SYMBOL_GPL(mpi_free); 131 132/**************** 133 * Note: This copy function should not interpret the MPI 134 * but copy it transparently. 135 */ 136int mpi_copy(MPI *copied, const MPI a) 137{ 138 size_t i; 139 MPI b; 140 141 *copied = NULL; 142 143 if (a) { 144 b = mpi_alloc(a->nlimbs); 145 if (!b) 146 return -ENOMEM; 147 148 b->nlimbs = a->nlimbs; 149 b->sign = a->sign; 150 b->flags = a->flags; 151 b->nbits = a->nbits; 152 153 for (i = 0; i < b->nlimbs; i++) 154 b->d[i] = a->d[i]; 155 156 *copied = b; 157 } 158 159 return 0; 160} 161 162int mpi_set(MPI w, const MPI u) 163{ 164 mpi_ptr_t wp, up; 165 mpi_size_t usize = u->nlimbs; 166 int usign = u->sign; 167 168 if (RESIZE_IF_NEEDED(w, (size_t) usize) < 0) 169 return -ENOMEM; 170 171 wp = w->d; 172 up = u->d; 173 MPN_COPY(wp, up, usize); 174 w->nlimbs = usize; 175 w->nbits = u->nbits; 176 w->flags = u->flags; 177 w->sign = usign; 178 return 0; 179} 180 181int mpi_set_ui(MPI w, unsigned long u) 182{ 183 if (RESIZE_IF_NEEDED(w, 1) < 0) 184 return -ENOMEM; 185 w->d[0] = u; 186 w->nlimbs = u ? 1 : 0; 187 w->sign = 0; 188 w->nbits = 0; 189 w->flags = 0; 190 return 0; 191} 192 193MPI mpi_alloc_set_ui(unsigned long u) 194{ 195 MPI w = mpi_alloc(1); 196 if (!w) 197 return w; 198 w->d[0] = u; 199 w->nlimbs = u ? 1 : 0; 200 w->sign = 0; 201 return w; 202} 203 204void mpi_swap(MPI a, MPI b) 205{ 206 struct gcry_mpi tmp; 207 208 tmp = *a; 209 *a = *b; 210 *b = tmp; 211}