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