/*
mprsa.c
Simple implementation of RSA encryption and signing based on the
PKCS #1, v. 1.5 encoding standard. Uses the MPI library for the
mathematical computations.
by Michael J. Fromberger
Copyright (C) 2001 Michael J. Fromberger, All Rights Reserved
$Id: mprsa.c,v 1.1 2004/02/08 04:29:29 sting Exp $
*/
#include "mprsa.h"
#include
#include
/* {{{ mp_i2osp(x, out, len) */
mp_err mp_i2osp(mp_int *x, char *out, int len)
{
int xlen;
ARGCHK(x != NULL && out != NULL && len > 0, MP_BADARG);
if((xlen = mp_unsigned_bin_size(x)) > len) {
return MP_RANGE;
}
xlen -= len;
if(xlen > 0)
memset(out, 0, xlen);
mp_to_unsigned_bin(x, (unsigned char *)out + xlen);
return MP_OKAY;
} /* end mp_i2osp() */
/* }}} */
/* {{{ mp_os2ip(x, in, len) */
mp_err mp_os2ip(mp_int *x, char *in, int len)
{
return mp_read_unsigned_bin(x, (unsigned char *)in, len);
} /* end mp_os2ip() */
/* }}} */
/* {{{ mp_rsaep(msg, e, modulus, cipher) */
mp_err mp_rsaep(mp_int *msg, mp_int *e, mp_int *modulus, mp_int *cipher)
{
ARGCHK(msg != NULL && e != NULL &&
modulus != NULL && cipher != NULL, MP_BADARG);
/* Insure that message representative is in range of modulus */
if((mp_cmp_z(msg) < 0) ||
(mp_cmp(msg, modulus) >= 0)) {
return MP_RANGE;
}
return mp_exptmod(msg, e, modulus, cipher);
} /* end mp_rsaep() */
/* }}} */
/* {{{ mp_rsadp(cipher, d, modulus, msg) */
mp_err mp_rsadp(mp_int *cipher, mp_int *d, mp_int *modulus, mp_int *msg)
{
ARGCHK(cipher != NULL && d != NULL &&
modulus != NULL && msg != NULL, MP_BADARG);
/* Insure that ciphertext representative is in range of modulus */
if((mp_cmp_z(cipher) < 0) ||
(mp_cmp(cipher, modulus) >= 0)) {
return MP_RANGE;
}
return mp_exptmod(cipher, d, modulus, msg);
} /* end mp_rsadp() */
/* }}} */
/* {{{ mp_rsasp(msg, d, modulus, sig) */
mp_err mp_rsasp(mp_int *msg, mp_int *d, mp_int *modulus, mp_int *sig)
{
ARGCHK(msg != NULL && d != NULL &&
modulus != NULL && sig != NULL, MP_BADARG);
if((mp_cmp_z(msg) < 0) ||
(mp_cmp(msg, modulus) >= 0)) {
return MP_RANGE;
}
return mp_exptmod(msg, d, modulus, sig);
} /* end mp_rsasp() */
/* }}} */
/* {{{ mp_rsavp(sig, e, modulus, msg) */
mp_err mp_rsavp(mp_int *sig, mp_int *e, mp_int *modulus, mp_int *msg)
{
ARGCHK(sig != NULL && e != NULL &&
modulus != NULL && msg != NULL, MP_BADARG);
if((mp_cmp_z(sig) < 0) ||
(mp_cmp(sig, modulus) >= 0)) {
return MP_RANGE;
}
return mp_exptmod(sig, e, modulus, msg);
} /* end mp_rsavp() */
/* }}} */
/* {{{ mp_pkcs1v15_encode(msg, mlen, emsg, emlen, rand) */
mp_err mp_pkcs1v15_encode(char *msg, int mlen,
char *emsg, int emlen, rnd_f rand)
{
int poffset;
ARGCHK(msg != NULL && mlen >= 0 &&
emsg != NULL && emlen > 0 && rand != NULL, MP_BADARG);
if(mlen > emlen - 10)
return MP_RANGE;
emsg[0] = 0x02;
poffset = emlen - mlen; /* offset of end of padding */
(rand)(emsg + 1, poffset - 2); /* generate random pad */
emsg[poffset - 1] = 0x00; /* zero separator */
memcpy(emsg + poffset, msg, mlen);
return MP_OKAY;
} /* end mp_pkcs1v15_encode() */
/* }}} */
/* {{{ mp_pkcs1v15_decode(emsg, emlen, msg, mlen) */
mp_err mp_pkcs1v15_decode(char *emsg, int emlen, char *msg, int *mlen)
{
int ix, jx, outlen;
ARGCHK(emsg != NULL, MP_BADARG);
/* If message is less than minimum length, it's an error */
if(emlen < 10)
return MP_RANGE;
/* Check the format of the packet, error if it's invalid */
if(emsg[0] != 0x02)
return MP_UNDEF;
/* Look for zero separator */
for(ix = 9; ix < emlen; ix++)
if(emsg[ix] == 0x00)
break;
if(ix == emlen)
return MP_UNDEF;
/* Make sure padding bytes are valid */
for(jx = 1; jx < ix; jx++)
if(emsg[jx] == 0)
return MP_UNDEF;
outlen = emlen - (ix + 1);
if(msg != NULL && outlen > 0)
memmove(msg, emsg + (ix + 1), outlen);
if(mlen != NULL)
*mlen = outlen;
return MP_OKAY;
} /* end mp_pkcs1v15_decode() */
/* }}} */
/* {{{ mp_pkcs1v15_encrypt(msg, mlen, e, modulus, out, olen, rand) */
mp_err mp_pkcs1v15_encrypt(char *msg, int mlen,
mp_int *e, mp_int *modulus,
char **out, int *olen,
rnd_f rand)
{
int k;
char *buf;
mp_err res;
mp_int mrep;
ARGCHK(msg != NULL && mlen >= 0 && e != NULL &&
modulus != NULL && out != NULL && olen != NULL, MP_BADARG);
k = mp_unsigned_bin_size(modulus); /* length of modulus, in bytes */
if((buf = malloc(k)) == NULL)
return MP_MEM;
/* Encode according to PKCS #1 v1.5 */
if((res = mp_pkcs1v15_encode(msg, mlen, buf, k, rand)) != MP_OKAY)
goto CLEANUP;
/* Convert encoded message to a big number for encryption */
if((res = mp_init(&mrep)) != MP_OKAY)
goto CLEANUP;
if((res = mp_os2ip(&mrep, buf, k)) != MP_OKAY) {
mp_clear(&mrep);
goto CLEANUP;
}
/* Now, encrypt... */
if((res = mp_rsaep(&mrep, e, modulus, &mrep)) != MP_OKAY) {
mp_clear(&mrep);
goto CLEANUP;
}
/* Unpack message representative... */
if((res = mp_i2osp(&mrep, buf, k)) != MP_OKAY) {
mp_clear(&mrep);
goto CLEANUP;
}
mp_clear(&mrep);
*out = buf;
*olen = k;
return MP_OKAY;
CLEANUP:
memset(buf, 0, k);
free(buf);
return res;
} /* end mp_pkcs1v15_encrypt() */
/* }}} */
/* {{{ mp_pkcs1v15_decrypt(msg, mlen, d, modulus, out, olen) */
mp_err mp_pkcs1v15_decrypt(char *msg, int mlen,
mp_int *d, mp_int *modulus,
char **out, int *olen)
{
int k;
char *buf;
mp_err res;
mp_int mrep;
ARGCHK(msg != NULL && d != NULL && modulus != NULL &&
out != NULL && olen != NULL, MP_BADARG);
k = mp_unsigned_bin_size(modulus); /* size of modulus, in bytes */
if(mlen != k)
return MP_UNDEF;
if((buf = malloc(k)) == NULL)
return MP_MEM;
/* Convert ciphertext to integer representative */
if((res = mp_init(&mrep)) != MP_OKAY) {
free(buf);
return res;
}
if((res = mp_os2ip(&mrep, msg, mlen)) != MP_OKAY)
goto CLEANUP;
/* Decrypt ... */
if((res = mp_rsadp(&mrep, d, modulus, &mrep)) != MP_OKAY)
goto CLEANUP;
if((res = mp_i2osp(&mrep, buf, k)) != MP_OKAY)
goto CLEANUP;
if((res = mp_pkcs1v15_decode(buf, k, buf, olen)) == MP_OKAY) {
*out = buf;
return MP_OKAY;
}
CLEANUP:
memset(buf, 0, k - 1);
free(buf);
mp_clear(&mrep);
return res;
} /* end mp_pkcs1v15_decrypt() */
/* }}} */
/* {{{ mp_pkcs1v15_maxlen(modulus) */
int mp_pkcs1v15_maxlen(mp_int *modulus)
{
int modlen = mp_unsigned_bin_size(modulus);
if(modlen < 10)
return 0;
else
return modlen - 10;
} /* end mp_pkcs1v15_maxlen() */
/* }}} */
/*------------------------------------------------------------------------*/
/* HERE THERE BE DRAGONS */