From 95e6da1b07e27ed373ab744594442be685f77020 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 27 Nov 2001 18:38:59 +0000 Subject: [PATCH] --armor does now produce PEM format. --- sm/base64.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++---- sm/encrypt.c | 8 ++- sm/gpgsm.c | 4 ++ sm/gpgsm.h | 1 + sm/sign.c | 6 ++ 5 files changed, 188 insertions(+), 12 deletions(-) diff --git a/sm/base64.c b/sm/base64.c index f60015dd7..1efe31d55 100644 --- a/sm/base64.c +++ b/sm/base64.c @@ -32,6 +32,11 @@ #include "gpgsm.h" #include "i18n.h" +#ifdef HAVE_DOSISH_SYSTEM + #define LF "\r\n" +#else + #define LF "\n" +#endif /* data used by the reader callbacks */ struct reader_cb_parm_s { @@ -57,9 +62,29 @@ struct reader_cb_parm_s { } base64; }; +/* data used by the writer callbacks */ +struct writer_cb_parm_s { + FILE *fp; + const char *pem_name; + + int wrote_begin; + int did_finish; + struct { + int idx; + int quad_count; + unsigned char radbuf[4]; + } base64; + +}; + + +/* context for this module's functions */ struct base64_context_s { - struct reader_cb_parm_s rparm; + union { + struct reader_cb_parm_s rparm; + struct writer_cb_parm_s wparm; + } u; }; @@ -278,6 +303,122 @@ simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread) + +static int +base64_writer_cb (void *cb_value, const void *buffer, size_t count) +{ + struct writer_cb_parm_s *parm = cb_value; + unsigned char radbuf[4]; + int i, c, idx, quad_count; + const unsigned char *p; + FILE *fp = parm->fp; + + if (!count) + return 0; + + if (!parm->wrote_begin) + { + if (parm->pem_name) + { + fputs ("-----BEGIN ", fp); + fputs (parm->pem_name, fp); + fputs ("-----\n", fp); + } + parm->wrote_begin = 1; + parm->base64.idx = 0; + parm->base64.quad_count = 0; + } + + idx = parm->base64.idx; + quad_count = parm->base64.quad_count; + for (i=0; i < idx; i++) + radbuf[i] = parm->base64.radbuf[i]; + + for (p=buffer; count; p++, count--) + { + radbuf[idx++] = *p; + if (idx > 2) + { + idx = 0; + c = bintoasc[(*radbuf >> 2) & 077]; + putc (c, fp); + c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077]; + putc (c, fp); + c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077]; + putc (c, fp); + c = bintoasc[radbuf[2]&077]; + putc (c, fp); + if (++quad_count >= (64/4)) + { + fputs (LF, fp); + quad_count = 0; + } + } + } + for (i=0; i < idx; i++) + parm->base64.radbuf[i] = radbuf[i]; + parm->base64.idx = idx; + parm->base64.quad_count = quad_count; + + return ferror (fp) ? KSBA_Write_Error:0; +} + +static int +base64_finish_write (struct writer_cb_parm_s *parm) +{ + unsigned char radbuf[4]; + int i, c, idx, quad_count; + FILE *fp = parm->fp; + + if (!parm->wrote_begin) + return 0; /* nothing written */ + + /* flush the base64 encoding */ + idx = parm->base64.idx; + quad_count = parm->base64.quad_count; + for (i=0; i < idx; i++) + radbuf[i] = parm->base64.radbuf[i]; + + if (idx) + { + c = bintoasc[(*radbuf>>2)&077]; + putc (c, fp); + if (idx == 1) + { + c = bintoasc[((*radbuf << 4) & 060) & 077]; + putc (c, fp); + putc ('=', fp); + putc ('=', fp); + } + else + { + c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077]; + putc (c, fp); + c = bintoasc[((radbuf[1] << 2) & 074) & 077]; + putc (c, fp); + putc ('=', fp); + + } + if (++quad_count >= (64/4)) + { + fputs (LF, fp); + quad_count = 0; + } + } + + if (quad_count) + fputs (LF, fp); + + if (parm->pem_name) + { + fputs ("-----END ", fp); + fputs (parm->pem_name, fp); + fputs ("-----\n", fp); + } + return ferror (fp)? GNUPG_Write_Error : 0; +} + + /* Create a reader for the given file descriptor. Depending on the @@ -305,25 +446,25 @@ gpgsm_create_reader (Base64Context *ctx, return seterr (Out_Of_Core); } - (*ctx)->rparm.fp = fp; + (*ctx)->u.rparm.fp = fp; if (ctrl->is_pem) { - (*ctx)->rparm.assume_pem = 1; - (*ctx)->rparm.assume_base64 = 1; - rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->rparm); + (*ctx)->u.rparm.assume_pem = 1; + (*ctx)->u.rparm.assume_base64 = 1; + rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm); } else if (ctrl->is_base64) { - (*ctx)->rparm.assume_base64 = 1; - rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->rparm); + (*ctx)->u.rparm.assume_base64 = 1; + rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm); } else if (ctrl->autodetect_encoding) { - (*ctx)->rparm.autodetect = 1; - rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->rparm); + (*ctx)->u.rparm.autodetect = 1; + rc = ksba_reader_set_cb (r, base64_reader_cb, &(*ctx)->u.rparm); } else - rc = ksba_reader_set_cb (r, simple_reader_cb, &(*ctx)->rparm); + rc = ksba_reader_set_cb (r, simple_reader_cb, &(*ctx)->u.rparm); if (rc) { @@ -372,7 +513,9 @@ gpgsm_create_writer (Base64Context *ctx, if (ctrl->create_pem || ctrl->create_base64) { - return seterr (Not_Implemented); + (*ctx)->u.wparm.fp = fp; + (*ctx)->u.wparm.pem_name = "CMS OBJECT"; /* fixme */ + rc = ksba_writer_set_cb (w, base64_writer_cb, &(*ctx)->u.wparm); } else rc = ksba_writer_set_file (w, fp); @@ -389,6 +532,22 @@ gpgsm_create_writer (Base64Context *ctx, } +int +gpgsm_finish_writer (Base64Context ctx) +{ + struct writer_cb_parm_s *parm; + + if (!ctx) + return GNUPG_Invalid_Value; + parm = &ctx->u.wparm; + if (parm->did_finish) + return 0; /* already done */ + parm->did_finish = 1; + if (!parm->fp) + return 0; /* callback was not used */ + return base64_finish_write (parm); +} + void gpgsm_destroy_writer (Base64Context ctx) { diff --git a/sm/encrypt.c b/sm/encrypt.c index 2b30463bb..401bc4142 100644 --- a/sm/encrypt.c +++ b/sm/encrypt.c @@ -242,7 +242,13 @@ gpgsm_encrypt (CTRL ctrl, int data_fd, FILE *out_fp) } while (stopreason != KSBA_SR_READY); - log_info ("signature created\n"); + rc = gpgsm_finish_writer (b64writer); + if (rc) + { + log_error ("write failed: %s\n", gnupg_strerror (rc)); + goto leave; + } + log_info ("encrypted data created\n"); leave: ksba_cms_release (cms); diff --git a/sm/gpgsm.c b/sm/gpgsm.c index f6cf4aeef..78d1a435f 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -828,6 +828,7 @@ main ( int argc, char **argv) gcry_control (GCRYCTL_RESUME_SECMEM_WARN); set_debug (); + /* FIXME: should set filenames of libgcrypt explicitly * gpg_opt_homedir = opt.homedir; */ @@ -863,6 +864,9 @@ main ( int argc, char **argv) xfree(p); } + if (opt.armor) + ctrl.create_pem = 1; + if (!cmd && opt.fingerprint && !with_fpr) set_cmd (&cmd, aListKeys); diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 916a2cd38..7655eae47 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -124,6 +124,7 @@ int gpgsm_create_reader (Base64Context *ctx, void gpgsm_destroy_reader (Base64Context ctx); int gpgsm_create_writer (Base64Context *ctx, CTRL ctrl, FILE *fp, KsbaWriter *r_writer); +int gpgsm_finish_writer (Base64Context ctx); void gpgsm_destroy_writer (Base64Context ctx); diff --git a/sm/sign.c b/sm/sign.c index 42f409a7d..3101892f7 100644 --- a/sm/sign.c +++ b/sm/sign.c @@ -328,6 +328,12 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp) } while (stopreason != KSBA_SR_READY); + rc = gpgsm_finish_writer (b64writer); + if (rc) + { + log_error ("write failed: %s\n", gnupg_strerror (rc)); + goto leave; + } log_info ("signature created\n"); leave: