2010-09-05 09:10:54 +00:00
|
|
|
/*
|
|
|
|
* call-rsa.c -- Glue code between RSA computation and OpenPGP card protocol
|
|
|
|
*
|
2011-11-01 02:10:09 +00:00
|
|
|
* Copyright (C) 2010, 2011 Free Software Initiative of Japan
|
2010-09-05 09:10:54 +00:00
|
|
|
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
|
|
|
*
|
|
|
|
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
|
|
|
*
|
|
|
|
* Gnuk 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 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* Gnuk 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, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2010-09-08 05:24:12 +00:00
|
|
|
#include <stdlib.h>
|
2010-09-05 09:10:54 +00:00
|
|
|
#include "config.h"
|
|
|
|
#include "ch.h"
|
|
|
|
#include "gnuk.h"
|
2012-01-18 09:59:16 +00:00
|
|
|
#include "openpgp.h"
|
2010-09-05 09:10:54 +00:00
|
|
|
#include "polarssl/config.h"
|
|
|
|
#include "polarssl/rsa.h"
|
|
|
|
|
2011-11-01 02:10:09 +00:00
|
|
|
#define RSA_SIGNATURE_LENGTH KEY_CONTENT_LEN
|
|
|
|
/* 256 byte == 2048-bit */
|
|
|
|
/* 128 byte == 1024-bit */
|
2010-10-16 00:22:18 +00:00
|
|
|
|
2010-09-05 09:10:54 +00:00
|
|
|
static rsa_context rsa_ctx;
|
|
|
|
|
|
|
|
int
|
2010-11-30 01:04:30 +00:00
|
|
|
rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
|
|
|
|
struct key_data *kd)
|
2010-09-05 09:10:54 +00:00
|
|
|
{
|
|
|
|
mpi P1, Q1, H;
|
|
|
|
int r;
|
2010-12-07 05:34:25 +00:00
|
|
|
unsigned char temp[RSA_SIGNATURE_LENGTH];
|
2010-09-05 09:10:54 +00:00
|
|
|
|
|
|
|
mpi_init (&P1, &Q1, &H, NULL);
|
|
|
|
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
|
|
|
|
|
2011-11-01 02:10:09 +00:00
|
|
|
rsa_ctx.len = KEY_CONTENT_LEN;
|
2010-09-05 09:10:54 +00:00
|
|
|
mpi_read_string (&rsa_ctx.E, 16, "10001");
|
2010-11-30 01:04:30 +00:00
|
|
|
mpi_read_binary (&rsa_ctx.P, &kd->data[0], rsa_ctx.len / 2);
|
2011-11-01 02:10:09 +00:00
|
|
|
mpi_read_binary (&rsa_ctx.Q, &kd->data[KEY_CONTENT_LEN/2], rsa_ctx.len / 2);
|
2010-09-05 09:10:54 +00:00
|
|
|
mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q);
|
|
|
|
mpi_sub_int (&P1, &rsa_ctx.P, 1);
|
|
|
|
mpi_sub_int (&Q1, &rsa_ctx.Q, 1);
|
|
|
|
mpi_mul_mpi (&H, &P1, &Q1);
|
|
|
|
mpi_inv_mod (&rsa_ctx.D , &rsa_ctx.E, &H);
|
|
|
|
mpi_mod_mpi (&rsa_ctx.DP, &rsa_ctx.D, &P1);
|
|
|
|
mpi_mod_mpi (&rsa_ctx.DQ, &rsa_ctx.D, &Q1);
|
|
|
|
mpi_inv_mod (&rsa_ctx.QP, &rsa_ctx.Q, &rsa_ctx.P);
|
|
|
|
mpi_free (&P1, &Q1, &H, NULL);
|
|
|
|
|
2010-09-08 05:24:12 +00:00
|
|
|
DEBUG_INFO ("RSA sign...");
|
2010-12-07 05:34:25 +00:00
|
|
|
#if 0
|
2010-09-05 09:10:54 +00:00
|
|
|
if ((r = rsa_check_privkey (&rsa_ctx)) == 0)
|
|
|
|
DEBUG_INFO ("ok...");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DEBUG_INFO ("failed.\r\n");
|
|
|
|
DEBUG_SHORT (r);
|
|
|
|
rsa_free (&rsa_ctx);
|
|
|
|
return r;
|
|
|
|
}
|
2010-12-07 05:34:25 +00:00
|
|
|
#endif
|
2010-09-05 09:10:54 +00:00
|
|
|
|
|
|
|
r = rsa_pkcs1_sign (&rsa_ctx, RSA_PRIVATE, SIG_RSA_RAW,
|
2010-12-07 05:34:25 +00:00
|
|
|
msg_len, raw_message, temp);
|
|
|
|
memcpy (output, temp, RSA_SIGNATURE_LENGTH);
|
2010-09-05 09:10:54 +00:00
|
|
|
rsa_free (&rsa_ctx);
|
|
|
|
if (r < 0)
|
|
|
|
{
|
|
|
|
DEBUG_INFO ("fail:");
|
|
|
|
DEBUG_SHORT (r);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-01-18 09:59:16 +00:00
|
|
|
res_APDU_size = RSA_SIGNATURE_LENGTH;
|
2010-09-05 09:10:54 +00:00
|
|
|
DEBUG_INFO ("done.\r\n");
|
2012-01-18 09:59:16 +00:00
|
|
|
GPG_SUCCESS ();
|
2010-09-05 09:10:54 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-01 02:10:09 +00:00
|
|
|
/*
|
|
|
|
* LEN: length in byte
|
|
|
|
*/
|
2010-09-05 09:10:54 +00:00
|
|
|
const uint8_t *
|
|
|
|
modulus_calc (const uint8_t *p, int len)
|
|
|
|
{
|
|
|
|
mpi P, Q, N;
|
|
|
|
uint8_t *modulus;
|
|
|
|
|
2011-11-01 02:10:09 +00:00
|
|
|
modulus = malloc (len);
|
2010-09-05 09:10:54 +00:00
|
|
|
if (modulus == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
mpi_init (&P, &Q, &N, NULL);
|
2011-11-01 02:10:09 +00:00
|
|
|
mpi_read_binary (&P, p, len / 2);
|
|
|
|
mpi_read_binary (&Q, p + len / 2, len / 2);
|
2010-09-05 09:10:54 +00:00
|
|
|
mpi_mul_mpi (&N, &P, &Q);
|
|
|
|
|
2011-11-01 02:10:09 +00:00
|
|
|
mpi_write_binary (&N, modulus, len);
|
2010-09-05 09:10:54 +00:00
|
|
|
mpi_free (&P, &Q, &N, NULL);
|
|
|
|
return modulus;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
modulus_free (const uint8_t *p)
|
|
|
|
{
|
|
|
|
free ((void *)p);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2010-11-30 01:04:30 +00:00
|
|
|
rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
|
|
|
|
struct key_data *kd)
|
2010-09-05 09:10:54 +00:00
|
|
|
{
|
|
|
|
mpi P1, Q1, H;
|
|
|
|
int r;
|
|
|
|
int output_len;
|
|
|
|
|
2010-09-12 07:18:59 +00:00
|
|
|
DEBUG_INFO ("RSA decrypt:");
|
|
|
|
DEBUG_WORD ((uint32_t)&output_len);
|
2010-09-08 05:24:12 +00:00
|
|
|
|
2010-09-05 09:10:54 +00:00
|
|
|
mpi_init (&P1, &Q1, &H, NULL);
|
|
|
|
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
|
|
|
|
|
|
|
|
rsa_ctx.len = msg_len;
|
2010-09-08 05:24:12 +00:00
|
|
|
DEBUG_WORD (msg_len);
|
|
|
|
|
2010-09-05 09:10:54 +00:00
|
|
|
mpi_read_string (&rsa_ctx.E, 16, "10001");
|
2011-11-01 02:10:09 +00:00
|
|
|
mpi_read_binary (&rsa_ctx.P, &kd->data[0], KEY_CONTENT_LEN / 2);
|
|
|
|
mpi_read_binary (&rsa_ctx.Q, &kd->data[KEY_CONTENT_LEN/2],
|
|
|
|
KEY_CONTENT_LEN / 2);
|
2010-09-05 09:10:54 +00:00
|
|
|
mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q);
|
|
|
|
mpi_sub_int (&P1, &rsa_ctx.P, 1);
|
|
|
|
mpi_sub_int (&Q1, &rsa_ctx.Q, 1);
|
|
|
|
mpi_mul_mpi (&H, &P1, &Q1);
|
|
|
|
mpi_inv_mod (&rsa_ctx.D , &rsa_ctx.E, &H);
|
|
|
|
mpi_mod_mpi (&rsa_ctx.DP, &rsa_ctx.D, &P1);
|
|
|
|
mpi_mod_mpi (&rsa_ctx.DQ, &rsa_ctx.D, &Q1);
|
|
|
|
mpi_inv_mod (&rsa_ctx.QP, &rsa_ctx.Q, &rsa_ctx.P);
|
|
|
|
mpi_free (&P1, &Q1, &H, NULL);
|
|
|
|
|
2010-09-08 05:24:12 +00:00
|
|
|
DEBUG_INFO ("RSA decrypt ...");
|
|
|
|
#if 0
|
|
|
|
/* This consume some memory */
|
2010-09-05 09:10:54 +00:00
|
|
|
if ((r = rsa_check_privkey (&rsa_ctx)) == 0)
|
|
|
|
DEBUG_INFO ("ok...");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DEBUG_INFO ("failed.\r\n");
|
|
|
|
DEBUG_SHORT (r);
|
|
|
|
rsa_free (&rsa_ctx);
|
|
|
|
return r;
|
|
|
|
}
|
2010-09-08 05:24:12 +00:00
|
|
|
#endif
|
2010-09-05 09:10:54 +00:00
|
|
|
|
|
|
|
r = rsa_pkcs1_decrypt (&rsa_ctx, RSA_PRIVATE, &output_len,
|
2012-01-20 09:18:23 +00:00
|
|
|
input, output, MAX_RES_APDU_DATA_SIZE);
|
2010-09-05 09:10:54 +00:00
|
|
|
rsa_free (&rsa_ctx);
|
|
|
|
if (r < 0)
|
|
|
|
{
|
|
|
|
DEBUG_INFO ("fail:");
|
|
|
|
DEBUG_SHORT (r);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-01-18 09:59:16 +00:00
|
|
|
res_APDU_size = output_len;
|
2010-09-05 09:10:54 +00:00
|
|
|
DEBUG_INFO ("done.\r\n");
|
2012-01-18 09:59:16 +00:00
|
|
|
GPG_SUCCESS ();
|
2010-09-05 09:10:54 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2012-05-29 03:14:10 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
rsa_verify (const uint8_t *pubkey, const uint8_t *hash, int hashlen,
|
|
|
|
const uint8_t *signature)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
|
|
|
|
rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
|
|
|
|
rsa_ctx.len = KEY_CONTENT_LEN;
|
|
|
|
mpi_read_string (&rsa_ctx.E, 16, "10001");
|
|
|
|
mpi_read_binary (&rsa_ctx.N, pubkey, KEY_CONTENT_LEN);
|
|
|
|
|
|
|
|
DEBUG_INFO ("RSA verify...");
|
|
|
|
|
|
|
|
r = rsa_pkcs1_verify (&rsa_ctx, RSA_PUBLIC, SIG_RSA_RAW, hashlen,
|
|
|
|
hash, signature);
|
|
|
|
|
|
|
|
rsa_free (&rsa_ctx);
|
|
|
|
if (r < 0)
|
|
|
|
{
|
|
|
|
DEBUG_INFO ("fail:");
|
|
|
|
DEBUG_SHORT (r);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DEBUG_INFO ("verified.\r\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|