import core of imath 1.1.9

git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@17471 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Love Hörnquist Åstrand
2006-05-06 12:31:07 +00:00
parent 6ce1a8fb4d
commit 3d256d3f4a
9 changed files with 5182 additions and 0 deletions

3261
lib/des/imath/imath.c Executable file

File diff suppressed because it is too large Load Diff

209
lib/des/imath/imath.h Executable file
View File

@@ -0,0 +1,209 @@
/*
Name: imath.h
Purpose: Arbitrary precision integer arithmetic routines.
Author: M. J. Fromberger <http://www.dartmouth.edu/~sting/>
Info: $Id$
Copyright (C) 2002 Michael J. Fromberger, All Rights Reserved.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef IMATH_H_
#define IMATH_H_
#include <limits.h>
typedef unsigned char mp_sign;
typedef unsigned int mp_size;
typedef int mp_result;
#ifdef USE_LONG_LONG
typedef unsigned int mp_digit;
typedef unsigned long long mp_word;
#else
typedef unsigned short mp_digit;
typedef unsigned int mp_word;
#endif
typedef struct mpz {
mp_digit *digits;
mp_size alloc;
mp_size used;
mp_sign sign;
} mpz_t, *mp_int;
#define MP_DIGITS(Z) ((Z)->digits)
#define MP_ALLOC(Z) ((Z)->alloc)
#define MP_USED(Z) ((Z)->used)
#define MP_SIGN(Z) ((Z)->sign)
extern const mp_result MP_OK;
extern const mp_result MP_FALSE;
extern const mp_result MP_TRUE;
extern const mp_result MP_MEMORY;
extern const mp_result MP_RANGE;
extern const mp_result MP_UNDEF;
extern const mp_result MP_TRUNC;
extern const mp_result MP_BADARG;
#define MP_DIGIT_BIT (sizeof(mp_digit) * CHAR_BIT)
#define MP_WORD_BIT (sizeof(mp_word) * CHAR_BIT)
#ifdef USE_LONG_LONG
# ifndef ULONG_LONG_MAX
# ifdef ULLONG_MAX
# define ULONG_LONG_MAX ULLONG_MAX
# else
# error "Maximum value of unsigned long long not defined!"
# endif
# endif
# define MP_DIGIT_MAX (ULONG_MAX * 1ULL)
# define MP_WORD_MAX ULONG_LONG_MAX
#else
# define MP_DIGIT_MAX (USHRT_MAX * 1UL)
# define MP_WORD_MAX (UINT_MAX * 1UL)
#endif
#define MP_MIN_RADIX 2
#define MP_MAX_RADIX 36
extern const mp_sign MP_NEG;
extern const mp_sign MP_ZPOS;
#define mp_int_is_odd(Z) ((Z)->digits[0] & 1)
#define mp_int_is_even(Z) !((Z)->digits[0] & 1)
mp_size mp_get_default_precision(void);
void mp_set_default_precision(mp_size s);
mp_size mp_get_multiply_threshold(void);
void mp_set_multiply_threshold(mp_size s);
mp_result mp_int_init(mp_int z);
mp_int mp_int_alloc(void);
mp_result mp_int_init_size(mp_int z, mp_size prec);
mp_result mp_int_init_copy(mp_int z, mp_int old);
mp_result mp_int_init_value(mp_int z, int value);
mp_result mp_int_set_value(mp_int z, int value);
void mp_int_clear(mp_int z);
void mp_int_free(mp_int z);
mp_result mp_int_copy(mp_int a, mp_int c); /* c = a */
void mp_int_swap(mp_int a, mp_int c); /* swap a, c */
void mp_int_zero(mp_int z); /* z = 0 */
mp_result mp_int_abs(mp_int a, mp_int c); /* c = |a| */
mp_result mp_int_neg(mp_int a, mp_int c); /* c = -a */
mp_result mp_int_add(mp_int a, mp_int b, mp_int c); /* c = a + b */
mp_result mp_int_add_value(mp_int a, int value, mp_int c);
mp_result mp_int_sub(mp_int a, mp_int b, mp_int c); /* c = a - b */
mp_result mp_int_sub_value(mp_int a, int value, mp_int c);
mp_result mp_int_mul(mp_int a, mp_int b, mp_int c); /* c = a * b */
mp_result mp_int_mul_value(mp_int a, int value, mp_int c);
mp_result mp_int_mul_pow2(mp_int a, int p2, mp_int c);
mp_result mp_int_sqr(mp_int a, mp_int c); /* c = a * a */
mp_result mp_int_div(mp_int a, mp_int b, /* q = a / b */
mp_int q, mp_int r); /* r = a % b */
mp_result mp_int_div_value(mp_int a, int value, /* q = a / value */
mp_int q, int *r); /* r = a % value */
mp_result mp_int_div_pow2(mp_int a, int p2, /* q = a / 2^p2 */
mp_int q, mp_int r); /* r = q % 2^p2 */
mp_result mp_int_mod(mp_int a, mp_int m, mp_int c); /* c = a % m */
#define mp_int_mod_value(A, V, R) mp_int_div_value((A), (V), 0, (R))
mp_result mp_int_expt(mp_int a, int b, mp_int c); /* c = a^b */
mp_result mp_int_expt_value(int a, int b, mp_int c); /* c = a^b */
int mp_int_compare(mp_int a, mp_int b); /* a <=> b */
int mp_int_compare_unsigned(mp_int a, mp_int b); /* |a| <=> |b| */
int mp_int_compare_zero(mp_int z); /* a <=> 0 */
int mp_int_compare_value(mp_int z, int value); /* a <=> v */
/* Returns true if v|a, false otherwise (including errors) */
int mp_int_divisible_value(mp_int a, int v);
/* Returns k >= 0 such that z = 2^k, if one exists; otherwise < 0 */
int mp_int_is_pow2(mp_int z);
mp_result mp_int_exptmod(mp_int a, mp_int b, mp_int m,
mp_int c); /* c = a^b (mod m) */
mp_result mp_int_exptmod_evalue(mp_int a, int value,
mp_int m, mp_int c); /* c = a^v (mod m) */
mp_result mp_int_exptmod_bvalue(int value, mp_int b,
mp_int m, mp_int c); /* c = v^b (mod m) */
mp_result mp_int_exptmod_known(mp_int a, mp_int b,
mp_int m, mp_int mu,
mp_int c); /* c = a^b (mod m) */
mp_result mp_int_redux_const(mp_int m, mp_int c);
mp_result mp_int_invmod(mp_int a, mp_int m, mp_int c); /* c = 1/a (mod m) */
mp_result mp_int_gcd(mp_int a, mp_int b, mp_int c); /* c = gcd(a, b) */
mp_result mp_int_egcd(mp_int a, mp_int b, mp_int c, /* c = gcd(a, b) */
mp_int x, mp_int y); /* c = ax + by */
mp_result mp_int_sqrt(mp_int a, mp_int c); /* c = floor(sqrt(q)) */
/* Convert to an int, if representable (returns MP_RANGE if not). */
mp_result mp_int_to_int(mp_int z, int *out);
/* Convert to nul-terminated string with the specified radix, writing at
most limit characters including the nul terminator */
mp_result mp_int_to_string(mp_int z, mp_size radix,
char *str, int limit);
/* Return the number of characters required to represent
z in the given radix. May over-estimate. */
mp_result mp_int_string_len(mp_int z, mp_size radix);
/* Read zero-terminated string into z */
mp_result mp_int_read_string(mp_int z, mp_size radix, const char *str);
mp_result mp_int_read_cstring(mp_int z, mp_size radix, const char *str,
char **end);
/* Return the number of significant bits in z */
mp_result mp_int_count_bits(mp_int z);
/* Convert z to two's complement binary, writing at most limit bytes */
mp_result mp_int_to_binary(mp_int z, unsigned char *buf, int limit);
/* Read a two's complement binary value into z from the given buffer */
mp_result mp_int_read_binary(mp_int z, unsigned char *buf, int len);
/* Return the number of bytes required to represent z in binary. */
mp_result mp_int_binary_len(mp_int z);
/* Convert z to unsigned binary, writing at most limit bytes */
mp_result mp_int_to_unsigned(mp_int z, unsigned char *buf, int limit);
/* Read an unsigned binary value into z from the given buffer */
mp_result mp_int_read_unsigned(mp_int z, unsigned char *buf, int len);
/* Return the number of bytes required to represent z as unsigned output */
mp_result mp_int_unsigned_len(mp_int z);
/* Return a statically allocated string describing error code res */
const char *mp_error_string(mp_result res);
#if DEBUG
void s_print(char *tag, mp_int z);
void s_print_buf(char *tag, mp_digit *buf, mp_size num);
#endif
#endif /* end IMATH_H_ */

24
lib/des/imath/import.sh Normal file
View File

@@ -0,0 +1,24 @@
#!/bin/sh
# $Id$
dir=$1
if test ! -f "$dir"/imdrover.c ; then
echo $dir doesnt seem to contain imath
exit 1
fi
rm *.[ch]
headers=`grep ^HDRS "$dir"/Makefile |sed 's/^HDRS=//' | sed 's/imdrover.h//'`
code=`echo $headers | sed 's/\.h/.c/g'`
for a in $headers $code ; do
cp "$dir"/"$a" .
done
echo "imathsource = \\"
for a in $headers $code ; do
echo " imath/$a \\"
done | sort

1121
lib/des/imath/imrat.c Executable file

File diff suppressed because it is too large Load Diff

117
lib/des/imath/imrat.h Executable file
View File

@@ -0,0 +1,117 @@
/*
Name: imrat.h
Purpose: Arbitrary precision rational arithmetic routines.
Author: M. J. Fromberger <http://www.dartmouth.edu/~sting/>
Info: $Id$
Copyright (C) 2002 Michael J. Fromberger, All Rights Reserved.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef IMRAT_H_
#define IMRAT_H_
#include "imath.h"
typedef struct mpq {
mpz_t num; /* Numerator */
mpz_t den; /* Denominator, <> 0 */
} mpq_t, *mp_rat;
#define MP_NUMER_P(Q) (&((Q)->num)) /* Pointer to numerator */
#define MP_DENOM_P(Q) (&((Q)->den)) /* Pointer to denominator */
/* Rounding constants */
extern const mp_result MP_ROUND_DOWN;
extern const mp_result MP_ROUND_HALF_UP;
extern const mp_result MP_ROUND_UP;
extern const mp_result MP_ROUND_HALF_DOWN;
void mp_rat_set_rounding(mp_result rnd);
mp_result mp_rat_get_rounding(void);
mp_result mp_rat_init(mp_rat r);
mp_rat mp_rat_alloc(void);
mp_result mp_rat_init_size(mp_rat r, mp_size n_prec, mp_size d_prec);
mp_result mp_rat_init_copy(mp_rat r, mp_rat old);
mp_result mp_rat_set_value(mp_rat r, int numer, int denom);
void mp_rat_clear(mp_rat r);
void mp_rat_free(mp_rat r);
mp_result mp_rat_numer(mp_rat r, mp_int z); /* z = num(r) */
mp_result mp_rat_denom(mp_rat r, mp_int z); /* z = den(r) */
mp_sign mp_rat_sign(mp_rat r);
mp_result mp_rat_copy(mp_rat a, mp_rat c); /* c = a */
void mp_rat_zero(mp_rat r); /* r = 0 */
mp_result mp_rat_abs(mp_rat a, mp_rat c); /* c = |a| */
mp_result mp_rat_neg(mp_rat a, mp_rat c); /* c = -a */
mp_result mp_rat_recip(mp_rat a, mp_rat c); /* c = 1 / a */
mp_result mp_rat_add(mp_rat a, mp_rat b, mp_rat c); /* c = a + b */
mp_result mp_rat_sub(mp_rat a, mp_rat b, mp_rat c); /* c = a - b */
mp_result mp_rat_mul(mp_rat a, mp_rat b, mp_rat c); /* c = a * b */
mp_result mp_rat_div(mp_rat a, mp_rat b, mp_rat c); /* c = a / b */
mp_result mp_rat_add_int(mp_rat a, mp_int b, mp_rat c); /* c = a + b */
mp_result mp_rat_sub_int(mp_rat a, mp_int b, mp_rat c); /* c = a - b */
mp_result mp_rat_mul_int(mp_rat a, mp_int b, mp_rat c); /* c = a * b */
mp_result mp_rat_div_int(mp_rat a, mp_int b, mp_rat c); /* c = a / b */
mp_result mp_rat_expt(mp_rat a, int b, mp_rat c); /* c = a ^ b */
int mp_rat_compare(mp_rat a, mp_rat b); /* a <=> b */
int mp_rat_compare_unsigned(mp_rat a, mp_rat b); /* |a| <=> |b| */
int mp_rat_compare_zero(mp_rat r); /* r <=> 0 */
int mp_rat_compare_value(mp_rat r, int n, int d); /* r <=> n/d */
int mp_rat_is_integer(mp_rat r);
/* Convert to integers, if representable (returns MP_RANGE if not). */
mp_result mp_rat_to_ints(mp_rat r, int *num, int *den);
/* Convert to nul-terminated string with the specified radix, writing
at most limit characters including the nul terminator. */
mp_result mp_rat_to_string(mp_rat r, mp_size radix, char *str, int limit);
/* Convert to decimal format in the specified radix and precision,
writing at most limit characters including a nul terminator. */
mp_result mp_rat_to_decimal(mp_rat r, mp_size radix, mp_size prec,
char *str, int limit);
/* Return the number of characters required to represent r in the given
radix. May over-estimate. */
mp_result mp_rat_string_len(mp_rat r, mp_size radix);
/* Return the number of characters required to represent r in decimal
format with the given radix and precision. May over-estimate. */
mp_result mp_rat_decimal_len(mp_rat r, mp_size radix, mp_size prec);
/* Read zero-terminated string into r */
mp_result mp_rat_read_string(mp_rat r, mp_size radix, const char *str);
mp_result mp_rat_read_cstring(mp_rat r, mp_size radix, const char *str,
char **end);
mp_result mp_rat_read_ustring(mp_rat r, mp_size radix, const char *str,
char **end);
/* Read zero-terminated string in decimal format into r */
mp_result mp_rat_read_decimal(mp_rat r, mp_size radix, const char *str);
mp_result mp_rat_read_cdecimal(mp_rat r, mp_size radix, const char *str,
char **end);
#endif /* IMRAT_H_ */

