1 /* b64dec.c - Simple Base64 decoder.
2 * Copyright (C) 2008 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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.
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.
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/>.
31 /* The reverse base-64 list used for base-64 decoding. */
32 static unsigned char const asctobin
[128] =
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
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
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.
66 Not yet implemented: If TITLE is either "PGP" or begins with "PGP "
67 the PGP armor lines are skipped as well. */
69 b64dec_start (struct b64state
*state
, const char *title
)
71 memset (state
, 0, sizeof *state
);
74 if (!strncmp (title
, "PGP", 3) && (!title
[3] || title
[3] == ' '))
75 return gpg_error (GPG_ERR_NOT_IMPLEMENTED
);
77 state
->title
= xtrystrdup (title
);
79 return gpg_error_from_syserror ();
88 /* Do in-place decoding of base-64 data of LENGTH in BUFFER. Stores the
89 new length of the buffer at R_NBYTES. */
91 b64dec_proc (struct b64state
*state
, void *buffer
, size_t length
,
94 enum decoder_states ds
= state
->idx
;
95 unsigned char val
= state
->radbuf
[0];
96 int pos
= state
->quad_count
;
102 return gpg_error (GPG_ERR_EOF
);
105 for (s
=d
=buffer
; length
&& !state
->stop_seen
; length
--, s
++)
119 if (*s
!= "-----BEGIN "[pos
])
137 if (*s
== '-' && state
->title
)
139 /* Not a valid Base64 character: assume end
145 /* Pad character: stop */
148 ds
= state
->title
? s_waitendtitle
: s_waitend
;
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)
155 /* Skip invalid encodings. */
156 state
->invalid_encoding
= 1;
158 else if (ds
== s_b64_0
)
163 else if (ds
== s_b64_1
)
170 else if (ds
== s_b64_2
)
191 state
->stop_seen
= 1;
200 state
->radbuf
[0] = val
;
201 state
->quad_count
= pos
;
202 *r_nbytes
= (d
-(char*) buffer
);
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. */
211 b64dec_finish (struct b64state
*state
)
213 xfree (state
->title
);
215 return state
->invalid_encoding
? gpg_error(GPG_ERR_BAD_DATA
): 0;