Bug Summary

File:lib/opencdk/armor.c
Location:line 278, column 15
Description:Although the value stored to 'nread' is used in the enclosing expression, the value is never actually read from 'nread'

Annotated Source Code

1/* armor.c - Armor filters
2 * Copyright (C) 1998-2003, 2007-2008, 2010, 2012 Free Software
3 * Foundation, Inc.
4 *
5 * Author: Timo Schulz
6 *
7 * This file is part of OpenCDK.
8 *
9 * The OpenCDK library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 3 of
12 * the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>
21 *
22 * ChangeLog for basic BASE64 code (base64_encode, base64_decode):
23 * Original author: Eric S. Raymond (Fetchmail)
24 * Heavily modified by Brendan Cully <brendan@kublai.com> (Mutt)
25 * Modify the code for generic use by Timo Schulz <twoaday@freakmail.de>
26 */
27
28#ifdef HAVE_CONFIG_H1
29#include <config.h>
30#endif
31#include <stdio.h>
32#include <string.h>
33#include <sys/stat.h>
34
35#include "opencdk.h"
36#include "main.h"
37#include "filters.h"
38
39#ifdef __MINGW32__
40#define LF"\n" "\r\n"
41#define ALTLF"\r\n" "\n"
42#else
43#define LF"\n" "\n"
44#define ALTLF"\r\n" "\r\n"
45#endif
46
47#define CRCINIT0xB704CE 0xB704CE
48
49#define BAD-1 -1
50#define b64val(c)index64[(unsigned int)(c)] index64[(unsigned int)(c)]
51
52static u32 crc_table[] = {
53 0x000000, 0x864CFB, 0x8AD50D, 0x0C99F6, 0x93E6E1, 0x15AA1A, 0x1933EC,
54 0x9F7F17,
55 0xA18139, 0x27CDC2, 0x2B5434, 0xAD18CF, 0x3267D8, 0xB42B23, 0xB8B2D5,
56 0x3EFE2E,
57 0xC54E89, 0x430272, 0x4F9B84, 0xC9D77F, 0x56A868, 0xD0E493, 0xDC7D65,
58 0x5A319E,
59 0x64CFB0, 0xE2834B, 0xEE1ABD, 0x685646, 0xF72951, 0x7165AA, 0x7DFC5C,
60 0xFBB0A7,
61 0x0CD1E9, 0x8A9D12, 0x8604E4, 0x00481F, 0x9F3708, 0x197BF3, 0x15E205,
62 0x93AEFE,
63 0xAD50D0, 0x2B1C2B, 0x2785DD, 0xA1C926, 0x3EB631, 0xB8FACA, 0xB4633C,
64 0x322FC7,
65 0xC99F60, 0x4FD39B, 0x434A6D, 0xC50696, 0x5A7981, 0xDC357A, 0xD0AC8C,
66 0x56E077,
67 0x681E59, 0xEE52A2, 0xE2CB54, 0x6487AF, 0xFBF8B8, 0x7DB443, 0x712DB5,
68 0xF7614E,
69 0x19A3D2, 0x9FEF29, 0x9376DF, 0x153A24, 0x8A4533, 0x0C09C8, 0x00903E,
70 0x86DCC5,
71 0xB822EB, 0x3E6E10, 0x32F7E6, 0xB4BB1D, 0x2BC40A, 0xAD88F1, 0xA11107,
72 0x275DFC,
73 0xDCED5B, 0x5AA1A0, 0x563856, 0xD074AD, 0x4F0BBA, 0xC94741, 0xC5DEB7,
74 0x43924C,
75 0x7D6C62, 0xFB2099, 0xF7B96F, 0x71F594, 0xEE8A83, 0x68C678, 0x645F8E,
76 0xE21375,
77 0x15723B, 0x933EC0, 0x9FA736, 0x19EBCD, 0x8694DA, 0x00D821, 0x0C41D7,
78 0x8A0D2C,
79 0xB4F302, 0x32BFF9, 0x3E260F, 0xB86AF4, 0x2715E3, 0xA15918, 0xADC0EE,
80 0x2B8C15,
81 0xD03CB2, 0x567049, 0x5AE9BF, 0xDCA544, 0x43DA53, 0xC596A8, 0xC90F5E,
82 0x4F43A5,
83 0x71BD8B, 0xF7F170, 0xFB6886, 0x7D247D, 0xE25B6A, 0x641791, 0x688E67,
84 0xEEC29C,
85 0x3347A4, 0xB50B5F, 0xB992A9, 0x3FDE52, 0xA0A145, 0x26EDBE, 0x2A7448,
86 0xAC38B3,
87 0x92C69D, 0x148A66, 0x181390, 0x9E5F6B, 0x01207C, 0x876C87, 0x8BF571,
88 0x0DB98A,
89 0xF6092D, 0x7045D6, 0x7CDC20, 0xFA90DB, 0x65EFCC, 0xE3A337, 0xEF3AC1,
90 0x69763A,
91 0x578814, 0xD1C4EF, 0xDD5D19, 0x5B11E2, 0xC46EF5, 0x42220E, 0x4EBBF8,
92 0xC8F703,
93 0x3F964D, 0xB9DAB6, 0xB54340, 0x330FBB, 0xAC70AC, 0x2A3C57, 0x26A5A1,
94 0xA0E95A,
95 0x9E1774, 0x185B8F, 0x14C279, 0x928E82, 0x0DF195, 0x8BBD6E, 0x872498,
96 0x016863,
97 0xFAD8C4, 0x7C943F, 0x700DC9, 0xF64132, 0x693E25, 0xEF72DE, 0xE3EB28,
98 0x65A7D3,
99 0x5B59FD, 0xDD1506, 0xD18CF0, 0x57C00B, 0xC8BF1C, 0x4EF3E7, 0x426A11,
100 0xC426EA,
101 0x2AE476, 0xACA88D, 0xA0317B, 0x267D80, 0xB90297, 0x3F4E6C, 0x33D79A,
102 0xB59B61,
103 0x8B654F, 0x0D29B4, 0x01B042, 0x87FCB9, 0x1883AE, 0x9ECF55, 0x9256A3,
104 0x141A58,
105 0xEFAAFF, 0x69E604, 0x657FF2, 0xE33309, 0x7C4C1E, 0xFA00E5, 0xF69913,
106 0x70D5E8,
107 0x4E2BC6, 0xC8673D, 0xC4FECB, 0x42B230, 0xDDCD27, 0x5B81DC, 0x57182A,
108 0xD154D1,
109 0x26359F, 0xA07964, 0xACE092, 0x2AAC69, 0xB5D37E, 0x339F85, 0x3F0673,
110 0xB94A88,
111 0x87B4A6, 0x01F85D, 0x0D61AB, 0x8B2D50, 0x145247, 0x921EBC, 0x9E874A,
112 0x18CBB1,
113 0xE37B16, 0x6537ED, 0x69AE1B, 0xEFE2E0, 0x709DF7, 0xF6D10C, 0xFA48FA,
114 0x7C0401,
115 0x42FA2F, 0xC4B6D4, 0xC82F22, 0x4E63D9, 0xD11CCE, 0x575035, 0x5BC9C3,
116 0xDD8538
117};
118
119static const char *armor_begin[] = {
120 "BEGIN PGP MESSAGE",
121 "BEGIN PGP PUBLIC KEY BLOCK",
122 "BEGIN PGP PRIVATE KEY BLOCK",
123 "BEGIN PGP SIGNATURE",
124 NULL((void*)0)
125};
126
127static const char *armor_end[] = {
128 "END PGP MESSAGE",
129 "END PGP PUBLIC KEY BLOCK",
130 "END PGP PRIVATE KEY BLOCK",
131 "END PGP SIGNATURE",
132 NULL((void*)0)
133};
134
135static const char *valid_headers[] = {
136 "Comment",
137 "Version",
138 "MessageID",
139 "Hash",
140 "Charset",
141 NULL((void*)0)
142};
143
144static char b64chars[] =
145 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
146
147static int index64[128] = {
148 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
149 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
150 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
151 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
152 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
153 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
154 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
155 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
156};
157
158
159/* encode a raw binary buffer to a null-terminated base64 strings */
160static int
161base64_encode (char *out, const byte * in, size_t len, size_t olen)
162{
163 if (!out || !in)
164 {
165 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "armor.c",165); } while(0);
;
166 return CDK_Inv_Value;
167 }
168
169 while (len >= 3 && olen > 10)
170 {
171 *out++ = b64chars[in[0] >> 2];
172 *out++ = b64chars[((in[0] << 4) & 0x30) | (in[1] >> 4)];
173 *out++ = b64chars[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
174 *out++ = b64chars[in[2] & 0x3f];
175 olen -= 4;
176 len -= 3;
177 in += 3;
178 }
179
180 /* clean up remainder */
181 if (len > 0 && olen > 4)
182 {
183 byte fragment = 0;
184 *out++ = b64chars[in[0] >> 2];
185 fragment = (in[0] << 4) & 0x30;
186 if (len > 1)
187 fragment |= in[1] >> 4;
188 *out++ = b64chars[fragment];
189 *out++ = (len < 2) ? '=' : b64chars[(in[1] << 2) & 0x3c];
190 *out++ = '=';
191 }
192 *out = '\0';
193 return 0;
194}
195
196
197/* Convert '\0'-terminated base64 string to raw byte buffer.
198 Returns length of returned buffer, or -1 on error. */
199static int
200base64_decode (byte * out, const char *in)
201{
202 size_t len;
203 byte digit1, digit2, digit3, digit4;
204
205 if (!out || !in)
206 {
207 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "armor.c",207); } while(0);
;
208 return -1;
209 }
210
211 len = 0;
212 do
213 {
214 digit1 = in[0];
215 if (digit1 > 127 || b64val (digit1)index64[(unsigned int)(digit1)] == BAD-1)
216 {
217 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "armor.c",217); } while(0);
;
218 return -1;
219 }
220 digit2 = in[1];
221 if (digit2 > 127 || b64val (digit2)index64[(unsigned int)(digit2)] == BAD-1)
222 {
223 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "armor.c",223); } while(0);
;
224 return -1;
225 }
226 digit3 = in[2];
227 if (digit3 > 127 || ((digit3 != '=') && (b64val (digit3)index64[(unsigned int)(digit3)] == BAD-1)))
228 {
229 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "armor.c",229); } while(0);
;
230 return -1;
231 }
232 digit4 = in[3];
233 if (digit4 > 127 || ((digit4 != '=') && (b64val (digit4)index64[(unsigned int)(digit4)] == BAD-1)))
234 {
235 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "armor.c",235); } while(0);
;
236 return -1;
237 }
238 in += 4;
239
240 /* digits are already sanity-checked */
241 *out++ = (b64val (digit1)index64[(unsigned int)(digit1)] << 2) | (b64val (digit2)index64[(unsigned int)(digit2)] >> 4);
242 len++;
243 if (digit3 != '=')
244 {
245 *out++ = ((b64val (digit2)index64[(unsigned int)(digit2)] << 4) & 0xf0) | (b64val (digit3)index64[(unsigned int)(digit3)] >> 2);
246 len++;
247 if (digit4 != '=')
248 {
249 *out++ = ((b64val (digit3)index64[(unsigned int)(digit3)] << 6) & 0xc0) | b64val (digit4)index64[(unsigned int)(digit4)];
250 len++;
251 }
252 }
253 }
254 while (*in && digit4 != '=');
255
256 return len;
257}
258
259
260/* Return the compression algorithm in @r_zipalgo.
261 If the parameter is not set after execution,
262 the stream is not compressed. */
263static int
264compress_get_algo (cdk_stream_t inp, int *r_zipalgo)
265{
266 byte plain[512];
267 char buf[128];
268 int nread, pkttype;
269
270 *r_zipalgo = 0;
271 cdk_stream_seek (inp, 0);
272 while (!cdk_stream_eof (inp))
273 {
274 nread = _cdk_stream_gets (inp, buf, DIM (buf)(sizeof (buf)/sizeof ((buf)[0])) - 1);
275 if (!nread || nread == -1)
276 break;
277 if (nread == 1 && !cdk_stream_eof (inp)
278 && (nread = _cdk_stream_gets (inp, buf, DIM (buf)(sizeof (buf)/sizeof ((buf)[0])) - 1)) > 0)
Although the value stored to 'nread' is used in the enclosing expression, the value is never actually read from 'nread'
279 {
280 base64_decode (plain, buf);
281 if (!(*plain & 0x80))
282 break;
283 pkttype = *plain & 0x40 ? (*plain & 0x3f) : ((*plain >> 2) & 0xf);
284 if (pkttype == CDK_PKT_COMPRESSED && r_zipalgo)
285 {
286 _gnutls_buffers_log ("armor compressed (algo=%d)\n",do { if (__builtin_expect((_gnutls_log_level == 6 || _gnutls_log_level
> 9), 0)) _gnutls_log( 6, "armor compressed (algo=%d)\n",
*(plain + 1)); } while(0)
287 *(plain + 1))do { if (__builtin_expect((_gnutls_log_level == 6 || _gnutls_log_level
> 9), 0)) _gnutls_log( 6, "armor compressed (algo=%d)\n",
*(plain + 1)); } while(0)
;
288 *r_zipalgo = *(plain + 1);
289 }
290 break;
291 }
292 }
293 return 0;
294}
295
296
297static int
298check_armor (cdk_stream_t inp, int *r_zipalgo)
299{
300 char buf[4096];
301 size_t nread;
302 int check;
303
304 check = 0;
305 nread = cdk_stream_read (inp, buf, DIM (buf)(sizeof (buf)/sizeof ((buf)[0])) - 1);
306 if (nread > 0)
307 {
308 buf[nread] = '\0';
309 if (strstr (buf, "-----BEGIN PGP"))
310 {
311 compress_get_algo (inp, r_zipalgo);
312 check = 1;
313 }
314 cdk_stream_seek (inp, 0);
315 }
316 return check;
317}
318
319
320static int
321is_armored (int ctb)
322{
323 int pkttype = 0;
324
325 if (!(ctb & 0x80))
326 {
327 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "armor.c",327); } while(0);
;
328 return 1; /* invalid packet: assume it is armored */
329 }
330 pkttype = ctb & 0x40 ? (ctb & 0x3f) : ((ctb >> 2) & 0xf);
331 switch (pkttype)
332 {
333 case CDK_PKT_MARKER:
334 case CDK_PKT_ONEPASS_SIG:
335 case CDK_PKT_PUBLIC_KEY:
336 case CDK_PKT_SECRET_KEY:
337 case CDK_PKT_PUBKEY_ENC:
338 case CDK_PKT_SIGNATURE:
339 case CDK_PKT_LITERAL:
340 case CDK_PKT_COMPRESSED:
341 return 0; /* seems to be a regular packet: not armored */
342 }
343 return 1;
344}
345
346
347static u32
348update_crc (u32 crc, const byte * buf, size_t buflen)
349{
350 unsigned int j;
351
352 if (!crc)
353 crc = CRCINIT0xB704CE;
354
355 for (j = 0; j < buflen; j++)
356 crc = (crc << 8) ^ crc_table[0xff & ((crc >> 16) ^ buf[j])];
357 crc &= 0xffffff;
358 return crc;
359}
360
361
362static cdk_error_t
363armor_encode (void *data, FILE * in, FILE * out)
364{
365 armor_filter_t *afx = data;
366 struct stat statbuf;
367 char crcbuf[5], buf[128], raw[49];
368 byte crcbuf2[3];
369 size_t nread = 0;
370 const char *lf;
371
372 if (!afx)
373 {
374 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "armor.c",374); } while(0);
;
375 return CDK_Inv_Value;
376 }
377 if (afx->idx < 0 || afx->idx > (int) DIM (armor_begin)(sizeof (armor_begin)/sizeof ((armor_begin)[0])) ||
378 afx->idx2 < 0 || afx->idx2 > (int) DIM (armor_end)(sizeof (armor_end)/sizeof ((armor_end)[0])))
379 {
380 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "armor.c",380); } while(0);
;
381 return CDK_Inv_Value;
382 }
383
384 _gnutls_buffers_log ("armor filter: encode\n")do { if (__builtin_expect((_gnutls_log_level == 6 || _gnutls_log_level
> 9), 0)) _gnutls_log( 6, "armor filter: encode\n"); } while
(0)
;
385
386 memset (crcbuf, 0, sizeof (crcbuf));
387
388 lf = afx->le ? afx->le : LF"\n";
389 fprintf (out, "-----%s-----%s", armor_begin[afx->idx], lf);
390 fprintf (out, "Version: OpenPrivacy " PACKAGE_VERSION"3.0.12" "%s", lf);
391 if (afx->hdrlines)
392 fwrite (afx->hdrlines, 1, strlen (afx->hdrlines), out);
393 fprintf (out, "%s", lf);
394
395 if (fstat (fileno (in), &statbuf))
396 {
397 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "armor.c",397); } while(0);
;
398 return CDK_General_Error;
399 }
400
401 while (!feof (in))
402 {
403 nread = fread (raw, 1, DIM (raw)(sizeof (raw)/sizeof ((raw)[0])) - 1, in);
404 if (!nread)
405 break;
406 if (ferror (in))
407 {
408 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "armor.c",408); } while(0);
;
409 return CDK_File_Error;
410 }
411 afx->crc = update_crc (afx->crc, (byte *) raw, nread);
412 base64_encode (buf, (byte *) raw, nread, DIM (buf)(sizeof (buf)/sizeof ((buf)[0])) - 1);
413 fprintf (out, "%s%s", buf, lf);
414 }
415
416 crcbuf2[0] = afx->crc >> 16;
417 crcbuf2[1] = afx->crc >> 8;
418 crcbuf2[2] = afx->crc;
419 crcbuf[0] = b64chars[crcbuf2[0] >> 2];
420 crcbuf[1] = b64chars[((crcbuf2[0] << 4) & 0x30) | (crcbuf2[1] >> 4)];
421 crcbuf[2] = b64chars[((crcbuf2[1] << 2) & 0x3c) | (crcbuf2[2] >> 6)];
422 crcbuf[3] = b64chars[crcbuf2[2] & 0x3f];
423 fprintf (out, "=%s%s", crcbuf, lf);
424 fprintf (out, "-----%s-----%s", armor_end[afx->idx2], lf);
425
426 return 0;
427}
428
429static int
430search_header (const char *buf, const char **array)
431{
432 const char *s;
433 int i;
434
435 if (strlen (buf) < 5 || strncmp (buf, "-----", 5))
436 {
437 return -1;
438 }
439 for (i = 0; (s = array[i]); i++)
440 {
441 if (!strncmp (s, buf + 5, strlen (s)))
442 return i;
443 }
444 return -1;
445}
446
447
448const char *
449_cdk_armor_get_lineend (void)
450{
451 return LF"\n";
452}
453
454
455static cdk_error_t
456armor_decode (void *data, FILE * in, FILE * out)
457{
458 armor_filter_t *afx = data;
459 const char *s;
460 char buf[127];
461 byte raw[128], crcbuf[4];
462 u32 crc2 = 0;
463 ssize_t nread = 0;
464 int i, pgp_data = 0;
465 cdk_error_t rc = 0;
466 int len;
467
468 if (!afx)
469 {
470 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "armor.c",470); } while(0);
;
471 return CDK_Inv_Value;
472 }
473
474 _gnutls_buffers_log ("armor filter: decode\n")do { if (__builtin_expect((_gnutls_log_level == 6 || _gnutls_log_level
> 9), 0)) _gnutls_log( 6, "armor filter: decode\n"); } while
(0)
;
475
476 fseek (in, 0, SEEK_SET0);
477 /* Search the begin of the message */
478 while (!feof (in) && !pgp_data)
479 {
480 s = fgets (buf, DIM (buf)(sizeof (buf)/sizeof ((buf)[0])) - 1, in);
481 if (!s)
482 break;
483 afx->idx = search_header (buf, armor_begin);
484 if (afx->idx >= 0)
485 pgp_data = 1;
486 }
487
488 if (feof (in) || !pgp_data)
489 {
490 return CDK_Armor_Error; /* no data found */
491 }
492
493 /* Parse header until the empty line is reached */
494 while (!feof (in))
495 {
496 s = fgets (buf, DIM (buf)(sizeof (buf)/sizeof ((buf)[0])) - 1, in);
497 if (!s)
498 return CDK_EOF;
499 if (strcmp (s, LF"\n") == 0 || strcmp (s, ALTLF"\r\n") == 0)
500 {
501 rc = 0;
502 break; /* empty line */
503 }
504 /* From RFC2440: OpenPGP should consider improperly formatted Armor
505 Headers to be corruption of the ASCII Armor. A colon and a single
506 space separate the key and value. */
507 if (!strstr (buf, ": "))
508 {
509 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "armor.c",509); } while(0);
;
510 return CDK_Armor_Error;
511 }
512 rc = CDK_General_Error;
513 for (i = 0; (s = valid_headers[i]); i++)
514 {
515 if (!strncmp (s, buf, strlen (s)))
516 rc = 0;
517 }
518 if (rc)
519 {
520 /* From RFC2440: Unknown keys should be reported to the user,
521 but OpenPGP should continue to process the message. */
522 _cdk_log_info ("unknown header: `%s'\n", buf)do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "unknown header: `%s'\n", buf); } while(0)
;
523 rc = 0;
524 }
525 }
526
527 /* Read the data body */
528 while (!feof (in))
529 {
530 s = fgets (buf, DIM (buf)(sizeof (buf)/sizeof ((buf)[0])) - 1, in);
531 if (!s)
532 break;
533
534 len = strlen(buf);
535
536 if (buf[len - 1] == '\n')
537 buf[len - 1] = '\0';
538 if (buf[len - 1] == '\r')
539 buf[len - 1] = '\0';
540 if (buf[0] == '=' && strlen (s) == 5)
541 { /* CRC */
542 memset (crcbuf, 0, sizeof (crcbuf));
543 base64_decode (crcbuf, buf + 1);
544 crc2 = (crcbuf[0] << 16) | (crcbuf[1] << 8) | crcbuf[2];
545 break; /* stop here */
546 }
547 else
548 {
549 nread = base64_decode (raw, buf);
550 if (nread == -1 || nread == 0)
551 break;
552 afx->crc = update_crc (afx->crc, raw, nread);
553 fwrite (raw, 1, nread, out);
554 }
555 }
556
557 /* Search the tail of the message */
558 s = fgets (buf, DIM (buf)(sizeof (buf)/sizeof ((buf)[0])) - 1, in);
559 if (s)
560 {
561 int len = strlen(buf);
562 if (buf[len - 1] == '\n')
563 buf[len - 1] = '\0';
564 if (buf[len - 1] == '\r')
565 buf[len - 1] = '\0';
566 rc = CDK_General_Error;
567 afx->idx2 = search_header (buf, armor_end);
568 if (afx->idx2 >= 0)
569 rc = 0;
570 }
571
572 /* This catches error when no tail was found or the header is
573 different then the tail line. */
574 if (rc || afx->idx != afx->idx2)
575 rc = CDK_Armor_Error;
576
577 afx->crc_okay = (afx->crc == crc2) ? 1 : 0;
578 if (!afx->crc_okay && !rc)
579 {
580 _gnutls_buffers_log ("file crc=%08X afx_crc=%08X\n",do { if (__builtin_expect((_gnutls_log_level == 6 || _gnutls_log_level
> 9), 0)) _gnutls_log( 6, "file crc=%08X afx_crc=%08X\n",
(unsigned int) crc2, (unsigned int) afx->crc); } while(0)
581 (unsigned int) crc2, (unsigned int) afx->crc)do { if (__builtin_expect((_gnutls_log_level == 6 || _gnutls_log_level
> 9), 0)) _gnutls_log( 6, "file crc=%08X afx_crc=%08X\n",
(unsigned int) crc2, (unsigned int) afx->crc); } while(0)
;
582 rc = CDK_Armor_CRC_Error;
583 }
584
585 return rc;
586}
587
588int
589_cdk_filter_armor (void *data, int ctl, FILE * in, FILE * out)
590{
591 if (ctl == STREAMCTL_READ)
592 return armor_decode (data, in, out);
593 else if (ctl == STREAMCTL_WRITE)
594 return armor_encode (data, in, out);
595 else if (ctl == STREAMCTL_FREE)
596 {
597 armor_filter_t *afx = data;
598 if (afx)
599 {
600 _gnutls_buffers_log ("free armor filter\n")do { if (__builtin_expect((_gnutls_log_level == 6 || _gnutls_log_level
> 9), 0)) _gnutls_log( 6, "free armor filter\n"); } while
(0)
;
601 afx->idx = afx->idx2 = 0;
602 afx->crc = afx->crc_okay = 0;
603 return 0;
604 }
605 }
606
607 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "armor.c",607); } while(0);
;
608 return CDK_Inv_Mode;
609}
610
611
612/**
613 * cdk_armor_encode_buffer:
614 * @inbuf: the raw input buffer
615 * @inlen: raw buffer len
616 * @outbuf: the destination buffer for the base64 output
617 * @outlen: destination buffer len
618 * @nwritten: actual length of the base64 data
619 * @type: the base64 file type.
620 *
621 * Encode the given buffer into base64 format. The base64
622 * string will be null terminated but the null will
623 * not be contained in the size.
624 **/
625cdk_error_t
626cdk_armor_encode_buffer (const byte * inbuf, size_t inlen,
627 char *outbuf, size_t outlen,
628 size_t * nwritten, int type)
629{
630 const char *head, *tail, *le;
631 byte tempbuf[48];
632 char tempout[128];
633 size_t pos, off, len, rest;
634
635 if (!inbuf || !nwritten)
636 {
637 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "armor.c",637); } while(0);
;
638 return CDK_Inv_Value;
639 }
640 if (type > CDK_ARMOR_SIGNATURE)
641 {
642 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "armor.c",642); } while(0);
;
643 return CDK_Inv_Mode;
644 }
645
646 head = armor_begin[type];
647 tail = armor_end[type];
648 le = _cdk_armor_get_lineend ();
649 pos = strlen (head) + 10 + 2 + 2 + strlen (tail) + 10 + 2 + 5 + 2 + 1;
650 /* The output data is 4/3 times larger, plus a line end for each line. */
651 pos += (4 * inlen / 3) + 2 * (4 * inlen / 3 / 64) + 1;
652
653 if (outbuf && outlen < pos)
654 {
655 gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log
( 2, "ASSERT: %s:%d\n", "armor.c",655); } while(0);
;
656 *nwritten = pos;
657 return CDK_Too_Short;
658 }
659
660 /* Only return the size of the output. */
661 if (!outbuf)
662 {
663 *nwritten = pos;
664 return 0;
665 }
666
667 pos = 0;
668 memset (outbuf, 0, outlen);
669 memcpy (outbuf + pos, "-----", 5);
670 pos += 5;
671 memcpy (outbuf + pos, head, strlen (head));
672 pos += strlen (head);
673 memcpy (outbuf + pos, "-----", 5);
674 pos += 5;
675 memcpy (outbuf + pos, le, strlen (le));
676 pos += strlen (le);
677 memcpy (outbuf + pos, le, strlen (le));
678 pos += strlen (le);
679 rest = inlen;
680 for (off = 0; off < inlen;)
681 {
682 if (rest > 48)
683 {
684 memcpy (tempbuf, inbuf + off, 48);
685 off += 48;
686 len = 48;
687 }
688 else
689 {
690 memcpy (tempbuf, inbuf + off, rest);
691 off += rest;
692 len = rest;
693 }
694 rest -= len;
695 base64_encode (tempout, tempbuf, len, DIM (tempout)(sizeof (tempout)/sizeof ((tempout)[0])) - 1);
696 memcpy (outbuf + pos, tempout, strlen (tempout));
697 pos += strlen (tempout);
698 memcpy (outbuf + pos, le, strlen (le));
699 pos += strlen (le);
700 }
701
702 memcpy (outbuf + pos, "-----", 5);
703 pos += 5;
704 memcpy (outbuf + pos, tail, strlen (tail));
705 pos += strlen (tail);
706 memcpy (outbuf + pos, "-----", 5);
707 pos += 5;
708 memcpy (outbuf + pos, le, strlen (le));
709 pos += strlen (le);
710 outbuf[pos] = 0;
711 *nwritten = pos - 1;
712 return 0;
713}