⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bignum.c

📁 一个用纯C写的RSA_SHA1数字签名库
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  Multi-precision integer library * *  Copyright (C) 2006-2007  Christophe Devine * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License along *  with this program; if not, write to the Free Software Foundation, Inc., *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *//* *  This MPI implementation is based on: * *  http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf *  http://www.stillhq.com/extracted/gnupg-api/mpi/ *  http://math.libtomcrypt.com/files/tommath.pdf */#include "config.h"#if defined(XYSSL_BIGNUM_C)#include "bignum.h"#include "bn_mul.h"#include <string.h>#include <stdlib.h>#include <stdarg.h>#define ciL    ((int) sizeof(t_int))    /* chars in limb  */#define biL    (ciL << 3)               /* bits  in limb  */#define biH    (ciL << 2)               /* half limb size *//* * Convert between bits/chars and number of limbs */#define BITS_TO_LIMBS(i)  (((i) + biL - 1) / biL)#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL)/* * Initialize one or more mpi */void mpi_init( mpi *X, ... ){    va_list args;    va_start( args, X );    while( X != NULL )    {        X->s = 1;        X->n = 0;        X->p = NULL;        X = va_arg( args, mpi* );    }    va_end( args );}/* * Unallocate one or more mpi */void mpi_free( mpi *X, ... ){    va_list args;    va_start( args, X );    while( X != NULL )    {        if( X->p != NULL )        {            memset( X->p, 0, X->n * ciL );            free( X->p );        }        X->s = 1;        X->n = 0;        X->p = NULL;        X = va_arg( args, mpi* );    }    va_end( args );}/* * Enlarge to the specified number of limbs */int mpi_grow( mpi *X, int nblimbs ){    t_int *p;    if( X->n < nblimbs )    {        if( ( p = (t_int *) malloc( nblimbs * ciL ) ) == NULL )            return( 1 );        memset( p, 0, nblimbs * ciL );        if( X->p != NULL )        {            memcpy( p, X->p, X->n * ciL );            memset( X->p, 0, X->n * ciL );            free( X->p );        }        X->n = nblimbs;        X->p = p;    }    return( 0 );}/* * Copy the contents of Y into X */int mpi_copy( mpi *X, mpi *Y ){    int ret, i;    if( X == Y )        return( 0 );    for( i = Y->n - 1; i > 0; i-- )        if( Y->p[i] != 0 )            break;    i++;    X->s = Y->s;    MPI_CHK( mpi_grow( X, i ) );    memset( X->p, 0, X->n * ciL );    memcpy( X->p, Y->p, i * ciL );cleanup:    return( ret );}/* * Swap the contents of X and Y */void mpi_swap( mpi *X, mpi *Y ){    mpi T;    memcpy( &T,  X, sizeof( mpi ) );    memcpy(  X,  Y, sizeof( mpi ) );    memcpy(  Y, &T, sizeof( mpi ) );}/* * Set value from integer */int mpi_lset( mpi *X, int z ){    int ret;    MPI_CHK( mpi_grow( X, 1 ) );    memset( X->p, 0, X->n * ciL );    X->p[0] = ( z < 0 ) ? -z : z;    X->s    = ( z < 0 ) ? -1 : 1;cleanup:    return( ret );}/* * Return the number of least significant bits */int mpi_lsb( mpi *X ){    int i, j, count = 0;    for( i = 0; i < X->n; i++ )        for( j = 0; j < (int) biL; j++, count++ )            if( ( ( X->p[i] >> j ) & 1 ) != 0 )                return( count );    return( 0 );}/* * Return the number of most significant bits */int mpi_msb( mpi *X ){    int i, j;    for( i = X->n - 1; i > 0; i-- )        if( X->p[i] != 0 )            break;    for( j = biL - 1; j >= 0; j-- )        if( ( ( X->p[i] >> j ) & 1 ) != 0 )            break;    return( ( i * biL ) + j + 1 );}/* * Return the total size in bytes */int mpi_size( mpi *X ){    return( ( mpi_msb( X ) + 7 ) >> 3 );}/* * Convert an ASCII character to digit value */static int mpi_get_digit( t_int *d, int radix, char c ){    *d = 255;    if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;    if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;    if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;    if( *d >= (t_int) radix )        return( XYSSL_ERR_MPI_INVALID_CHARACTER );    return( 0 );}/* * Import from an ASCII string */int mpi_read_string( mpi *X, int radix, char *s ){    int ret, i, j, n;    t_int d;    mpi T;    if( radix < 2 || radix > 16 )        return( XYSSL_ERR_MPI_BAD_INPUT_DATA );    mpi_init( &T, NULL );    if( radix == 16 )    {        n = BITS_TO_LIMBS( strlen( s ) << 2 );        MPI_CHK( mpi_grow( X, n ) );        MPI_CHK( mpi_lset( X, 0 ) );        for( i = strlen( s ) - 1, j = 0; i >= 0; i--, j++ )        {            if( i == 0 && s[i] == '-' )            {                X->s = -1;                break;            }            MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );            X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );        }    }    else    {        MPI_CHK( mpi_lset( X, 0 ) );        for( i = 0; i < (int) strlen( s ); i++ )        {            if( i == 0 && s[i] == '-' )            {                X->s = -1;                continue;            }            MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );            MPI_CHK( mpi_mul_int( &T, X, radix ) );            MPI_CHK( mpi_add_int( X, &T, d ) );        }    }cleanup:    mpi_free( &T, NULL );    return( ret );}/* * Helper to write the digits high-order first */static int mpi_write_hlp( mpi *X, int radix, char **p ){    int ret;    t_int r;    if( radix < 2 || radix > 16 )        return( XYSSL_ERR_MPI_BAD_INPUT_DATA );    MPI_CHK( mpi_mod_int( &r, X, radix ) );    MPI_CHK( mpi_div_int( X, NULL, X, radix ) );    if( mpi_cmp_int( X, 0 ) != 0 )        MPI_CHK( mpi_write_hlp( X, radix, p ) );    if( r < 10 )        *(*p)++ = (char)( r + 0x30 );    else        *(*p)++ = (char)( r + 0x37 );cleanup:    return( ret );}/* * Export into an ASCII string */int mpi_write_string( mpi *X, int radix, char *s, int *slen ){    int ret = 0, n;    char *p;    mpi T;    if( radix < 2 || radix > 16 )        return( XYSSL_ERR_MPI_BAD_INPUT_DATA );    n = mpi_msb( X );    if( radix >=  4 ) n >>= 1;    if( radix >= 16 ) n >>= 1;    n += 3;    if( *slen < n )    {        *slen = n;        return( XYSSL_ERR_MPI_BUFFER_TOO_SMALL );    }    p = s;    mpi_init( &T, NULL );    if( X->s == -1 )        *p++ = '-';    if( radix == 16 )    {        int c, i, j, k;        for( i = X->n - 1, k = 0; i >= 0; i-- )        {            for( j = ciL - 1; j >= 0; j-- )            {                c = ( X->p[i] >> (j << 3) ) & 0xFF;                if( c == 0 && k == 0 && (i + j) != 0 )                    continue;                p += sprintf( p, "%02X", c );                k = 1;            }        }    }    else    {        MPI_CHK( mpi_copy( &T, X ) );        MPI_CHK( mpi_write_hlp( &T, radix, &p ) );    }    *p++ = '\0';    *slen = p - s;cleanup:    mpi_free( &T, NULL );    return( ret );}/* * Read X from an opened file */int mpi_read_file( mpi *X, int radix, FILE *fin ){    t_int d;    int slen;    char *p;    char s[1024];    memset( s, 0, sizeof( s ) );    if( fgets( s, sizeof( s ) - 1, fin ) == NULL )        return( XYSSL_ERR_MPI_FILE_IO_ERROR );    slen = strlen( s );    if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }    if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }    p = s + slen;    while( --p >= s )        if( mpi_get_digit( &d, radix, *p ) != 0 )            break;    return( mpi_read_string( X, radix, p + 1 ) );}/* * Write X into an opened file (or stdout if fout == NULL) */int mpi_write_file( char *p, mpi *X, int radix, FILE *fout ){    int n, ret;    size_t slen;    size_t plen;    char s[1024];    n = sizeof( s );    memset( s, 0, n );    n -= 2;    MPI_CHK( mpi_write_string( X, radix, s, (int *) &n ) );    if( p == NULL ) p = "";    plen = strlen( p );    slen = strlen( s );    s[slen++] = '\r';    s[slen++] = '\n';    if( fout != NULL )    {        if( fwrite( p, 1, plen, fout ) != plen ||            fwrite( s, 1, slen, fout ) != slen )            return( XYSSL_ERR_MPI_FILE_IO_ERROR );    }    else        printf( "%s%s", p, s );cleanup:    return( ret );}/* * Import X from unsigned binary data, big endian */int mpi_read_binary( mpi *X, unsigned char *buf, int buflen ){    int ret, i, j, n;    for( n = 0; n < buflen; n++ )        if( buf[n] != 0 )            break;    MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );    MPI_CHK( mpi_lset( X, 0 ) );    for( i = buflen - 1, j = 0; i >= n; i--, j++ )        X->p[j / ciL] |= ((t_int) buf[i]) << ((j % ciL) << 3);cleanup:    return( ret );}/* * Export X into unsigned binary data, big endian */int mpi_write_binary( mpi *X, unsigned char *buf, int buflen ){    int i, j, n;    n = mpi_size( X );    if( buflen < n )        return( XYSSL_ERR_MPI_BUFFER_TOO_SMALL );    memset( buf, 0, buflen );    for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )        buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );    return( 0 );}/* * Left-shift: X <<= count */int mpi_shift_l( mpi *X, int count ){    int ret, i, v0, t1;    t_int r0 = 0, r1;    v0 = count / (biL    );    t1 = count & (biL - 1);    i = mpi_msb( X ) + count;    if( X->n * (int) biL < i )        MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );    ret = 0;    /*     * shift by count / limb_size     */    if( v0 > 0 )    {        for( i = X->n - 1; i >= v0; i-- )            X->p[i] = X->p[i - v0];        for( ; i >= 0; i-- )            X->p[i] = 0;    }    /*     * shift by count % limb_size     */    if( t1 > 0 )    {        for( i = v0; i < X->n; i++ )        {            r1 = X->p[i] >> (biL - t1);            X->p[i] <<= t1;            X->p[i] |= r0;            r0 = r1;        }    }cleanup:    return( ret );}/* * Right-shift: X >>= count */int mpi_shift_r( mpi *X, int count ){    int i, v0, v1;    t_int r0 = 0, r1;    v0 = count /  biL;    v1 = count & (biL - 1);    /*     * shift by count / limb_size     */    if( v0 > 0 )    {        for( i = 0; i < X->n - v0; i++ )            X->p[i] = X->p[i + v0];        for( ; i < X->n; i++ )            X->p[i] = 0;    }    /*     * shift by count % limb_size     */    if( v1 > 0 )    {        for( i = X->n - 1; i >= 0; i-- )        {            r1 = X->p[i] << (biL - v1);            X->p[i] >>= v1;            X->p[i] |= r0;            r0 = r1;        }    }    return( 0 );}/* * Compare unsigned values */int mpi_cmp_abs( mpi *X, mpi *Y ){    int i, j;    for( i = X->n - 1; i >= 0; i-- )        if( X->p[i] != 0 )            break;    for( j = Y->n - 1; j >= 0; j-- )        if( Y->p[j] != 0 )            break;    if( i < 0 && j < 0 )        return( 0 );    if( i > j ) return(  1 );    if( j > i ) return( -1 );    for( ; i >= 0; i-- )    {        if( X->p[i] > Y->p[i] ) return(  1 );        if( X->p[i] < Y->p[i] ) return( -1 );    }    return( 0 );}/* * Compare signed values */int mpi_cmp_mpi( mpi *X, mpi *Y ){    int i, j;    for( i = X->n - 1; i >= 0; i-- )        if( X->p[i] != 0 )            break;    for( j = Y->n - 1; j >= 0; j-- )        if( Y->p[j] != 0 )            break;    if( i < 0 && j < 0 )        return( 0 );    if( i > j ) return(  X->s );    if( j > i ) return( -X->s );    if( X->s > 0 && Y->s < 0 ) return(  1 );    if( Y->s > 0 && X->s < 0 ) return( -1 );    for( ; i >= 0; i-- )    {        if( X->p[i] > Y->p[i] ) return(  X->s );        if( X->p[i] < Y->p[i] ) return( -X->s );    }    return( 0 );}/* * Compare signed values */int mpi_cmp_int( mpi *X, int z ){    mpi Y;    t_int p[1];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -