common: Add new helper function, strsplit.
[gnupg.git] / common / b64enc.c
1 /* b64enc.c - Simple Base64 encoder.
2  * Copyright (C) 2001, 2003, 2004, 2008, 2010,
3  *               2011 Free Software Foundation, Inc.
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 <http://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 <assert.h>
37
38 #include "i18n.h"
39 #include "util.h"
40
41 #define B64ENC_DID_HEADER   1
42 #define B64ENC_DID_TRAILER  2
43 #define B64ENC_NO_LINEFEEDS 16
44 #define B64ENC_USE_PGPCRC   32
45
46 /* The base-64 character list */
47 static unsigned char bintoasc[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
48                                     "abcdefghijklmnopqrstuvwxyz"
49                                     "0123456789+/";
50
51 /* Stuff required to create the OpenPGP CRC.  This crc_table has been
52    created using this code:
53
54    #include <stdio.h>
55    #include <stdint.h>
56
57    #define CRCPOLY 0x864CFB
58
59    int
60    main (void)
61    {
62      int i, j;
63      uint32_t t;
64      uint32_t crc_table[256];
65
66      crc_table[0] = 0;
67      for (i=j=0; j < 128; j++ )
68        {
69          t = crc_table[j];
70          if ( (t & 0x00800000) )
71            {
72              t <<= 1;
73              crc_table[i++] = t ^ CRCPOLY;
74              crc_table[i++] = t;
75         }
76          else
77            {
78              t <<= 1;
79              crc_table[i++] = t;
80              crc_table[i++] = t ^ CRCPOLY;
81         }
82        }
83
84      puts ("static const u32 crc_table[256] = {");
85      for (i=j=0; i < 256; i++)
86        {
87          printf ("%s 0x%08lx", j? "":" ", (unsigned long)crc_table[i]);
88          if (i != 255)
89            {
90              putchar (',');
91              if ( ++j > 5)
92                {
93                  j = 0;
94                  putchar ('\n');
95                }
96            }
97        }
98      puts ("\n};");
99      return 0;
100    }
101 */
102 #define CRCINIT 0xB704CE
103 static const u32 crc_table[256] = {
104   0x00000000, 0x00864cfb, 0x018ad50d, 0x010c99f6, 0x0393e6e1, 0x0315aa1a,
105   0x021933ec, 0x029f7f17, 0x07a18139, 0x0727cdc2, 0x062b5434, 0x06ad18cf,
106   0x043267d8, 0x04b42b23, 0x05b8b2d5, 0x053efe2e, 0x0fc54e89, 0x0f430272,
107   0x0e4f9b84, 0x0ec9d77f, 0x0c56a868, 0x0cd0e493, 0x0ddc7d65, 0x0d5a319e,
108   0x0864cfb0, 0x08e2834b, 0x09ee1abd, 0x09685646, 0x0bf72951, 0x0b7165aa,
109   0x0a7dfc5c, 0x0afbb0a7, 0x1f0cd1e9, 0x1f8a9d12, 0x1e8604e4, 0x1e00481f,
110   0x1c9f3708, 0x1c197bf3, 0x1d15e205, 0x1d93aefe, 0x18ad50d0, 0x182b1c2b,
111   0x192785dd, 0x19a1c926, 0x1b3eb631, 0x1bb8faca, 0x1ab4633c, 0x1a322fc7,
112   0x10c99f60, 0x104fd39b, 0x11434a6d, 0x11c50696, 0x135a7981, 0x13dc357a,
113   0x12d0ac8c, 0x1256e077, 0x17681e59, 0x17ee52a2, 0x16e2cb54, 0x166487af,
114   0x14fbf8b8, 0x147db443, 0x15712db5, 0x15f7614e, 0x3e19a3d2, 0x3e9fef29,
115   0x3f9376df, 0x3f153a24, 0x3d8a4533, 0x3d0c09c8, 0x3c00903e, 0x3c86dcc5,
116   0x39b822eb, 0x393e6e10, 0x3832f7e6, 0x38b4bb1d, 0x3a2bc40a, 0x3aad88f1,
117   0x3ba11107, 0x3b275dfc, 0x31dced5b, 0x315aa1a0, 0x30563856, 0x30d074ad,
118   0x324f0bba, 0x32c94741, 0x33c5deb7, 0x3343924c, 0x367d6c62, 0x36fb2099,
119   0x37f7b96f, 0x3771f594, 0x35ee8a83, 0x3568c678, 0x34645f8e, 0x34e21375,
120   0x2115723b, 0x21933ec0, 0x209fa736, 0x2019ebcd, 0x228694da, 0x2200d821,
121   0x230c41d7, 0x238a0d2c, 0x26b4f302, 0x2632bff9, 0x273e260f, 0x27b86af4,
122   0x252715e3, 0x25a15918, 0x24adc0ee, 0x242b8c15, 0x2ed03cb2, 0x2e567049,
123   0x2f5ae9bf, 0x2fdca544, 0x2d43da53, 0x2dc596a8, 0x2cc90f5e, 0x2c4f43a5,
124   0x2971bd8b, 0x29f7f170, 0x28fb6886, 0x287d247d, 0x2ae25b6a, 0x2a641791,
125   0x2b688e67, 0x2beec29c, 0x7c3347a4, 0x7cb50b5f, 0x7db992a9, 0x7d3fde52,
126   0x7fa0a145, 0x7f26edbe, 0x7e2a7448, 0x7eac38b3, 0x7b92c69d, 0x7b148a66,
127   0x7a181390, 0x7a9e5f6b, 0x7801207c, 0x78876c87, 0x798bf571, 0x790db98a,
128   0x73f6092d, 0x737045d6, 0x727cdc20, 0x72fa90db, 0x7065efcc, 0x70e3a337,
129   0x71ef3ac1, 0x7169763a, 0x74578814, 0x74d1c4ef, 0x75dd5d19, 0x755b11e2,
130   0x77c46ef5, 0x7742220e, 0x764ebbf8, 0x76c8f703, 0x633f964d, 0x63b9dab6,
131   0x62b54340, 0x62330fbb, 0x60ac70ac, 0x602a3c57, 0x6126a5a1, 0x61a0e95a,
132   0x649e1774, 0x64185b8f, 0x6514c279, 0x65928e82, 0x670df195, 0x678bbd6e,
133   0x66872498, 0x66016863, 0x6cfad8c4, 0x6c7c943f, 0x6d700dc9, 0x6df64132,
134   0x6f693e25, 0x6fef72de, 0x6ee3eb28, 0x6e65a7d3, 0x6b5b59fd, 0x6bdd1506,
135   0x6ad18cf0, 0x6a57c00b, 0x68c8bf1c, 0x684ef3e7, 0x69426a11, 0x69c426ea,
136   0x422ae476, 0x42aca88d, 0x43a0317b, 0x43267d80, 0x41b90297, 0x413f4e6c,
137   0x4033d79a, 0x40b59b61, 0x458b654f, 0x450d29b4, 0x4401b042, 0x4487fcb9,
138   0x461883ae, 0x469ecf55, 0x479256a3, 0x47141a58, 0x4defaaff, 0x4d69e604,
139   0x4c657ff2, 0x4ce33309, 0x4e7c4c1e, 0x4efa00e5, 0x4ff69913, 0x4f70d5e8,
140   0x4a4e2bc6, 0x4ac8673d, 0x4bc4fecb, 0x4b42b230, 0x49ddcd27, 0x495b81dc,
141   0x4857182a, 0x48d154d1, 0x5d26359f, 0x5da07964, 0x5cace092, 0x5c2aac69,
142   0x5eb5d37e, 0x5e339f85, 0x5f3f0673, 0x5fb94a88, 0x5a87b4a6, 0x5a01f85d,
143   0x5b0d61ab, 0x5b8b2d50, 0x59145247, 0x59921ebc, 0x589e874a, 0x5818cbb1,
144   0x52e37b16, 0x526537ed, 0x5369ae1b, 0x53efe2e0, 0x51709df7, 0x51f6d10c,
145   0x50fa48fa, 0x507c0401, 0x5542fa2f, 0x55c4b6d4, 0x54c82f22, 0x544e63d9,
146   0x56d11cce, 0x56575035, 0x575bc9c3, 0x57dd8538
147 };
148
149
150 static gpg_error_t
151 enc_start (struct b64state *state, FILE *fp, estream_t stream,
152            const char *title)
153 {
154   memset (state, 0, sizeof *state);
155   state->fp = fp;
156   state->stream = stream;
157   state->lasterr = 0;
158   if (title && !*title)
159     state->flags |= B64ENC_NO_LINEFEEDS;
160   else if (title)
161     {
162       if (!strncmp (title, "PGP ", 4))
163         {
164           state->flags |= B64ENC_USE_PGPCRC;
165           state->crc = CRCINIT;
166         }
167       state->title = xtrystrdup (title);
168       if (!state->title)
169         state->lasterr = gpg_error_from_syserror ();
170     }
171   return state->lasterr;
172 }
173
174
175 /* Prepare for base-64 writing to the stream FP.  If TITLE is not NULL
176    and not an empty string, this string will be used as the title for
177    the armor lines, with TITLE being an empty string, we don't write
178    the header lines and furthermore even don't write any linefeeds.
179    If TITLE starts with "PGP " the OpenPGP CRC checksum will be
180    written as well.  With TITLE beeing NULL, we merely don't write
181    header but make sure that lines are not too long. Note, that we
182    don't write any output unless at least one byte get written using
183    b64enc_write. */
184 gpg_error_t
185 b64enc_start (struct b64state *state, FILE *fp, const char *title)
186 {
187   return enc_start (state, fp, NULL, title);
188 }
189
190 /* Same as b64enc_start but takes an estream.  */
191 gpg_error_t
192 b64enc_start_es (struct b64state *state, estream_t fp, const char *title)
193 {
194   return enc_start (state, NULL, fp, title);
195 }
196
197
198 static int
199 my_fputs (const char *string, struct b64state *state)
200 {
201   if (state->stream)
202     return es_fputs (string, state->stream);
203   else
204     return fputs (string, state->fp);
205 }
206
207
208 /* Write NBYTES from BUFFER to the Base 64 stream identified by
209    STATE. With BUFFER and NBYTES being 0, merely do a fflush on the
210    stream. */
211 gpg_error_t
212 b64enc_write (struct b64state *state, const void *buffer, size_t nbytes)
213 {
214   unsigned char radbuf[4];
215   int idx, quad_count;
216   const unsigned char *p;
217
218   if (state->lasterr)
219     return state->lasterr;
220
221   if (!nbytes)
222     {
223       if (buffer)
224         if (state->stream? es_fflush (state->stream) : fflush (state->fp))
225           goto write_error;
226       return 0;
227     }
228
229   if (!(state->flags & B64ENC_DID_HEADER))
230     {
231       if (state->title)
232         {
233           if ( my_fputs ("-----BEGIN ", state) == EOF
234                || my_fputs (state->title, state) == EOF
235                || my_fputs ("-----\n", state) == EOF)
236             goto write_error;
237           if ( (state->flags & B64ENC_USE_PGPCRC)
238                && my_fputs ("\n", state) == EOF)
239             goto write_error;
240         }
241
242       state->flags |= B64ENC_DID_HEADER;
243     }
244
245   idx = state->idx;
246   quad_count = state->quad_count;
247   assert (idx < 4);
248   memcpy (radbuf, state->radbuf, idx);
249
250   if ( (state->flags & B64ENC_USE_PGPCRC) )
251     {
252       size_t n;
253       u32 crc = state->crc;
254
255       for (p=buffer, n=nbytes; n; p++, n-- )
256         crc = ((u32)crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ *p];
257       state->crc = (crc & 0x00ffffff);
258     }
259
260   for (p=buffer; nbytes; p++, nbytes--)
261     {
262       radbuf[idx++] = *p;
263       if (idx > 2)
264         {
265           char tmp[4];
266
267           tmp[0] = bintoasc[(*radbuf >> 2) & 077];
268           tmp[1] = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
269           tmp[2] = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
270           tmp[3] = bintoasc[radbuf[2]&077];
271           if (state->stream)
272             {
273               for (idx=0; idx < 4; idx++)
274                 es_putc (tmp[idx], state->stream);
275               idx = 0;
276               if (es_ferror (state->stream))
277                 goto write_error;
278             }
279           else
280             {
281               for (idx=0; idx < 4; idx++)
282                 putc (tmp[idx], state->fp);
283               idx = 0;
284               if (ferror (state->fp))
285                 goto write_error;
286             }
287           if (++quad_count >= (64/4))
288             {
289               quad_count = 0;
290               if (!(state->flags & B64ENC_NO_LINEFEEDS)
291                   && my_fputs ("\n", state) == EOF)
292                 goto write_error;
293             }
294         }
295     }
296   memcpy (state->radbuf, radbuf, idx);
297   state->idx = idx;
298   state->quad_count = quad_count;
299   return 0;
300
301  write_error:
302   state->lasterr = gpg_error_from_syserror ();
303   if (state->title)
304     {
305       xfree (state->title);
306       state->title = NULL;
307     }
308   return state->lasterr;
309 }
310
311
312 gpg_error_t
313 b64enc_finish (struct b64state *state)
314 {
315   gpg_error_t err = 0;
316   unsigned char radbuf[4];
317   int idx, quad_count;
318   char tmp[4];
319
320   if (state->lasterr)
321     return state->lasterr;
322
323   if (!(state->flags & B64ENC_DID_HEADER))
324     goto cleanup;
325
326   /* Flush the base64 encoding */
327   idx = state->idx;
328   quad_count = state->quad_count;
329   assert (idx < 4);
330   memcpy (radbuf, state->radbuf, idx);
331
332   if (idx)
333     {
334       tmp[0] = bintoasc[(*radbuf>>2)&077];
335       if (idx == 1)
336         {
337           tmp[1] = bintoasc[((*radbuf << 4) & 060) & 077];
338           tmp[2] = '=';
339           tmp[3] = '=';
340         }
341       else
342         {
343           tmp[1] = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077];
344           tmp[2] = bintoasc[((radbuf[1] << 2) & 074) & 077];
345           tmp[3] = '=';
346         }
347       if (state->stream)
348         {
349           for (idx=0; idx < 4; idx++)
350             es_putc (tmp[idx], state->stream);
351           idx = 0;
352           if (es_ferror (state->stream))
353             goto write_error;
354         }
355       else
356         {
357           for (idx=0; idx < 4; idx++)
358             putc (tmp[idx], state->fp);
359           idx = 0;
360           if (ferror (state->fp))
361             goto write_error;
362         }
363
364       if (++quad_count >= (64/4))
365         {
366           quad_count = 0;
367           if (!(state->flags & B64ENC_NO_LINEFEEDS)
368               && my_fputs ("\n", state) == EOF)
369             goto write_error;
370         }
371     }
372
373   /* Finish the last line and write the trailer. */
374   if (quad_count
375       && !(state->flags & B64ENC_NO_LINEFEEDS)
376       && my_fputs ("\n", state) == EOF)
377     goto write_error;
378
379   if ( (state->flags & B64ENC_USE_PGPCRC) )
380     {
381       /* Write the CRC.  */
382       my_fputs ("=", state);
383       radbuf[0] = state->crc >>16;
384       radbuf[1] = state->crc >> 8;
385       radbuf[2] = state->crc;
386       tmp[0] = bintoasc[(*radbuf>>2)&077];
387       tmp[1] = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077];
388       tmp[2] = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
389       tmp[3] = bintoasc[radbuf[2]&077];
390       if (state->stream)
391         {
392           for (idx=0; idx < 4; idx++)
393             es_putc (tmp[idx], state->stream);
394           if (es_ferror (state->stream))
395             goto write_error;
396         }
397       else
398         {
399           for (idx=0; idx < 4; idx++)
400             putc (tmp[idx], state->fp);
401           if (ferror (state->fp))
402             goto write_error;
403         }
404       if (!(state->flags & B64ENC_NO_LINEFEEDS)
405           && my_fputs ("\n", state) == EOF)
406         goto write_error;
407     }
408
409   if (state->title)
410     {
411       if ( my_fputs ("-----END ", state) == EOF
412            || my_fputs (state->title, state) == EOF
413            || my_fputs ("-----\n", state) == EOF)
414         goto write_error;
415     }
416
417   goto cleanup;
418
419  write_error:
420   err = gpg_error_from_syserror ();
421
422  cleanup:
423   if (state->title)
424     {
425       xfree (state->title);
426       state->title = NULL;
427     }
428   state->fp = NULL;
429   state->stream = NULL;
430   state->lasterr = err;
431   return err;
432 }