docker: source checking container
[gnuk/gnuk.git] / src / call-rsa.c
1 /*
2  * call-rsa.c -- Glue code between RSA computation and OpenPGP card protocol
3  *
4  * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015
5  *               Free Software Initiative of Japan
6  * Author: NIIBE Yutaka <gniibe@fsij.org>
7  *
8  * This file is a part of Gnuk, a GnuPG USB Token implementation.
9  *
10  * Gnuk is free software: you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * Gnuk is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
18  * License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #include <stdint.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <chopstx.h>
29
30 #include "config.h"
31
32 #include "gnuk.h"
33 #include "status-code.h"
34 #include "random.h"
35 #include "polarssl/config.h"
36 #include "polarssl/rsa.h"
37
38 static rsa_context rsa_ctx;
39 static struct chx_cleanup clp;
40
41 static void
42 rsa_cleanup (void *arg)
43 {
44   free (arg);
45   rsa_free (&rsa_ctx);
46 }
47
48
49 int
50 rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len,
51           struct key_data *kd, int pubkey_len)
52 {
53   mpi P1, Q1, H;
54   int ret = 0;
55   unsigned char temp[pubkey_len];
56
57   rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
58
59   mpi_init (&P1);  mpi_init (&Q1);  mpi_init (&H);
60
61   rsa_ctx.len = pubkey_len;
62   MPI_CHK( mpi_lset (&rsa_ctx.E, 0x10001) );
63   MPI_CHK( mpi_read_binary (&rsa_ctx.P, &kd->data[0], pubkey_len / 2) );
64   MPI_CHK( mpi_read_binary (&rsa_ctx.Q, &kd->data[pubkey_len / 2],
65                             pubkey_len / 2) );
66 #if 0
67   MPI_CHK( mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q) );
68 #endif
69   MPI_CHK( mpi_sub_int (&P1, &rsa_ctx.P, 1) );
70   MPI_CHK( mpi_sub_int (&Q1, &rsa_ctx.Q, 1) );
71   MPI_CHK( mpi_mul_mpi (&H, &P1, &Q1) );
72   MPI_CHK( mpi_inv_mod (&rsa_ctx.D , &rsa_ctx.E, &H) );
73   MPI_CHK( mpi_mod_mpi (&rsa_ctx.DP, &rsa_ctx.D, &P1) );
74   MPI_CHK( mpi_mod_mpi (&rsa_ctx.DQ, &rsa_ctx.D, &Q1) );
75   MPI_CHK( mpi_inv_mod (&rsa_ctx.QP, &rsa_ctx.Q, &rsa_ctx.P) );
76  cleanup:
77   mpi_free (&P1);  mpi_free (&Q1);  mpi_free (&H);
78   if (ret == 0)
79     {
80       int cs;
81
82       DEBUG_INFO ("RSA sign...");
83       clp.next = NULL;
84       clp.routine = rsa_cleanup;
85       clp.arg = NULL;
86       chopstx_cleanup_push (&clp);
87       cs = chopstx_setcancelstate (0); /* Allow cancellation.  */
88       ret = rsa_rsassa_pkcs1_v15_sign (&rsa_ctx, NULL, NULL,
89                                        RSA_PRIVATE, SIG_RSA_RAW,
90                                        msg_len, raw_message, temp);
91       memcpy (output, temp, pubkey_len);
92       chopstx_setcancelstate (cs);
93       chopstx_cleanup_pop (0);
94     }
95
96   rsa_free (&rsa_ctx);
97   if (ret != 0)
98     {
99       DEBUG_INFO ("fail:");
100       DEBUG_SHORT (ret);
101       return -1;
102     }
103   else
104     {
105       DEBUG_INFO ("done.\r\n");
106       GPG_SUCCESS ();
107       return 0;
108     }
109 }
110
111 /*
112  * LEN: length in byte
113  */
114 uint8_t *
115 modulus_calc (const uint8_t *p, int len)
116 {
117   mpi P, Q, N;
118   uint8_t *modulus;
119   int ret;
120
121   modulus = malloc (len);
122   if (modulus == NULL)
123     return NULL;
124
125   mpi_init (&P);  mpi_init (&Q);  mpi_init (&N);
126   MPI_CHK( mpi_read_binary (&P, p, len / 2) );
127   MPI_CHK( mpi_read_binary (&Q, p + len / 2, len / 2) );
128   MPI_CHK( mpi_mul_mpi (&N, &P, &Q) );
129   MPI_CHK( mpi_write_binary (&N, modulus, len) );
130  cleanup:
131   mpi_free (&P);  mpi_free (&Q);  mpi_free (&N);
132   if (ret != 0)
133     {
134       free (modulus);
135       return NULL;
136     }
137   return modulus;
138 }
139
140
141 int
142 rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len,
143              struct key_data *kd, unsigned int *output_len_p)
144 {
145   mpi P1, Q1, H;
146   int ret;
147
148   DEBUG_INFO ("RSA decrypt:");
149   DEBUG_WORD ((uint32_t)&ret);
150
151   rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
152   mpi_init (&P1);  mpi_init (&Q1);  mpi_init (&H);
153
154   rsa_ctx.len = msg_len;
155   DEBUG_WORD (msg_len);
156
157   MPI_CHK( mpi_lset (&rsa_ctx.E, 0x10001) );
158   MPI_CHK( mpi_read_binary (&rsa_ctx.P, &kd->data[0], msg_len / 2) );
159   MPI_CHK( mpi_read_binary (&rsa_ctx.Q, &kd->data[msg_len / 2], msg_len / 2) );
160 #if 0
161   MPI_CHK( mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q) );
162 #endif
163   MPI_CHK( mpi_sub_int (&P1, &rsa_ctx.P, 1) );
164   MPI_CHK( mpi_sub_int (&Q1, &rsa_ctx.Q, 1) );
165   MPI_CHK( mpi_mul_mpi (&H, &P1, &Q1) );
166   MPI_CHK( mpi_inv_mod (&rsa_ctx.D , &rsa_ctx.E, &H) );
167   MPI_CHK( mpi_mod_mpi (&rsa_ctx.DP, &rsa_ctx.D, &P1) );
168   MPI_CHK( mpi_mod_mpi (&rsa_ctx.DQ, &rsa_ctx.D, &Q1) );
169   MPI_CHK( mpi_inv_mod (&rsa_ctx.QP, &rsa_ctx.Q, &rsa_ctx.P) );
170  cleanup:
171   mpi_free (&P1);  mpi_free (&Q1);  mpi_free (&H);
172   if (ret == 0)
173     {
174       int cs;
175
176       DEBUG_INFO ("RSA decrypt ...");
177       clp.next = NULL;
178       clp.routine = rsa_cleanup;
179       clp.arg = NULL;
180       chopstx_cleanup_push (&clp);
181       cs = chopstx_setcancelstate (0); /* Allow cancellation.  */
182       ret = rsa_rsaes_pkcs1_v15_decrypt (&rsa_ctx, NULL, NULL,
183                                          RSA_PRIVATE, output_len_p, input,
184                                          output, MAX_RES_APDU_DATA_SIZE);
185       chopstx_setcancelstate (cs);
186       chopstx_cleanup_pop (0);
187     }
188
189   rsa_free (&rsa_ctx);
190   if (ret != 0)
191     {
192       DEBUG_INFO ("fail:");
193       DEBUG_SHORT (ret);
194       return -1;
195     }
196   else
197     {
198       DEBUG_INFO ("done.\r\n");
199       GPG_SUCCESS ();
200       return 0;
201     }
202 }
203
204 int
205 rsa_verify (const uint8_t *pubkey, int pubkey_len,
206             const uint8_t *hash, const uint8_t *sig)
207 {
208   int ret;
209
210   rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
211   rsa_ctx.len = pubkey_len;
212   MPI_CHK( mpi_lset (&rsa_ctx.E, 0x10001) );
213   MPI_CHK( mpi_read_binary (&rsa_ctx.N, pubkey, pubkey_len) );
214
215   DEBUG_INFO ("RSA verify...");
216
217   MPI_CHK( rsa_rsassa_pkcs1_v15_verify (&rsa_ctx, NULL, NULL,
218                                         RSA_PUBLIC, SIG_RSA_SHA256, 32,
219                                         hash, sig) );
220  cleanup:
221   rsa_free (&rsa_ctx);
222   if (ret != 0)
223     {
224       DEBUG_INFO ("fail:");
225       DEBUG_SHORT (ret);
226       return -1;
227     }
228   else
229     {
230       DEBUG_INFO ("verified.\r\n");
231       return 0;
232     }
233 }
234
235 #define RSA_EXPONENT 0x10001
236
237 uint8_t *
238 rsa_genkey (int pubkey_len)
239 {
240   int ret;
241   uint8_t index = 0;
242   uint8_t *p_q_modulus = (uint8_t *)malloc (pubkey_len * 2);
243   uint8_t *p = p_q_modulus;
244   uint8_t *q = p_q_modulus + pubkey_len / 2;
245   uint8_t *modulus = p_q_modulus + pubkey_len;
246   int cs;
247
248   extern int prng_seed (int (*f_rng)(void *, unsigned char *, size_t),
249                         void *p_rng);
250   extern void neug_flush (void);
251
252   if (p_q_modulus == NULL)
253     return NULL;
254
255   neug_flush ();
256   prng_seed (random_gen, &index);
257   rsa_init (&rsa_ctx, RSA_PKCS_V15, 0);
258
259   clp.next = NULL;
260   clp.routine = rsa_cleanup;
261   clp.arg = (void *)p_q_modulus;
262   chopstx_cleanup_push (&clp);
263   cs = chopstx_setcancelstate (0); /* Allow cancellation.  */
264   MPI_CHK( rsa_gen_key (&rsa_ctx, random_gen, &index, pubkey_len * 8,
265                         RSA_EXPONENT) );
266   MPI_CHK( mpi_write_binary (&rsa_ctx.P, p, pubkey_len / 2) );
267   MPI_CHK( mpi_write_binary (&rsa_ctx.Q, q, pubkey_len / 2) );
268   MPI_CHK( mpi_write_binary (&rsa_ctx.N, modulus, pubkey_len) );
269   clp.arg = NULL;
270
271  cleanup:
272   chopstx_setcancelstate (cs);
273   chopstx_cleanup_pop (1);
274   if (ret != 0)
275       return NULL;
276   else
277     return p_q_modulus;
278 }