88c92fc915b0a94dd67acf412fbdab5dd73a0620
[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 CLS(a) a.cmd_apdu_head[0]
33 #define INS(a) a.cmd_apdu_head[1]
34 #define P1(a) a.cmd_apdu_head[2]
35 #define P2(a) a.cmd_apdu_head[3]
36
37 #define INS_VERIFY                              0x20
38 #define INS_CHANGE_REFERENCE_DATA               0x24
39 #define INS_PSO                                 0x2a
40 #define INS_RESET_RETRY_COUNTER                 0x2c
41 #define INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR    0x47
42 #define INS_INTERNAL_AUTHENTICATE               0x88
43 #define INS_SELECT_FILE                         0xa4
44 #define INS_READ_BINARY                         0xb0
45 #define INS_GET_DATA                            0xca
46 #define INS_WRITE_BINARY                        0xd0
47 #define INS_UPDATE_BINARY                       0xd6
48 #define INS_PUT_DATA                            0xda
49 #define INS_PUT_DATA_ODD                        0xdb    /* For key import */
50
51 static const uint8_t
52 select_file_TOP_result[] __attribute__ ((aligned (1))) = {
53   0x00, 0x00,        /* unused */
54   0x00, 0x00,        /* number of bytes in this directory: to be filled */
55   0x3f, 0x00,        /* field of selected file: MF, 3f00 */
56   0x38,                 /* it's DF */
57   0xff,                 /* unused */
58   0xff, 0x44, 0x44,     /* access conditions */
59   0x01,                 /* status of the selected file (OK, unblocked) */
60   0x05,                 /* number of bytes of data follow */
61     0x03,                       /* Features: unused */
62     0x01,                       /* number of subdirectories (OpenPGP) */
63     0x01,                       /* number of elementary files (SerialNo) */
64     0x00,                       /* number of secret codes */
65     0x00,                       /* Unused */
66   0x00, 0x00            /* PIN status: OK, PIN blocked?: No */
67 };
68
69 void
70 set_res_sw (uint8_t sw1, uint8_t sw2)
71 {
72   apdu.sw = (sw1 << 8) | sw2;
73 }
74
75 #define FILE_NONE       0
76 #define FILE_DF_OPENPGP 1
77 #define FILE_MF         2
78 #define FILE_EF_DIR     3
79 #define FILE_EF_SERIAL  4
80 #define FILE_EF_CH_CERTIFICATE  5
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  * 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   int r;
110
111   chEvtSignal (main_thread, LED_INPUT_MODE);
112   r = pinpad_getline (msg_code, MS2ST (8000));
113   chEvtSignal (main_thread, LED_STATUS_MODE);
114   return r;
115 }
116 #endif
117
118 static void
119 cmd_verify (void)
120 {
121   int len;
122   uint8_t p2 = P2 (apdu);
123   int r;
124   const uint8_t *pw;
125
126   DEBUG_INFO (" - VERIFY\r\n");
127   DEBUG_BYTE (p2);
128
129   len = apdu.cmd_apdu_data_len;
130   pw = apdu.cmd_apdu_data;
131
132   if (p2 == 0x81)
133     r = verify_pso_cds (pw, len);
134   else if (p2 == 0x82)
135     r = verify_other (pw, len);
136   else
137     r = verify_admin (pw, len);
138
139   if (r < 0)
140     {
141       DEBUG_INFO ("failed\r\n");
142       GPG_SECURITY_FAILURE ();
143     }
144   else if (r == 0)
145     {
146       DEBUG_INFO ("blocked\r\n");
147       GPG_SECURITY_AUTH_BLOCKED ();
148     }
149   else
150     {
151       DEBUG_INFO ("good\r\n");
152       GPG_SUCCESS ();
153     }
154 }
155
156 int
157 gpg_change_keystring (int who_old, const uint8_t *old_ks,
158                       int who_new, const uint8_t *new_ks)
159 {
160   int r;
161   int prv_keys_exist = 0;
162
163   r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, who_old, old_ks);
164   if (r < 0)
165     return r;
166
167   if (r > 0)
168     prv_keys_exist++;
169
170   r = gpg_do_chks_prvkey (GPG_KEY_FOR_SIGNING, who_old, old_ks,
171                           who_new, new_ks);
172   if (r < 0)
173     return -2;
174
175   r = gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPTION, who_old, old_ks);
176   if (r < 0)
177     return r;
178
179   if (r > 0)
180     prv_keys_exist++;
181
182   r = gpg_do_chks_prvkey (GPG_KEY_FOR_DECRYPTION, who_old, old_ks,
183                           who_new, new_ks);
184   if (r < 0)
185     return -2;
186
187   r = gpg_do_load_prvkey (GPG_KEY_FOR_AUTHENTICATION, who_old, old_ks);
188   if (r < 0)
189     return r;
190
191   if (r > 0)
192     prv_keys_exist++;
193
194   r = gpg_do_chks_prvkey (GPG_KEY_FOR_AUTHENTICATION, who_old, old_ks,
195                           who_new, new_ks);
196   if (r < 0)
197     return -2;
198
199   if (prv_keys_exist)
200     return 1;
201   else
202     return 0;
203 }
204
205 static void
206 cmd_change_password (void)
207 {
208   uint8_t old_ks[KEYSTRING_MD_SIZE];
209   uint8_t new_ks0[KEYSTRING_MD_SIZE+1];
210   uint8_t *new_ks = &new_ks0[1];
211   uint8_t p1 = P1 (apdu);       /* 0: change (old+new), 1: exchange (new) */
212   uint8_t p2 = P2 (apdu);
213   int len;
214   const uint8_t *pw;
215   const uint8_t *newpw;
216   int pw_len, newpw_len;
217   int who = p2 - 0x80;
218   int r;
219
220   DEBUG_INFO ("Change PW\r\n");
221   DEBUG_BYTE (who);
222
223   len = apdu.cmd_apdu_data_len;
224   pw = apdu.cmd_apdu_data;
225
226   if (p1 != 0)
227     {
228       GPG_FUNCTION_NOT_SUPPORTED();
229       return;
230     }
231
232   if (who == BY_USER)                   /* PW1 */
233     {
234       const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
235
236       pw_len = verify_user_0 (AC_PSO_CDS_AUTHORIZED, pw, len, -1, ks_pw1);
237
238       if (pw_len < 0)
239         {
240           DEBUG_INFO ("permission denied.\r\n");
241           GPG_SECURITY_FAILURE ();
242           return;
243         }
244       else if (pw_len == 0)
245         {
246           DEBUG_INFO ("blocked.\r\n");
247           GPG_SECURITY_AUTH_BLOCKED ();
248           return;
249         }
250       else
251         {
252           newpw = pw + pw_len;
253           newpw_len = len - pw_len;
254         }
255     }
256   else                          /* PW3 (0x83) */
257     {
258       pw_len = verify_admin_0 (pw, len, -1);
259
260       if (pw_len < 0)
261         {
262           DEBUG_INFO ("permission denied.\r\n");
263           GPG_SECURITY_FAILURE ();
264           return;
265         }
266       else if (pw_len == 0)
267         {
268           DEBUG_INFO ("blocked.\r\n");
269           GPG_SECURITY_AUTH_BLOCKED ();
270           return;
271         }
272       else
273         {
274           newpw = pw + pw_len;
275           newpw_len = len - pw_len;
276           gpg_set_pw3 (newpw, newpw_len);
277         }
278     }
279
280   sha1 (pw, pw_len, old_ks);
281   sha1 (newpw, newpw_len, new_ks);
282   new_ks0[0] = newpw_len;
283
284   r = gpg_change_keystring (who, old_ks, who, new_ks);
285   if (r <= -2)
286     {
287       DEBUG_INFO ("memory error.\r\n");
288       GPG_MEMORY_FAILURE ();
289     }
290   else if (r < 0)
291     {
292       DEBUG_INFO ("security error.\r\n");
293       GPG_SECURITY_FAILURE ();
294     }
295   else if (r == 0 && who == BY_USER)    /* no prvkey */
296     {
297       gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, KEYSTRING_SIZE_PW1);
298       ac_reset_pso_cds ();
299       ac_reset_other ();
300       DEBUG_INFO ("Changed DO_KEYSTRING_PW1.\r\n");
301       GPG_SUCCESS ();
302     }
303   else if (r > 0 && who == BY_USER)
304     {
305       gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0, 1);
306       ac_reset_pso_cds ();
307       ac_reset_other ();
308       DEBUG_INFO ("Changed length of DO_KEYSTRING_PW1.\r\n");
309       GPG_SUCCESS ();
310     }
311   else                          /* r >= 0 && who == BY_ADMIN */
312     {
313       DEBUG_INFO ("done.\r\n");
314       ac_reset_admin ();
315       GPG_SUCCESS ();
316     }
317 }
318
319 static void
320 cmd_reset_user_password (void)
321 {
322   uint8_t p1 = P1 (apdu);
323   int len;
324   const uint8_t *pw;
325   const uint8_t *newpw;
326   int pw_len, newpw_len;
327   int r;
328   uint8_t new_ks0[KEYSTRING_MD_SIZE+1];
329   uint8_t *new_ks = &new_ks0[1];
330
331   DEBUG_INFO ("Reset PW1\r\n");
332   DEBUG_BYTE (p1);
333
334   len = apdu.cmd_apdu_data_len;
335   pw = apdu.cmd_apdu_data;
336
337   if (p1 == 0x00)               /* by User with Reseting Code */
338     {
339       const uint8_t *ks_rc = gpg_do_read_simple (NR_DO_KEYSTRING_RC);
340       uint8_t old_ks[KEYSTRING_MD_SIZE];
341
342       if (gpg_pw_locked (PW_ERR_RC))
343         {
344           DEBUG_INFO ("blocked.\r\n");
345           GPG_SECURITY_AUTH_BLOCKED ();
346           return;
347         }
348
349       if (ks_rc == NULL)
350         {
351           DEBUG_INFO ("security error.\r\n");
352           GPG_SECURITY_FAILURE ();
353           return;
354         }
355
356       pw_len = ks_rc[0];
357       newpw = pw + pw_len;
358       newpw_len = len - pw_len;
359       sha1 (pw, pw_len, old_ks);
360       sha1 (newpw, newpw_len, new_ks);
361       new_ks0[0] = newpw_len;
362       r = gpg_change_keystring (BY_RESETCODE, old_ks, BY_USER, new_ks);
363       if (r <= -2)
364         {
365           DEBUG_INFO ("memory error.\r\n");
366           GPG_MEMORY_FAILURE ();
367         }
368       else if (r < 0)
369         {
370         sec_fail:
371           DEBUG_INFO ("failed.\r\n");
372           gpg_pw_increment_err_counter (PW_ERR_RC);
373           GPG_SECURITY_FAILURE ();
374         }
375       else if (r == 0)
376         {
377           if (memcmp (ks_rc+1, old_ks, KEYSTRING_MD_SIZE) != 0)
378             goto sec_fail;
379           DEBUG_INFO ("done (no prvkey).\r\n");
380           gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0,
381                                KEYSTRING_SIZE_PW1);
382           ac_reset_pso_cds ();
383           ac_reset_other ();
384           gpg_pw_reset_err_counter (PW_ERR_RC);
385           gpg_pw_reset_err_counter (PW_ERR_PW1);
386           GPG_SUCCESS ();
387         }
388       else
389         {
390           DEBUG_INFO ("done.\r\n");
391           ac_reset_pso_cds ();
392           ac_reset_other ();
393           gpg_pw_reset_err_counter (PW_ERR_RC);
394           gpg_pw_reset_err_counter (PW_ERR_PW1);
395           GPG_SUCCESS ();
396         }
397     }
398   else                          /* by Admin (p1 == 0x02) */
399     {
400       const uint8_t *old_ks = keystring_md_pw3;
401
402       if (!ac_check_status (AC_ADMIN_AUTHORIZED))
403         {
404           DEBUG_INFO ("permission denied.\r\n");
405           GPG_SECURITY_FAILURE ();
406           return;
407         }
408
409       newpw_len = len;
410       newpw = pw;
411       sha1 (newpw, newpw_len, new_ks);
412       new_ks0[0] = newpw_len;
413       r = gpg_change_keystring (admin_authorized, old_ks, BY_USER, new_ks);
414       if (r <= -2)
415         {
416           DEBUG_INFO ("memory error.\r\n");
417           GPG_MEMORY_FAILURE ();
418         }
419       else if (r < 0)
420         {
421           DEBUG_INFO ("security error.\r\n");
422           GPG_SECURITY_FAILURE ();
423         }
424       else if (r == 0)
425         {
426           DEBUG_INFO ("done (no privkey).\r\n");
427           gpg_do_write_simple (NR_DO_KEYSTRING_PW1, new_ks0,
428                                KEYSTRING_SIZE_PW1);
429           ac_reset_pso_cds ();
430           ac_reset_other ();
431           gpg_pw_reset_err_counter (PW_ERR_PW1);
432           GPG_SUCCESS ();
433         }
434       else
435         {
436           DEBUG_INFO ("done.\r\n");
437           ac_reset_pso_cds ();
438           ac_reset_other ();
439           gpg_pw_reset_err_counter (PW_ERR_PW1);
440           GPG_SUCCESS ();
441         }
442     }
443 }
444
445 static void
446 cmd_put_data (void)
447 {
448   uint8_t *data;
449   uint16_t tag;
450   int len;
451
452   DEBUG_INFO (" - PUT DATA\r\n");
453
454   if (file_selection != FILE_DF_OPENPGP)
455     GPG_NO_RECORD();
456
457   tag = ((P1 (apdu)<<8) | P2 (apdu));
458   len = apdu.cmd_apdu_data_len;
459   data = apdu.cmd_apdu_data;
460   gpg_do_put_data (tag, data, len);
461 }
462
463 static void
464 cmd_pgp_gakp (void)
465 {
466   DEBUG_INFO (" - Generate Asymmetric Key Pair\r\n");
467   DEBUG_BYTE (P1 (apdu));
468
469   if (P1 (apdu) == 0x81)
470     /* Get public key */
471     gpg_do_public_key (apdu.cmd_apdu_data[0]);
472   else
473     {                                   /* Generate key pair */
474       if (!ac_check_status (AC_ADMIN_AUTHORIZED))
475         GPG_SECURITY_FAILURE ();
476
477       /* XXX: Not yet supported */
478       GPG_ERROR ();
479     }
480 }
481
482 static void
483 cmd_read_binary (void)
484 {
485   DEBUG_INFO (" - Read binary\r\n");
486
487   if (file_selection == FILE_EF_SERIAL)
488     {
489       if (P2 (apdu) >= 6)
490         GPG_BAD_P0_P1 ();
491       else
492         {
493           gpg_do_get_data (0x004f, 1); /* AID */
494           res_APDU[0] = 0x5a;
495         }
496     }
497   else
498     GPG_NO_RECORD();
499 }
500
501 static void
502 cmd_select_file (void)
503 {
504   if (P1 (apdu) == 4)   /* Selection by DF name */
505     {
506       DEBUG_INFO (" - select DF by name\r\n");
507
508       /* name = D2 76 00 01 24 01 */
509       if (apdu.cmd_apdu_data_len != 6
510           || memcmp (openpgpcard_aid, apdu.cmd_apdu_data, 6) != 0)
511         {
512           DEBUG_SHORT (apdu.cmd_apdu_data_len);
513           DEBUG_BINARY (apdu.cmd_apdu_data, apdu.cmd_apdu_data_len);
514
515           GPG_NO_FILE ();
516           return;
517         }
518
519       file_selection = FILE_DF_OPENPGP;
520       if ((P2 (apdu) & 0x0c) == 0x0c)   /* No FCI */
521         GPG_SUCCESS ();
522       else
523         {
524           gpg_do_get_data (0x004f, 1); /* AID */
525           memmove (res_APDU+2, res_APDU, res_APDU_size);
526           res_APDU[0] = 0x6f;
527           res_APDU[1] = 0x12;
528           res_APDU[2] = 0x84;   /* overwrite: DF name */
529           res_APDU_size += 2;
530           GPG_SUCCESS ();
531         }
532     }
533   else if (apdu.cmd_apdu_data_len == 2
534            && apdu.cmd_apdu_data[0] == 0x2f && apdu.cmd_apdu_data[1] == 0x02)
535     {
536       DEBUG_INFO (" - select 0x2f02 EF\r\n");
537       /*
538        * MF.EF-GDO -- Serial number of the card and name of the owner
539        */
540       GPG_SUCCESS ();
541       file_selection = FILE_EF_SERIAL;
542     }
543   else if (apdu.cmd_apdu_data_len == 2
544            && apdu.cmd_apdu_data[0] == 0x3f && apdu.cmd_apdu_data[1] == 0x00)
545     {
546       DEBUG_INFO (" - select ROOT MF\r\n");
547       if (P2 (apdu) == 0x0c)
548         {
549           GPG_SUCCESS ();
550         }
551       else
552         {
553           int len = sizeof (select_file_TOP_result);
554
555           res_APDU_size = len;
556           memcpy (res_APDU, select_file_TOP_result, len);
557           res_APDU[2] = (data_objects_number_of_bytes & 0xff);
558           res_APDU[3] = (data_objects_number_of_bytes >> 8);
559           GPG_SUCCESS ();
560         }
561
562       file_selection = FILE_MF;
563       ac_fini ();               /* Reset authentication */
564     }
565   else
566     {
567       DEBUG_INFO (" - select ?? \r\n");
568
569       file_selection = FILE_NONE;
570       GPG_NO_FILE ();
571     }
572 }
573
574 static void
575 cmd_get_data (void)
576 {
577   uint16_t tag = ((P1 (apdu)<<8) | P2 (apdu));
578
579   DEBUG_INFO (" - Get Data\r\n");
580
581   if (file_selection != FILE_DF_OPENPGP)
582     GPG_NO_RECORD ();
583
584   gpg_do_get_data (tag, 0);
585 }
586
587 static void
588 cmd_pso (void)
589 {
590   int len = apdu.cmd_apdu_data_len;
591   int r;
592
593   DEBUG_INFO (" - PSO: ");
594   DEBUG_WORD ((uint32_t)&r);
595   DEBUG_BINARY (apdu.cmd_apdu_data, apdu.cmd_apdu_data_len);
596
597   if (P1 (apdu) == 0x9e && P2 (apdu) == 0x9a)
598     {
599       if (!ac_check_status (AC_PSO_CDS_AUTHORIZED))
600         {
601           DEBUG_INFO ("security error.");
602           GPG_SECURITY_FAILURE ();
603           return;
604         }
605
606       /* Check size of digestInfo */
607       if (len != 34             /* MD5 */
608           && len != 35          /* SHA1 / RIPEMD-160 */
609           && len != 47          /* SHA224 */
610           && len != 51          /* SHA256 */
611           && len != 67          /* SHA384 */
612           && len != 83)         /* SHA512 */
613         {
614           DEBUG_INFO (" wrong length: ");
615           DEBUG_SHORT (len);
616           GPG_ERROR ();
617         }
618       else
619         {
620           DEBUG_SHORT (len);
621           DEBUG_BINARY (&kd[GPG_KEY_FOR_SIGNING], KEY_CONTENT_LEN);
622
623           r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len,
624                         &kd[GPG_KEY_FOR_SIGNING]);
625           if (r < 0)
626             {
627               ac_reset_pso_cds ();
628               GPG_ERROR ();
629             }
630           else
631             /* Success */
632             gpg_increment_digital_signature_counter ();
633         }
634     }
635   else if (P1 (apdu) == 0x80 && P2 (apdu) == 0x86)
636     {
637       DEBUG_SHORT (len);
638       DEBUG_BINARY (&kd[GPG_KEY_FOR_DECRYPTION], KEY_CONTENT_LEN);
639
640       if (!ac_check_status (AC_OTHER_AUTHORIZED))
641         {
642           DEBUG_INFO ("security error.");
643           GPG_SECURITY_FAILURE ();
644           return;
645         }
646
647       /* Skip padding 0x00 */
648       len--;
649       r = rsa_decrypt (apdu.cmd_apdu_data+1, res_APDU, len,
650                        &kd[GPG_KEY_FOR_DECRYPTION]);
651       if (r < 0)
652         GPG_ERROR ();
653     }
654   else
655     {
656       DEBUG_INFO (" - ??");
657       DEBUG_BYTE (P1 (apdu));
658       DEBUG_INFO (" - ??");
659       DEBUG_BYTE (P2 (apdu));
660       GPG_ERROR ();
661     }
662
663   DEBUG_INFO ("PSO done.\r\n");
664 }
665
666 static void
667 cmd_internal_authenticate (void)
668 {
669   int len = apdu.cmd_apdu_data_len;
670   int r;
671
672   DEBUG_INFO (" - INTERNAL AUTHENTICATE\r\n");
673
674   if (P1 (apdu) == 0x00 && P2 (apdu) == 0x00)
675     {
676       DEBUG_SHORT (len);
677
678       if (!ac_check_status (AC_OTHER_AUTHORIZED))
679         {
680           DEBUG_INFO ("security error.");
681           GPG_SECURITY_FAILURE ();
682           return;
683         }
684
685       r = rsa_sign (apdu.cmd_apdu_data, res_APDU, len,
686                     &kd[GPG_KEY_FOR_AUTHENTICATION]);
687       if (r < 0)
688         GPG_ERROR ();
689     }
690   else
691     {
692       DEBUG_INFO (" - ??");
693       DEBUG_BYTE (P1 (apdu));
694       DEBUG_INFO (" - ??");
695       DEBUG_BYTE (P2 (apdu));
696       GPG_ERROR ();
697     }
698
699   DEBUG_INFO ("INTERNAL AUTHENTICATE done.\r\n");
700 }
701
702
703 #if defined(CERTDO_SUPPORT)
704 static void
705 cmd_update_binary (void)
706 {
707   int len = apdu.cmd_apdu_data_len;
708   uint16_t offset;
709   int r;
710
711   DEBUG_INFO (" - UPDATE BINARY\r\n");
712
713   if (!ac_check_status (AC_ADMIN_AUTHORIZED))
714     {
715       DEBUG_INFO ("security error.");
716       GPG_SECURITY_FAILURE ();
717       return;
718     }
719
720   if ((P1 (apdu) & 0x80))
721     if ((P1 (apdu) & 0x7f) == FILEID_CH_CERTIFICATE)
722       {
723         file_selection = FILE_EF_CH_CERTIFICATE;
724         r = flash_erase_binary (FILEID_CH_CERTIFICATE);
725         if (r < 0)
726           {
727             DEBUG_INFO ("memory error.\r\n");
728             GPG_MEMORY_FAILURE ();
729             return;
730           }
731
732         offset = 0;
733       }
734     else
735       {
736         GPG_NO_FILE ();
737         return;
738       }
739   else
740     {
741       if (file_selection != FILE_EF_CH_CERTIFICATE)
742         {
743           GPG_COMMAND_NOT_ALLOWED ();
744           return;
745         }
746
747       offset = (P1 (apdu) << 8) | P2 (apdu);
748     }
749
750   DEBUG_SHORT (len);
751   DEBUG_SHORT (offset);
752
753   r = flash_write_binary (FILEID_CH_CERTIFICATE,
754                           apdu.cmd_apdu_data, len, offset);
755   if (r < 0)
756     {
757       DEBUG_INFO ("memory error.\r\n");
758       GPG_MEMORY_FAILURE ();
759       return;
760     }
761
762   GPG_SUCCESS ();
763   DEBUG_INFO ("UPDATE BINARY done.\r\n");
764 }
765 #endif
766
767
768 static void
769 cmd_write_binary (void)
770 {
771   int len = apdu.cmd_apdu_data_len;
772   uint16_t offset;
773   int r;
774
775   DEBUG_INFO (" - WRITE BINARY\r\n");
776
777   if (!ac_check_status (AC_ADMIN_AUTHORIZED))
778     {
779       DEBUG_INFO ("security error.");
780       GPG_SECURITY_FAILURE ();
781       return;
782     }
783
784   if ((P1 (apdu) & 0x80))
785     if ((P1 (apdu) & 0x7f) <= FILEID_CH_CERTIFICATE)
786       {
787         file_selection = FILE_EF_SERIAL + (P1 (apdu) & 0x7f);
788         offset = 0;
789       }
790     else
791       {
792         GPG_NO_FILE ();
793         return;
794       }
795   else
796     {
797       if (file_selection != FILE_EF_SERIAL
798           && file_selection != FILE_EF_CH_CERTIFICATE)
799         {
800           GPG_COMMAND_NOT_ALLOWED ();
801           return;
802         }
803
804       offset = (P1 (apdu) << 8) | P2 (apdu);
805     }
806
807   DEBUG_SHORT (len);
808   DEBUG_SHORT (offset);
809
810   r = flash_write_binary (file_selection - FILE_EF_SERIAL,
811                           apdu.cmd_apdu_data, len, offset);
812   if (r < 0)
813     {
814       DEBUG_INFO ("memory error.\r\n");
815       GPG_MEMORY_FAILURE ();
816       return;
817     }
818
819   GPG_SUCCESS ();
820   DEBUG_INFO ("WRITE BINARY done.\r\n");
821 }
822
823
824 struct command
825 {
826   uint8_t command;
827   void (*cmd_handler) (void);
828 };
829
830 const struct command cmds[] = {
831   { INS_VERIFY, cmd_verify },
832   { INS_CHANGE_REFERENCE_DATA, cmd_change_password },
833   { INS_PSO, cmd_pso },
834   { INS_RESET_RETRY_COUNTER, cmd_reset_user_password },
835   { INS_PGP_GENERATE_ASYMMETRIC_KEY_PAIR, cmd_pgp_gakp },
836   { INS_INTERNAL_AUTHENTICATE, cmd_internal_authenticate },
837   { INS_SELECT_FILE, cmd_select_file },
838   { INS_READ_BINARY, cmd_read_binary },
839   { INS_GET_DATA, cmd_get_data },
840   { INS_WRITE_BINARY, cmd_write_binary}, /* Not in OpenPGP card protocol */
841 #if defined(CERTDO_SUPPORT)
842   { INS_UPDATE_BINARY, cmd_update_binary }, /* Not in OpenPGP card protocol */
843 #endif
844   { INS_PUT_DATA, cmd_put_data },
845   { INS_PUT_DATA_ODD, cmd_put_data },
846 };
847 #define NUM_CMDS ((int)(sizeof (cmds) / sizeof (struct command)))
848
849 static void
850 process_command_apdu (void)
851 {
852   int i;
853   uint8_t cmd = INS (apdu);
854
855   for (i = 0; i < NUM_CMDS; i++)
856     if (cmds[i].command == cmd)
857       break;
858
859   if (i < NUM_CMDS)
860     cmds[i].cmd_handler ();
861   else
862     {
863       DEBUG_INFO (" - ??");
864       DEBUG_BYTE (cmd);
865       GPG_NO_INS ();
866     }
867 }
868
869 msg_t
870 GPGthread (void *arg)
871 {
872   Thread *icc_thread = (Thread *)arg;
873
874   gpg_init ();
875
876   chEvtClear (ALL_EVENTS);
877
878   while (!chThdShouldTerminate ())
879     {
880       eventmask_t m = chEvtWaitOne (ALL_EVENTS);
881 #if defined(PINPAD_SUPPORT)
882       int len, pw_len, newpw_len;
883 #endif
884
885       DEBUG_INFO ("GPG!: ");
886
887       if (m == EV_VERIFY_CMD_AVAILABLE)
888         {
889 #if defined(PINPAD_SUPPORT)
890           if (INS (apdu) != INS_VERIFY)
891             {
892               GPG_CONDITION_NOT_SATISFIED ();
893               goto done;
894             }
895
896           pw_len = get_pinpad_input (PIN_INPUT_CURRENT);
897           if (pw_len < 0)
898             {
899               GPG_ERROR ();
900               goto done;
901             }
902           memcpy (apdu.cmd_apdu_data, pin_input_buffer, pw_len);
903           apdu.cmd_apdu_data_len = pw_len;
904 #else
905           GPG_ERROR ();
906           goto done;
907 #endif
908         }
909       else if (m == EV_MODIFY_CMD_AVAILABLE)
910         {
911 #if defined(PINPAD_SUPPORT)
912           uint8_t bConfirmPIN = apdu.cmd_apdu_data[5];
913           uint8_t *p = apdu.cmd_apdu_data;
914
915           if (INS (apdu) != INS_CHANGE_REFERENCE_DATA
916               && INS (apdu) != INS_RESET_RETRY_COUNTER
917               && INS (apdu) != INS_PUT_DATA)
918             {
919               GPG_CONDITION_NOT_SATISFIED ();
920               goto done;
921             }
922
923           if ((bConfirmPIN & 2))        /* Require old PIN */
924             {
925               pw_len = get_pinpad_input (PIN_INPUT_CURRENT);
926               if (pw_len < 0)
927                 {
928                   GPG_ERROR ();
929                   goto done;
930                 }
931               memcpy (p, pin_input_buffer, pw_len);
932               p += pw_len;
933             }
934           else
935             pw_len = 0;
936
937           newpw_len = get_pinpad_input (PIN_INPUT_NEW);
938           if (newpw_len < 0)
939             {
940               GPG_ERROR ();
941               goto done;
942             }
943           memcpy (p, pin_input_buffer, newpw_len);
944
945           if ((bConfirmPIN & 1))        /* New PIN twice */
946             {
947               len = get_pinpad_input (PIN_INPUT_CONFIRM);
948               if (len < 0)
949                 {
950                   GPG_ERROR ();
951                   goto done;
952                 }
953
954               if (len != newpw_len || memcmp (p, pin_input_buffer, len) != 0)
955                 {
956                   GPG_SECURITY_FAILURE ();
957                   goto done;
958                 }
959             }
960
961           apdu.cmd_apdu_data_len = pw_len + newpw_len;
962 #else
963           GPG_ERROR ();
964           goto done;
965 #endif
966         }
967       else if (m == EV_NOP)
968         continue;
969
970       process_command_apdu ();
971     done:
972       chEvtSignal (icc_thread, EV_EXEC_FINISHED);
973     }
974
975   gpg_fini ();
976   return 0;
977 }