2  * armor.c - Routines to (de)armor OpenPGP packet streams.
 
   4  * Jonathan McDowell <noodles@earth.li>
 
   6  * Copyright 2002 Project Purple
 
   8  * $Id: armor.c,v 1.8 2003/11/01 19:23:38 noodles Exp $
 
  15 #include "keystructs.h"
 
  16 #include "onak-conf.h"
 
  19 #define ARMOR_WIDTH 64
 
  21 #define CRC24_INIT 0xb704ceL
 
  22 #define CRC24_POLY 0x1864cfbL
 
  27 static unsigned char encode64(unsigned char c) {
 
  30         } else if (c >= 26 && c <= 51) {
 
  32         } else if (c >= 52 && c <= 61) {
 
  48 static unsigned char decode64(unsigned char c) {
 
  49         if (c >= 'A' && c <= 'Z') {
 
  51         } else if (c >= 'a' && c <= 'z') {
 
  53         } else if (c >= '0' && c <= '9') {
 
  55         } else if (c == '+') {
 
  57         } else if (c == '/') {
 
  59         } else if (c == '=' || c == '-') {
 
  69  *      @lastoctet: The last octet we got.
 
  70  *      @curoctet: The current octet we're expecting (0, 1 or 2).
 
  71  *      @count: The number of octets we've seen.
 
  72  *      @crc24: A running CRC24 of the data we've seen.
 
  73  *      @putchar_func: The function to output a character.
 
  74  *      @ctx: Context for putchar_func.
 
  76 struct armor_context {
 
  77         unsigned char lastoctet;
 
  81         int (*putchar_func)(void *ctx, size_t count, unsigned char *c);
 
  85 static void armor_init(struct armor_context *ctx)
 
  90         ctx->crc24 = CRC24_INIT;
 
  93 static void armor_finish(struct armor_context *state)
 
  97         switch (state->curoctet++) {
 
 101                 c = encode64((state->lastoctet & 3) << 4);
 
 102                 state->putchar_func(state->ctx, 1, &c);
 
 103                 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
 
 104                 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
 
 106                 if ((state->count % ARMOR_WIDTH) == 0) {
 
 107                         state->putchar_func(state->ctx, 1,
 
 108                                  (unsigned char *) "\n");
 
 112                 c = encode64((state->lastoctet & 0xF) << 2);
 
 113                 state->putchar_func(state->ctx, 1, &c);
 
 114                 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
 
 116                 if ((state->count % ARMOR_WIDTH) == 0) {
 
 117                         state->putchar_func(state->ctx, 1,
 
 118                                  (unsigned char *) "\n");
 
 123         state->crc24 &= 0xffffffL;
 
 124         if ((state->count % ARMOR_WIDTH) != 0) {
 
 125                 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
 
 127         state->putchar_func(state->ctx, 1, (unsigned char *) "=");
 
 128         c = encode64(state->crc24 >> 18);
 
 129         state->putchar_func(state->ctx, 1, &c);
 
 130         c = encode64((state->crc24 >> 12) & 0x3F);
 
 131         state->putchar_func(state->ctx, 1, &c);
 
 132         c = encode64((state->crc24 >> 6) & 0x3F);
 
 133         state->putchar_func(state->ctx, 1, &c);
 
 134         c = encode64(state->crc24 & 0x3F);
 
 135         state->putchar_func(state->ctx, 1, &c);
 
 136         state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
 
 141 static int armor_putchar_int(void *ctx, unsigned char c)
 
 143         struct armor_context *state;
 
 148         state = (struct armor_context *) ctx;
 
 150         switch (state->curoctet++) {
 
 152                 t = encode64(c >> 2);
 
 153                 state->putchar_func(state->ctx, 1, &t);
 
 157                 t = encode64(((state->lastoctet & 3) << 4) + (c >> 4));
 
 158                 state->putchar_func(state->ctx, 1, &t);
 
 162                 t = encode64(((state->lastoctet & 0xF) << 2) + (c >> 6));
 
 163                 state->putchar_func(state->ctx, 1, &t);
 
 164                 t = encode64(c & 0x3F);
 
 165                 state->putchar_func(state->ctx, 1, &t);
 
 169         state->curoctet %= 3;
 
 170         state->lastoctet = c;
 
 172         state->crc24 ^= c << 16;
 
 173         for (i = 0; i < 8; i++) {
 
 175                 if (state->crc24 & 0x1000000) {
 
 176                         state->crc24 ^= CRC24_POLY;
 
 180         if ((state->count % ARMOR_WIDTH) == 0) {
 
 181                 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
 
 188 static int armor_putchar(void *ctx, size_t count, unsigned char *c)
 
 192         for (i = 0; i < count; i++) {
 
 193                 armor_putchar_int(ctx, c[i]);
 
 200  *      @lastoctet: The last octet we got.
 
 201  *      @curoctet: The current octet we're expecting (0, 1 or 2).
 
 202  *      @count: The number of octets we've seen.
 
 203  *      @crc24: A running CRC24 of the data we've seen.
 
 204  *      @putchar_func: The function to output a character.
 
 205  *      @ctx: Context for putchar_func.
 
 207 struct dearmor_context {
 
 208         unsigned char lastoctet;
 
 212         int (*getchar_func)(void *ctx, size_t count, unsigned char *c);
 
 216 static void dearmor_init(struct dearmor_context *ctx)
 
 221         ctx->crc24 = CRC24_INIT;
 
 224 static void dearmor_finish(struct dearmor_context *state)
 
 230         state->crc24 &= 0xffffffL;
 
 232         state->putchar_func(state->ctx, '\n');
 
 233         state->putchar_func(state->ctx, '=');
 
 234         state->putchar_func(state->ctx, encode64(state->crc24 >> 18));
 
 235         state->putchar_func(state->ctx, encode64((state->crc24 >> 12) & 0x3F));
 
 236         state->putchar_func(state->ctx, encode64((state->crc24 >> 6) & 0x3F));
 
 237         state->putchar_func(state->ctx, encode64(state->crc24 & 0x3F));
 
 242 static int dearmor_getchar(void *ctx, unsigned char *c)
 
 244         struct dearmor_context *state;
 
 249         state = (struct dearmor_context *) ctx;
 
 254                 state->getchar_func(state->ctx, 1, &tmpc);
 
 255                 tmpc = decode64(tmpc);
 
 259                 switch (state->curoctet++) {
 
 261                         state->lastoctet = tmpc;
 
 264                                 state->getchar_func(state->ctx, 1, &tmpc);
 
 265                                 tmpc = decode64(tmpc);
 
 267                         *c = (state->lastoctet << 2) + (tmpc >> 4);
 
 270                         *c = ((state->lastoctet & 0xF) << 4) + (tmpc >> 2);
 
 273                         *c = ((state->lastoctet & 3) << 6) + tmpc;
 
 277                 state->curoctet %= 3;
 
 278                 state->lastoctet = tmpc;
 
 281                 state->crc24 ^= *c << 16;
 
 282                 for (i = 0; i < 8; i++) {
 
 284                         if (state->crc24 & 0x1000000) {
 
 285                                 state->crc24 ^= CRC24_POLY;
 
 293 static int dearmor_getchar_c(void *ctx, size_t count, unsigned char *c)
 
 297         for (i = 0; i < count && rc == 0; i++) {
 
 298                 rc = dearmor_getchar(ctx, &c[i]);
 
 305  *      armor_openpgp_stream - Takes a list of OpenPGP packets and armors it.
 
 306  *      @putchar_func: The function to output the next armor character.
 
 307  *      @ctx: The context pointer for putchar_func.
 
 308  *      @packets: The list of packets to output.
 
 310  *      This function ASCII armors a list of OpenPGP packets and outputs it
 
 311  *      using putchar_func.
 
 313 int armor_openpgp_stream(int (*putchar_func)(void *ctx, size_t count,
 
 316                                 struct openpgp_packet_list *packets)
 
 318         struct armor_context armor_ctx;
 
 323         putchar_func(ctx, sizeof("-----BEGIN PGP PUBLIC KEY BLOCK-----\n") - 1,
 
 324                 (unsigned char *) "-----BEGIN PGP PUBLIC KEY BLOCK-----\n");
 
 325         putchar_func(ctx, sizeof("Version: onak " VERSION "\n\n") - 1,
 
 326                 (unsigned char *) "Version: onak " VERSION "\n\n");
 
 328         armor_init(&armor_ctx);
 
 329         armor_ctx.putchar_func = putchar_func;
 
 331         write_openpgp_stream(armor_putchar, &armor_ctx, packets);
 
 332         armor_finish(&armor_ctx);
 
 337         putchar_func(ctx, sizeof("-----END PGP PUBLIC KEY BLOCK-----\n") - 1,
 
 338                 (unsigned char *) "-----END PGP PUBLIC KEY BLOCK-----\n");
 
 344  *      dearmor_openpgp_stream - Reads & decodes an ACSII armored OpenPGP msg.
 
 345  *      @getchar_func: The function to get the next character from the stream.
 
 346  *      @ctx: The context pointer for getchar_func.
 
 347  *      @packets: The list of packets.
 
 349  *      This function uses getchar_func to read characters from an ASCII
 
 350  *      armored OpenPGP stream and outputs the data as a linked list of
 
 353 int dearmor_openpgp_stream(int (*getchar_func)(void *ctx, size_t count,
 
 356                                 struct openpgp_packet_list **packets)
 
 358         struct dearmor_context dearmor_ctx;
 
 359         unsigned char curchar;
 
 364          * Look for armor header. We want "-----BEGIN.*\n", then some headers
 
 365          * with :s in them, then a blank line, then the data.
 
 368         while (state != 4 && !getchar_func(ctx, 1, &curchar)) {
 
 371                                 if (curchar == '\n') {
 
 377                                 if (curchar == '-') {
 
 382                                 } else if (curchar != '\n') {
 
 387                                 if (curchar == 'B') {
 
 395                                 if (curchar == '\n') {
 
 400                                 } else if (curchar != '\r') {
 
 408                 dearmor_init(&dearmor_ctx);
 
 409                 dearmor_ctx.getchar_func = getchar_func;
 
 410                 dearmor_ctx.ctx = ctx;
 
 411                 read_openpgp_stream(dearmor_getchar_c, &dearmor_ctx,
 
 413                 dearmor_finish(&dearmor_ctx);
 
 415                  * TODO: Look for armor footer