LCOV - code coverage report
Current view: top level - sm - base64.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 109 300 36.3 %
Date: 2015-11-05 17:10:59 Functions: 4 13 30.8 %

          Line data    Source code
       1             : /* base64.c
       2             :  * Copyright (C) 2001, 2003, 2010 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 3 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, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #include <config.h>
      21             : #include <stdio.h>
      22             : #include <stdlib.h>
      23             : #include <string.h>
      24             : #include <errno.h>
      25             : #include <unistd.h>
      26             : #include <time.h>
      27             : #include <assert.h>
      28             : 
      29             : #include "gpgsm.h"
      30             : 
      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             : {
      45             :   estream_t fp;
      46             : 
      47             :   unsigned char line[1024];
      48             :   int linelen;
      49             :   int readpos;
      50             :   int have_lf;
      51             :   unsigned long line_counter;
      52             : 
      53             :   int allow_multi_pem;  /* Allow processing of multiple PEM objects. */
      54             :   int autodetect;       /* Try to detect the input encoding. */
      55             :   int assume_pem;       /* Assume input encoding is PEM. */
      56             :   int assume_base64;    /* Assume input is base64 encoded. */
      57             : 
      58             :   int identified;
      59             :   int is_pem;
      60             :   int is_base64;
      61             :   int stop_seen;
      62             :   int might_be_smime;
      63             : 
      64             :   int eof_seen;
      65             : 
      66             :   struct {
      67             :     int idx;
      68             :     unsigned char val;
      69             :     int stop_seen;
      70             :   } base64;
      71             : };
      72             : 
      73             : 
      74             : /* Data used by the writer callbacks.  */
      75             : struct writer_cb_parm_s
      76             : {
      77             :   estream_t stream;    /* Output stream.  */
      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           0 : has_only_base64 (const unsigned char *line, int linelen)
     141             : {
     142           0 :   if (linelen < 20)
     143           0 :     return 0;
     144           0 :   for (; linelen; line++, linelen--)
     145             :     {
     146           0 :       if (*line == '\n' || (linelen > 1 && *line == '\r' && line[1] == '\n'))
     147             :           break;
     148           0 :       if ( !strchr (bintoasc, *line) )
     149           0 :         return 0;
     150             :     }
     151           0 :   return 1;  /* yes */
     152             : }
     153             : 
     154             : static int
     155           0 : is_empty_line (const unsigned char *line, int linelen)
     156             : {
     157           0 :   if (linelen >= 2 && *line == '\r' && line[1] == '\n')
     158           0 :     return 1;
     159           0 :   if (linelen >= 1 && *line == '\n')
     160           0 :     return 1;
     161           0 :   return 0;
     162             : }
     163             : 
     164             : 
     165             : static int
     166         680 : base64_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
     167             : {
     168         680 :   struct reader_cb_parm_s *parm = cb_value;
     169             :   size_t n;
     170             :   int c, c2;
     171             : 
     172         680 :   *nread = 0;
     173         680 :   if (!buffer)
     174           0 :     return -1; /* not supported */
     175             : 
     176             :  next:
     177         696 :   if (!parm->linelen)
     178             :     {
     179             :       /* read an entire line or up to the size of the buffer */
     180          86 :       parm->line_counter++;
     181          86 :       parm->have_lf = 0;
     182        4561 :       for (n=0; n < DIM(parm->line);)
     183             :         {
     184        4475 :           c = es_getc (parm->fp);
     185        4475 :           if (c == EOF)
     186             :             {
     187           3 :               parm->eof_seen = 1;
     188           3 :               if (es_ferror (parm->fp))
     189           0 :                 return -1;
     190           3 :               break;
     191             :             }
     192        4472 :           parm->line[n++] = c;
     193        4472 :           if (c == '\n')
     194             :             {
     195          83 :               parm->have_lf = 1;
     196             :               /* Fixme: we need to skip overlong lines while detecting
     197             :                  the dashed lines */
     198          83 :               break;
     199             :             }
     200             :         }
     201          86 :       parm->linelen = n;
     202          86 :       if (!n)
     203           3 :         return -1; /* eof */
     204          83 :       parm->readpos = 0;
     205             :     }
     206             : 
     207         693 :   if (!parm->identified)
     208             :     {
     209          19 :       if (!parm->autodetect)
     210             :         {
     211           0 :           if (parm->assume_pem)
     212             :             {
     213             :               /* wait for the header line */
     214           0 :               parm->linelen = parm->readpos = 0;
     215           0 :               if (!parm->have_lf
     216           0 :                   || strncmp ((char*)parm->line, "-----BEGIN ", 11)
     217           0 :                   || !strncmp ((char*)parm->line+11, "PGP ", 4))
     218             :                 goto next;
     219           0 :               parm->is_pem = 1;
     220             :             }
     221           0 :           else if (parm->assume_base64)
     222           0 :             parm->is_base64 = 1;
     223             :         }
     224          19 :       else if (parm->line_counter == 1 && !parm->have_lf)
     225             :         {
     226             :           /* first line too long - assume DER encoding */
     227           0 :           parm->is_pem = 0;
     228             :         }
     229          19 :       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           0 :           parm->is_pem = 0;
     233             :         }
     234          19 :       else if ( parm->have_lf
     235          19 :                 && !strncmp ((char*)parm->line, "-----BEGIN ", 11)
     236           3 :                 && strncmp ((char *)parm->line+11, "PGP ", 4) )
     237             :         {
     238             :           /* Fixme: we must only compare if the line really starts at
     239             :              the beginning */
     240           3 :           parm->is_pem = 1;
     241           3 :           parm->linelen = parm->readpos = 0;
     242             :         }
     243          16 :       else if ( parm->have_lf && parm->line_counter == 1
     244           1 :                 && parm->linelen >= 13
     245           0 :                 && !ascii_memcasecmp (parm->line, "Content-Type:", 13))
     246             :         { /* might be a S/MIME body */
     247           0 :           parm->might_be_smime = 1;
     248           0 :           parm->linelen = parm->readpos = 0;
     249           0 :           goto next;
     250             :         }
     251          16 :       else if (parm->might_be_smime == 1
     252           0 :                && is_empty_line (parm->line, parm->linelen))
     253             :         {
     254           0 :           parm->might_be_smime = 2;
     255           0 :           parm->linelen = parm->readpos = 0;
     256           0 :           goto next;
     257             :         }
     258          16 :       else if (parm->might_be_smime == 2)
     259             :         {
     260           0 :           parm->might_be_smime = 0;
     261           0 :           if ( !has_only_base64 (parm->line, parm->linelen))
     262             :             {
     263           0 :               parm->linelen = parm->readpos = 0;
     264           0 :               goto next;
     265             :             }
     266           0 :           parm->is_pem = 1;
     267             :         }
     268             :       else
     269             :         {
     270          16 :           parm->linelen = parm->readpos = 0;
     271          16 :           goto next;
     272             :         }
     273           3 :       parm->identified = 1;
     274           3 :       parm->base64.stop_seen = 0;
     275           3 :       parm->base64.idx = 0;
     276             :     }
     277             : 
     278             : 
     279         677 :   n = 0;
     280         677 :   if (parm->is_pem || parm->is_base64)
     281             :     {
     282        1351 :       if (parm->is_pem && parm->have_lf
     283         677 :           && !strncmp ((char*)parm->line, "-----END ", 9))
     284             :         {
     285           3 :           parm->identified = 0;
     286           3 :           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           3 :           if (parm->allow_multi_pem)
     296             :             {
     297           3 :               parm->identified = 0;
     298           3 :               parm->autodetect = 0;
     299           3 :               parm->assume_pem = 1;
     300           3 :               parm->stop_seen = 0;
     301           3 :               return -1; /* Send EOF now. */
     302             :             }
     303             :         }
     304         674 :       else if (parm->stop_seen)
     305             :         { /* skip the rest of the line */
     306           3 :           parm->linelen = parm->readpos = 0;
     307             :         }
     308             :       else
     309             :         {
     310         671 :           int idx = parm->base64.idx;
     311         671 :           unsigned char val = parm->base64.val;
     312             : 
     313        5160 :           while (n < count && parm->readpos < parm->linelen )
     314             :             {
     315        3821 :               c = parm->line[parm->readpos++];
     316        3821 :               if (c == '\n' || c == ' ' || c == '\r' || c == '\t')
     317          58 :                 continue;
     318        3763 :               if (c == '=')
     319             :                 { /* pad character: stop */
     320           3 :                   if (idx == 1)
     321           0 :                     buffer[n++] = val;
     322           3 :                   parm->stop_seen = 1;
     323           3 :                   break;
     324             :                 }
     325        3760 :               if( (c = asctobin[(c2=c)]) == 255 )
     326             :                 {
     327           0 :                   log_error (_("invalid radix64 character %02x skipped\n"),
     328             :                              c2);
     329           0 :                   continue;
     330             :                 }
     331        3760 :               switch (idx)
     332             :                 {
     333             :                 case 0:
     334         941 :                   val = c << 2;
     335         941 :                   break;
     336             :                 case 1:
     337         941 :                   val |= (c>>4)&3;
     338         941 :                   buffer[n++] = val;
     339         941 :                   val = (c<<4)&0xf0;
     340         941 :                   break;
     341             :                 case 2:
     342         940 :                   val |= (c>>2)&15;
     343         940 :                   buffer[n++] = val;
     344         940 :                   val = (c<<6)&0xc0;
     345         940 :                   break;
     346             :                 case 3:
     347         938 :                   val |= c&0x3f;
     348         938 :                   buffer[n++] = val;
     349         938 :                   break;
     350             :                 }
     351        3760 :               idx = (idx+1) % 4;
     352             :             }
     353         671 :           if (parm->readpos == parm->linelen)
     354          61 :             parm->linelen = parm->readpos = 0;
     355             : 
     356         671 :           parm->base64.idx = idx;
     357         671 :           parm->base64.val = val;
     358             :         }
     359             :     }
     360             :   else
     361             :     { /* DER encoded */
     362           0 :       while (n < count && parm->readpos < parm->linelen)
     363           0 :           buffer[n++] = parm->line[parm->readpos++];
     364           0 :       if (parm->readpos == parm->linelen)
     365           0 :         parm->linelen = parm->readpos = 0;
     366             :     }
     367             : 
     368         674 :   *nread = n;
     369         674 :   return 0;
     370             : }
     371             : 
     372             : 
     373             : 
     374             : static int
     375           0 : simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
     376             : {
     377           0 :   struct reader_cb_parm_s *parm = cb_value;
     378             :   size_t n;
     379           0 :   int c = 0;
     380             : 
     381           0 :   *nread = 0;
     382           0 :   if (!buffer)
     383           0 :     return -1; /* not supported */
     384             : 
     385           0 :   for (n=0; n < count; n++)
     386             :     {
     387           0 :       c = es_getc (parm->fp);
     388           0 :       if (c == EOF)
     389             :         {
     390           0 :           parm->eof_seen = 1;
     391           0 :           if (es_ferror (parm->fp))
     392           0 :             return -1;
     393           0 :           if (n)
     394           0 :             break; /* Return what we have before an EOF.  */
     395           0 :           return -1;
     396             :         }
     397           0 :       *(byte *)buffer++ = c;
     398             :     }
     399             : 
     400           0 :   *nread = n;
     401           0 :   return 0;
     402             : }
     403             : 
     404             : 
     405             : 
     406             : 
     407             : static int
     408           0 : base64_writer_cb (void *cb_value, const void *buffer, size_t count)
     409             : {
     410           0 :   struct writer_cb_parm_s *parm = cb_value;
     411             :   unsigned char radbuf[4];
     412             :   int i, c, idx, quad_count;
     413             :   const unsigned char *p;
     414           0 :   estream_t stream = parm->stream;
     415             : 
     416           0 :   if (!count)
     417           0 :     return 0;
     418             : 
     419           0 :   if (!parm->wrote_begin)
     420             :     {
     421           0 :       if (parm->pem_name)
     422             :         {
     423           0 :           es_fputs ("-----BEGIN ", stream);
     424           0 :           es_fputs (parm->pem_name, stream);
     425           0 :           es_fputs ("-----\n", stream);
     426             :         }
     427           0 :       parm->wrote_begin = 1;
     428           0 :       parm->base64.idx = 0;
     429           0 :       parm->base64.quad_count = 0;
     430             :     }
     431             : 
     432           0 :   idx = parm->base64.idx;
     433           0 :   quad_count = parm->base64.quad_count;
     434           0 :   for (i=0; i < idx; i++)
     435           0 :     radbuf[i] = parm->base64.radbuf[i];
     436             : 
     437           0 :   for (p=buffer; count; p++, count--)
     438             :     {
     439           0 :       radbuf[idx++] = *p;
     440           0 :       if (idx > 2)
     441             :         {
     442           0 :           idx = 0;
     443           0 :           c = bintoasc[(*radbuf >> 2) & 077];
     444           0 :           es_putc (c, stream);
     445           0 :           c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
     446           0 :           es_putc (c, stream);
     447           0 :           c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
     448           0 :           es_putc (c, stream);
     449           0 :           c = bintoasc[radbuf[2]&077];
     450           0 :           es_putc (c, stream);
     451           0 :           if (++quad_count >= (64/4))
     452             :             {
     453           0 :               es_fputs (LF, stream);
     454           0 :               quad_count = 0;
     455             :             }
     456             :         }
     457             :     }
     458           0 :   for (i=0; i < idx; i++)
     459           0 :     parm->base64.radbuf[i] = radbuf[i];
     460           0 :   parm->base64.idx = idx;
     461           0 :   parm->base64.quad_count = quad_count;
     462             : 
     463           0 :   return es_ferror (stream)? gpg_error_from_syserror () : 0;
     464             : }
     465             : 
     466             : 
     467             : /* This callback is only used in stream mode.  Hiowever, we don't
     468             :    restrict it to this.  */
     469             : static int
     470           0 : plain_writer_cb (void *cb_value, const void *buffer, size_t count)
     471             : {
     472           0 :   struct writer_cb_parm_s *parm = cb_value;
     473           0 :   estream_t stream = parm->stream;
     474             : 
     475           0 :   if (!count)
     476           0 :     return 0;
     477             : 
     478           0 :   es_write (stream, buffer, count, NULL);
     479             : 
     480           0 :   return es_ferror (stream)? gpg_error_from_syserror () : 0;
     481             : }
     482             : 
     483             : 
     484             : static int
     485           0 : base64_finish_write (struct writer_cb_parm_s *parm)
     486             : {
     487             :   unsigned char *radbuf;
     488             :   int c, idx, quad_count;
     489           0 :   estream_t stream = parm->stream;
     490             : 
     491           0 :   if (!parm->wrote_begin)
     492           0 :     return 0; /* Nothing written or we are not called in base-64 mode. */
     493             : 
     494             :   /* flush the base64 encoding */
     495           0 :   idx = parm->base64.idx;
     496           0 :   quad_count = parm->base64.quad_count;
     497           0 :   if (idx)
     498             :     {
     499           0 :       radbuf = parm->base64.radbuf;
     500             : 
     501           0 :       c = bintoasc[(*radbuf>>2)&077];
     502           0 :       es_putc (c, stream);
     503           0 :       if (idx == 1)
     504             :         {
     505           0 :           c = bintoasc[((*radbuf << 4) & 060) & 077];
     506           0 :           es_putc (c, stream);
     507           0 :           es_putc ('=', stream);
     508           0 :           es_putc ('=', stream);
     509             :         }
     510             :       else
     511             :         {
     512           0 :           c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077];
     513           0 :           es_putc (c, stream);
     514           0 :           c = bintoasc[((radbuf[1] << 2) & 074) & 077];
     515           0 :           es_putc (c, stream);
     516           0 :           es_putc ('=', stream);
     517             : 
     518             :         }
     519           0 :       if (++quad_count >= (64/4))
     520             :         {
     521           0 :           es_fputs (LF, stream);
     522           0 :           quad_count = 0;
     523             :         }
     524             :     }
     525             : 
     526           0 :   if (quad_count)
     527           0 :     es_fputs (LF, stream);
     528             : 
     529           0 :   if (parm->pem_name)
     530             :     {
     531           0 :       es_fputs ("-----END ", stream);
     532           0 :       es_fputs (parm->pem_name, stream);
     533           0 :       es_fputs ("-----\n", stream);
     534             :     }
     535             : 
     536           0 :   return es_ferror (stream)? gpg_error_from_syserror () : 0;
     537             : }
     538             : 
     539             : 
     540             : 
     541             : 
     542             : /* Create a reader for the given file descriptor.  Depending on the
     543             :    control information an input decoding is automagically choosen.
     544             :    The function returns a Base64Context object which must be passed to
     545             :    the gpgme_destroy_reader function.  The created KsbaReader object
     546             :    is also returned, but the caller must not call the
     547             :    ksba_reader_release function on.  If ALLOW_MULTI_PEM is true, the
     548             :    reader expects that the caller uses ksba_reader_clear after EOF
     549             :    until no more objects were found. */
     550             : int
     551           3 : gpgsm_create_reader (Base64Context *ctx,
     552             :                      ctrl_t ctrl, estream_t fp, int allow_multi_pem,
     553             :                      ksba_reader_t *r_reader)
     554             : {
     555             :   int rc;
     556             :   ksba_reader_t r;
     557             : 
     558           3 :   *r_reader = NULL;
     559           3 :   *ctx = xtrycalloc (1, sizeof **ctx);
     560           3 :   if (!*ctx)
     561           0 :     return out_of_core ();
     562           3 :   (*ctx)->u.rparm.allow_multi_pem = allow_multi_pem;
     563             : 
     564           3 :   rc = ksba_reader_new (&r);
     565           3 :   if (rc)
     566             :     {
     567           0 :       xfree (*ctx); *ctx = NULL;
     568           0 :       return rc;
     569             :     }
     570             : 
     571           3 :   (*ctx)->u.rparm.fp = fp;
     572           3 :   if (ctrl->is_pem)
     573             :     {
     574           0 :       (*ctx)->u.rparm.assume_pem = 1;
     575           0 :       (*ctx)->u.rparm.assume_base64 = 1;
     576           0 :       rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm);
     577             :     }
     578           3 :   else if (ctrl->is_base64)
     579             :     {
     580           0 :       (*ctx)->u.rparm.assume_base64 = 1;
     581           0 :       rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm);
     582             :     }
     583           3 :   else if (ctrl->autodetect_encoding)
     584             :     {
     585           3 :       (*ctx)->u.rparm.autodetect = 1;
     586           3 :       rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm);
     587             :     }
     588             :   else
     589           0 :       rc = ksba_reader_set_cb (r, simple_reader_cb, &(*ctx)->u.rparm);
     590             : 
     591           3 :   if (rc)
     592             :     {
     593           0 :       ksba_reader_release (r);
     594           0 :       xfree (*ctx); *ctx = NULL;
     595           0 :       return rc;
     596             :     }
     597             : 
     598           3 :   (*ctx)->u2.reader = r;
     599           3 :   *r_reader = r;
     600           3 :   return 0;
     601             : }
     602             : 
     603             : 
     604             : int
     605           3 : gpgsm_reader_eof_seen (Base64Context ctx)
     606             : {
     607           3 :   return ctx && ctx->u.rparm.eof_seen;
     608             : }
     609             : 
     610             : void
     611           3 : gpgsm_destroy_reader (Base64Context ctx)
     612             : {
     613           3 :   if (!ctx)
     614           3 :     return;
     615             : 
     616           3 :   ksba_reader_release (ctx->u2.reader);
     617           3 :   xfree (ctx);
     618             : }
     619             : 
     620             : 
     621             : 
     622             : /* Create a writer for the given STREAM.  Depending on
     623             :    the control information an output encoding is automagically
     624             :    choosen.  The function returns a Base64Context object which must be
     625             :    passed to the gpgme_destroy_writer function.  The created
     626             :    KsbaWriter object is also returned, but the caller must not call
     627             :    the ksba_reader_release function on it. */
     628             : int
     629           0 : gpgsm_create_writer (Base64Context *ctx, ctrl_t ctrl, estream_t stream,
     630             :                      ksba_writer_t *r_writer)
     631             : {
     632             :   int rc;
     633             :   ksba_writer_t w;
     634             : 
     635           0 :   *r_writer = NULL;
     636           0 :   *ctx = xtrycalloc (1, sizeof **ctx);
     637           0 :   if (!*ctx)
     638           0 :     return out_of_core ();
     639             : 
     640           0 :   rc = ksba_writer_new (&w);
     641           0 :   if (rc)
     642             :     {
     643           0 :       xfree (*ctx); *ctx = NULL;
     644           0 :       return rc;
     645             :     }
     646             : 
     647           0 :   if (ctrl->create_pem || ctrl->create_base64)
     648             :     {
     649           0 :       (*ctx)->u.wparm.stream = stream;
     650           0 :       if (ctrl->create_pem)
     651           0 :         (*ctx)->u.wparm.pem_name = ctrl->pem_name? ctrl->pem_name
     652           0 :                                                  : "CMS OBJECT";
     653           0 :       rc = ksba_writer_set_cb (w, base64_writer_cb, &(*ctx)->u.wparm);
     654             :     }
     655           0 :   else if (stream)
     656             :     {
     657           0 :       (*ctx)->u.wparm.stream = stream;
     658           0 :       rc = ksba_writer_set_cb (w, plain_writer_cb, &(*ctx)->u.wparm);
     659             :     }
     660             :   else
     661           0 :     rc = gpg_error (GPG_ERR_INV_ARG);
     662             : 
     663           0 :   if (rc)
     664             :     {
     665           0 :       ksba_writer_release (w);
     666           0 :       xfree (*ctx); *ctx = NULL;
     667           0 :       return rc;
     668             :     }
     669             : 
     670           0 :   (*ctx)->u2.writer = w;
     671           0 :   *r_writer = w;
     672           0 :   return 0;
     673             : }
     674             : 
     675             : 
     676             : int
     677           0 : gpgsm_finish_writer (Base64Context ctx)
     678             : {
     679             :   struct writer_cb_parm_s *parm;
     680             : 
     681           0 :   if (!ctx)
     682           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     683           0 :   parm = &ctx->u.wparm;
     684           0 :   if (parm->did_finish)
     685           0 :     return 0; /* Already done. */
     686           0 :   parm->did_finish = 1;
     687           0 :   if (!parm->stream)
     688           0 :     return 0; /* Callback was not used.  */
     689           0 :   return base64_finish_write (parm);
     690             : }
     691             : 
     692             : void
     693           0 : gpgsm_destroy_writer (Base64Context ctx)
     694             : {
     695           0 :   if (!ctx)
     696           0 :     return;
     697             : 
     698           0 :   ksba_writer_release (ctx->u2.writer);
     699           0 :   xfree (ctx);
     700             : }

Generated by: LCOV version 1.11