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.5 2003/06/04 20:57:06 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 *) "=");
107 c = encode64((state->lastoctet & 0xF) << 2);
108 state->putchar_func(state->ctx, 1, &c);
109 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
113 state->crc24 &= 0xffffffL;
114 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
115 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
116 c = encode64(state->crc24 >> 18);
117 state->putchar_func(state->ctx, 1, &c);
118 c = encode64((state->crc24 >> 12) & 0x3F);
119 state->putchar_func(state->ctx, 1, &c);
120 c = encode64((state->crc24 >> 6) & 0x3F);
121 state->putchar_func(state->ctx, 1, &c);
122 c = encode64(state->crc24 & 0x3F);
123 state->putchar_func(state->ctx, 1, &c);
124 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
129 static int armor_putchar_int(void *ctx, unsigned char c)
131 struct armor_context *state;
136 state = (struct armor_context *) ctx;
138 switch (state->curoctet++) {
140 t = encode64(c >> 2);
141 state->putchar_func(state->ctx, 1, &t);
145 t = encode64(((state->lastoctet & 3) << 4) + (c >> 4));
146 state->putchar_func(state->ctx, 1, &t);
150 t = encode64(((state->lastoctet & 0xF) << 2) + (c >> 6));
151 state->putchar_func(state->ctx, 1, &t);
152 t = encode64(c & 0x3F);
153 state->putchar_func(state->ctx, 1, &t);
157 state->curoctet %= 3;
158 state->lastoctet = c;
160 state->crc24 ^= c << 16;
161 for (i = 0; i < 8; i++) {
163 if (state->crc24 & 0x1000000) {
164 state->crc24 ^= CRC24_POLY;
168 if ((state->count % ARMOR_WIDTH) == 0) {
169 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
176 static int armor_putchar(void *ctx, size_t count, unsigned char *c)
180 for (i = 0; i < count; i++) {
181 armor_putchar_int(ctx, c[i]);
188 * @lastoctet: The last octet we got.
189 * @curoctet: The current octet we're expecting (0, 1 or 2).
190 * @count: The number of octets we've seen.
191 * @crc24: A running CRC24 of the data we've seen.
192 * @putchar_func: The function to output a character.
193 * @ctx: Context for putchar_func.
195 struct dearmor_context {
196 unsigned char lastoctet;
200 int (*getchar_func)(void *ctx, size_t count, unsigned char *c);
204 static void dearmor_init(struct dearmor_context *ctx)
209 ctx->crc24 = CRC24_INIT;
212 static void dearmor_finish(struct dearmor_context *state)
214 // Check the checksum,
216 state->crc24 &= 0xffffffL;
217 // state->putchar_func(state->ctx, '\n');
218 // state->putchar_func(state->ctx, '=');
219 // state->putchar_func(state->ctx, encode64(state->crc24 >> 18));
220 // state->putchar_func(state->ctx, encode64((state->crc24 >> 12) & 0x3F));
221 // state->putchar_func(state->ctx, encode64((state->crc24 >> 6) & 0x3F));
222 // state->putchar_func(state->ctx, encode64(state->crc24 & 0x3F));
227 static int dearmor_getchar(void *ctx, unsigned char *c)
229 struct dearmor_context *state;
234 state = (struct dearmor_context *) ctx;
239 state->getchar_func(state->ctx, 1, &tmpc);
240 tmpc = decode64(tmpc);
244 switch (state->curoctet++) {
246 state->lastoctet = tmpc;
249 state->getchar_func(state->ctx, 1, &tmpc);
250 tmpc = decode64(tmpc);
252 *c = (state->lastoctet << 2) + (tmpc >> 4);
255 *c = ((state->lastoctet & 0xF) << 4) + (tmpc >> 2);
258 *c = ((state->lastoctet & 3) << 6) + tmpc;
262 state->curoctet %= 3;
263 state->lastoctet = tmpc;
266 state->crc24 ^= *c << 16;
267 for (i = 0; i < 8; i++) {
269 if (state->crc24 & 0x1000000) {
270 state->crc24 ^= CRC24_POLY;
278 static int dearmor_getchar_c(void *ctx, size_t count, unsigned char *c)
282 for (i = 0; i < count && rc == 0; i++) {
283 rc = dearmor_getchar(ctx, &c[i]);
290 * armor_openpgp_stream - Takes a list of OpenPGP packets and armors it.
291 * @putchar_func: The function to output the next armor character.
292 * @ctx: The context pointer for putchar_func.
293 * @packets: The list of packets to output.
295 * This function ASCII armors a list of OpenPGP packets and outputs it
296 * using putchar_func.
298 int armor_openpgp_stream(int (*putchar_func)(void *ctx, size_t count,
301 struct openpgp_packet_list *packets)
303 struct armor_context armor_ctx;
308 putchar_func(ctx, sizeof("-----BEGIN PGP PUBLIC KEY BLOCK-----\n") - 1,
309 (unsigned char *) "-----BEGIN PGP PUBLIC KEY BLOCK-----\n");
310 putchar_func(ctx, sizeof("Version: onak " VERSION "\n\n") - 1,
311 (unsigned char *) "Version: onak " VERSION "\n\n");
313 armor_init(&armor_ctx);
314 armor_ctx.putchar_func = putchar_func;
316 write_openpgp_stream(armor_putchar, &armor_ctx, packets);
317 armor_finish(&armor_ctx);
322 putchar_func(ctx, sizeof("-----END PGP PUBLIC KEY BLOCK-----\n") - 1,
323 (unsigned char *) "-----END PGP PUBLIC KEY BLOCK-----\n");
329 * dearmor_openpgp_stream - Reads & decodes an ACSII armored OpenPGP msg.
330 * @getchar_func: The function to get the next character from the stream.
331 * @ctx: The context pointer for getchar_func.
332 * @packets: The list of packets.
334 * This function uses getchar_func to read characters from an ASCII
335 * armored OpenPGP stream and outputs the data as a linked list of
338 int dearmor_openpgp_stream(int (*getchar_func)(void *ctx, size_t count,
341 struct openpgp_packet_list **packets)
343 struct dearmor_context dearmor_ctx;
344 unsigned char curchar;
349 * Look for armor header. We want "-----BEGIN.*\n", then some headers
350 * with :s in them, then a blank line, then the data.
353 while (state != 4 && !getchar_func(ctx, 1, &curchar)) {
356 if (curchar == '\n') {
362 if (curchar == '-') {
367 } else if (curchar != '\n') {
372 if (curchar == 'B') {
380 if (curchar == '\n') {
385 } else if (curchar != '\r') {
393 dearmor_init(&dearmor_ctx);
394 dearmor_ctx.getchar_func = getchar_func;
395 dearmor_ctx.ctx = ctx;
396 read_openpgp_stream(dearmor_getchar_c, &dearmor_ctx, packets);
397 dearmor_finish(&dearmor_ctx);
398 // TODO: Look for armor footer