110
lib/des/imath/iprime.c Executable file
View File

@@ -0,0 +1,110 @@
/*
Name: iprime.c
Purpose: Pseudoprimality testing routines
Author: M. J. Fromberger <http://www.dartmouth.edu/~sting/>
Info: $Id$
Copyright (C) 2002 Michael J. Fromberger, All Rights Reserved.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "iprime.h"
#include <stdlib.h>
static int s_ptab_size = 32;
static int s_ptab[] = {
2, 3, 5, 7, 11, 13, 17, 19,
23, 29, 31, 37, 41, 43, 47, 53,
59, 61, 67, 71, 73, 79, 83, 89,
97, 101, 103, 107, 109, 113, 127, 131
};
/* {{{ mp_int_is_prime(z) */
/* Test whether z is likely to be prime:
MP_TRUE means it is probably prime
MP_FALSE means it is definitely composite
*/
mp_result mp_int_is_prime(mp_int z)
{
int i, rem;
mp_result res;
/* First check for divisibility by small primes; this eliminates a
large number of composite candidates quickly
*/
for(i = 0; i < s_ptab_size; ++i) {
if((res = mp_int_div_value(z, s_ptab[i], NULL, &rem)) != MP_OK)
return res;
if(rem == 0)
return MP_FALSE;
}
/* Now try Fermat's test for several prime witnesses (since we now
know from the above that z is not a multiple of any of them)
*/
{
mpz_t tmp;
if((res = mp_int_init(&tmp)) != MP_OK) return res;
for(i = 0; i < 10 && i < s_ptab_size; ++i) {
if((res = mp_int_exptmod_bvalue(s_ptab[i], z, z, &tmp)) != MP_OK)
return res;
if(mp_int_compare_value(&tmp, s_ptab[i]) != 0) {
mp_int_clear(&tmp);
return MP_FALSE;
}
}
mp_int_clear(&tmp);
}
return MP_TRUE;
}
/* }}} */
/* {{{ mp_int_find_prime(z) */
/* Find the first apparent prime in ascending order from z */
mp_result mp_int_find_prime(mp_int z)
{
mp_result res;
if(mp_int_is_even(z) && ((res = mp_int_add_value(z, 1, z)) != MP_OK))
return res;
while((res = mp_int_is_prime(z)) == MP_FALSE) {
if((res = mp_int_add_value(z, 2, z)) != MP_OK)
break;
}
return res;
}
/* }}} */
/* Here there be dragons */

