Commit 7681801e authored by Davide Galassi's avatar Davide Galassi

RSA padding modes refactory

OEAP padding mode is not implemented yet
parent b5527de0
Pipeline #68689611 passed with stages
in 1 minute and 31 seconds
......@@ -8,16 +8,21 @@
#include <cry/mpi.h>
#define CRY_RSA_FLAG_SIGN (1 << 0)
/** PKCS1 v1.5 encryption padding */
#define CRY_RSA_PADDING_PKCS1 1
/** PKCS1 v2.0 (OEAP) encryption padding */
#define CRY_RSA_PADDING_PKCS1_OEAP 2
/** PKCS1 v2.1 (PSS) signature padding */
#define CRY_RSA_PADDING_PKCS1_PSS 3
/**
* Structure used for both private and public key.
*/
struct cry_rsa_ctx {
cry_mpi m; /**< Modulus */
cry_mpi e; /**< Encrypt exponent */
cry_mpi d; /**< Decrypt exponent */
int flags; /**< Behaviour flags */
cry_mpi n; /**< Modulus */
cry_mpi e; /**< Public exponent */
cry_mpi d; /**< Private exponent */
int padding; /**< Padding mode */
};
typedef struct cry_rsa_ctx cry_rsa_ctx;
......@@ -26,6 +31,8 @@ typedef struct cry_rsa_ctx cry_rsa_ctx;
extern "C" {
#endif
int cry_rsa_init(cry_rsa_ctx *ctc, int padding);
int cry_rsa_encrypt(cry_rsa_ctx *ctx, unsigned char **out, size_t *outlen,
const unsigned char *in, size_t inlen);
......
......@@ -2,6 +2,8 @@
#include <cry/prng.h>
#include <string.h>
#include <stdlib.h>
#include "misc.h"
/*
* Compute c = m^e mod n.
......@@ -28,26 +30,147 @@
static int nozero_rand(unsigned char *dst, size_t n)
{
int res;
size_t k;
unsigned char buf[16];
if ((res = cry_prng_aes_rand(dst, n)) < 0)
return res;
while (n-- > 0) {
if (dst[n] == 0) {
cry_prng_aes_rand(buf, sizeof(buf));
for (k = 0; k < sizeof(buf); k++) {
if (buf[k] != 0) {
dst[n] = buf[k];
break;
}
}
if (dst[n] == 0) {
res = -1; /* No Way!!! */
break;
}
}
if (dst[n] == 0)
dst[n] = (n != 0) ? n : 1;
}
return res;
}
static int rsa_padding_add(unsigned char *dst, size_t dlen,
const unsigned char *src, size_t slen,
int padding)
{
int res = 0;
unsigned char *p = dst;
size_t j;
if (slen > (dlen - 11))
return -1;
*(p++) = 0;
*(p++) = 2; /* Public Key BT (Block Type) */
/* pad out with non-zero random data */
j = dlen - 3 - slen;
switch (padding) {
case CRY_RSA_PADDING_PKCS1:
res = nozero_rand(p, j);
break;
case CRY_RSA_PADDING_PKCS1_OEAP:
/* not implemented yet */
res = -1;
break;
case CRY_RSA_PADDING_PKCS1_PSS:
memset(p, 0xFF, j);
break;
default:
res = -1;
break;
}
if (res != 0)
return res;
p += j;
*(p++) = '\0';
memcpy(p, src, slen);
return 0;
}
static int rsa_padding_del(unsigned char *dst, size_t dlen,
const unsigned char *src, size_t slen,
int padding)
{
size_t i;
if (src[0] != 0 || src[1] != 0x02)
/* Unrecognized block type */
return -1;
/*
* Find next 0 byte after padding type byte;
* this signifies start of data
*/
for (i = 2; i < slen && src[i] != 0; i++) {
if (padding == CRY_RSA_PADDING_PKCS1_PSS && src[i] != 0xFF)
return -1;
}
if(i == slen)
return -1;
i++; /* skip zero */
if (slen - i < dlen)
dlen = slen - i;
memcpy(dst, src + i, dlen);
return dlen;
}
static int cry_rsa_encrypt_block(cry_rsa_ctx *ctx, unsigned char *out,
const unsigned char *in, size_t in_siz)
{
int res;
unsigned char *buf;
size_t mod_len;
cry_mpi c, m;
cry_mpi *key;
key = (ctx->padding == CRY_RSA_PADDING_PKCS1_PSS) ? &ctx->d : &ctx->e;
mod_len = cry_mpi_count_bytes(&ctx->n);
buf = malloc(mod_len);
if (buf == NULL)
return -1;
if ((res = cry_mpi_init_list(&c, &m, (cry_mpi *)NULL)) != 0)
goto e;
if ((res = rsa_padding_add(buf, mod_len, in, in_siz, ctx->padding)) != 0)
goto e1;
if ((res = cry_mpi_load_bin(&m, buf, mod_len)) != 0)
goto e1;
if ((res = cry_mpi_mod_exp(&c, &m, key, &ctx->n)) != 0)
goto e1;
res = cry_mpi_store_bin(&c, out, mod_len, 1);
e1: cry_mpi_clear_list(&c, &m, (cry_mpi *)NULL);
e: free(buf);
return res;
}
static int cry_rsa_decrypt_block(cry_rsa_ctx *ctx, unsigned char *out,
const unsigned char *in, size_t in_siz)
{
int res = 0;
unsigned char *buf;
size_t mod_len;
cry_mpi c, m;
cry_mpi *key;
key = (ctx->padding == CRY_RSA_PADDING_PKCS1_PSS) ? &ctx->e : &ctx->d;
mod_len = cry_mpi_count_bytes(&ctx->n);
if (in_siz != mod_len)
return -1;
buf = malloc(mod_len);
if (buf == NULL)
return -1;
if ((res = cry_mpi_init_list(&c, &m, (cry_mpi *)NULL)) != 0)
goto e;
if ((res = cry_mpi_load_bin(&c, in, mod_len)) != 0)
goto e1;
if ((res = cry_mpi_mod_exp(&m, &c, key, &ctx->n)) != 0)
goto e1;
if ((res = cry_mpi_store_bin(&m, buf, mod_len, 1)) != 0)
goto e1;
res = rsa_padding_del(out, mod_len, buf, mod_len, ctx->padding);
e1: cry_mpi_clear_list(&c, &m, (cry_mpi *)NULL);
e: free(buf);
return res;
}
......@@ -58,64 +181,36 @@ int cry_rsa_encrypt(cry_rsa_ctx *ctx, unsigned char **out, size_t *out_siz,
const unsigned char *in, size_t in_siz)
{
int res;
cry_mpi c, m;
size_t mod_siz, block_siz;
unsigned char *padded_block;
*out = NULL;
*out_siz = 0;
mod_siz = cry_mpi_count_bytes(&ctx->m);
padded_block = malloc(mod_siz);
if (!padded_block)
return -1;
if ((res = cry_mpi_init_list(&c, &m, (cry_mpi *)NULL)) != 0) {
free(padded_block);
return res;
}
mod_siz = cry_mpi_count_bytes(&ctx->n);
while (in_siz) {
*out_siz += mod_siz;
block_siz = (in_siz < mod_siz - 11) ?
in_siz : (mod_siz - 11);
memset(padded_block, 0, mod_siz);
memcpy(padded_block + (mod_siz - block_siz), in, block_siz);
padded_block[1] = 0x02; /* Block type */
if (ctx->flags & CRY_RSA_FLAG_SIGN) {
memset(padded_block + 2, 0xFF, mod_siz - block_siz - 3);
} else {
if ((res = nozero_rand(padded_block + 2,
mod_siz - block_siz - 3)) < 0)
break;
}
*out = realloc(*out, *out_siz);
*out = realloc(*out, *out_siz + mod_siz);
if (*out == NULL) {
res = -1;
break;
}
if ((res = cry_mpi_load_bin(&m, padded_block, mod_siz)) != 0)
break;
if ((res = cry_mpi_mod_exp(&c, &m, &ctx->e, &ctx->m)) != 0)
break;
if (cry_mpi_store_bin(&c, *out + (*out_siz - mod_siz),
mod_siz, 1) != 0) {
res = -1;
block_siz = (in_siz < mod_siz - 11) ? in_siz : (mod_siz - 11);
res = cry_rsa_encrypt_block(ctx, *out + *out_siz, in, block_siz);
if (res != 0)
break;
}
*out_siz += mod_siz;
in_siz -= block_siz;
in += block_siz;
}
free(padded_block);
cry_mpi_clear_list(&c, &m, (cry_mpi *)NULL);
if (res != 0) {
if (*out != NULL) {
free(*out);
*out = NULL;
}
*out_siz = 0;
*out = NULL;
}
return res;
}
......@@ -127,22 +222,11 @@ int cry_rsa_decrypt(cry_rsa_ctx *ctx, unsigned char **out, size_t *out_siz,
const unsigned char *in, size_t in_siz)
{
int res;
cry_mpi c, m;
size_t i, mod_siz;
unsigned char *padded_block;
size_t mod_siz;
*out = NULL;
*out_siz = 0;
mod_siz = cry_mpi_count_bytes(&ctx->m);
padded_block = malloc(mod_siz);
if (padded_block == NULL)
return -1;
if ((res = cry_mpi_init_list(&c, &m, (cry_mpi *)NULL)) != 0) {
free(padded_block);
return res;
}
mod_siz = cry_mpi_count_bytes(&ctx->n);
while (in_siz > 0) {
if (in_siz < mod_siz) {
......@@ -151,47 +235,23 @@ int cry_rsa_decrypt(cry_rsa_ctx *ctx, unsigned char **out, size_t *out_siz,
break;
}
if ((res = cry_mpi_load_bin(&c, in, mod_siz)) != 0)
break;
if ((res = cry_mpi_mod_exp(&m, &c, &ctx->d, &ctx->m)) != 0)
break;
if (cry_mpi_store_bin(&m, padded_block, mod_siz, 1) != 0) {
res = -1;
break;
}
*out = realloc(*out, *out_siz + mod_siz);
if (padded_block[1] > 0x02) {
/* Decryption error or unrecognized block type */
res = -1;
res = cry_rsa_decrypt_block(ctx, *out, in, mod_siz);
if (res < 0)
break;
}
/*
* Find next 0 byte after padding type byte; this signifies
* start of data
*/
i = 2;
while (padded_block[i++]) {
}
*out_siz += mod_siz - i;
*out = realloc(*out, *out_siz);
if (*out == NULL) {
res = -1;
break;
}
memcpy(*out + (*out_siz - (mod_siz - i)),
padded_block + i, mod_siz - i);
*out_siz += res;
in_siz -= mod_siz;
in += mod_siz;
res = 0; /* decrypt block returns the number of decrypted bytes */
}
free(padded_block);
cry_mpi_clear_list(&c, &m, (cry_mpi *)NULL);
if (res != 0) {
if (*out != NULL) {
free(*out);
*out = NULL;
}
*out_siz = 0;
*out = NULL;
}
return res;
}
......@@ -207,7 +267,7 @@ int cry_rsa_keygen(cry_rsa_ctx *ctx, size_t bits)
unsigned int i;
if ((res = cry_mpi_init_list(&ctx->d, &ctx->e, &ctx->m,
if ((res = cry_mpi_init_list(&ctx->d, &ctx->e, &ctx->n,
(cry_mpi *)NULL)) != 0)
return res;
if ((res = cry_mpi_init_list(&p, &q, &p1, &q1, &phi,
......@@ -219,7 +279,7 @@ int cry_rsa_keygen(cry_rsa_ctx *ctx, size_t bits)
i = MAX_ITER;
if ((res = cry_mpi_prime(&q, hbits, &i)) != 0)
goto e;
if ((res = cry_mpi_mul(&ctx->m, &p, &q)) != 0)
if ((res = cry_mpi_mul(&ctx->n, &p, &q)) != 0)
goto e;
one.alloc = 1;
......@@ -242,6 +302,13 @@ int cry_rsa_keygen(cry_rsa_ctx *ctx, size_t bits)
}
e: cry_mpi_clear_list(&p, &q, &p1, &q1, &phi, (cry_mpi *)NULL);
if (res != 0)
cry_mpi_clear_list(&ctx->d, &ctx->e, &ctx->m, (cry_mpi *)NULL);
cry_mpi_clear_list(&ctx->d, &ctx->e, &ctx->n, (cry_mpi *)NULL);
return res;
}
int cry_rsa_init(cry_rsa_ctx *ctx, int padding)
{
memset(ctx, 0, sizeof(*ctx));
ctx->padding = padding;
return 0;
}
......@@ -14,7 +14,7 @@ static void keygen(void)
ASSERT_OK(cry_rsa_keygen(&rsa, KEYGEN_BITS));
cry_mpi_clear_list(&rsa.m, &rsa.e, &rsa.d, NULL);
cry_mpi_clear_list(&rsa.n, &rsa.e, &rsa.d, NULL);
}
static const unsigned char modulus[] = {
......@@ -47,20 +47,21 @@ static const unsigned char plain_text[] = {
0x09
};
/* Ciphertext wether the PKCS#1 SSA padding is enabled (SIGN flag) */
static const unsigned char cipher_text[] = {
0x6a, 0x2d, 0x1d, 0x54, 0x25, 0xe8, 0x0d, 0xd3,
0xdc, 0xaf, 0x1c, 0x0b, 0xe7, 0x62, 0x1f, 0xa7,
0x2b, 0xaa, 0x3e, 0xc2, 0x5b, 0x52, 0x5b, 0x8f,
0xfb, 0x29, 0xa9, 0x35, 0xae, 0xb2, 0xb5, 0x96,
0x54, 0x42, 0x22, 0xbf, 0x96, 0x17, 0xee, 0x9f,
0x15, 0x8a, 0x7f, 0x8c, 0x59, 0x9d, 0x4e, 0x5d,
0xbd, 0x48, 0x57, 0x6b, 0x67, 0xd4, 0x07, 0x09,
0x84, 0x43, 0xa2, 0x3f, 0xe7, 0xb3, 0x53, 0x96
/* Signature for RSA PSS */
static const unsigned char sign[] = {
0xb7, 0x96, 0xb6, 0x06, 0xb9, 0x25, 0xeb, 0x1c,
0x4d, 0x38, 0xa8, 0xcf, 0xe4, 0xae, 0x2a, 0x34,
0xa9, 0x10, 0x09, 0x57, 0x3b, 0x45, 0x5a, 0x34,
0x2f, 0xf5, 0xa7, 0x19, 0x0a, 0x05, 0x12, 0xd3,
0xa8, 0xcf, 0xff, 0xc5, 0x47, 0x99, 0x16, 0x11,
0x24, 0xf7, 0x66, 0x0b, 0x29, 0x42, 0xac, 0x6c,
0xb9, 0x77, 0xdd, 0xc9, 0x49, 0xd7, 0xfc, 0x0d,
0xf2, 0x33, 0x8d, 0x78, 0x80, 0xb3, 0x8f, 0x65
};
#define PLAIN_LEN sizeof(plain_text)
#define CIPHER_LEN sizeof(cipher_text)
#define SIGN_LEN sizeof(sign)
#define CIPHER_LEN SIGN_LEN
static void encrypt_decrypt(void)
{
......@@ -69,11 +70,11 @@ static void encrypt_decrypt(void)
unsigned char *cipher_buf;
unsigned char *plain_buf;
cry_mpi_init_bin(&rsa.m, modulus, sizeof(modulus));
cry_rsa_init(&rsa, CRY_RSA_PADDING_PKCS1);
cry_mpi_init_bin(&rsa.n, modulus, sizeof(modulus));
cry_mpi_init_bin(&rsa.e, public, sizeof(public));
cry_mpi_init_bin(&rsa.d, private, sizeof(private));
rsa.flags = 0;
ASSERT_OK(cry_rsa_encrypt(&rsa, &cipher_buf, &outlen,
plain_text, PLAIN_LEN));
if (cipher_buf) {
......@@ -88,7 +89,7 @@ static void encrypt_decrypt(void)
}
free(cipher_buf);
}
cry_mpi_clear_list(&rsa.m, &rsa.e, &rsa.d, NULL);
cry_mpi_clear_list(&rsa.n, &rsa.e, &rsa.d, NULL);
}
......@@ -99,16 +100,16 @@ static void sign_verify(void)
unsigned char *cipher_buf;
unsigned char *plain_buf;
cry_mpi_init_bin(&rsa.m, modulus, sizeof(modulus));
cry_rsa_init(&rsa, CRY_RSA_PADDING_PKCS1_PSS);
cry_mpi_init_bin(&rsa.n, modulus, sizeof(modulus));
cry_mpi_init_bin(&rsa.e, public, sizeof(public));
cry_mpi_init_bin(&rsa.d, private, sizeof(private));
rsa.flags = CRY_RSA_FLAG_SIGN;
ASSERT_OK(cry_rsa_encrypt(&rsa, &cipher_buf, &outlen,
plain_text, PLAIN_LEN));
if (cipher_buf) {
ASSERT_EQ(outlen, CIPHER_LEN);
ASSERT_EQ_BUF(cipher_buf, cipher_text, outlen);
ASSERT_EQ_BUF(cipher_buf, sign, outlen);
ASSERT_OK(cry_rsa_decrypt(&rsa, &plain_buf, &outlen,
cipher_buf, outlen));
......@@ -119,7 +120,7 @@ static void sign_verify(void)
}
free(cipher_buf);
}
cry_mpi_clear_list(&rsa.m, &rsa.e, &rsa.d, NULL);
cry_mpi_clear_list(&rsa.n, &rsa.e, &rsa.d, NULL);
}
struct rsa_param {
......@@ -170,16 +171,17 @@ static void rsa_pkcs1_encrypt(int argc, char *argv[])
cry_prng_aes_init(NULL, 0);
rsa_param_init(&par, argc, argv);
cry_mpi_init_bin(&rsa.m, par.mraw, par.mlen);
cry_rsa_init(&rsa, CRY_RSA_PADDING_PKCS1);
cry_mpi_init_bin(&rsa.n, par.mraw, par.mlen);
cry_mpi_init_bin(&rsa.e, par.eraw, par.elen);
rsa.flags = 0;
ASSERT_OK(cry_rsa_encrypt(&rsa, &cipher_buf, &outlen,
par.clrraw, par.clrlen));
free(par.mraw);
free(cipher_buf);
cry_mpi_clear_list(&rsa.m, &rsa.e, NULL);
cry_mpi_clear_list(&rsa.n, &rsa.e, NULL);
}
static void dispatch(int argc, char *argv[])
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment