Version 0.10
[gnuk/gnuk.git] / src / openpgp.c
1 /*
2  * openpgp.c -- OpenPGP card protocol support
3  *
4  * Copyright (C) 2010, 2011 Free Software Initiative of Japan
5  * Author: NIIBE Yutaka <gniibe@fsij.org>
6  *
7  * This file is a part of Gnuk, a GnuPG USB Token implementation.
8  *
9  * Gnuk is free software: you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * Gnuk is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "config.h"
25 #include "ch.h"
26 #include "hal.h"
27 #include "gnuk.h"
28 #include "openpgp.h"
29 #include "polarssl/config.h"
30 #include "polarssl/sha1.h"
31
32 #define INS_VERIFY                              0x20
33 #define INS_CHANGE_REFERENCE_DATA               0x24
34 #define INS_PSO                                 0x2a
35 #define INS_RESET_RETRY_COUNTER                 0x2c
36 #define INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR    0x47
37 #define INS_INTERNAL_AUTHENTICATE               0x88
38 #define INS_SELECT_FILE                         0xa4
39 #define INS_READ_BINARY                         0xb0
40 #define INS_GET_DATA                            0xca
41 #define INS_WRITE_BINARY                        0xd0
42 #define INS_UPDATE_BINARY                       0xd6
43 #define INS_PUT_DATA                            0xda
44 #define INS_PUT_DATA_ODD                        0xdb    /* For key import */
45
46 static const uint8_t
47 select_file_TOP_result[] __attribute__ ((aligned (1))) = {
48   0x00, 0x00,        /* unused */
49   0x00, 0x00,        /* number of bytes in this directory: to be filled */
50   0x3f, 0x00,        /* field of selected file: MF, 3f00 */
51   0x38,                 /* it's DF */
52   0xff,                 /* unused */
53   0xff, 0x44, 0x44,     /* access conditions */
54   0x01,                 /* status of the selected file (OK, unblocked) */
55   0x05,                 /* number of bytes of data follow */
56     0x03,                       /* Features: unused */
57     0x01,                       /* number of subdirectories (OpenPGP) */
58     0x01,                       /* number of elementary files (SerialNo) */
59     0x00,                       /* number of secret codes */
60     0x00,                       /* Unused */
61   0x00, 0x00            /* PIN status: OK, PIN blocked?: No */
62 };
63
64 void
65 write_res_apdu (const uint8_t *p, int len, uint8_t sw1, uint8_t sw2)
66 {
67   res_APDU_size = 2 + len;
68   if (len)
69     memcpy (res_APDU, p, len);
70   res_APDU[len] = sw1;
71   res_APDU[len+1] = sw2;
72 }
73
74 #define FILE_NONE       0
75 #define FILE_DF_OPENPGP 1
76 #define FILE_MF         2
77 #define FILE_EF_DIR     3
78 #define FILE_EF_SERIAL  4
79 #define FILE_EF_CH_CERTIFICATE  5
80 #define FILE_EF_RANDOM          6
81
82 static uint8_t file_selection;
83
84 static void
85 gpg_init (void)
86 {
87   const uint8_t *flash_data_start;
88
89   file_selection = FILE_NONE;
90   flash_data_start = flash_init ();
91   gpg_data_scan (flash_data_start);
92 }
93
94 static void
95 gpg_fini (void)
96 {
97   ac_fini ();
98 }
99
100 #if defined(PINPAD_SUPPORT)
101 /* 
102  * Invoke the thread PIN_MAIN, and let user input PIN string.
103  * Return length of the string.
104  * The string itself is in PIN_INPUT_BUFFER.
105  */
106 static int
107 get_pinpad_input (int msg_code)
108 {
109   Thread *t;
110
111   t = chThdCreateFromHeap (NULL, THD_WA_SIZE (128),
112                            NORMALPRIO, pin_main, (void *)msg_code);
113   if (t == NULL)
114     return -1;
115   else
116     {
117       chThdWait (t);
118       return pin_input_len;
119     }
120 }
121 #endif
122
123 static void
124 cmd_verify (void)
125 {
126   int len;
127   uint8_t p2 = cmd_APDU[3];
128   int r;
129   int data_start = 5;
130   const uint8_t *pw;
131
132   DEBUG_INFO (" - VERIFY\r\n");
133   DEBUG_BYTE (p2);
134
135 #if defined(PINPAD_SUPPORT)
136   if (cmd_APDU_size == 4)
137     /* Verification with pinpad */
138     {
139       len = get_pinpad_input (PIN_INPUT_CURRENT);
140       if (len < 0)
141         {
142           GPG_ERROR ();
143           return;
144         }
145
146       pw = pin_input_buffer;
147     }
148   else
149 #endif
150     {
151       len = cmd_APDU[4];
152       if (len == 0)                     /* extended length */
153         {
154           len = (cmd_APDU[5]<<8) | cmd_APDU[6];
155           data_start = 7;
156         }
157
158       pw = &cmd_APDU[data_start];
159     }
160
161
162   if (p2 == 0x81)
163     r = verify_pso_cds (pw, len);
164   else if (p2 == 0x82)
165     r = verify_other (pw, len);
166   else
167     r = verify_admin (pw, len);
168
169   if (r < 0)
170     {
171       DEBUG_INFO ("failed\r\n");
172       GPG_SECURITY_FAILURE ();
173     }
174   else if (r == 0)
175     {
176       DEBUG_INFO ("blocked\r\n");
177       GPG_SECURITY_AUTH_BLOCKED ();
178     }
179   else
180     {
181       DEBUG_INFO ("good\r\n");
182       GPG_SUCCESS ();
183     }
184 }
185
186 int
187 gpg_change_keystring (int who_old, const uint8_t *old_ks,
188                       int who_new, const uint8_t *new_ks)
189 {
190   int r;
191   int prv_keys_exist = 0;
192
193   r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, who_old, old_ks);
194   if (r < 0)
195     return r;
196
197   if (r > 0)
198     prv_keys_exist++;
199
200   r = gpg_do_chks_prvkey (GPG_KEY_FOR_SIGNING, who_old, old_ks,
201                           who_new, new_ks);
202   if (r < 0)
203     return -2;
204
205   r = gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPTION, who_old, old_ks);
206   if (r < 0)
207     return r;
208
209   if (r > 0)
210     prv_keys_exist++;
211
212   r = gpg_do_chks_prvkey (GPG_KEY_FOR_DECRYPTION, who_old, old_ks,
213                           who_new, new_ks);
214   if (r < 0)
215     return -2;
216
217   r = gpg_do_load_prvkey (GPG_KEY_FOR_AUTHENTICATION, who_old, old_ks);
218   if (r < 0)
219     return r;
220
221   if (r > 0)
222     prv_keys_exist++;
223
224   r = gpg_do_chks_prvkey (GPG_KEY_FOR_AUTHENTICATION, who_old, old_ks,
225                           who_new, new_ks);
226   if (r < 0)
227     return -2;
228
229   if (prv_keys_exist)
230     return 1;
231   else
232     return 0;
233 }
234
235 static void
236 cmd_change_password (void)
237 {
238   uint8_t old_ks[KEYSTRING_MD_SIZE];
239   uint8_t new_ks0[KEYSTRING_MD_SIZE+1];
240   uint8_t *new_ks = &new_ks0[1];
241   uint8_t p2 = cmd_APDU[3];
242   int len;
243   const uint8_t *pw;
244   const uint8_t *newpw;
245   int pw_len, newpw_len;
246   int who = p2 - 0x80;
247   int r;
248
249   DEBUG_INFO ("Change PW\r\n");
250   DEBUG_BYTE (who);
251
252 #if defined(PINPAD_SUPPORT)
253   if (cmd_APDU_size == 4)
254     /* Modification with pinpad */
255     {
256       pw_len = get_pinpad_input (PIN_INPUT_CURRENT);
257       if (pw_len < 0)
258         {
259           GPG_ERROR ();
260           return;
261         }
262
263       pw = &cmd_APDU[5];
264       memcpy (&cmd_APDU[5], pin_input_buffer, pw_len);
265       newpw = pw + pw_len;
266
267       newpw_len = get_pinpad_input (PIN_INPUT_NEW);
268       if (newpw_len < 0)
269         {
270           GPG_ERROR ();
271           return;
272         }
273
274       memcpy (&cmd_APDU[5]+pw_len, pin_input_buffer, newpw_len);
275
276       len = get_pinpad_input (PIN_INPUT_CONFIRM);
277       if (len < 0)
278         {
279           GPG_ERROR ();
280           return;
281         }
282
283       if (len != newpw_len || memcmp (newpw, pin_input_buffer, len) != 0)
284         {
285           GPG_SECURITY_FAILURE ();
286           return;
287         }
288
289       len = cmd_APDU[4] = pw_len + newpw_len;
290     }
291   else
292 #endif
293     {
294       len = cmd_APDU[4];
295       pw = &cmd_APDU[5];
296       if (len == 0)                     /* extended length */
297         {
298           len = (cmd_APDU[5]<<8) | cmd_APDU[6];
299           pw += 2;
300         }
301     }
302
303   if (who == BY_USER)                   /* PW1 */
304     {
305       const uint8_t *pk = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
306
307       if (pk == NULL)
308         {
309           if (len < (int)strlen (OPENPGP_CARD_INITIAL_PW1))
310             {
311               DEBUG_INFO ("permission denied.\r\n");
312               GPG_SECURITY_FAILURE ();
313               return;
314             }
315
316           pw_len = strlen (OPENPGP_CARD_INITIAL_PW1);
317           newpw = pw + pw_len;
318           newpw_len = len - pw_len;
319         }
320       else
321         {
322           pw_len = pk[0];
323           newpw = pw + pw_len;
324           newpw_len = len - pw_len;
325         }
326     }
327   else                          /* PW3 (0x83) */
328     {
329       pw_len = verify_admin_0 (pw, len, -1);
330
331       if (pw_len < 0)
332         {
333           DEBUG_INFO ("permission denied.\r\n");
334           GPG_SECURITY_FAILURE ();
335           return;
336         }
337       else if (pw_len == 0)
338         {
339           DEBUG_INFO ("blocked.\r\n");
340           GPG_SECURITY_AUTH_BLOCKED ();
341           return;
342         }
343       else
344         {
345           newpw = pw + pw_len;
346           newpw_len = len - pw_len;
347           gpg_set_pw3 (newpw, newpw_len);
348         }
349     }
350
351   sha1 (pw, pw_len, old_ks);
352   sha1 (newpw, newpw_len, new_ks);
353   new_ks0[0] = newpw_len;
354
355   r = gpg_change_keystring (who, old_ks, who, new_ks);
356   if (r < -2)
357     {
358       DEBUG_INFO ("memory error.\r\n");
359       GPG_MEMORY_FAILURE ();
360     }
361   else if (r < 0)
362     {
363       DEBUG_INFO ("security error.\r\n");
364       GPG_SECURITY_FAILURE ();
365     }
366   else if (r == 0 && who == BY_USER)    /* no prvkey */
367     {
368       gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
369       ac_reset_pso_cds ();
370       ac_reset_other ();
371       gpg_reset_pw_err_counter (PW_ERR_PW1);
372       DEBUG_INFO ("Changed DO_KEYSTRING_PW1.\r\n");
373       GPG_SUCCESS ();
374     }
375   else if (r > 0 && who == BY_USER)
376     {
377       gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, 1);
378       ac_reset_pso_cds ();
379       ac_reset_other ();
380       gpg_reset_pw_err_counter (PW_ERR_PW1);
381       DEBUG_INFO ("Changed length of DO_KEYSTRING_PW1.\r\n");
382       GPG_SUCCESS ();
383     }
384   else                          /* r >= 0 && who == BY_ADMIN */
385     {
386       DEBUG_INFO ("done.\r\n");
387       ac_reset_admin ();
388       gpg_reset_pw_err_counter (PW_ERR_PW3);
389       GPG_SUCCESS ();
390     }
391 }
392
393 static void
394 cmd_reset_user_password (void)
395 {
396   uint8_t p1 = cmd_APDU[2];
397   int len;
398   const uint8_t *pw;
399   const uint8_t *newpw;
400   int pw_len, newpw_len;
401   int r;
402   uint8_t new_ks0[KEYSTRING_MD_SIZE+1];
403   uint8_t *new_ks = &new_ks0[1];
404
405   DEBUG_INFO ("Reset PW1\r\n");
406   DEBUG_BYTE (p1);
407
408 #if defined(PINPAD_SUPPORT)
409   if (cmd_APDU_size == 4)
410     /* Modification with pinpad */
411     {
412       if (p1 == 0x00)           /* by User with Reseting Code */
413         {
414           pw_len = get_pinpad_input (PIN_INPUT_CURRENT);
415           if (pw_len < 0)
416             {
417               GPG_ERROR ();
418               return;
419             }
420
421           memcpy (&cmd_APDU[5], pin_input_buffer, pw_len);
422         }
423       else
424         pw_len = 0;
425
426       pw = &cmd_APDU[5];
427       newpw = pw + pw_len;
428       newpw_len = get_pinpad_input (PIN_INPUT_NEW);
429       if (newpw_len < 0)
430         {
431           GPG_ERROR ();
432           return;
433         }
434
435       memcpy (&cmd_APDU[5]+pw_len, pin_input_buffer, newpw_len);
436
437       len = get_pinpad_input (PIN_INPUT_CONFIRM);
438       if (len < 0)
439         {
440           GPG_ERROR ();
441           return;
442         }
443
444       if (len != newpw_len || memcmp (newpw, pin_input_buffer, len) != 0)
445         {
446           GPG_SECURITY_FAILURE ();
447           return;
448         }
449
450       len = cmd_APDU[4] = pw_len + newpw_len;
451     }
452   else
453 #endif
454     {
455       len = cmd_APDU[4];
456       pw = &cmd_APDU[5];
457       if (len == 0)                     /* extended length */
458         {
459           len = (cmd_APDU[5]<<8) | cmd_APDU[6];
460           pw += 2;
461         }
462     }
463
464   if (p1 == 0x00)               /* by User with Reseting Code */
465     {
466       const uint8_t *ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC);
467       uint8_t old_ks[KEYSTRING_MD_SIZE];
468
469       if (gpg_passwd_locked (PW_ERR_RC))
470         {
471           DEBUG_INFO ("blocked.\r\n");
472           GPG_SECURITY_AUTH_BLOCKED ();
473           return;
474         }
475
476       if (ks_rc == NULL)
477         {
478           DEBUG_INFO ("security error.\r\n");
479           GPG_SECURITY_FAILURE ();
480           return;
481         }
482
483       pw_len = ks_rc[0];
484       newpw = pw + pw_len;
485       newpw_len = len - pw_len;
486       sha1 (pw, pw_len, old_ks);
487       sha1 (newpw, newpw_len, new_ks);
488       new_ks0[0] = newpw_len;
489       r = gpg_change_keystring (BY_RESETCODE, old_ks, BY_USER, new_ks);
490       if (r < -2)
491         {
492           DEBUG_INFO ("memory error.\r\n");
493           GPG_MEMORY_FAILURE ();
494         }
495       else if (r < 0)
496         {
497         sec_fail:
498           DEBUG_INFO ("failed.\r\n");
499           gpg_increment_pw_err_counter (PW_ERR_RC);
500           GPG_SECURITY_FAILURE ();
501         }
502       else if (r == 0)
503         {
504           if (memcmp (ks_rc+1, old_ks, KEYSTRING_MD_SIZE) != 0)
505             goto sec_fail;
506           DEBUG_INFO ("done (no prvkey).\r\n");
507           gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0,
508                                KEYSTRING_SIZE_PW1);
509           ac_reset_pso_cds ();
510           ac_reset_other ();
511           gpg_reset_pw_err_counter (PW_ERR_RC);
512           gpg_reset_pw_err_counter (PW_ERR_PW1);
513           GPG_SUCCESS ();
514         }
515       else
516         {
517           DEBUG_INFO ("done.\r\n");
518           ac_reset_pso_cds ();
519           ac_reset_other ();
520           gpg_reset_pw_err_counter (PW_ERR_RC);
521           gpg_reset_pw_err_counter (PW_ERR_PW1);
522           GPG_SUCCESS ();
523         }
524     }
525   else                          /* by Admin (p1 == 0x02) */
526     {
527       const uint8_t *old_ks = keystring_md_pw3;
528
529       if (!ac_check_status (AC_ADMIN_AUTHORIZED))
530         {
531           DEBUG_INFO ("permission denied.\r\n");
532           GPG_SECURITY_FAILURE ();
533           return;
534         }
535
536       newpw_len = len;
537       newpw = pw;
538       sha1 (newpw, newpw_len, new_ks);
539       new_ks0[0] = newpw_len;
540       r = gpg_change_keystring (BY_ADMIN, old_ks, BY_USER, new_ks);
541       if (r < -2)
542         {
543           DEBUG_INFO ("memory error.\r\n");
544           GPG_MEMORY_FAILURE ();
545         }
546       else if (r < 0)
547         {
548           DEBUG_INFO ("security error.\r\n");
549           GPG_SECURITY_FAILURE ();
550         }
551       else if (r == 0)
552         {
553           DEBUG_INFO ("done (no privkey).\r\n");
554           gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0,
555                                KEYSTRING_SIZE_PW1);
556           ac_reset_pso_cds ();
557           ac_reset_other ();
558           gpg_reset_pw_err_counter (PW_ERR_PW1);
559           GPG_SUCCESS ();
560         }
561       else
562         {
563           DEBUG_INFO ("done.\r\n");
564           ac_reset_pso_cds ();
565           ac_reset_other ();
566           gpg_reset_pw_err_counter (PW_ERR_PW1);
567           GPG_SUCCESS ();
568         }
569     }
570 }
571
572 static void
573 cmd_put_data (void)
574 {
575   uint8_t *data;
576   uint16_t tag;
577   int len;
578
579   DEBUG_INFO (" - PUT DATA\r\n");
580
581   if (file_selection != FILE_DF_OPENPGP)
582     GPG_NO_RECORD();
583
584   tag = ((cmd_APDU[2]<<8) | cmd_APDU[3]);
585   len = cmd_APDU_size - 5;
586   data = &cmd_APDU[5];
587   if (len >= 256)
588     /* extended Lc */
589     {
590       data += 2;
591       len -= 2;
592     }
593
594   gpg_do_put_data (tag, data, len);
595 }
596
597 static void
598 cmd_pgp_gakp (void)
599 {
600   DEBUG_INFO (" - Generate Asymmetric Key Pair\r\n");
601   DEBUG_BYTE (cmd_APDU[2]);
602
603   if (cmd_APDU[2] == 0x81)
604     /* Get public key */
605     {
606       if (cmd_APDU[4] == 0)
607         gpg_do_public_key (cmd_APDU[7]);
608       else
609         gpg_do_public_key (cmd_APDU[5]);
610     }
611   else
612     {                                   /* Generate key pair */
613       if (!ac_check_status (AC_ADMIN_AUTHORIZED))
614         GPG_SECURITY_FAILURE ();
615
616       /* XXX: Not yet supported */
617       GPG_ERROR ();
618     }
619 }
620
621 static void
622 cmd_read_binary (void)
623 {
624   DEBUG_INFO (" - Read binary\r\n");
625
626   if (file_selection == FILE_EF_SERIAL)
627     {
628       if (cmd_APDU[3] >= 6)
629         GPG_BAD_P0_P1 ();
630       else
631         {
632           gpg_do_get_data (0x004f, 1); /* AID */
633           res_APDU[0] = 0x5a;
634         }
635     }
636   else
637     GPG_NO_RECORD();
638 }
639
640 static void
641 cmd_select_file (void)
642 {
643   if (cmd_APDU[2] == 4) /* Selection by DF name: it must be OpenPGP card */
644     {
645       DEBUG_INFO (" - select DF by name\r\n");
646
647       /*
648        * P2 == 0, LC=6, name = D2 76 00 01 24 01
649        */
650
651       file_selection = FILE_DF_OPENPGP;
652       if (cmd_APDU[3] == 0x0c)  /* No FCI */
653         GPG_SUCCESS ();
654       else
655         {
656           gpg_do_get_data (0x004f, 1); /* AID */
657           memmove (res_APDU+2, res_APDU, res_APDU_size);
658           res_APDU[0] = 0x6f;
659           res_APDU[1] = 0x12;
660           res_APDU[2] = 0x84;   /* overwrite: DF name */
661           res_APDU_size += 2;
662         }
663     }
664   else if (cmd_APDU[4] == 2
665            && cmd_APDU[5] == 0x2f && cmd_APDU[6] == 0x02)
666     {
667       DEBUG_INFO (" - select 0x2f02 EF\r\n");
668       /*
669        * MF.EF-GDO -- Serial number of the card and name of the owner
670        */
671       GPG_SUCCESS ();
672       file_selection = FILE_EF_SERIAL;
673     }
674   else if (cmd_APDU[4] == 2
675            && cmd_APDU[5] == 0x3f && cmd_APDU[6] == 0x00)
676     {
677       DEBUG_INFO (" - select ROOT MF\r\n");
678       if (cmd_APDU[3] == 0x0c)
679         {
680           GPG_SUCCESS ();
681         }
682       else
683         {
684           write_res_apdu (select_file_TOP_result,
685                           sizeof (select_file_TOP_result), 0x90, 0x00);
686           res_APDU[2] = (data_objects_number_of_bytes & 0xff);
687           res_APDU[3] = (data_objects_number_of_bytes >> 8);
688         }
689
690       file_selection = FILE_MF;
691       ac_fini ();               /* Reset authentication */
692     }
693   else
694     {
695       DEBUG_INFO (" - select ?? \r\n");
696
697       file_selection = FILE_NONE;
698       GPG_NO_FILE ();
699     }
700 }
701
702 static void
703 cmd_get_data (void)
704 {
705   uint16_t tag = ((cmd_APDU[2]<<8) | cmd_APDU[3]);
706
707   DEBUG_INFO (" - Get Data\r\n");
708
709   if (file_selection != FILE_DF_OPENPGP)
710     GPG_NO_RECORD ();
711
712   gpg_do_get_data (tag, 0);
713 }
714
715 static void
716 cmd_pso (void)
717 {
718   int len = cmd_APDU[4];
719   int data_start = 5;
720   int r;
721
722   if (len == 0)
723     {
724       len = (cmd_APDU[5]<<8) | cmd_APDU[6];
725       data_start = 7;
726     }
727
728   DEBUG_INFO (" - PSO: ");
729   DEBUG_WORD ((uint32_t)&r);
730
731   if (cmd_APDU[2] == 0x9e && cmd_APDU[3] == 0x9a)
732     {
733       if (!ac_check_status (AC_PSO_CDS_AUTHORIZED))
734         {
735           DEBUG_INFO ("security error.");
736           GPG_SECURITY_FAILURE ();
737           return;
738         }
739
740       if (cmd_APDU_size != 7 + 34 + 2  /* MD5 */
741           /* Header (with Extended Lc)=7, size of digestInfo, and Le=2-byte */
742           && cmd_APDU_size != 7 + 35 + 2  /* SHA1 / RIPEMD-160 */
743           && cmd_APDU_size != 7 + 47 + 2  /* SHA224 */
744           && cmd_APDU_size != 7 + 51 + 2  /* SHA256 */
745           && cmd_APDU_size != 7 + 67 + 2  /* SHA384 */
746           && cmd_APDU_size != 7 + 83 + 2) /* SHA512 */
747         {
748           DEBUG_INFO (" wrong length: ");
749           DEBUG_SHORT (cmd_APDU_size);
750           GPG_ERROR ();
751         }
752       else
753         {
754           DEBUG_SHORT (len);  /* Should be cmd_APDU_size - 8 [- 1] */
755
756           r = rsa_sign (&cmd_APDU[data_start], res_APDU, len,
757                         &kd[GPG_KEY_FOR_SIGNING]);
758           if (r < 0)
759             {
760               ac_reset_pso_cds ();
761               GPG_ERROR ();
762             }
763           else
764             {                   /* Success */
765               if (gpg_get_pw1_lifetime () == 0)
766                 ac_reset_pso_cds ();
767
768               gpg_increment_digital_signature_counter ();
769             }
770         }
771     }
772   else if (cmd_APDU[2] == 0x80 && cmd_APDU[3] == 0x86)
773     {
774       DEBUG_SHORT (len);
775
776       if (gpg_passwd_locked (PW_ERR_PW1)
777           || !ac_check_status (AC_OTHER_AUTHORIZED))
778         {
779           DEBUG_INFO ("security error.");
780           GPG_SECURITY_FAILURE ();
781           return;
782         }
783
784       /* Skip padding 0x00 */
785       data_start++;
786       len--;
787       r = rsa_decrypt (&cmd_APDU[data_start], res_APDU, len,
788                        &kd[GPG_KEY_FOR_DECRYPTION]);
789       if (r < 0)
790         GPG_ERROR ();
791     }
792   else
793     {                           /* XXX: not yet supported */
794       DEBUG_INFO (" - ??");
795       DEBUG_BYTE (cmd_APDU[2]);
796       DEBUG_INFO (" - ??");
797       DEBUG_BYTE (cmd_APDU[3]);
798       GPG_ERROR ();
799     }
800
801   DEBUG_INFO ("PSO done.\r\n");
802 }
803
804 static void
805 cmd_internal_authenticate (void)
806 {
807   int len = cmd_APDU[4];
808   int data_start = 5;
809   int r;
810
811   if (len == 0)
812     {
813       len = (cmd_APDU[5]<<8) | cmd_APDU[6];
814       data_start = 7;
815     }
816
817   DEBUG_INFO (" - INTERNAL AUTHENTICATE\r\n");
818
819   if (cmd_APDU[2] == 0x00 && cmd_APDU[3] == 0x00)
820     {
821       DEBUG_SHORT (len);
822
823       if (gpg_passwd_locked (PW_ERR_PW1)
824           || !ac_check_status (AC_OTHER_AUTHORIZED))
825         {
826           DEBUG_INFO ("security error.");
827           GPG_SECURITY_FAILURE ();
828           return;
829         }
830
831       r = rsa_sign (&cmd_APDU[data_start], res_APDU, len,
832                     &kd[GPG_KEY_FOR_AUTHENTICATION]);
833       if (r < 0)
834         GPG_ERROR ();
835     }
836   else
837     {
838       DEBUG_INFO (" - ??");
839       DEBUG_BYTE (cmd_APDU[2]);
840       DEBUG_INFO (" - ??");
841       DEBUG_BYTE (cmd_APDU[3]);
842       GPG_ERROR ();
843     }
844
845   DEBUG_INFO ("INTERNAL AUTHENTICATE done.\r\n");
846 }
847
848
849 static void
850 cmd_update_binary (void)
851 {
852   int len = cmd_APDU[4];
853   int data_start = 5;
854   uint16_t offset;
855   int r;
856
857   if (len == 0)
858     {
859       len = (cmd_APDU[5]<<8) | cmd_APDU[6];
860       data_start = 7;
861     }
862
863   DEBUG_INFO (" - UPDATE BINARY\r\n");
864
865   if (gpg_passwd_locked (PW_ERR_PW3) || !ac_check_status (AC_ADMIN_AUTHORIZED))
866     {
867       DEBUG_INFO ("security error.");
868       GPG_SECURITY_FAILURE ();
869       return;
870     }
871
872   if ((cmd_APDU[2] & 0x80))
873     if ((cmd_APDU[2] & 0x7f) <= FILEID_RANDOM)
874       {
875         file_selection = FILE_EF_CH_CERTIFICATE + (cmd_APDU[2] & 0x7f);
876         r = flash_erase_binary (file_selection - FILE_EF_CH_CERTIFICATE);
877         if (r < 0)
878           {
879             DEBUG_INFO ("memory error.\r\n");
880             GPG_MEMORY_FAILURE ();
881             return;
882           }
883
884         offset = 0;
885       }
886     else
887       {
888         GPG_NO_FILE ();
889         return;
890       }
891   else
892     {
893       if (file_selection != FILE_EF_CH_CERTIFICATE
894           && file_selection != FILE_EF_RANDOM)
895         {
896           GPG_COMMAND_NOT_ALLOWED ();
897           return;
898         }
899
900       offset = (cmd_APDU[2] << 8) | cmd_APDU[3];
901     }
902
903   DEBUG_SHORT (len);
904   DEBUG_SHORT (offset);
905
906   r = flash_write_binary (file_selection - FILE_EF_CH_CERTIFICATE,
907                           &cmd_APDU[data_start], len, offset);
908   if (r < 0)
909     {
910       DEBUG_INFO ("memory error.\r\n");
911       GPG_MEMORY_FAILURE ();
912       return;
913     }
914
915   GPG_SUCCESS ();
916   DEBUG_INFO ("UPDATE BINARY done.\r\n");
917 }
918
919
920 static void
921 cmd_write_binary (void)
922 {
923   int len = cmd_APDU[4];
924   int data_start = 5;
925   uint16_t offset;
926   int r;
927
928   if (len == 0)
929     {
930       len = (cmd_APDU[5]<<8) | cmd_APDU[6];
931       data_start = 7;
932     }
933
934   DEBUG_INFO (" - WRITE BINARY\r\n");
935
936   if (gpg_passwd_locked (PW_ERR_PW3) || !ac_check_status (AC_ADMIN_AUTHORIZED))
937     {
938       DEBUG_INFO ("security error.");
939       GPG_SECURITY_FAILURE ();
940       return;
941     }
942
943   if ((cmd_APDU[2] & 0x80))
944     if ((cmd_APDU[2] & 0x7f) <= FILEID_SERIAL_NO)
945       {
946         file_selection = FILE_EF_CH_CERTIFICATE + (cmd_APDU[2] & 0x7f);
947         offset = 0;
948       }
949     else
950       {
951         GPG_NO_FILE ();
952         return;
953       }
954   else
955     {
956       if (file_selection != FILE_EF_CH_CERTIFICATE
957           && file_selection != FILE_EF_RANDOM
958           && file_selection != FILEID_SERIAL_NO)
959         {
960           GPG_COMMAND_NOT_ALLOWED ();
961           return;
962         }
963
964       offset = (cmd_APDU[2] << 8) | cmd_APDU[3];
965     }
966
967   DEBUG_SHORT (len);
968   DEBUG_SHORT (offset);
969
970   r = flash_write_binary (file_selection - FILE_EF_CH_CERTIFICATE,
971                           &cmd_APDU[data_start], len, offset);
972   if (r < 0)
973     {
974       DEBUG_INFO ("memory error.\r\n");
975       GPG_MEMORY_FAILURE ();
976       return;
977     }
978
979   GPG_SUCCESS ();
980   DEBUG_INFO ("WRITE BINARY done.\r\n");
981 }
982
983
984 struct command
985 {
986   uint8_t command;
987   void (*cmd_handler) (void);
988 };
989
990 const struct command cmds[] = {
991   { INS_VERIFY, cmd_verify },
992   { INS_CHANGE_REFERENCE_DATA, cmd_change_password },
993   { INS_PSO, cmd_pso },
994   { INS_RESET_RETRY_COUNTER, cmd_reset_user_password },
995   { INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR, cmd_pgp_gakp },
996   { INS_INTERNAL_AUTHENTICATE, cmd_internal_authenticate },
997   { INS_SELECT_FILE, cmd_select_file },
998   { INS_READ_BINARY, cmd_read_binary },
999   { INS_GET_DATA, cmd_get_data },
1000   { INS_WRITE_BINARY, cmd_write_binary}, /* Not in OpenPGP card protocol */
1001   { INS_UPDATE_BINARY, cmd_update_binary }, /* Not in OpenPGP card protocol */
1002   { INS_PUT_DATA, cmd_put_data },
1003   { INS_PUT_DATA_ODD, cmd_put_data },
1004 };
1005 #define NUM_CMDS ((int)(sizeof (cmds) / sizeof (struct command)))
1006
1007 static void
1008 process_command_apdu (void)
1009 {
1010   int i;
1011   uint8_t cmd = cmd_APDU[1];
1012
1013   for (i = 0; i < NUM_CMDS; i++)
1014     if (cmds[i].command == cmd)
1015       break;
1016
1017   if (i < NUM_CMDS)
1018     cmds[i].cmd_handler ();
1019   else
1020     {
1021       DEBUG_INFO (" - ??");
1022       DEBUG_BYTE (cmd);
1023       GPG_NO_INS ();
1024     }
1025 }
1026
1027 msg_t
1028 GPGthread (void *arg)
1029 {
1030   Thread *icc_thread = (Thread *)arg;
1031
1032   gpg_init ();
1033
1034   chEvtClear (ALL_EVENTS);
1035
1036   while (!chThdShouldTerminate ())
1037     {
1038       eventmask_t m;
1039
1040       m = chEvtWaitOne (ALL_EVENTS);
1041
1042       DEBUG_INFO ("GPG!: ");
1043       DEBUG_WORD ((uint32_t)&m);
1044
1045       res_APDU_pointer = NULL; /* default */
1046
1047       if (icc_data_size != 0)
1048         {
1049           process_command_apdu ();
1050           chEvtSignal (icc_thread, EV_EXEC_FINISHED);
1051         }
1052     }
1053
1054   gpg_fini ();
1055   return 0;
1056 }