44
lib/des/imath/iprime.h Executable file
View File

@@ -0,0 +1,44 @@
/*
Name: iprime.h
Purpose: Pseudoprimality testing routines
Author: M. J. Fromberger <http://www.dartmouth.edu/~sting/>
Info: $Id$
Copyright (C) 2002 Michael J. Fromberger, All Rights Reserved.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef IPRIME_H_
#define IPRIME_H_
#include "imath.h"
/* Test whether z is likely to be prime
MP_YES means it is probably prime
MP_NO means it is definitely composite
*/
mp_result mp_int_is_prime(mp_int z);
/* Find the first apparent prime in ascending order from z */
mp_result mp_int_find_prime(mp_int z);
#endif /* IPRIME_H_ */

205
lib/des/imath/rsamath.c Executable file
View File

@@ -0,0 +1,205 @@
/*
Name: rsamath.c
Purpose: Implements part of PKCS#1, v. 2.1, June 14, 2002 (RSA Labs)
Author: M. J. Fromberger <http://www.dartmouth.edu/~sting/>
Copyright (C) 2002 Michael J. Fromberger, All Rights Reserved.
Info: $Id$
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "rsamath.h"
#include <string.h>
#include <limits.h>
static mp_result s_rsa_transform(mp_int msg, mp_int exp,
mp_int mod, mp_int out);
/* {{{ rsa_i2osp(z, out, len) */
/* Convert integer to octet string, per PKCS#1 v.2.1 */
mp_result rsa_i2osp(mp_int z, unsigned char *out, int len)
{
int excess_len = mp_int_binary_len(z);
if(excess_len < len)
return MP_RANGE;
memset(out, 0, len);
excess_len -= len;
mp_int_to_binary(z, out + excess_len, len);
return MP_OK;
}
/* }}} */
/* {{{ rsa_os2ip(z, in, len) */
/* Convert octet string to integer, per PKCS#1 v.2.1 */
mp_result rsa_os2ip(mp_int z, unsigned char *in, int len)
{
return mp_int_read_binary(z, in, len);
}
/* }}} */
/* {{{ rsa_rsaep(msg, exp, mod, cipher) */
/* Primitive RSA encryption operation */
mp_result rsa_rsaep(mp_int msg, mp_int exp, mp_int mod, mp_int cipher)
{
return s_rsa_transform(msg, exp, mod, cipher);
}
/* }}} */
/* {{{ rsa_rsadp(cipher, exp, mod, msg) */
/* Primitive RSA decryption operation */
mp_result rsa_rsadp(mp_int cipher, mp_int exp, mp_int mod, mp_int msg)
{
return s_rsa_transform(cipher, exp, mod, msg);
}
/* }}} */
/* {{{ rsa_rsasp(msg, exp, mod, signature) */
/* Primitive RSA signing operation */
mp_result rsa_rsasp(mp_int msg, mp_int exp, mp_int mod, mp_int signature)
{
return s_rsa_transform(msg, exp, mod, signature);
}
/* }}} */
/* {{{ rsa_rsavp(signature, exp, mod, msg) */
/* Primitive RSA verification operation */
mp_result rsa_rsavp(mp_int signature, mp_int exp, mp_int mod, mp_int msg)
{
return s_rsa_transform(signature, exp, mod, msg);
}
/* }}} */
/* {{{ rsa_max_message_len(mod) */
/* Compute the maximum length in bytes a message can have using PKCS#1
v.1.5 encoding with the given modulus */
int rsa_max_message_len(mp_int mod)
{
int num_bits = mp_int_count_bits(mod);
int num_bytes = num_bits / CHAR_BIT;
if(num_bytes < 11)
return 0; /* at least eleven bytes are required for padding */
else
return num_bytes - 11;
}
/* }}} */
/* {{{ rsa_pkcs1v15_encode(buf, msg_len, buf_len, tag, filler) */
mp_result rsa_pkcs1v15_encode(unsigned char *buf, int msg_len,
int buf_len, int tag, random_f filler)
{
int pad_len, msg_start;
/* Make sure there is enough space for the encoded output */
if(msg_len > (buf_len - 11))
return MP_RANGE;
msg_start = buf_len - msg_len;
pad_len = msg_start - 3;
/* Move message to top of buffer -- these might overlap, so we rely
on the semantics of memmove() here */
memmove(buf + msg_start, buf, msg_len);
/* Set initial bytes as required by the specification */
buf[0] = 0x00;
buf[1] = (unsigned char)tag;
/* Fill with random padding. We'll just assume the filler function
does the right thing and only writes the requested number of
nonzero bytes */
(filler)(buf + 2, pad_len);
/* Write separator between pad and message body */
buf[msg_start - 1] = 0x00;
return MP_OK;
}
/* }}} */
/* {{{ rsa_pkcs1v15_decode(buf, buf_len, *msg_len) */
mp_result rsa_pkcs1v15_decode(unsigned char *buf, int buf_len,
int tag, int *msg_len)
{
int pad_len = 0, data_len, data_start, i;
/* Make sure the buffer is syntactically valid */
if(buf_len < 11 || buf[0] != 0x00 || buf[1] != (unsigned char)tag)
return MP_UNDEF;
/* Figure out how many bytes of random padding there are */
i = 2;
while(buf[i++] != '\0')
++pad_len;
data_start = i;
data_len = buf_len - data_start;
/* Shift the message to the front of the buffer */
memmove(buf, buf + data_start, data_len);
/* Zero out the rest of the buffer */
memset(buf + data_len, 0, pad_len + 3);
*msg_len = data_len;
return MP_OK;
}
/* }}} */
/* {{{ s_rsa_transform(msg, exp, mod, out) */
static mp_result s_rsa_transform(mp_int msg, mp_int exp,
mp_int mod, mp_int out)
{
if(mp_int_compare_zero(msg) < 0 ||
mp_int_compare(msg, mod) >= 0)
return MP_RANGE;
return mp_int_exptmod(msg, exp, mod, out);
}
/* }}} */
/* Here there be dragons */

