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"
18 #define ARMOR_WIDTH 64
20 #define CRC24_INIT 0xb704ceL
21 #define CRC24_POLY 0x1864cfbL
26 static unsigned char encode64(unsigned char c) {
29 } else if (c >= 26 && c <= 51) {
31 } else if (c >= 52 && c <= 61) {
47 static unsigned char decode64(unsigned char c) {
48 if (c >= 'A' && c <= 'Z') {
50 } else if (c >= 'a' && c <= 'z') {
52 } else if (c >= '0' && c <= '9') {
54 } else if (c == '+') {
56 } else if (c == '/') {
58 } else if (c == '=' || c == '-') {
68 * @lastoctet: The last octet we got.
69 * @curoctet: The current octet we're expecting (0, 1 or 2).
70 * @count: The number of octets we've seen.
71 * @crc24: A running CRC24 of the data we've seen.
72 * @putchar_func: The function to output a character.
73 * @ctx: Context for putchar_func.
75 struct armor_context {
76 unsigned char lastoctet;
80 int (*putchar_func)(void *ctx, size_t count, void *c);
84 static void armor_init(struct armor_context *ctx)
89 ctx->crc24 = CRC24_INIT;
92 static void armor_finish(struct armor_context *state)
96 switch (state->curoctet++) {
100 c = encode64((state->lastoctet & 3) << 4);
101 state->putchar_func(state->ctx, 1, &c);
102 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
103 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
105 if ((state->count % ARMOR_WIDTH) == 0) {
106 state->putchar_func(state->ctx, 1,
107 (unsigned char *) "\n");
111 c = encode64((state->lastoctet & 0xF) << 2);
112 state->putchar_func(state->ctx, 1, &c);
113 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
115 if ((state->count % ARMOR_WIDTH) == 0) {
116 state->putchar_func(state->ctx, 1,
117 (unsigned char *) "\n");
122 state->crc24 &= 0xffffffL;
123 if ((state->count % ARMOR_WIDTH) != 0) {
124 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
126 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
127 c = encode64(state->crc24 >> 18);
128 state->putchar_func(state->ctx, 1, &c);
129 c = encode64((state->crc24 >> 12) & 0x3F);
130 state->putchar_func(state->ctx, 1, &c);
131 c = encode64((state->crc24 >> 6) & 0x3F);
132 state->putchar_func(state->ctx, 1, &c);
133 c = encode64(state->crc24 & 0x3F);
134 state->putchar_func(state->ctx, 1, &c);
135 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
140 static int armor_putchar_int(void *ctx, unsigned char c)
142 struct armor_context *state;
146 log_assert(ctx != NULL);
147 state = (struct armor_context *) ctx;
149 switch (state->curoctet++) {
151 t = encode64(c >> 2);
152 state->putchar_func(state->ctx, 1, &t);
156 t = encode64(((state->lastoctet & 3) << 4) + (c >> 4));
157 state->putchar_func(state->ctx, 1, &t);
161 t = encode64(((state->lastoctet & 0xF) << 2) + (c >> 6));
162 state->putchar_func(state->ctx, 1, &t);
163 t = encode64(c & 0x3F);
164 state->putchar_func(state->ctx, 1, &t);
168 state->curoctet %= 3;
169 state->lastoctet = c;
171 state->crc24 ^= c << 16;
172 for (i = 0; i < 8; i++) {
174 if (state->crc24 & 0x1000000) {
175 state->crc24 ^= CRC24_POLY;
179 if ((state->count % ARMOR_WIDTH) == 0) {
180 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
187 static int armor_putchar(void *ctx, size_t count, void *c)
191 log_assert(c != NULL);
193 for (i = 0; i < count; i++) {
194 armor_putchar_int(ctx, ((char *) c)[i]);
201 * @lastoctet: The last octet we got.
202 * @curoctet: The current octet we're expecting (0, 1 or 2).
203 * @count: The number of octets we've seen.
204 * @crc24: A running CRC24 of the data we've seen.
205 * @putchar_func: The function to output a character.
206 * @ctx: Context for putchar_func.
208 struct dearmor_context {
209 unsigned char lastoctet;
213 int (*getchar_func)(void *ctx, size_t count, void *c);
217 static void dearmor_init(struct dearmor_context *ctx)
222 ctx->crc24 = CRC24_INIT;
225 static void dearmor_finish(struct dearmor_context *state)
231 state->crc24 &= 0xffffffL;
233 state->putchar_func(state->ctx, '\n');
234 state->putchar_func(state->ctx, '=');
235 state->putchar_func(state->ctx, encode64(state->crc24 >> 18));
236 state->putchar_func(state->ctx, encode64((state->crc24 >> 12) & 0x3F));
237 state->putchar_func(state->ctx, encode64((state->crc24 >> 6) & 0x3F));
238 state->putchar_func(state->ctx, encode64(state->crc24 & 0x3F));
243 static int dearmor_getchar(void *ctx, unsigned char *c)
245 struct dearmor_context *state;
249 log_assert(ctx != NULL);
250 state = (struct dearmor_context *) ctx;
255 state->getchar_func(state->ctx, 1, &tmpc);
256 tmpc = decode64(tmpc);
260 switch (state->curoctet++) {
262 state->lastoctet = tmpc;
265 state->getchar_func(state->ctx, 1, &tmpc);
266 tmpc = decode64(tmpc);
268 *c = (state->lastoctet << 2) + (tmpc >> 4);
271 *c = ((state->lastoctet & 0xF) << 4) + (tmpc >> 2);
274 *c = ((state->lastoctet & 3) << 6) + tmpc;
278 state->curoctet %= 3;
279 state->lastoctet = tmpc;
282 state->crc24 ^= *c << 16;
283 for (i = 0; i < 8; i++) {
285 if (state->crc24 & 0x1000000) {
286 state->crc24 ^= CRC24_POLY;
294 static int dearmor_getchar_c(void *ctx, size_t count, void *c)
298 for (i = 0; i < count && rc == 0; i++) {
299 rc = dearmor_getchar(ctx, &((unsigned char *) c)[i]);
306 * armor_openpgp_stream - Takes a list of OpenPGP packets and armors it.
307 * @putchar_func: The function to output the next armor character.
308 * @ctx: The context pointer for putchar_func.
309 * @packets: The list of packets to output.
311 * This function ASCII armors a list of OpenPGP packets and outputs it
312 * using putchar_func.
314 int armor_openpgp_stream(int (*putchar_func)(void *ctx, size_t count,
317 struct openpgp_packet_list *packets)
319 struct armor_context armor_ctx;
324 putchar_func(ctx, sizeof("-----BEGIN PGP PUBLIC KEY BLOCK-----\n") - 1,
325 (unsigned char *) "-----BEGIN PGP PUBLIC KEY BLOCK-----\n");
326 putchar_func(ctx, sizeof("Version: onak " ONAK_VERSION "\n\n") - 1,
327 (unsigned char *) "Version: onak " ONAK_VERSION "\n\n");
329 armor_init(&armor_ctx);
330 armor_ctx.putchar_func = putchar_func;
332 write_openpgp_stream(armor_putchar, &armor_ctx, packets);
333 armor_finish(&armor_ctx);
338 putchar_func(ctx, sizeof("-----END PGP PUBLIC KEY BLOCK-----\n") - 1,
339 (unsigned char *) "-----END PGP PUBLIC KEY BLOCK-----\n");
345 * dearmor_openpgp_stream - Reads & decodes an ACSII armored OpenPGP msg.
346 * @getchar_func: The function to get the next character from the stream.
347 * @ctx: The context pointer for getchar_func.
348 * @packets: The list of packets.
350 * This function uses getchar_func to read characters from an ASCII
351 * armored OpenPGP stream and outputs the data as a linked list of
354 int dearmor_openpgp_stream(int (*getchar_func)(void *ctx, size_t count,
357 struct openpgp_packet_list **packets)
359 struct dearmor_context dearmor_ctx;
360 unsigned char curchar;
365 * Look for armor header. We want "-----BEGIN.*\n", then some headers
366 * with :s in them, then a blank line, then the data.
369 while (state != 4 && !getchar_func(ctx, 1, &curchar)) {
372 if (curchar == '\n') {
378 if (curchar == '-') {
383 } else if (curchar != '\n') {
388 if (curchar == 'B') {
396 if (curchar == '\n') {
401 } else if (curchar != '\r') {
409 dearmor_init(&dearmor_ctx);
410 dearmor_ctx.getchar_func = getchar_func;
411 dearmor_ctx.ctx = ctx;
412 read_openpgp_stream(dearmor_getchar_c, &dearmor_ctx,
414 dearmor_finish(&dearmor_ctx);
416 * TODO: Look for armor footer