X-Git-Url: https://git.sommitrealweird.co.uk/onak.git/blobdiff_plain/4b8483ae278577a3adc8d84da81d77019704466f..refs/heads/switch-to-debhelper:/armor.c?ds=inline diff --git a/armor.c b/armor.c index e41cbad..9b61b1a 100644 --- a/armor.c +++ b/armor.c @@ -1,21 +1,43 @@ -/* - * armor.c - Routines to (de)armor OpenPGP packet streams. +/** + * @file armor.c + * @brief Routines to (de)armor OpenPGP packet streams. + * + * Copyright 2002-2004, 2011 Jonathan McDowell * - * Jonathan McDowell + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; version 2 of the License. * - * Copyright 2002 Project Purple + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include #include #include "armor.h" #include "keystructs.h" +#include "onak-conf.h" #include "parsekey.h" +#include "version.h" +/** + * @brief Line length we'll use for armored output + */ #define ARMOR_WIDTH 64 +/** + * @brief CRC24 initialisation value + */ #define CRC24_INIT 0xb704ceL +/** + * @brief CRC24 polynomial value + */ #define CRC24_POLY 0x1864cfbL /** @@ -33,7 +55,7 @@ static unsigned char encode64(unsigned char c) { } else if (c == 63) { c = '/'; } else { - assert(c < 64); + c = '?'; } return c; @@ -62,35 +84,21 @@ static unsigned char decode64(unsigned char c) { return c; } - -void putstring(int (*putchar_func)(void *ctx, unsigned char c), - void *ctx, - const char *string) -{ - int i; - - assert(putchar_func != NULL); - assert(string != NULL); - - for (i = 0; string[i] != 0; i++) { - putchar_func(ctx, string[i]); - } -} - /** - * @lastoctet: The last octet we got. - * @curoctet: The current octet we're expecting (0, 1 or 2). - * @count: The number of octets we've seen. - * @crc24: A running CRC24 of the data we've seen. - * @putchar_func: The function to output a character. - * @ctx: Context for putchar_func. + * @brief Holds the context of an ongoing ASCII armor operation */ struct armor_context { + /** The last octet we got. */ unsigned char lastoctet; + /** The current octet we're expecting (0, 1 or 2). */ int curoctet; + /** The number of octets we've seen. */ int count; + /** A running CRC24 of the data we've seen. */ long crc24; - int (*putchar_func)(void *ctx, unsigned char c); + /** The function to output a character. */ + int (*putchar_func)(void *ctx, size_t count, void *c); + /** Context for putchar_func. */ void *ctx; }; @@ -104,55 +112,76 @@ static void armor_init(struct armor_context *ctx) static void armor_finish(struct armor_context *state) { + unsigned char c; + switch (state->curoctet++) { case 0: break; case 1: - state->putchar_func(state->ctx, - encode64((state->lastoctet & 3) << 4)); - state->putchar_func(state->ctx, '='); - state->putchar_func(state->ctx, '='); + c = encode64((state->lastoctet & 3) << 4); + state->putchar_func(state->ctx, 1, &c); + state->putchar_func(state->ctx, 1, (unsigned char *) "="); + state->putchar_func(state->ctx, 1, (unsigned char *) "="); + state->count += 3; + if ((state->count % ARMOR_WIDTH) == 0) { + state->putchar_func(state->ctx, 1, + (unsigned char *) "\n"); + } break; case 2: - state->putchar_func(state->ctx, - encode64((state->lastoctet & 0xF) << 2)); - state->putchar_func(state->ctx, '='); + c = encode64((state->lastoctet & 0xF) << 2); + state->putchar_func(state->ctx, 1, &c); + state->putchar_func(state->ctx, 1, (unsigned char *) "="); + state->count += 2; + if ((state->count % ARMOR_WIDTH) == 0) { + state->putchar_func(state->ctx, 1, + (unsigned char *) "\n"); + } break; } state->crc24 &= 0xffffffL; - state->putchar_func(state->ctx, '\n'); - state->putchar_func(state->ctx, '='); - state->putchar_func(state->ctx, encode64(state->crc24 >> 18)); - state->putchar_func(state->ctx, encode64((state->crc24 >> 12) & 0x3F)); - state->putchar_func(state->ctx, encode64((state->crc24 >> 6) & 0x3F)); - state->putchar_func(state->ctx, encode64(state->crc24 & 0x3F)); - state->putchar_func(state->ctx, '\n'); + if ((state->count % ARMOR_WIDTH) != 0) { + state->putchar_func(state->ctx, 1, (unsigned char *) "\n"); + } + state->putchar_func(state->ctx, 1, (unsigned char *) "="); + c = encode64(state->crc24 >> 18); + state->putchar_func(state->ctx, 1, &c); + c = encode64((state->crc24 >> 12) & 0x3F); + state->putchar_func(state->ctx, 1, &c); + c = encode64((state->crc24 >> 6) & 0x3F); + state->putchar_func(state->ctx, 1, &c); + c = encode64(state->crc24 & 0x3F); + state->putchar_func(state->ctx, 1, &c); + state->putchar_func(state->ctx, 1, (unsigned char *) "\n"); } -static int armor_putchar(void *ctx, unsigned char c) + +static int armor_putchar_int(void *ctx, unsigned char c) { struct armor_context *state; + unsigned char t; int i; - assert(ctx != NULL); state = (struct armor_context *) ctx; switch (state->curoctet++) { case 0: - state->putchar_func(state->ctx, encode64(c >> 2)); + t = encode64(c >> 2); + state->putchar_func(state->ctx, 1, &t); state->count++; break; case 1: - state->putchar_func(state->ctx, - encode64(((state->lastoctet & 3) << 4) + (c >> 4))); + t = encode64(((state->lastoctet & 3) << 4) + (c >> 4)); + state->putchar_func(state->ctx, 1, &t); state->count++; break; case 2: - state->putchar_func(state->ctx, - encode64(((state->lastoctet & 0xF) << 2) + (c >> 6))); - state->putchar_func(state->ctx, encode64(c & 0x3F)); + t = encode64(((state->lastoctet & 0xF) << 2) + (c >> 6)); + state->putchar_func(state->ctx, 1, &t); + t = encode64(c & 0x3F); + state->putchar_func(state->ctx, 1, &t); state->count += 2; break; } @@ -168,26 +197,40 @@ static int armor_putchar(void *ctx, unsigned char c) } if ((state->count % ARMOR_WIDTH) == 0) { - state->putchar_func(state->ctx, '\n'); + state->putchar_func(state->ctx, 1, (unsigned char *) "\n"); } return 0; } + +static int armor_putchar(void *ctx, size_t count, void *c) +{ + int i; + + + for (i = 0; i < count; i++) { + armor_putchar_int(ctx, ((char *) c)[i]); + } + + return 0; +} + /** - * @lastoctet: The last octet we got. - * @curoctet: The current octet we're expecting (0, 1 or 2). - * @count: The number of octets we've seen. - * @crc24: A running CRC24 of the data we've seen. - * @putchar_func: The function to output a character. - * @ctx: Context for putchar_func. + * @brief Holds the context of an ongoing ASCII dearmor operation */ struct dearmor_context { + /** The last octet we got. */ unsigned char lastoctet; + /** The current octet we're expecting (0, 1 or 2). */ int curoctet; + /** The number of octets we've seen. */ int count; + /** A running CRC24 of the data we've seen. */ long crc24; - int (*getchar_func)(void *ctx, unsigned char *c); + /** The function to get the next character. */ + int (*getchar_func)(void *ctx, size_t count, void *c); + /** Context for getchar_func. */ void *ctx; }; @@ -201,16 +244,19 @@ static void dearmor_init(struct dearmor_context *ctx) static void dearmor_finish(struct dearmor_context *state) { - // Check the checksum, + /* + * Check the checksum + */ state->crc24 &= 0xffffffL; -// state->putchar_func(state->ctx, '\n'); -// state->putchar_func(state->ctx, '='); -// state->putchar_func(state->ctx, encode64(state->crc24 >> 18)); -// state->putchar_func(state->ctx, encode64((state->crc24 >> 12) & 0x3F)); -// state->putchar_func(state->ctx, encode64((state->crc24 >> 6) & 0x3F)); -// state->putchar_func(state->ctx, encode64(state->crc24 & 0x3F)); - + /* + state->putchar_func(state->ctx, '\n'); + state->putchar_func(state->ctx, '='); + state->putchar_func(state->ctx, encode64(state->crc24 >> 18)); + state->putchar_func(state->ctx, encode64((state->crc24 >> 12) & 0x3F)); + state->putchar_func(state->ctx, encode64((state->crc24 >> 6) & 0x3F)); + state->putchar_func(state->ctx, encode64(state->crc24 & 0x3F)); + */ } @@ -220,13 +266,12 @@ static int dearmor_getchar(void *ctx, unsigned char *c) unsigned char tmpc; int i; - assert(ctx != NULL); state = (struct dearmor_context *) ctx; *c = 0; tmpc = 65; while (tmpc == 65) { - state->getchar_func(state->ctx, &tmpc); + state->getchar_func(state->ctx, 1, &tmpc); tmpc = decode64(tmpc); } @@ -236,7 +281,7 @@ static int dearmor_getchar(void *ctx, unsigned char *c) state->lastoctet = tmpc; tmpc = 65; while (tmpc == 65) { - state->getchar_func(state->ctx, &tmpc); + state->getchar_func(state->ctx, 1, &tmpc); tmpc = decode64(tmpc); } *c = (state->lastoctet << 2) + (tmpc >> 4); @@ -265,38 +310,31 @@ static int dearmor_getchar(void *ctx, unsigned char *c) return (tmpc == 64); } -static int dearmor_getchar_c(void *ctx, size_t count, unsigned char *c) +static int dearmor_getchar_c(void *ctx, size_t count, void *c) { int i, rc = 0; for (i = 0; i < count && rc == 0; i++) { - rc = dearmor_getchar(ctx, &c[i]); + rc = dearmor_getchar(ctx, &((unsigned char *) c)[i]); } return rc; } -/** - * armor_openpgp_stream - Takes a list of OpenPGP packets and armors it. - * @putchar_func: The function to output the next armor character. - * @ctx: The context pointer for putchar_func. - * @packets: The list of packets to output. - * - * This function ASCII armors a list of OpenPGP packets and outputs it - * using putchar_func. - */ -int armor_openpgp_stream(int (*putchar_func)(void *ctx, unsigned char c), +int armor_openpgp_stream(int (*putchar_func)(void *ctx, size_t count, + void *c), void *ctx, struct openpgp_packet_list *packets) { struct armor_context armor_ctx; - /* * Print armor header */ - putstring(putchar_func, ctx, "-----BEGIN PGP PUBLIC KEY BLOCK-----\n"); - putstring(putchar_func, ctx, "Version: onak 0.0.1\n\n"); + putchar_func(ctx, sizeof("-----BEGIN PGP PUBLIC KEY BLOCK-----\n") - 1, + (unsigned char *) "-----BEGIN PGP PUBLIC KEY BLOCK-----\n"); + putchar_func(ctx, sizeof("Version: onak " ONAK_VERSION "\n\n") - 1, + (unsigned char *) "Version: onak " ONAK_VERSION "\n\n"); armor_init(&armor_ctx); armor_ctx.putchar_func = putchar_func; @@ -307,22 +345,14 @@ int armor_openpgp_stream(int (*putchar_func)(void *ctx, unsigned char c), /* * Print armor footer */ - putstring(putchar_func, ctx, "-----END PGP PUBLIC KEY BLOCK-----\n"); + putchar_func(ctx, sizeof("-----END PGP PUBLIC KEY BLOCK-----\n") - 1, + (unsigned char *) "-----END PGP PUBLIC KEY BLOCK-----\n"); return 0; } -/** - * dearmor_openpgp_stream - Reads & decodes an ACSII armored OpenPGP msg. - * @getchar_func: The function to get the next character from the stream. - * @ctx: The context pointer for getchar_func. - * @packets: The list of packets. - * - * This function uses getchar_func to read characters from an ASCII - * armored OpenPGP stream and outputs the data as a linked list of - * packets. - */ -int dearmor_openpgp_stream(int (*getchar_func)(void *ctx, unsigned char *c), +int dearmor_openpgp_stream(int (*getchar_func)(void *ctx, size_t count, + void *c), void *ctx, struct openpgp_packet_list **packets) { @@ -336,7 +366,7 @@ int dearmor_openpgp_stream(int (*getchar_func)(void *ctx, unsigned char *c), * with :s in them, then a blank line, then the data. */ state = 1; - while (state != 4 && !getchar_func(ctx, &curchar)) { + while (state != 4 && !getchar_func(ctx, 1, &curchar)) { switch (state) { case 0: if (curchar == '\n') { @@ -350,7 +380,7 @@ int dearmor_openpgp_stream(int (*getchar_func)(void *ctx, unsigned char *c), if (count == 5) { state = 2; } - } else { + } else if (curchar != '\n') { state = 0; } break; @@ -368,19 +398,24 @@ int dearmor_openpgp_stream(int (*getchar_func)(void *ctx, unsigned char *c), if (count == 2) { state = 4; } - } else { + } else if (curchar != '\r') { count = 0; } break; } } - dearmor_init(&dearmor_ctx); - dearmor_ctx.getchar_func = getchar_func; - dearmor_ctx.ctx = ctx; - read_openpgp_stream(dearmor_getchar_c, &dearmor_ctx, packets); - dearmor_finish(&dearmor_ctx); - // TODO: Look for armor footer + if (state == 4) { + dearmor_init(&dearmor_ctx); + dearmor_ctx.getchar_func = getchar_func; + dearmor_ctx.ctx = ctx; + read_openpgp_stream(dearmor_getchar_c, &dearmor_ctx, + packets, 0); + dearmor_finish(&dearmor_ctx); + /* + * TODO: Look for armor footer + */ + } return 0; }