2 * Copyright (C) 2001, 2003 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 2 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, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
37 #ifdef HAVE_DOSISH_SYSTEM
43 /* data used by the reader callbacks */
44 struct reader_cb_parm_s
{
46 unsigned char line
[1024];
50 unsigned long line_counter
;
52 int allow_multi_pem
; /* Allow processing of multiple PEM objects. */
53 int autodetect
; /* Try to detect the input encoding. */
54 int assume_pem
; /* Assume input encoding is PEM. */
55 int assume_base64
; /* Assume input is base64 encoded. */
72 /* data used by the writer callbacks */
73 struct writer_cb_parm_s
{
83 unsigned char radbuf
[4];
89 /* context for this module's functions */
90 struct base64_context_s
{
92 struct reader_cb_parm_s rparm
;
93 struct writer_cb_parm_s wparm
;
98 /* The base-64 character list */
99 static char bintoasc
[64] =
100 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
101 "abcdefghijklmnopqrstuvwxyz"
103 /* The reverse base-64 list */
104 static unsigned char asctobin
[256] = {
105 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
106 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
107 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
108 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
109 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
110 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
111 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
112 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
113 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
114 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
115 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
116 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
117 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
118 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
119 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
120 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
121 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
122 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
123 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
124 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
125 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
126 0xff, 0xff, 0xff, 0xff
131 has_only_base64 (const unsigned char *line
, int linelen
)
135 for (; linelen
; line
++, linelen
--)
137 if (*line
== '\n' || (linelen
> 1 && *line
== '\r' && line
[1] == '\n'))
139 if ( !strchr (bintoasc
, *line
) )
146 is_empty_line (const unsigned char *line
, int linelen
)
148 if (linelen
>= 2 && *line
== '\r' && line
[1] == '\n')
150 if (linelen
>= 1 && *line
== '\n')
157 base64_reader_cb (void *cb_value
, char *buffer
, size_t count
, size_t *nread
)
159 struct reader_cb_parm_s
*parm
= cb_value
;
165 return -1; /* not supported */
170 /* read an entire line or up to the size of the buffer */
171 parm
->line_counter
++;
173 for (n
=0; n
< DIM(parm
->line
);)
179 if (ferror (parm
->fp
))
187 /* Fixme: we need to skip overlong lines while detecting
198 if (!parm
->identified
)
200 if (!parm
->autodetect
)
202 if (parm
->assume_pem
)
204 /* wait for the header line */
205 parm
->linelen
= parm
->readpos
= 0;
207 || strncmp ((char*)parm
->line
, "-----BEGIN ", 11)
208 || !strncmp ((char*)parm
->line
+11, "PGP ", 4))
212 else if (parm
->assume_base64
)
215 else if (parm
->line_counter
== 1 && !parm
->have_lf
)
217 /* first line too long - assume DER encoding */
220 else if (parm
->line_counter
== 1 && parm
->linelen
&& *parm
->line
== 0x30)
222 /* the very first byte does pretty much look like a SEQUENCE tag*/
225 else if ( parm
->have_lf
226 && !strncmp ((char*)parm
->line
, "-----BEGIN ", 11)
227 && strncmp ((char *)parm
->line
+11, "PGP ", 4) )
229 /* Fixme: we must only compare if the line really starts at
232 parm
->linelen
= parm
->readpos
= 0;
234 else if ( parm
->have_lf
&& parm
->line_counter
== 1
235 && parm
->linelen
>= 13
236 && !ascii_memcasecmp (parm
->line
, "Content-Type:", 13))
237 { /* might be a S/MIME body */
238 parm
->might_be_smime
= 1;
239 parm
->linelen
= parm
->readpos
= 0;
242 else if (parm
->might_be_smime
== 1
243 && is_empty_line (parm
->line
, parm
->linelen
))
245 parm
->might_be_smime
= 2;
246 parm
->linelen
= parm
->readpos
= 0;
249 else if (parm
->might_be_smime
== 2)
251 parm
->might_be_smime
= 0;
252 if ( !has_only_base64 (parm
->line
, parm
->linelen
))
254 parm
->linelen
= parm
->readpos
= 0;
261 parm
->linelen
= parm
->readpos
= 0;
264 parm
->identified
= 1;
265 parm
->base64
.stop_seen
= 0;
266 parm
->base64
.idx
= 0;
271 if (parm
->is_pem
|| parm
->is_base64
)
273 if (parm
->is_pem
&& parm
->have_lf
274 && !strncmp ((char*)parm
->line
, "-----END ", 9))
276 parm
->identified
= 0;
277 parm
->linelen
= parm
->readpos
= 0;
279 /* If the caller want to read multiple PEM objects from one
280 file, we have to reset our internal state and return a
281 EOF immediately. The caller is the expected to use
282 ksba_reader_clear to clear the EOF condition and continue
283 to read. If we don't want to do that we just return 0
284 bytes which will force the ksba_reader to skip until
286 if (parm
->allow_multi_pem
)
288 parm
->identified
= 0;
289 parm
->autodetect
= 0;
290 parm
->assume_pem
= 1;
292 return -1; /* Send EOF now. */
295 else if (parm
->stop_seen
)
296 { /* skip the rest of the line */
297 parm
->linelen
= parm
->readpos
= 0;
301 int idx
= parm
->base64
.idx
;
302 unsigned char val
= parm
->base64
.val
;
304 while (n
< count
&& parm
->readpos
< parm
->linelen
)
306 c
= parm
->line
[parm
->readpos
++];
307 if (c
== '\n' || c
== ' ' || c
== '\r' || c
== '\t')
310 { /* pad character: stop */
316 if( (c
= asctobin
[(c2
=c
)]) == 255 )
318 log_error (_("invalid radix64 character %02x skipped\n"),
344 if (parm
->readpos
== parm
->linelen
)
345 parm
->linelen
= parm
->readpos
= 0;
347 parm
->base64
.idx
= idx
;
348 parm
->base64
.val
= val
;
353 while (n
< count
&& parm
->readpos
< parm
->linelen
)
354 buffer
[n
++] = parm
->line
[parm
->readpos
++];
355 if (parm
->readpos
== parm
->linelen
)
356 parm
->linelen
= parm
->readpos
= 0;
366 simple_reader_cb (void *cb_value
, char *buffer
, size_t count
, size_t *nread
)
368 struct reader_cb_parm_s
*parm
= cb_value
;
374 return -1; /* not supported */
376 for (n
=0; n
< count
; n
++)
382 if ( ferror (parm
->fp
) )
385 break; /* return what we have before an EOF */
388 *(byte
*)buffer
++ = c
;
399 base64_writer_cb (void *cb_value
, const void *buffer
, size_t count
)
401 struct writer_cb_parm_s
*parm
= cb_value
;
402 unsigned char radbuf
[4];
403 int i
, c
, idx
, quad_count
;
404 const unsigned char *p
;
410 if (!parm
->wrote_begin
)
414 fputs ("-----BEGIN ", fp
);
415 fputs (parm
->pem_name
, fp
);
416 fputs ("-----\n", fp
);
418 parm
->wrote_begin
= 1;
419 parm
->base64
.idx
= 0;
420 parm
->base64
.quad_count
= 0;
423 idx
= parm
->base64
.idx
;
424 quad_count
= parm
->base64
.quad_count
;
425 for (i
=0; i
< idx
; i
++)
426 radbuf
[i
] = parm
->base64
.radbuf
[i
];
428 for (p
=buffer
; count
; p
++, count
--)
434 c
= bintoasc
[(*radbuf
>> 2) & 077];
436 c
= bintoasc
[(((*radbuf
<<4)&060)|((radbuf
[1] >> 4)&017))&077];
438 c
= bintoasc
[(((radbuf
[1]<<2)&074)|((radbuf
[2]>>6)&03))&077];
440 c
= bintoasc
[radbuf
[2]&077];
442 if (++quad_count
>= (64/4))
449 for (i
=0; i
< idx
; i
++)
450 parm
->base64
.radbuf
[i
] = radbuf
[i
];
451 parm
->base64
.idx
= idx
;
452 parm
->base64
.quad_count
= quad_count
;
454 return ferror (fp
) ? gpg_error_from_errno (errno
) : 0;
458 base64_finish_write (struct writer_cb_parm_s
*parm
)
460 unsigned char radbuf
[4];
461 int i
, c
, idx
, quad_count
;
464 if (!parm
->wrote_begin
)
465 return 0; /* nothing written */
467 /* flush the base64 encoding */
468 idx
= parm
->base64
.idx
;
469 quad_count
= parm
->base64
.quad_count
;
470 for (i
=0; i
< idx
; i
++)
471 radbuf
[i
] = parm
->base64
.radbuf
[i
];
475 c
= bintoasc
[(*radbuf
>>2)&077];
479 c
= bintoasc
[((*radbuf
<< 4) & 060) & 077];
486 c
= bintoasc
[(((*radbuf
<<4)&060)|((radbuf
[1]>>4)&017))&077];
488 c
= bintoasc
[((radbuf
[1] << 2) & 074) & 077];
493 if (++quad_count
>= (64/4))
505 fputs ("-----END ", fp
);
506 fputs (parm
->pem_name
, fp
);
507 fputs ("-----\n", fp
);
509 return ferror (fp
)? gpg_error (gpg_err_code_from_errno (errno
)) : 0;
515 /* Create a reader for the given file descriptor. Depending on the
516 control information an input decoding is automagically choosen.
517 The function returns a Base64Context object which must be passed to
518 the gpgme_destroy_reader function. The created KsbaReader object
519 is also returned, but the caller must not call the
520 ksba_reader_release function on. If ALLOW_MULTI_PEM is true, the
521 reader expects that the caller uses ksba_reader_clear after EOF
522 until no more objects were found. */
524 gpgsm_create_reader (Base64Context
*ctx
,
525 ctrl_t ctrl
, FILE *fp
, int allow_multi_pem
,
526 ksba_reader_t
*r_reader
)
532 *ctx
= xtrycalloc (1, sizeof **ctx
);
534 return out_of_core ();
535 (*ctx
)->u
.rparm
.allow_multi_pem
= allow_multi_pem
;
537 rc
= ksba_reader_new (&r
);
540 xfree (*ctx
); *ctx
= NULL
;
544 (*ctx
)->u
.rparm
.fp
= fp
;
547 (*ctx
)->u
.rparm
.assume_pem
= 1;
548 (*ctx
)->u
.rparm
.assume_base64
= 1;
549 rc
= ksba_reader_set_cb (r
, base64_reader_cb
, &(*ctx
)->u
.rparm
);
551 else if (ctrl
->is_base64
)
553 (*ctx
)->u
.rparm
.assume_base64
= 1;
554 rc
= ksba_reader_set_cb (r
, base64_reader_cb
, &(*ctx
)->u
.rparm
);
556 else if (ctrl
->autodetect_encoding
)
558 (*ctx
)->u
.rparm
.autodetect
= 1;
559 rc
= ksba_reader_set_cb (r
, base64_reader_cb
, &(*ctx
)->u
.rparm
);
562 rc
= ksba_reader_set_cb (r
, simple_reader_cb
, &(*ctx
)->u
.rparm
);
566 ksba_reader_release (r
);
567 xfree (*ctx
); *ctx
= NULL
;
577 gpgsm_reader_eof_seen (Base64Context ctx
)
579 return ctx
&& ctx
->u
.rparm
.eof_seen
;
583 gpgsm_destroy_reader (Base64Context ctx
)
590 /* Create a writer for the given stream. Depending on the control
591 information an output encoding is automagically choosen. The
592 function returns a Base64Context object which must be passed to the
593 gpgme_destroy_writer function. The created KsbaWriter object is
594 also returned, but the caller must not call the ksba_reader_release
597 gpgsm_create_writer (Base64Context
*ctx
,
598 ctrl_t ctrl
, FILE *fp
, ksba_writer_t
*r_writer
)
604 *ctx
= xtrycalloc (1, sizeof **ctx
);
606 return out_of_core ();
608 rc
= ksba_writer_new (&w
);
611 xfree (*ctx
); *ctx
= NULL
;
615 if (ctrl
->create_pem
|| ctrl
->create_base64
)
617 (*ctx
)->u
.wparm
.fp
= fp
;
618 if (ctrl
->create_pem
)
619 (*ctx
)->u
.wparm
.pem_name
= ctrl
->pem_name
? ctrl
->pem_name
621 rc
= ksba_writer_set_cb (w
, base64_writer_cb
, &(*ctx
)->u
.wparm
);
624 rc
= ksba_writer_set_file (w
, fp
);
628 ksba_writer_release (w
);
629 xfree (*ctx
); *ctx
= NULL
;
639 gpgsm_finish_writer (Base64Context ctx
)
641 struct writer_cb_parm_s
*parm
;
644 return gpg_error (GPG_ERR_INV_VALUE
);
645 parm
= &ctx
->u
.wparm
;
646 if (parm
->did_finish
)
647 return 0; /* already done */
648 parm
->did_finish
= 1;
650 return 0; /* callback was not used */
651 return base64_finish_write (parm
);
655 gpgsm_destroy_writer (Base64Context ctx
)