ch1_mpi                 1 
ch1_mpi                 2  * Modified by No Such Labs. (C) 2015. See README.
ch1_mpi                 3  *
ch1_mpi                 4  * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10,
ch1_mpi                 5  * SHA256(gnupg-1.4.10.tar.gz):
ch1_mpi                 6  *        0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a
ch1_mpi                 7  * (C) 1994-2005 Free Software Foundation, Inc.
ch1_mpi                 8  *
ch1_mpi                 9  * This program is free software: you can redistribute it and/or modify
ch1_mpi                10  * it under the terms of the GNU General Public License as published by
ch1_mpi                11  * the Free Software Foundation, either version 3 of the License, or
ch1_mpi                12  * (at your option) any later version.
ch1_mpi                13  *
ch1_mpi                14  * This program is distributed in the hope that it will be useful,
ch1_mpi                15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
ch1_mpi                16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ch1_mpi                17  * GNU General Public License for more details.
ch1_mpi                18  *
ch1_mpi                19  * You should have received a copy of the GNU General Public License
ch1_mpi                20  * along with this program.  If not, see <http:
ch1_mpi                21  */
ch1_mpi                22 
ch1_mpi                23 #include <stdio.h>
ch1_mpi                24 #include <string.h>
ch1_mpi                25 #include <stdlib.h>
ch1_mpi                26 #include <assert.h>
ch1_mpi                27 
ch1_mpi                28 #include "knobs.h"
ch1_mpi                29 #include "mpi.h"
ch1_mpi                30 #include "mpi-internal.h"
ch1_mpi                31 #include "memory.h"
ch1_mpi                32 #include "util.h"
ch1_mpi                33 
ch1_mpi                34 #ifdef M_DEBUG
ch1_mpi                35 #undef mpi_read
ch1_mpi                36 #endif
ch1_mpi                37 
ch1_mpi                38 #define MAX_EXTERN_MPI_BITS 16384
ch1_mpi                39 
ch1_mpi                40 
ch1_mpi                41 MPI
ch1_mpi                42 mpi_read_from_buffer(byte *buffer, unsigned int *ret_nread, int secure)
ch1_mpi                43 {
ch1_mpi                44     int i, j;
ch1_mpi                45     unsigned nbits, nbytes, nlimbs, nread=0;
ch1_mpi                46     mpi_limb_t a;
ch1_mpi                47     MPI val = NULL;
ch1_mpi                48 
ch1_mpi                49     if( *ret_nread < 2 )
ch1_mpi                50 	goto leave;
ch1_mpi                51     nbits = buffer[0] << 8 | buffer[1];
ch1_mpi                52     if( nbits > MAX_EXTERN_MPI_BITS ) {
ch1_mpi                53 	log_info ("mpi too large (%u bits)\n", nbits);
ch1_mpi                54 	goto leave;
ch1_mpi                55     }
ch1_mpi                56     buffer += 2;
ch1_mpi                57     nread = 2;
ch1_mpi                58 
ch1_mpi                59     nbytes = (nbits+7) / 8;
ch1_mpi                60     nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
ch1_mpi                61     val = secure? mpi_alloc_secure( nlimbs )
ch1_mpi                62 		: mpi_alloc( nlimbs );
ch1_mpi                63     i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
ch1_mpi                64     i %= BYTES_PER_MPI_LIMB;
ch1_mpi                65     val->nbits = nbits;
ch1_mpi                66     j= val->nlimbs = nlimbs;
ch1_mpi                67     val->sign = 0;
ch1_mpi                68     for( ; j > 0; j-- ) {
ch1_mpi                69 	a = 0;
ch1_mpi                70 	for(; i < BYTES_PER_MPI_LIMB; i++ ) {
ch1_mpi                71           if( ++nread > *ret_nread ) {
ch1_mpi                72               
ch1_mpi                73                  happen if we use this function to parse a decrypted
ch1_mpi                74                  MPI which didn't turn out to be a real MPI - possible
ch1_mpi                75                  because the supplied key was wrong but the OpenPGP
ch1_mpi                76                  checksum didn't caught it. */
ch1_mpi                77 		log_info ("mpi larger than buffer\n");
ch1_mpi                78                 mpi_free (val);
ch1_mpi                79                 val = NULL;
ch1_mpi                80                 goto leave;
ch1_mpi                81           }
ch1_mpi                82           a <<= 8;
ch1_mpi                83           a |= *buffer++;
ch1_mpi                84 	}
ch1_mpi                85 	i = 0;
ch1_mpi                86 	val->d[j-1] = a;
ch1_mpi                87     }
ch1_mpi                88 
ch1_mpi                89   leave:
ch1_mpi                90     *ret_nread = nread;
ch1_mpi                91     return val;
ch1_mpi                92 }
ch1_mpi                93 
ch1_mpi                94 
ch1_mpi                95 
ch1_mpi                96  * Make an mpi from a character string.
ch1_mpi                97  */
ch1_mpi                98 int
ch1_mpi                99 mpi_fromstr(MPI val, const char *str)
ch1_mpi               100 {
ch1_mpi               101     int hexmode=0, sign=0, prepend_zero=0, i, j, c, c1, c2;
ch1_mpi               102     unsigned nbits, nbytes, nlimbs;
ch1_mpi               103     mpi_limb_t a;
ch1_mpi               104 
ch1_mpi               105     if( *str == '-' ) {
ch1_mpi               106 	sign = 1;
ch1_mpi               107 	str++;
ch1_mpi               108     }
ch1_mpi               109     if( *str == '0' && str[1] == 'x' )
ch1_mpi               110 	hexmode = 1;
ch1_mpi               111     else
ch1_mpi               112 	return 1; 
ch1_mpi               113     str += 2;
ch1_mpi               114 
ch1_mpi               115     nbits = strlen(str)*4;
ch1_mpi               116     if( nbits % 8 )
ch1_mpi               117 	prepend_zero = 1;
ch1_mpi               118     nbytes = (nbits+7) / 8;
ch1_mpi               119     nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
ch1_mpi               120     if( val->alloced < nlimbs )
ch1_mpi               121 	mpi_resize(val, nlimbs );
ch1_mpi               122     i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
ch1_mpi               123     i %= BYTES_PER_MPI_LIMB;
ch1_mpi               124     j= val->nlimbs = nlimbs;
ch1_mpi               125     val->sign = sign;
ch1_mpi               126     for( ; j > 0; j-- ) {
ch1_mpi               127 	a = 0;
ch1_mpi               128 	for(; i < BYTES_PER_MPI_LIMB; i++ ) {
ch1_mpi               129 	    if( prepend_zero ) {
ch1_mpi               130 		c1 = '0';
ch1_mpi               131 		prepend_zero = 0;
ch1_mpi               132 	    }
ch1_mpi               133 	    else
ch1_mpi               134 		c1 = *str++;
ch1_mpi               135 	    assert(c1);
ch1_mpi               136 	    c2 = *str++;
ch1_mpi               137 	    assert(c2);
ch1_mpi               138 	    if( c1 >= '0' && c1 <= '9' )
ch1_mpi               139 		c = c1 - '0';
ch1_mpi               140 	    else if( c1 >= 'a' && c1 <= 'f' )
ch1_mpi               141 		c = c1 - 'a' + 10;
ch1_mpi               142 	    else if( c1 >= 'A' && c1 <= 'F' )
ch1_mpi               143 		c = c1 - 'A' + 10;
ch1_mpi               144 	    else {
ch1_mpi               145 		mpi_clear(val);
ch1_mpi               146 		return 1;
ch1_mpi               147 	    }
ch1_mpi               148 	    c <<= 4;
ch1_mpi               149 	    if( c2 >= '0' && c2 <= '9' )
ch1_mpi               150 		c |= c2 - '0';
ch1_mpi               151 	    else if( c2 >= 'a' && c2 <= 'f' )
ch1_mpi               152 		c |= c2 - 'a' + 10;
ch1_mpi               153 	    else if( c2 >= 'A' && c2 <= 'F' )
ch1_mpi               154 		c |= c2 - 'A' + 10;
ch1_mpi               155 	    else {
ch1_mpi               156 		mpi_clear(val);
ch1_mpi               157 		return 1;
ch1_mpi               158 	    }
ch1_mpi               159 	    a <<= 8;
ch1_mpi               160 	    a |= c;
ch1_mpi               161 	}
ch1_mpi               162 	i = 0;
ch1_mpi               163 	val->d[j-1] = a;
ch1_mpi               164     }
ch1_mpi               165 
ch1_mpi               166     return 0;
ch1_mpi               167 }
ch1_mpi               168 
ch1_mpi               169 
ch1_mpi               170 
ch1_mpi               171  * print an MPI to the given stream and return the number of characters
ch1_mpi               172  * printed.
ch1_mpi               173  */
ch1_mpi               174 int
ch1_mpi               175 mpi_print( FILE *fp, MPI a, int mode )
ch1_mpi               176 {
ch1_mpi               177     int i, n=0;
ch1_mpi               178 
ch1_mpi               179     if( a == NULL )
ch1_mpi               180 	return fprintf(fp, "[MPI_NULL]");
ch1_mpi               181     if( !mode ) {
ch1_mpi               182 	unsigned int n1;
ch1_mpi               183 
ch1_mpi               184 	n1 = mpi_get_nbits(a);
ch1_mpi               185         n += fprintf(fp, "[%u bits]", n1);
ch1_mpi               186     }
ch1_mpi               187     else {
ch1_mpi               188 	if( a->sign )
ch1_mpi               189 	    putc('-', fp);
ch1_mpi               190 #if BYTES_PER_MPI_LIMB == 2
ch1_mpi               191 #define X "4"
ch1_mpi               192 #elif BYTES_PER_MPI_LIMB == 4
ch1_mpi               193 #define X "8"
ch1_mpi               194 #elif BYTES_PER_MPI_LIMB == 8
ch1_mpi               195 #define X "16"
ch1_mpi               196 #else
ch1_mpi               197 #error please define the format here
ch1_mpi               198 #endif
ch1_mpi               199 	for(i=a->nlimbs; i > 0 ; i-- ) {
ch1_mpi               200 	    n += fprintf(fp, i!=a->nlimbs? "%0" X "lX":"%lX", (ulong)a->d[i-1]);
ch1_mpi               201 #undef X
ch1_mpi               202 	}
ch1_mpi               203 	if( !a->nlimbs )
ch1_mpi               204 	    putc('0', fp );
ch1_mpi               205     }
ch1_mpi               206     return n;
ch1_mpi               207 }
ch1_mpi               208 
ch1_mpi               209 
ch1_mpi               210 
ch1_mpi               211 void
ch1_mpi               212 g10_log_mpidump( const char *text, MPI a )
ch1_mpi               213 {
ch1_mpi               214     FILE *fp = log_stream();
ch1_mpi               215 
ch1_mpi               216     g10_log_print_prefix(text);
ch1_mpi               217     mpi_print(fp, a, 1 );
ch1_mpi               218     fputc('\n', fp);
ch1_mpi               219 }
ch1_mpi               220 */
ch1_mpi               221 
ch1_mpi               222 
ch1_mpi               223 
ch1_mpi               224  * Return an xmalloced buffer with the MPI (msb first).
ch1_mpi               225  * NBYTES receives the length of this buffer. Caller must free the
ch1_mpi               226  * return string (This function does return a 0 byte buffer with NBYTES
ch1_mpi               227  * set to zero if the value of A is zero. If sign is not NULL, it will
ch1_mpi               228  * be set to the sign of the A.
ch1_mpi               229  */
ch1_mpi               230 static byte *
ch1_mpi               231 do_get_buffer( MPI a, unsigned *nbytes, int *sign, int force_secure )
ch1_mpi               232 {
ch1_mpi               233     byte *p, *buffer;
ch1_mpi               234     mpi_limb_t alimb;
ch1_mpi               235     int i;
ch1_mpi               236     unsigned int n;
ch1_mpi               237 
ch1_mpi               238     if( sign )
ch1_mpi               239 	*sign = a->sign;
ch1_mpi               240     *nbytes = n = a->nlimbs * BYTES_PER_MPI_LIMB;
ch1_mpi               241     if (!n)
ch1_mpi               242       n++; 
ch1_mpi               243     p = buffer = force_secure || mpi_is_secure(a) ? xmalloc_secure(n)
ch1_mpi               244 						  : xmalloc(n);
ch1_mpi               245 
ch1_mpi               246     for(i=a->nlimbs-1; i >= 0; i-- ) {
ch1_mpi               247 	alimb = a->d[i];
ch1_mpi               248 #if BYTES_PER_MPI_LIMB == 4
ch1_mpi               249 	*p++ = alimb >> 24;
ch1_mpi               250 	*p++ = alimb >> 16;
ch1_mpi               251 	*p++ = alimb >>  8;
ch1_mpi               252 	*p++ = alimb	  ;
ch1_mpi               253 #elif BYTES_PER_MPI_LIMB == 8
ch1_mpi               254 	*p++ = alimb >> 56;
ch1_mpi               255 	*p++ = alimb >> 48;
ch1_mpi               256 	*p++ = alimb >> 40;
ch1_mpi               257 	*p++ = alimb >> 32;
ch1_mpi               258 	*p++ = alimb >> 24;
ch1_mpi               259 	*p++ = alimb >> 16;
ch1_mpi               260 	*p++ = alimb >>  8;
ch1_mpi               261 	*p++ = alimb	  ;
ch1_mpi               262 #else
ch1_mpi               263 #error please implement for this limb size.
ch1_mpi               264 #endif
ch1_mpi               265     }
ch1_mpi               266 
ch1_mpi               267     
ch1_mpi               268      * because the caller has to free the returned buffer */
ch1_mpi               269     for(p=buffer; !*p && *nbytes; p++, --*nbytes )
ch1_mpi               270       ;
ch1_mpi               271     if( p != buffer )
ch1_mpi               272       memmove(buffer,p, *nbytes);
ch1_mpi               273 
ch1_mpi               274     return buffer;
ch1_mpi               275 }
ch1_mpi               276 
ch1_mpi               277 
ch1_mpi               278 byte *
ch1_mpi               279 mpi_get_buffer( MPI a, unsigned *nbytes, int *sign )
ch1_mpi               280 {
ch1_mpi               281     return do_get_buffer( a, nbytes, sign, 0 );
ch1_mpi               282 }
ch1_mpi               283 
ch1_mpi               284 byte *
ch1_mpi               285 mpi_get_secure_buffer( MPI a, unsigned *nbytes, int *sign )
ch1_mpi               286 {
ch1_mpi               287     return do_get_buffer( a, nbytes, sign, 1 );
ch1_mpi               288 }
ch1_mpi               289 
ch1_mpi               290 
ch1_mpi               291  * Use BUFFER to update MPI.
ch1_mpi               292  */
ch1_mpi               293 void
ch1_mpi               294 mpi_set_buffer( MPI a, const byte *buffer, unsigned nbytes, int sign )
ch1_mpi               295 {
ch1_mpi               296     const byte *p;
ch1_mpi               297     mpi_limb_t alimb;
ch1_mpi               298     int nlimbs;
ch1_mpi               299     int i;
ch1_mpi               300 
ch1_mpi               301     nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
ch1_mpi               302     RESIZE_IF_NEEDED(a, nlimbs);
ch1_mpi               303     a->sign = sign;
ch1_mpi               304 
ch1_mpi               305     for(i=0, p = buffer+nbytes-1; p >= buffer+BYTES_PER_MPI_LIMB; ) {
ch1_mpi               306 #if BYTES_PER_MPI_LIMB == 4
ch1_mpi               307 	alimb  = (mpi_limb_t)*p-- ;
ch1_mpi               308 	alimb |= (mpi_limb_t)*p-- <<  8 ;
ch1_mpi               309 	alimb |= (mpi_limb_t)*p-- << 16 ;
ch1_mpi               310 	alimb |= (mpi_limb_t)*p-- << 24 ;
ch1_mpi               311 #elif BYTES_PER_MPI_LIMB == 8
ch1_mpi               312 	alimb  = (mpi_limb_t)*p--	;
ch1_mpi               313 	alimb |= (mpi_limb_t)*p-- <<  8 ;
ch1_mpi               314 	alimb |= (mpi_limb_t)*p-- << 16 ;
ch1_mpi               315 	alimb |= (mpi_limb_t)*p-- << 24 ;
ch1_mpi               316 	alimb |= (mpi_limb_t)*p-- << 32 ;
ch1_mpi               317 	alimb |= (mpi_limb_t)*p-- << 40 ;
ch1_mpi               318 	alimb |= (mpi_limb_t)*p-- << 48 ;
ch1_mpi               319 	alimb |= (mpi_limb_t)*p-- << 56 ;
ch1_mpi               320 #else
ch1_mpi               321 #error please implement for this limb size.
ch1_mpi               322 #endif
ch1_mpi               323 	a->d[i++] = alimb;
ch1_mpi               324     }
ch1_mpi               325     if( p >= buffer ) {
ch1_mpi               326 #if BYTES_PER_MPI_LIMB == 4
ch1_mpi               327 	alimb  = *p--	    ;
ch1_mpi               328 	if( p >= buffer ) alimb |= (mpi_limb_t)*p-- <<  8 ;
ch1_mpi               329 	if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 16 ;
ch1_mpi               330 	if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 24 ;
ch1_mpi               331 #elif BYTES_PER_MPI_LIMB == 8
ch1_mpi               332 	alimb  = (mpi_limb_t)*p-- ;
ch1_mpi               333 	if( p >= buffer ) alimb |= (mpi_limb_t)*p-- <<	8 ;
ch1_mpi               334 	if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 16 ;
ch1_mpi               335 	if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 24 ;
ch1_mpi               336 	if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 32 ;
ch1_mpi               337 	if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 40 ;
ch1_mpi               338 	if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 48 ;
ch1_mpi               339 	if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 56 ;
ch1_mpi               340 #else
ch1_mpi               341 #error please implement for this limb size.
ch1_mpi               342 #endif
ch1_mpi               343 	a->d[i++] = alimb;
ch1_mpi               344     }
ch1_mpi               345     a->nlimbs = i;
ch1_mpi               346     assert( i == nlimbs );
ch1_mpi               347 }