1/* mpi-scan.c - MPI functions 2 * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. 3 * 4 * This file is part of Libgcrypt. 5 * 6 * Libgcrypt is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU Lesser General Public License as 8 * published by the Free Software Foundation; either version 2.1 of 9 * the License, or (at your option) any later version. 10 * 11 * Libgcrypt 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 Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License 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 <config.h> 22#include <stdio.h> 23#include <stdlib.h> 24#include "mpi-internal.h" 25#include "longlong.h" 26 27/**************** 28 * Scan through an mpi and return byte for byte. a -1 is returned to indicate 29 * the end of the mpi. Scanning is done from the lsb to the msb, returned 30 * values are in the range of 0 .. 255. 31 * 32 * FIXME: This code is VERY ugly! 33 */ 34int 35_gcry_mpi_getbyte( gcry_mpi_t a, unsigned idx ) 36{ 37 int i, j; 38 unsigned n; 39 mpi_ptr_t ap; 40 mpi_limb_t limb; 41 42 ap = a->d; 43 for(n=0,i=0; i < a->nlimbs; i++ ) { 44 limb = ap[i]; 45 for( j=0; j < BYTES_PER_MPI_LIMB; j++, n++ ) 46 if( n == idx ) 47 return (limb >> j*8) & 0xff; 48 } 49 return -1; 50} 51 52 53/**************** 54 * Put a value at position IDX into A. idx counts from lsb to msb 55 */ 56void 57_gcry_mpi_putbyte( gcry_mpi_t a, unsigned idx, int xc ) 58{ 59 int i, j; 60 unsigned n; 61 mpi_ptr_t ap; 62 mpi_limb_t limb, c; 63 64 c = xc & 0xff; 65 ap = a->d; 66 for(n=0,i=0; i < a->alloced; i++ ) { 67 limb = ap[i]; 68 for( j=0; j < BYTES_PER_MPI_LIMB; j++, n++ ) 69 if( n == idx ) { 70 #if BYTES_PER_MPI_LIMB == 4 71 if( j == 0 ) 72 limb = (limb & 0xffffff00) | c; 73 else if( j == 1 ) 74 limb = (limb & 0xffff00ff) | (c<<8); 75 else if( j == 2 ) 76 limb = (limb & 0xff00ffff) | (c<<16); 77 else 78 limb = (limb & 0x00ffffff) | (c<<24); 79 #elif BYTES_PER_MPI_LIMB == 8 80 if( j == 0 ) 81 limb = (limb & 0xffffffffffffff00) | c; 82 else if( j == 1 ) 83 limb = (limb & 0xffffffffffff00ff) | (c<<8); 84 else if( j == 2 ) 85 limb = (limb & 0xffffffffff00ffff) | (c<<16); 86 else if( j == 3 ) 87 limb = (limb & 0xffffffff00ffffff) | (c<<24); 88 else if( j == 4 ) 89 limb = (limb & 0xffffff00ffffffff) | (c<<32); 90 else if( j == 5 ) 91 limb = (limb & 0xffff00ffffffffff) | (c<<40); 92 else if( j == 6 ) 93 limb = (limb & 0xff00ffffffffffff) | (c<<48); 94 else 95 limb = (limb & 0x00ffffffffffffff) | (c<<56); 96 #else 97 #error please enhance this function, its ugly - i know. 98 #endif 99 if( a->nlimbs <= i ) 100 a->nlimbs = i+1; 101 ap[i] = limb; 102 return; 103 } 104 } 105 abort(); /* index out of range */ 106} 107 108 109/**************** 110 * Count the number of zerobits at the low end of A 111 */ 112unsigned 113_gcry_mpi_trailing_zeros( gcry_mpi_t a ) 114{ 115 unsigned n, count = 0; 116 117 for(n=0; n < a->nlimbs; n++ ) { 118 if( a->d[n] ) { 119 unsigned nn; 120 mpi_limb_t alimb = a->d[n]; 121 122 count_trailing_zeros( nn, alimb ); 123 count += nn; 124 break; 125 } 126 count += BITS_PER_MPI_LIMB; 127 } 128 return count; 129 130} 131