2 * armor.c - Routines to (de)armor OpenPGP packet streams.
4 * Jonathan McDowell <noodles@earth.li>
6 * Copyright 2002 Project Purple
12 #include "keystructs.h"
14 #include "onak-conf.h"
17 #define ARMOR_WIDTH 64
19 #define CRC24_INIT 0xb704ceL
20 #define CRC24_POLY 0x1864cfbL
25 static unsigned char encode64(unsigned char c) {
28 } else if (c >= 26 && c <= 51) {
30 } else if (c >= 52 && c <= 61) {
46 static unsigned char decode64(unsigned char c) {
47 if (c >= 'A' && c <= 'Z') {
49 } else if (c >= 'a' && c <= 'z') {
51 } else if (c >= '0' && c <= '9') {
53 } else if (c == '+') {
55 } else if (c == '/') {
57 } else if (c == '=' || c == '-') {
67 * @lastoctet: The last octet we got.
68 * @curoctet: The current octet we're expecting (0, 1 or 2).
69 * @count: The number of octets we've seen.
70 * @crc24: A running CRC24 of the data we've seen.
71 * @putchar_func: The function to output a character.
72 * @ctx: Context for putchar_func.
74 struct armor_context {
75 unsigned char lastoctet;
79 int (*putchar_func)(void *ctx, size_t count, unsigned char *c);
83 static void armor_init(struct armor_context *ctx)
88 ctx->crc24 = CRC24_INIT;
91 static void armor_finish(struct armor_context *state)
95 switch (state->curoctet++) {
99 c = encode64((state->lastoctet & 3) << 4);
100 state->putchar_func(state->ctx, 1, &c);
101 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
102 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
104 if ((state->count % ARMOR_WIDTH) == 0) {
105 state->putchar_func(state->ctx, 1,
106 (unsigned char *) "\n");
110 c = encode64((state->lastoctet & 0xF) << 2);
111 state->putchar_func(state->ctx, 1, &c);
112 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
114 if ((state->count % ARMOR_WIDTH) == 0) {
115 state->putchar_func(state->ctx, 1,
116 (unsigned char *) "\n");
121 state->crc24 &= 0xffffffL;
122 if ((state->count % ARMOR_WIDTH) != 0) {
123 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
125 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
126 c = encode64(state->crc24 >> 18);
127 state->putchar_func(state->ctx, 1, &c);
128 c = encode64((state->crc24 >> 12) & 0x3F);
129 state->putchar_func(state->ctx, 1, &c);
130 c = encode64((state->crc24 >> 6) & 0x3F);
131 state->putchar_func(state->ctx, 1, &c);
132 c = encode64(state->crc24 & 0x3F);
133 state->putchar_func(state->ctx, 1, &c);
134 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
139 static int armor_putchar_int(void *ctx, unsigned char c)
141 struct armor_context *state;
145 log_assert(ctx != NULL);
146 state = (struct armor_context *) ctx;
148 switch (state->curoctet++) {
150 t = encode64(c >> 2);
151 state->putchar_func(state->ctx, 1, &t);
155 t = encode64(((state->lastoctet & 3) << 4) + (c >> 4));
156 state->putchar_func(state->ctx, 1, &t);
160 t = encode64(((state->lastoctet & 0xF) << 2) + (c >> 6));
161 state->putchar_func(state->ctx, 1, &t);
162 t = encode64(c & 0x3F);
163 state->putchar_func(state->ctx, 1, &t);
167 state->curoctet %= 3;
168 state->lastoctet = c;
170 state->crc24 ^= c << 16;
171 for (i = 0; i < 8; i++) {
173 if (state->crc24 & 0x1000000) {
174 state->crc24 ^= CRC24_POLY;
178 if ((state->count % ARMOR_WIDTH) == 0) {
179 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
186 static int armor_putchar(void *ctx, size_t count, unsigned char *c)
190 for (i = 0; i < count; i++) {
191 armor_putchar_int(ctx, c[i]);
198 * @lastoctet: The last octet we got.
199 * @curoctet: The current octet we're expecting (0, 1 or 2).
200 * @count: The number of octets we've seen.
201 * @crc24: A running CRC24 of the data we've seen.
202 * @putchar_func: The function to output a character.
203 * @ctx: Context for putchar_func.
205 struct dearmor_context {
206 unsigned char lastoctet;
210 int (*getchar_func)(void *ctx, size_t count, unsigned char *c);
214 static void dearmor_init(struct dearmor_context *ctx)
219 ctx->crc24 = CRC24_INIT;
222 static void dearmor_finish(struct dearmor_context *state)
228 state->crc24 &= 0xffffffL;
230 state->putchar_func(state->ctx, '\n');
231 state->putchar_func(state->ctx, '=');
232 state->putchar_func(state->ctx, encode64(state->crc24 >> 18));
233 state->putchar_func(state->ctx, encode64((state->crc24 >> 12) & 0x3F));
234 state->putchar_func(state->ctx, encode64((state->crc24 >> 6) & 0x3F));
235 state->putchar_func(state->ctx, encode64(state->crc24 & 0x3F));
240 static int dearmor_getchar(void *ctx, unsigned char *c)
242 struct dearmor_context *state;
246 log_assert(ctx != NULL);
247 state = (struct dearmor_context *) ctx;
252 state->getchar_func(state->ctx, 1, &tmpc);
253 tmpc = decode64(tmpc);
257 switch (state->curoctet++) {
259 state->lastoctet = tmpc;
262 state->getchar_func(state->ctx, 1, &tmpc);
263 tmpc = decode64(tmpc);
265 *c = (state->lastoctet << 2) + (tmpc >> 4);
268 *c = ((state->lastoctet & 0xF) << 4) + (tmpc >> 2);
271 *c = ((state->lastoctet & 3) << 6) + tmpc;
275 state->curoctet %= 3;
276 state->lastoctet = tmpc;
279 state->crc24 ^= *c << 16;
280 for (i = 0; i < 8; i++) {
282 if (state->crc24 & 0x1000000) {
283 state->crc24 ^= CRC24_POLY;
291 static int dearmor_getchar_c(void *ctx, size_t count, unsigned char *c)
295 for (i = 0; i < count && rc == 0; i++) {
296 rc = dearmor_getchar(ctx, &c[i]);
303 * armor_openpgp_stream - Takes a list of OpenPGP packets and armors it.
304 * @putchar_func: The function to output the next armor character.
305 * @ctx: The context pointer for putchar_func.
306 * @packets: The list of packets to output.
308 * This function ASCII armors a list of OpenPGP packets and outputs it
309 * using putchar_func.
311 int armor_openpgp_stream(int (*putchar_func)(void *ctx, size_t count,
314 struct openpgp_packet_list *packets)
316 struct armor_context armor_ctx;
321 putchar_func(ctx, sizeof("-----BEGIN PGP PUBLIC KEY BLOCK-----\n") - 1,
322 (unsigned char *) "-----BEGIN PGP PUBLIC KEY BLOCK-----\n");
323 putchar_func(ctx, sizeof("Version: onak " VERSION "\n\n") - 1,
324 (unsigned char *) "Version: onak " VERSION "\n\n");
326 armor_init(&armor_ctx);
327 armor_ctx.putchar_func = putchar_func;
329 write_openpgp_stream(armor_putchar, &armor_ctx, packets);
330 armor_finish(&armor_ctx);
335 putchar_func(ctx, sizeof("-----END PGP PUBLIC KEY BLOCK-----\n") - 1,
336 (unsigned char *) "-----END PGP PUBLIC KEY BLOCK-----\n");
342 * dearmor_openpgp_stream - Reads & decodes an ACSII armored OpenPGP msg.
343 * @getchar_func: The function to get the next character from the stream.
344 * @ctx: The context pointer for getchar_func.
345 * @packets: The list of packets.
347 * This function uses getchar_func to read characters from an ASCII
348 * armored OpenPGP stream and outputs the data as a linked list of
351 int dearmor_openpgp_stream(int (*getchar_func)(void *ctx, size_t count,
354 struct openpgp_packet_list **packets)
356 struct dearmor_context dearmor_ctx;
357 unsigned char curchar;
362 * Look for armor header. We want "-----BEGIN.*\n", then some headers
363 * with :s in them, then a blank line, then the data.
366 while (state != 4 && !getchar_func(ctx, 1, &curchar)) {
369 if (curchar == '\n') {
375 if (curchar == '-') {
380 } else if (curchar != '\n') {
385 if (curchar == 'B') {
393 if (curchar == '\n') {
398 } else if (curchar != '\r') {
406 dearmor_init(&dearmor_ctx);
407 dearmor_ctx.getchar_func = getchar_func;
408 dearmor_ctx.ctx = ctx;
409 read_openpgp_stream(dearmor_getchar_c, &dearmor_ctx,
411 dearmor_finish(&dearmor_ctx);
413 * TODO: Look for armor footer