1 /* b64enc.c - Simple Base64 encoder.
2 * Copyright (C) 2001, 2003, 2004, 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/>.
30 #define B64ENC_DID_HEADER 1
31 #define B64ENC_DID_TRAILER 2
32 #define B64ENC_NO_LINEFEEDS 16
33 #define B64ENC_USE_PGPCRC 32
35 /* The base-64 character list */
36 static unsigned char bintoasc
[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
37 "abcdefghijklmnopqrstuvwxyz"
40 /* Stuff required to create the OpenPGP CRC. This crc_table has been
41 created using this code:
46 #define CRCPOLY 0x864CFB
53 uint32_t crc_table[256];
56 for (i=j=0; j < 128; j++ )
59 if ( (t & 0x00800000) )
62 crc_table[i++] = t ^ CRCPOLY;
69 crc_table[i++] = t ^ CRCPOLY;
73 puts ("static const u32 crc_table[256] = {");
74 for (i=j=0; i < 256; i++)
76 printf ("%s 0x%08lx", j? "":" ", (unsigned long)crc_table[i]);
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
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
149 b64enc_start (struct b64state
*state
, FILE *fp
, const char *title
)
151 memset (state
, 0, sizeof *state
);
153 if (title
&& !*title
)
154 state
->flags
|= B64ENC_NO_LINEFEEDS
;
157 if (!strncmp (title
, "PGP ", 4))
159 state
->flags
|= B64ENC_USE_PGPCRC
;
160 state
->crc
= CRCINIT
;
162 state
->title
= xtrystrdup (title
);
164 return gpg_error_from_syserror ();
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
174 b64enc_write (struct b64state
*state
, const void *buffer
, size_t nbytes
)
176 unsigned char radbuf
[4];
178 const unsigned char *p
;
179 FILE *fp
= state
->fp
;
184 if (buffer
&& fflush (fp
))
189 if (!(state
->flags
& B64ENC_DID_HEADER
))
193 if ( fputs ("-----BEGIN ", fp
) == EOF
194 || fputs (state
->title
, fp
) == EOF
195 || fputs ("-----\n", fp
) == EOF
)
197 if ( (state
->flags
& B64ENC_USE_PGPCRC
)
198 && fputs ("\n", fp
) == EOF
)
202 state
->flags
|= B64ENC_DID_HEADER
;
206 quad_count
= state
->quad_count
;
208 memcpy (radbuf
, state
->radbuf
, idx
);
210 if ( (state
->flags
& B64ENC_USE_PGPCRC
) )
213 u32 crc
= state
->crc
;
215 for (p
=buffer
, n
=nbytes
; n
; p
++, n
-- )
216 crc
= (crc
<< 8) ^ crc_table
[((crc
>> 16)&0xff) ^ *p
];
217 state
->crc
= (crc
& 0x00ffffff);
220 for (p
=buffer
; nbytes
; p
++, nbytes
--)
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
++)
236 if (++quad_count
>= (64/4))
239 if (!(state
->flags
& B64ENC_NO_LINEFEEDS
)
240 && fputs ("\n", fp
) == EOF
)
245 memcpy (state
->radbuf
, radbuf
, idx
);
247 state
->quad_count
= quad_count
;
251 return gpg_error_from_syserror ();
255 b64enc_finish (struct b64state
*state
)
258 unsigned char radbuf
[4];
263 if (!(state
->flags
& B64ENC_DID_HEADER
))
266 /* Flush the base64 encoding */
269 quad_count
= state
->quad_count
;
271 memcpy (radbuf
, state
->radbuf
, idx
);
275 tmp
[0] = bintoasc
[(*radbuf
>>2)&077];
278 tmp
[1] = bintoasc
[((*radbuf
<< 4) & 060) & 077];
284 tmp
[1] = bintoasc
[(((*radbuf
<<4)&060)|((radbuf
[1]>>4)&017))&077];
285 tmp
[2] = bintoasc
[((radbuf
[1] << 2) & 074) & 077];
288 for (idx
=0; idx
< 4; idx
++)
294 if (++quad_count
>= (64/4))
297 if (!(state
->flags
& B64ENC_NO_LINEFEEDS
)
298 && fputs ("\n", fp
) == EOF
)
303 /* Finish the last line and write the trailer. */
305 && !(state
->flags
& B64ENC_NO_LINEFEEDS
)
306 && fputs ("\n", fp
) == EOF
)
309 if ( (state
->flags
& B64ENC_USE_PGPCRC
) )
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
++)
324 if (!(state
->flags
& B64ENC_NO_LINEFEEDS
)
325 && fputs ("\n", fp
) == EOF
)
331 if ( fputs ("-----END ", fp
) == EOF
332 || fputs (state
->title
, fp
) == EOF
333 || fputs ("-----\n", fp
) == EOF
)
340 err
= gpg_error_from_syserror ();
345 xfree (state
->title
);