LCOV - code coverage report
Current view: top level - common - b64dec.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 84 0.0 %
Date: 2015-11-05 17:10:59 Functions: 0 3 0.0 %

          Line data    Source code
       1             : /* b64dec.c - Simple Base64 decoder.
       2             :  * Copyright (C) 2008, 2011 Free Software Foundation, Inc.
       3             :  *
       4             :  * This file is part of GnuPG.
       5             :  *
       6             :  * This file is free software; you can redistribute it and/or modify
       7             :  * it under the terms of either
       8             :  *
       9             :  *   - the GNU Lesser General Public License as published by the Free
      10             :  *     Software Foundation; either version 3 of the License, or (at
      11             :  *     your option) any later version.
      12             :  *
      13             :  * or
      14             :  *
      15             :  *   - the GNU General Public License as published by the Free
      16             :  *     Software Foundation; either version 2 of the License, or (at
      17             :  *     your option) any later version.
      18             :  *
      19             :  * or both in parallel, as here.
      20             :  *
      21             :  * This file is distributed in the hope that it will be useful,
      22             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      23             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      24             :  * GNU General Public License for more details.
      25             :  *
      26             :  * You should have received a copy of the GNU General Public License
      27             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      28             :  */
      29             : 
      30             : #include <config.h>
      31             : #include <stdio.h>
      32             : #include <stdlib.h>
      33             : #include <string.h>
      34             : #include <errno.h>
      35             : #include <assert.h>
      36             : 
      37             : #include "i18n.h"
      38             : #include "util.h"
      39             : 
      40             : 
      41             : /* The reverse base-64 list used for base-64 decoding. */
      42             : static unsigned char const asctobin[128] =
      43             :   {
      44             :     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      45             :     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      46             :     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      47             :     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      48             :     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      49             :     0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
      50             :     0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
      51             :     0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
      52             :     0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
      53             :     0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
      54             :     0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
      55             :     0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
      56             :     0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
      57             :     0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
      58             :     0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
      59             :     0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
      60             :   };
      61             : 
      62             : enum decoder_states
      63             :   {
      64             :     s_init, s_idle, s_lfseen, s_begin,
      65             :     s_b64_0, s_b64_1, s_b64_2, s_b64_3,
      66             :     s_waitendtitle, s_waitend
      67             :   };
      68             : 
      69             : 
      70             : 
      71             : /* Initialize the context for the base64 decoder.  If TITLE is NULL a
      72             :    plain base64 decoding is done.  If it is the empty string the
      73             :    decoder will skip everything until a "-----BEGIN " line has been
      74             :    seen, decoding ends at a "----END " line.
      75             : 
      76             :    Not yet implemented: If TITLE is either "PGP" or begins with "PGP "
      77             :    the PGP armor lines are skipped as well.  */
      78             : gpg_error_t
      79           0 : b64dec_start (struct b64state *state, const char *title)
      80             : {
      81           0 :   memset (state, 0, sizeof *state);
      82           0 :   if (title)
      83             :     {
      84           0 :       if (!strncmp (title, "PGP", 3) && (!title[3] || title[3] == ' '))
      85           0 :         state->lasterr = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
      86             :       else
      87             :         {
      88           0 :           state->title = xtrystrdup (title);
      89           0 :           if (!state->title)
      90           0 :             state->lasterr = gpg_error_from_syserror ();
      91             :           else
      92           0 :             state->idx = s_init;
      93             :         }
      94             :     }
      95             :   else
      96           0 :     state->idx = s_b64_0;
      97           0 :   return state->lasterr;
      98             : }
      99             : 
     100             : 
     101             : /* Do in-place decoding of base-64 data of LENGTH in BUFFER.  Stores the
     102             :    new length of the buffer at R_NBYTES. */
     103             : gpg_error_t
     104           0 : b64dec_proc (struct b64state *state, void *buffer, size_t length,
     105             :              size_t *r_nbytes)
     106             : {
     107           0 :   enum decoder_states ds = state->idx;
     108           0 :   unsigned char val = state->radbuf[0];
     109           0 :   int pos = state->quad_count;
     110             :   char *d, *s;
     111             : 
     112           0 :   if (state->lasterr)
     113           0 :     return state->lasterr;
     114             : 
     115           0 :   if (state->stop_seen)
     116             :     {
     117           0 :       *r_nbytes = 0;
     118           0 :       state->lasterr = gpg_error (GPG_ERR_EOF);
     119           0 :       xfree (state->title);
     120           0 :       state->title = NULL;
     121           0 :       return state->lasterr;
     122             :     }
     123             : 
     124           0 :   for (s=d=buffer; length && !state->stop_seen; length--, s++)
     125             :     {
     126           0 :       switch (ds)
     127             :         {
     128             :         case s_idle:
     129           0 :           if (*s == '\n')
     130             :             {
     131           0 :               ds = s_lfseen;
     132           0 :               pos = 0;
     133             :             }
     134           0 :           break;
     135             :         case s_init:
     136           0 :           ds = s_lfseen;
     137             :         case s_lfseen:
     138           0 :           if (*s != "-----BEGIN "[pos])
     139           0 :             ds = s_idle;
     140           0 :           else if (pos == 10)
     141           0 :             ds = s_begin;
     142             :           else
     143           0 :             pos++;
     144           0 :           break;
     145             :         case s_begin:
     146           0 :           if (*s == '\n')
     147           0 :             ds = s_b64_0;
     148           0 :           break;
     149             :         case s_b64_0:
     150             :         case s_b64_1:
     151             :         case s_b64_2:
     152             :         case s_b64_3:
     153             :           {
     154             :             int c;
     155             : 
     156           0 :             if (*s == '-' && state->title)
     157             :               {
     158             :                 /* Not a valid Base64 character: assume end
     159             :                    header.  */
     160           0 :                 ds = s_waitend;
     161             :               }
     162           0 :             else if (*s == '=')
     163             :               {
     164             :                 /* Pad character: stop */
     165           0 :                 if (ds == s_b64_1)
     166           0 :                   *d++ = val;
     167           0 :                 ds = state->title? s_waitendtitle : s_waitend;
     168             :               }
     169           0 :             else if (*s == '\n' || *s == ' ' || *s == '\r' || *s == '\t')
     170             :               ; /* Skip white spaces. */
     171           0 :             else if ( (*s & 0x80)
     172           0 :                       || (c = asctobin[*(unsigned char *)s]) == 255)
     173             :               {
     174             :                 /* Skip invalid encodings.  */
     175           0 :                 state->invalid_encoding = 1;
     176             :               }
     177           0 :             else if (ds == s_b64_0)
     178             :               {
     179           0 :                 val = c << 2;
     180           0 :                 ds = s_b64_1;
     181             :               }
     182           0 :             else if (ds == s_b64_1)
     183             :               {
     184           0 :                 val |= (c>>4)&3;
     185           0 :                 *d++ = val;
     186           0 :                 val = (c<<4)&0xf0;
     187           0 :                 ds = s_b64_2;
     188             :               }
     189           0 :             else if (ds == s_b64_2)
     190             :               {
     191           0 :                 val |= (c>>2)&15;
     192           0 :                 *d++ = val;
     193           0 :                 val = (c<<6)&0xc0;
     194           0 :                 ds = s_b64_3;
     195             :               }
     196             :             else
     197             :               {
     198           0 :                 val |= c&0x3f;
     199           0 :                 *d++ = val;
     200           0 :                 ds = s_b64_0;
     201             :               }
     202             :           }
     203           0 :           break;
     204             :         case s_waitendtitle:
     205           0 :           if (*s == '-')
     206           0 :             ds = s_waitend;
     207           0 :           break;
     208             :         case s_waitend:
     209           0 :           if ( *s == '\n')
     210           0 :             state->stop_seen = 1;
     211           0 :           break;
     212             :         default:
     213           0 :           BUG();
     214             :         }
     215             :     }
     216             : 
     217             : 
     218           0 :   state->idx = ds;
     219           0 :   state->radbuf[0] = val;
     220           0 :   state->quad_count = pos;
     221           0 :   *r_nbytes = (d -(char*) buffer);
     222           0 :   return 0;
     223             : }
     224             : 
     225             : 
     226             : /* This function needs to be called before releasing the decoder
     227             :    state.  It may return an error code in case an encoding error has
     228             :    been found during decoding. */
     229             : gpg_error_t
     230           0 : b64dec_finish (struct b64state *state)
     231             : {
     232           0 :   if (state->lasterr)
     233           0 :     return state->lasterr;
     234             : 
     235           0 :   xfree (state->title);
     236           0 :   state->title = NULL;
     237           0 :   return state->invalid_encoding? gpg_error(GPG_ERR_BAD_DATA): 0;
     238             : }

Generated by: LCOV version 1.11