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