91
lib/des/imath/rsamath.h Executable file
View File

@@ -0,0 +1,91 @@
/*
Name: rsamath.h
Purpose: Implements part of PKCS#1, v. 2.1, June 14, 2002 (RSA Labs)
Author: M. J. Fromberger <http://www.dartmouth.edu/~sting/>
Info: $Id$
Copyright (C) 2002 Michael J. Fromberger, All Rights Reserved.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef RSAMATH_H_
#define RSAMATH_H_
#include "imath.h"
/* Function to fill a buffer with nonzero random bytes */
typedef void (*random_f)(unsigned char *, int);
/* Convert integer to octet string, per PKCS#1 v.2.1 */
mp_result rsa_i2osp(mp_int z, unsigned char *out, int len);
/* Convert octet string to integer, per PKCS#1 v.2.1 */
mp_result rsa_os2ip(mp_int z, unsigned char *in, int len);
/* The following operations assume that you have converted your keys
and message data into mp_int values somehow. */
/* Primitive RSA encryption operation */
mp_result rsa_rsaep(mp_int msg, mp_int exp, mp_int mod, mp_int cipher);
/* Primitive RSA decryption operation */
mp_result rsa_rsadp(mp_int cipher, mp_int exp, mp_int mod, mp_int msg);
/* Primitive RSA signing operation */
mp_result rsa_rsasp(mp_int msg, mp_int exp, mp_int mod, mp_int signature);
/* Primitive RSA verification operation */
mp_result rsa_rsavp(mp_int signature, mp_int exp, mp_int mod, mp_int msg);
/* Compute the maximum length in bytes a message can have using PKCS#1
v.1.5 encoding with the given modulus */
int rsa_max_message_len(mp_int mod);
/* Encode a raw message per PKCS#1 v.1.5
buf - the buffer containing the message
msg_len - the length in bytes of the message
buf_len - the size in bytes of the buffer
tag - the message tag (nonzero byte)
filler - function to generate pseudorandom nonzero padding
On input, the message is in the first msg_len bytes of the buffer;
on output, the contents of the buffer are replaced by the padded
message. If there is not enough room, MP_RANGE is returned.
*/
mp_result rsa_pkcs1v15_encode(unsigned char *buf, int msg_len,
int buf_len, int tag, random_f filler);
/* Decode a PKCS#1 v.1.5 message back to its raw form
buf - the buffer containing the encoded message
buf_len - the length in bytes of the buffer
tag - the expected message tag (nonzero byte)
msg_len - on output, receives the length of the message content
On output, the message is packed into the first msg_len bytes of
the buffer, and the rest of the buffer is zeroed. If the buffer is
not of the correct form, MP_UNDEF is returned and msg_len is undefined.
*/
mp_result rsa_pkcs1v15_decode(unsigned char *buf, int buf_len,
int tag, int *msg_len);
#endif /* end RSAMATH_H_ */