Make gpgconf aware of --p12-charset.
[gnupg.git] / sm / base64.c
1 /* base64.c 
2  *      Copyright (C) 2001, 2003 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19  * USA.
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <unistd.h> 
28 #include <time.h>
29 #include <assert.h>
30
31 #include "gpgsm.h"
32
33
34 #include <ksba.h>
35
36 #include "i18n.h"
37
38 #ifdef HAVE_DOSISH_SYSTEM
39   #define LF "\r\n"
40 #else
41   #define LF "\n"
42 #endif
43
44 /* data used by the reader callbacks */
45 struct reader_cb_parm_s {
46   FILE *fp;
47   
48   unsigned char line[1024];
49   int linelen;
50   int readpos;
51   int have_lf;
52   unsigned long line_counter;
53
54   int allow_multi_pem;  /* Allow processing of multiple PEM objects. */
55   int autodetect;       /* Try to detect the input encoding. */
56   int assume_pem;       /* Assume input encoding is PEM. */
57   int assume_base64;    /* Assume input is base64 encoded. */
58
59   int identified;
60   int is_pem;
61   int is_base64;
62   int stop_seen;
63   int might_be_smime;
64
65   int eof_seen;         
66
67   struct {
68     int idx;
69     unsigned char val;
70     int stop_seen;
71   } base64;
72 };
73
74 /* data used by the writer callbacks */
75 struct writer_cb_parm_s {
76   FILE *fp;            /* FP is only used if STREAM is NULL.  */
77   estream_t stream;    /* Alternative output if not NULL.  */
78
79   const char *pem_name;
80   
81   int wrote_begin;
82   int did_finish;
83
84   struct {
85     int idx;
86     int quad_count;
87     unsigned char radbuf[4];
88   } base64;
89
90 };
91
92
93 /* context for this module's functions */
94 struct base64_context_s {
95   union {
96     struct reader_cb_parm_s rparm;
97     struct writer_cb_parm_s wparm;
98   } u;
99
100   union {
101     ksba_reader_t reader;
102     ksba_writer_t writer;
103   } u2;
104 };
105
106
107 /* The base-64 character list */
108 static char bintoasc[64] = 
109        "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 
110        "abcdefghijklmnopqrstuvwxyz" 
111        "0123456789+/"; 
112 /* The reverse base-64 list */
113 static unsigned char asctobin[256] = {
114   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
115   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
116   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
117   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, 
118   0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, 
119   0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 
120   0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 
121   0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, 
122   0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 
123   0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 
124   0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
125   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
126   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
127   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
128   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
129   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
130   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
131   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
132   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
133   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
134   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
135   0xff, 0xff, 0xff, 0xff
136 };
137
138
139 static int
140 has_only_base64 (const unsigned char *line, int linelen)
141 {
142   if (linelen < 20)
143     return 0;
144   for (; linelen; line++, linelen--)
145     {
146       if (*line == '\n' || (linelen > 1 && *line == '\r' && line[1] == '\n'))
147           break;
148       if ( !strchr (bintoasc, *line) )
149         return 0;
150     }
151   return 1;  /* yes */
152 }
153
154 static int
155 is_empty_line (const unsigned char *line, int linelen)
156 {
157   if (linelen >= 2 && *line == '\r' && line[1] == '\n')
158     return 1;
159   if (linelen >= 1 && *line == '\n')
160     return 1;
161   return 0;
162 }
163
164
165 static int
166 base64_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
167 {
168   struct reader_cb_parm_s *parm = cb_value;
169   size_t n;
170   int c, c2;
171
172   *nread = 0;
173   if (!buffer)
174     return -1; /* not supported */
175
176  next:
177   if (!parm->linelen)
178     {
179       /* read an entire line or up to the size of the buffer */
180       parm->line_counter++;
181       parm->have_lf = 0;
182       for (n=0; n < DIM(parm->line);)
183         {
184           c = getc (parm->fp);
185           if (c == EOF)
186             {
187               parm->eof_seen = 1;
188               if (ferror (parm->fp))
189                 return -1;
190               break; 
191             }
192           parm->line[n++] = c;
193           if (c == '\n')
194             {
195               parm->have_lf = 1;
196               /* Fixme: we need to skip overlong lines while detecting
197                  the dashed lines */
198               break;
199             }
200         }
201       parm->linelen = n;
202       if (!n)
203         return -1; /* eof */
204       parm->readpos = 0;
205     }
206
207   if (!parm->identified)
208     {
209       if (!parm->autodetect)
210         {
211           if (parm->assume_pem)
212             {
213               /* wait for the header line */
214               parm->linelen = parm->readpos = 0;
215               if (!parm->have_lf 
216                   || strncmp ((char*)parm->line, "-----BEGIN ", 11)
217                   || !strncmp ((char*)parm->line+11, "PGP ", 4))
218                 goto next;
219               parm->is_pem = 1;
220             }
221           else if (parm->assume_base64)
222             parm->is_base64 = 1;
223         }
224       else if (parm->line_counter == 1 && !parm->have_lf)
225         {
226           /* first line too long - assume DER encoding */
227           parm->is_pem = 0;
228         }
229       else if (parm->line_counter == 1 && parm->linelen && *parm->line == 0x30)
230         {
231           /* the very first byte does pretty much look like a SEQUENCE tag*/
232           parm->is_pem = 0;
233         }
234       else if ( parm->have_lf
235                 && !strncmp ((char*)parm->line, "-----BEGIN ", 11)
236                 && strncmp ((char *)parm->line+11, "PGP ", 4) )
237         {
238           /* Fixme: we must only compare if the line really starts at
239              the beginning */
240           parm->is_pem = 1;
241           parm->linelen = parm->readpos = 0;
242         }
243       else if ( parm->have_lf && parm->line_counter == 1
244                 && parm->linelen >= 13
245                 && !ascii_memcasecmp (parm->line, "Content-Type:", 13))
246         { /* might be a S/MIME body */
247           parm->might_be_smime = 1;
248           parm->linelen = parm->readpos = 0;
249           goto next;
250         }
251       else if (parm->might_be_smime == 1
252                && is_empty_line (parm->line, parm->linelen))
253         {
254           parm->might_be_smime = 2;
255           parm->linelen = parm->readpos = 0;
256           goto next;
257         }
258       else if (parm->might_be_smime == 2)
259         {
260           parm->might_be_smime = 0;
261           if ( !has_only_base64 (parm->line, parm->linelen))
262             {
263               parm->linelen = parm->readpos = 0;
264               goto next;
265             }
266           parm->is_pem = 1;
267         }
268       else
269         {
270           parm->linelen = parm->readpos = 0;
271           goto next;
272         }
273       parm->identified = 1;
274       parm->base64.stop_seen = 0;
275       parm->base64.idx = 0;
276     }
277   
278
279   n = 0;
280   if (parm->is_pem || parm->is_base64)
281     {  
282       if (parm->is_pem && parm->have_lf
283           && !strncmp ((char*)parm->line, "-----END ", 9))
284         { 
285           parm->identified = 0;
286           parm->linelen = parm->readpos = 0;
287
288           /* If the caller want to read multiple PEM objects from one
289              file, we have to reset our internal state and return a
290              EOF immediately. The caller is the expected to use
291              ksba_reader_clear to clear the EOF condition and continue
292              to read.  If we don't want to do that we just return 0
293              bytes which will force the ksba_reader to skip until
294              EOF. */
295           if (parm->allow_multi_pem)
296             {
297               parm->identified = 0;
298               parm->autodetect = 0;
299               parm->assume_pem = 1;
300               parm->stop_seen = 0;
301               return -1; /* Send EOF now. */
302             }
303         }
304       else if (parm->stop_seen)
305         { /* skip the rest of the line */
306           parm->linelen = parm->readpos = 0;
307         }
308       else
309         {
310           int idx = parm->base64.idx;
311           unsigned char val = parm->base64.val;
312
313           while (n < count && parm->readpos < parm->linelen )
314             {
315               c = parm->line[parm->readpos++];
316               if (c == '\n' || c == ' ' || c == '\r' || c == '\t')
317                 continue;
318               if (c == '=')
319                 { /* pad character: stop */
320                   if (idx == 1)
321                     buffer[n++] = val; 
322                   parm->stop_seen = 1;
323                   break;
324                 }
325               if( (c = asctobin[(c2=c)]) == 255 ) 
326                 {
327                   log_error (_("invalid radix64 character %02x skipped\n"),
328                              c2);
329                   continue;
330                 }
331               switch (idx) 
332                 {
333                 case 0: 
334                   val = c << 2;
335                   break;
336                 case 1: 
337                   val |= (c>>4)&3;
338                   buffer[n++] = val;
339                   val = (c<<4)&0xf0;
340                   break;
341                 case 2: 
342                   val |= (c>>2)&15;
343                   buffer[n++] = val;
344                   val = (c<<6)&0xc0;
345                   break;
346                 case 3: 
347                   val |= c&0x3f;
348                   buffer[n++] = val;
349                   break;
350                 }
351               idx = (idx+1) % 4;
352             }
353           if (parm->readpos == parm->linelen)
354             parm->linelen = parm->readpos = 0;
355
356           parm->base64.idx = idx;
357           parm->base64.val = val;
358         }
359     }
360   else
361     { /* DER encoded */
362       while (n < count && parm->readpos < parm->linelen)
363           buffer[n++] = parm->line[parm->readpos++];
364       if (parm->readpos == parm->linelen)
365         parm->linelen = parm->readpos = 0;
366     }
367
368   *nread = n;
369   return 0;
370 }
371
372
373
374 static int
375 simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
376 {
377   struct reader_cb_parm_s *parm = cb_value;
378   size_t n;
379   int c = 0;
380
381   *nread = 0;
382   if (!buffer)
383     return -1; /* not supported */
384
385   for (n=0; n < count; n++)
386     {
387       c = getc (parm->fp);
388       if (c == EOF)
389         {
390           parm->eof_seen = 1;
391           if ( ferror (parm->fp) )
392             return -1;
393           if (n)
394             break; /* return what we have before an EOF */
395           return -1;
396         }
397       *(byte *)buffer++ = c;
398     }
399
400   *nread = n;
401   return 0;
402 }
403
404
405
406 \f
407 /* Call either es_putc or the plain putc.  */
408 static void
409 do_putc (int value, FILE *fp, estream_t stream)
410 {
411   if (stream)
412     es_putc (value, stream);
413   else
414     putc (value, fp);
415 }
416
417 /* Call either es_fputs or the plain fputs.  */
418 static void
419 do_fputs (const char *string, FILE *fp, estream_t stream)
420 {
421   if (stream)
422     es_fputs (string, stream);
423   else
424     fputs (string, fp);
425 }
426
427
428 static int
429 base64_writer_cb (void *cb_value, const void *buffer, size_t count)
430 {
431   struct writer_cb_parm_s *parm = cb_value;
432   unsigned char radbuf[4];
433   int i, c, idx, quad_count;
434   const unsigned char *p;
435   FILE *fp = parm->fp;
436   estream_t stream = parm->stream;
437
438   if (!count)
439     return 0;
440
441   if (!parm->wrote_begin)
442     {
443       if (parm->pem_name)
444         {
445           do_fputs ("-----BEGIN ", fp, stream);
446           do_fputs (parm->pem_name, fp, stream);
447           do_fputs ("-----\n", fp, stream);
448         }
449       parm->wrote_begin = 1;
450       parm->base64.idx = 0;
451       parm->base64.quad_count = 0;
452     }
453
454   idx = parm->base64.idx;
455   quad_count = parm->base64.quad_count;
456   for (i=0; i < idx; i++)
457     radbuf[i] = parm->base64.radbuf[i];
458
459   for (p=buffer; count; p++, count--)
460     {
461       radbuf[idx++] = *p;
462       if (idx > 2)
463         {
464           idx = 0;
465           c = bintoasc[(*radbuf >> 2) & 077];
466           do_putc (c, fp, stream);
467           c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
468           do_putc (c, fp, stream);
469           c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
470           do_putc (c, fp, stream);
471           c = bintoasc[radbuf[2]&077];
472           do_putc (c, fp, stream);
473           if (++quad_count >= (64/4)) 
474             {
475               do_fputs (LF, fp, stream);
476               quad_count = 0;
477             }
478         }
479     }
480   for (i=0; i < idx; i++)
481     parm->base64.radbuf[i] = radbuf[i];
482   parm->base64.idx = idx;
483   parm->base64.quad_count = quad_count;
484
485   return ((stream? es_ferror (stream) : ferror (fp)) 
486           ? gpg_error_from_syserror () 
487           : 0);
488 }
489
490 /* This callback is only used in stream mode.  Hiowever, we don't
491    restrict it to this.  */
492 static int
493 plain_writer_cb (void *cb_value, const void *buffer, size_t count)
494 {
495   struct writer_cb_parm_s *parm = cb_value;
496   FILE *fp = parm->fp;
497   estream_t stream = parm->stream;
498
499   if (!count)
500     return 0;
501
502   if (stream)
503     es_write (stream, buffer, count, NULL);
504   else
505     fwrite (buffer, count, 1, fp);
506
507   return ((stream? es_ferror (stream) : ferror (fp)) 
508           ? gpg_error_from_syserror () 
509           : 0);
510 }
511
512 static int
513 base64_finish_write (struct writer_cb_parm_s *parm)
514 {
515   unsigned char radbuf[4];
516   int i, c, idx, quad_count;
517   FILE *fp = parm->fp;
518   estream_t stream = parm->stream;
519
520   if (!parm->wrote_begin)
521     return 0; /* Nothing written or we are not called in base-64 mode. */
522
523   /* flush the base64 encoding */
524   idx = parm->base64.idx;
525   quad_count = parm->base64.quad_count;
526   for (i=0; i < idx; i++)
527     radbuf[i] = parm->base64.radbuf[i];
528
529   if (idx)
530     {
531       c = bintoasc[(*radbuf>>2)&077];
532       do_putc (c, fp, stream);
533       if (idx == 1)
534         {
535           c = bintoasc[((*radbuf << 4) & 060) & 077];
536           do_putc (c, fp, stream);
537           do_putc ('=', fp, stream);
538           do_putc ('=', fp, stream);
539         }
540       else 
541         { 
542           c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077];
543           do_putc (c, fp, stream);
544           c = bintoasc[((radbuf[1] << 2) & 074) & 077];
545           do_putc (c, fp, stream);
546           do_putc ('=', fp, stream);
547
548         }
549       if (++quad_count >= (64/4)) 
550         {
551           do_fputs (LF, fp, stream);
552           quad_count = 0;
553         }
554     }
555
556   if (quad_count)
557     do_fputs (LF, fp, stream);
558
559   if (parm->pem_name)
560     {
561       do_fputs ("-----END ", fp, stream);
562       do_fputs (parm->pem_name, fp, stream);
563       do_fputs ("-----\n", fp, stream);
564     }
565
566   return ((stream? es_ferror (stream) : ferror (fp)) 
567           ? gpg_error_from_syserror () 
568           : 0);
569 }
570
571
572
573 \f
574 /* Create a reader for the given file descriptor.  Depending on the
575    control information an input decoding is automagically choosen.
576    The function returns a Base64Context object which must be passed to
577    the gpgme_destroy_reader function.  The created KsbaReader object
578    is also returned, but the caller must not call the
579    ksba_reader_release function on.  If ALLOW_MULTI_PEM is true, the
580    reader expects that the caller uses ksba_reader_clear after EOF
581    until no more objects were found. */
582 int
583 gpgsm_create_reader (Base64Context *ctx,
584                      ctrl_t ctrl, FILE *fp, int allow_multi_pem,
585                      ksba_reader_t *r_reader)
586 {
587   int rc;
588   ksba_reader_t r;
589
590   *r_reader = NULL;
591   *ctx = xtrycalloc (1, sizeof **ctx);
592   if (!*ctx)
593     return out_of_core ();
594   (*ctx)->u.rparm.allow_multi_pem = allow_multi_pem;
595
596   rc = ksba_reader_new (&r);
597   if (rc)
598     {
599       xfree (*ctx); *ctx = NULL;
600       return rc;
601     }
602
603   (*ctx)->u.rparm.fp = fp;
604   if (ctrl->is_pem)
605     {
606       (*ctx)->u.rparm.assume_pem = 1;
607       (*ctx)->u.rparm.assume_base64 = 1;
608       rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm);
609     }
610   else if (ctrl->is_base64)
611     {
612       (*ctx)->u.rparm.assume_base64 = 1;
613       rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm);
614     }
615   else if (ctrl->autodetect_encoding)
616     {
617       (*ctx)->u.rparm.autodetect = 1;
618       rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm);
619     }
620   else
621       rc = ksba_reader_set_cb (r, simple_reader_cb, &(*ctx)->u.rparm);
622
623   if (rc)
624     {
625       ksba_reader_release (r);
626       xfree (*ctx); *ctx = NULL;
627       return rc;
628     }
629
630   (*ctx)->u2.reader = r;
631   *r_reader = r;
632   return 0;
633 }
634
635
636 int
637 gpgsm_reader_eof_seen (Base64Context ctx)
638 {
639   return ctx && ctx->u.rparm.eof_seen;
640 }
641
642 void
643 gpgsm_destroy_reader (Base64Context ctx)
644 {
645   if (!ctx)
646     return;
647
648   ksba_reader_release (ctx->u2.reader);  
649   xfree (ctx);
650 }
651
652
653 \f
654 /* Create a writer for the given stream FP or STREAM.  Depending on
655    the control information an output encoding is automagically
656    choosen.  The function returns a Base64Context object which must be
657    passed to the gpgme_destroy_writer function.  The created
658    KsbaWriter object is also returned, but the caller must not call
659    the ksba_reader_release function on. */
660 int
661 gpgsm_create_writer (Base64Context *ctx,
662                      ctrl_t ctrl, FILE *fp, estream_t stream,
663                      ksba_writer_t *r_writer)
664 {
665   int rc;
666   ksba_writer_t w;
667
668   *r_writer = NULL;
669   *ctx = xtrycalloc (1, sizeof **ctx);
670   if (!*ctx)
671     return out_of_core ();
672
673   rc = ksba_writer_new (&w);
674   if (rc)
675     {
676       xfree (*ctx); *ctx = NULL;
677       return rc;
678     }
679
680   if (ctrl->create_pem || ctrl->create_base64)
681     {
682       (*ctx)->u.wparm.fp = fp;
683       (*ctx)->u.wparm.stream = stream;
684       if (ctrl->create_pem)
685         (*ctx)->u.wparm.pem_name = ctrl->pem_name? ctrl->pem_name
686                                                  : "CMS OBJECT";
687       rc = ksba_writer_set_cb (w, base64_writer_cb, &(*ctx)->u.wparm);
688     }
689   else if (stream)
690     {
691       (*ctx)->u.wparm.fp = fp;
692       (*ctx)->u.wparm.stream = stream;
693       rc = ksba_writer_set_cb (w, plain_writer_cb, &(*ctx)->u.wparm);
694     }
695   else
696     rc = ksba_writer_set_file (w, fp);
697
698   if (rc)
699     {
700       ksba_writer_release (w);
701       xfree (*ctx); *ctx = NULL;
702       return rc;
703     }
704
705   (*ctx)->u2.writer = w;
706   *r_writer = w;
707   return 0;
708 }
709
710
711 int
712 gpgsm_finish_writer (Base64Context ctx)
713 {
714   struct writer_cb_parm_s *parm;
715   
716   if (!ctx)
717     return gpg_error (GPG_ERR_INV_VALUE);
718   parm = &ctx->u.wparm;
719   if (parm->did_finish)
720     return 0; /* Already done. */
721   parm->did_finish = 1;
722   if (!parm->fp && !parm->stream)
723     return 0; /* Callback was not used.  */
724   return base64_finish_write (parm);
725 }
726
727 void
728 gpgsm_destroy_writer (Base64Context ctx)
729 {
730   if (!ctx)
731     return;
732
733   ksba_writer_release (ctx->u2.writer);
734   xfree (ctx);
735 }