~ubuntu-branches/ubuntu/precise/gnupg2/precise-proposed

« back to all changes in this revision

Viewing changes to common/b64dec.c

  • Committer: Bazaar Package Importer
  • Author(s): Eric Dorland
  • Date: 2009-03-08 22:46:47 UTC
  • mfrom: (1.1.11 upstream)
  • Revision ID: james.westby@ubuntu.com-20090308224647-gq17gatcl71lrc2k
Tags: 2.0.11-1
* New upstream release. (Closes: #496663)
* debian/control: Make the description a little more distinctive than
  gnupg v1's. Thanks Jari Aalto. (Closes: #496323)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* b64dec.c - Simple Base64 decoder.
 
2
 * Copyright (C) 2008 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 <assert.h>
 
26
 
 
27
#include "i18n.h"
 
28
#include "util.h"
 
29
 
 
30
 
 
31
/* The reverse base-64 list used for base-64 decoding. */
 
32
static unsigned char const asctobin[128] = 
 
33
  {
 
34
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 
35
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 
36
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 
37
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 
38
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 
39
    0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
 
40
    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
 
41
    0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 
42
    0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
 
43
    0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
 
44
    0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
 
45
    0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
 
46
    0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
 
47
    0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
 
48
    0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
 
49
    0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
 
50
  };
 
51
 
 
52
enum decoder_states 
 
53
  {
 
54
    s_init, s_idle, s_lfseen, s_begin,
 
55
    s_b64_0, s_b64_1, s_b64_2, s_b64_3,
 
56
    s_waitendtitle, s_waitend
 
57
  };
 
58
 
 
59
 
 
60
 
 
61
/* Initialize the context for the base64 decoder.  If TITLE is NULL a
 
62
   plain base64 decoding is done.  If it is the empty string the
 
63
   decoder will skip everything until a "-----BEGIN " line has been
 
64
   seen, decoding ends at a "----END " line.
 
65
   
 
66
   Not yet implemented: If TITLE is either "PGP" or begins with "PGP "
 
67
   the PGP armor lines are skipped as well.  */
 
68
gpg_error_t
 
69
b64dec_start (struct b64state *state, const char *title)
 
70
{
 
71
  memset (state, 0, sizeof *state);
 
72
  if (title)
 
73
    {
 
74
      if (!strncmp (title, "PGP", 3) && (!title[3] || title[3] == ' '))
 
75
        return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
 
76
 
 
77
      state->title = xtrystrdup (title);
 
78
      if (!state->title)
 
79
        return gpg_error_from_syserror ();
 
80
      state->idx = s_init;
 
81
    }
 
82
  else
 
83
    state->idx = s_b64_0;
 
84
  return 0;
 
85
}
 
86
 
 
87
 
 
88
/* Do in-place decoding of base-64 data of LENGTH in BUFFER.  Stores the
 
89
   new length of the buffer at R_NBYTES. */
 
90
gpg_error_t
 
91
b64dec_proc (struct b64state *state, void *buffer, size_t length,
 
92
             size_t *r_nbytes)
 
93
{
 
94
  enum decoder_states ds = state->idx;
 
95
  unsigned char val = state->radbuf[0];
 
96
  int pos = state->quad_count; 
 
97
  char *d, *s;
 
98
 
 
99
  if (state->stop_seen)
 
100
    {
 
101
      *r_nbytes = 0;
 
102
      return gpg_error (GPG_ERR_EOF);
 
103
    }
 
104
 
 
105
  for (s=d=buffer; length && !state->stop_seen; length--, s++)
 
106
    {
 
107
      switch (ds)
 
108
        {
 
109
        case s_idle:
 
110
          if (*s == '\n')
 
111
            {
 
112
              ds = s_lfseen;
 
113
              pos = 0;
 
114
            }
 
115
          break;
 
116
        case s_init:
 
117
          ds = s_lfseen;
 
118
        case s_lfseen:
 
119
          if (*s != "-----BEGIN "[pos])
 
120
            ds = s_idle;
 
121
          else if (pos == 10)
 
122
            ds = s_begin;
 
123
          else
 
124
            pos++;
 
125
          break;
 
126
        case s_begin:
 
127
          if (*s == '\n')
 
128
            ds = s_b64_0;
 
129
          break;
 
130
        case s_b64_0:
 
131
        case s_b64_1:
 
132
        case s_b64_2:
 
133
        case s_b64_3:
 
134
          {
 
135
            int c;
 
136
 
 
137
            if (*s == '-' && state->title) 
 
138
              {
 
139
                /* Not a valid Base64 character: assume end
 
140
                   header.  */
 
141
                ds = s_waitend;
 
142
              }
 
143
            else if (*s == '=')
 
144
              {
 
145
                /* Pad character: stop */
 
146
                if (ds == s_b64_1)
 
147
                  *d++ = val;
 
148
                ds = state->title? s_waitendtitle : s_waitend;
 
149
              }
 
150
            else if (*s == '\n' || *s == ' ' || *s == '\r' || *s == '\t')
 
151
              ; /* Skip white spaces. */
 
152
            else if ( (*s & 0x80) 
 
153
                      || (c = asctobin[*(unsigned char *)s]) == 255)
 
154
              {
 
155
                /* Skip invalid encodings.  */
 
156
                state->invalid_encoding = 1;
 
157
              }
 
158
            else if (ds == s_b64_0)
 
159
              {
 
160
                val = c << 2;
 
161
                ds = s_b64_1;
 
162
              }
 
163
            else if (ds == s_b64_1)
 
164
              {
 
165
                val |= (c>>4)&3;
 
166
                *d++ = val;
 
167
                val = (c<<4)&0xf0;
 
168
                ds = s_b64_2;
 
169
              }
 
170
            else if (ds == s_b64_2)
 
171
              {
 
172
                val |= (c>>2)&15;
 
173
                *d++ = val;
 
174
                val = (c<<6)&0xc0;
 
175
                ds = s_b64_3;
 
176
              }
 
177
            else
 
178
              {
 
179
                val |= c&0x3f;
 
180
                *d++ = val;
 
181
                ds = s_b64_0;
 
182
              }
 
183
          }
 
184
          break;
 
185
        case s_waitendtitle:
 
186
          if (*s == '-')
 
187
            ds = s_waitend;
 
188
          break;
 
189
        case s_waitend:
 
190
          if ( *s == '\n')
 
191
            state->stop_seen = 1;
 
192
          break; 
 
193
        default: 
 
194
          BUG();
 
195
        }
 
196
    }
 
197
 
 
198
 
 
199
  state->idx = ds;
 
200
  state->radbuf[0] = val;
 
201
  state->quad_count = pos; 
 
202
  *r_nbytes = (d -(char*) buffer);
 
203
  return 0;
 
204
}
 
205
 
 
206
 
 
207
/* This function needs to be called before releasing the decoder
 
208
   state.  It may return an error code in case an encoding error has
 
209
   been found during decoding. */
 
210
gpg_error_t
 
211
b64dec_finish (struct b64state *state)
 
212
{
 
213
  xfree (state->title);
 
214
  state->title = NULL;
 
215
  return state->invalid_encoding? gpg_error(GPG_ERR_BAD_DATA): 0;
 
216
}
 
217