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