2 * armor.c - Routines to (de)armor OpenPGP packet streams.
4 * Copyright 2002-2004, 2011 Jonathan McDowell <noodles@earth.li>
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 51
17 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 #include "keystructs.h"
25 #include "onak-conf.h"
29 #define ARMOR_WIDTH 64
31 #define CRC24_INIT 0xb704ceL
32 #define CRC24_POLY 0x1864cfbL
37 static unsigned char encode64(unsigned char c) {
40 } else if (c >= 26 && c <= 51) {
42 } else if (c >= 52 && c <= 61) {
58 static unsigned char decode64(unsigned char c) {
59 if (c >= 'A' && c <= 'Z') {
61 } else if (c >= 'a' && c <= 'z') {
63 } else if (c >= '0' && c <= '9') {
65 } else if (c == '+') {
67 } else if (c == '/') {
69 } else if (c == '=' || c == '-') {
79 * @lastoctet: The last octet we got.
80 * @curoctet: The current octet we're expecting (0, 1 or 2).
81 * @count: The number of octets we've seen.
82 * @crc24: A running CRC24 of the data we've seen.
83 * @putchar_func: The function to output a character.
84 * @ctx: Context for putchar_func.
86 struct armor_context {
87 unsigned char lastoctet;
91 int (*putchar_func)(void *ctx, size_t count, void *c);
95 static void armor_init(struct armor_context *ctx)
100 ctx->crc24 = CRC24_INIT;
103 static void armor_finish(struct armor_context *state)
107 switch (state->curoctet++) {
111 c = encode64((state->lastoctet & 3) << 4);
112 state->putchar_func(state->ctx, 1, &c);
113 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
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");
122 c = encode64((state->lastoctet & 0xF) << 2);
123 state->putchar_func(state->ctx, 1, &c);
124 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
126 if ((state->count % ARMOR_WIDTH) == 0) {
127 state->putchar_func(state->ctx, 1,
128 (unsigned char *) "\n");
133 state->crc24 &= 0xffffffL;
134 if ((state->count % ARMOR_WIDTH) != 0) {
135 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
137 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
138 c = encode64(state->crc24 >> 18);
139 state->putchar_func(state->ctx, 1, &c);
140 c = encode64((state->crc24 >> 12) & 0x3F);
141 state->putchar_func(state->ctx, 1, &c);
142 c = encode64((state->crc24 >> 6) & 0x3F);
143 state->putchar_func(state->ctx, 1, &c);
144 c = encode64(state->crc24 & 0x3F);
145 state->putchar_func(state->ctx, 1, &c);
146 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
151 static int armor_putchar_int(void *ctx, unsigned char c)
153 struct armor_context *state;
157 log_assert(ctx != NULL);
158 state = (struct armor_context *) ctx;
160 switch (state->curoctet++) {
162 t = encode64(c >> 2);
163 state->putchar_func(state->ctx, 1, &t);
167 t = encode64(((state->lastoctet & 3) << 4) + (c >> 4));
168 state->putchar_func(state->ctx, 1, &t);
172 t = encode64(((state->lastoctet & 0xF) << 2) + (c >> 6));
173 state->putchar_func(state->ctx, 1, &t);
174 t = encode64(c & 0x3F);
175 state->putchar_func(state->ctx, 1, &t);
179 state->curoctet %= 3;
180 state->lastoctet = c;
182 state->crc24 ^= c << 16;
183 for (i = 0; i < 8; i++) {
185 if (state->crc24 & 0x1000000) {
186 state->crc24 ^= CRC24_POLY;
190 if ((state->count % ARMOR_WIDTH) == 0) {
191 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
198 static int armor_putchar(void *ctx, size_t count, void *c)
202 log_assert(c != NULL);
204 for (i = 0; i < count; i++) {
205 armor_putchar_int(ctx, ((char *) c)[i]);
212 * @lastoctet: The last octet we got.
213 * @curoctet: The current octet we're expecting (0, 1 or 2).
214 * @count: The number of octets we've seen.
215 * @crc24: A running CRC24 of the data we've seen.
216 * @putchar_func: The function to output a character.
217 * @ctx: Context for putchar_func.
219 struct dearmor_context {
220 unsigned char lastoctet;
224 int (*getchar_func)(void *ctx, size_t count, void *c);
228 static void dearmor_init(struct dearmor_context *ctx)
233 ctx->crc24 = CRC24_INIT;
236 static void dearmor_finish(struct dearmor_context *state)
242 state->crc24 &= 0xffffffL;
244 state->putchar_func(state->ctx, '\n');
245 state->putchar_func(state->ctx, '=');
246 state->putchar_func(state->ctx, encode64(state->crc24 >> 18));
247 state->putchar_func(state->ctx, encode64((state->crc24 >> 12) & 0x3F));
248 state->putchar_func(state->ctx, encode64((state->crc24 >> 6) & 0x3F));
249 state->putchar_func(state->ctx, encode64(state->crc24 & 0x3F));
254 static int dearmor_getchar(void *ctx, unsigned char *c)
256 struct dearmor_context *state;
260 log_assert(ctx != NULL);
261 state = (struct dearmor_context *) ctx;
266 state->getchar_func(state->ctx, 1, &tmpc);
267 tmpc = decode64(tmpc);
271 switch (state->curoctet++) {
273 state->lastoctet = tmpc;
276 state->getchar_func(state->ctx, 1, &tmpc);
277 tmpc = decode64(tmpc);
279 *c = (state->lastoctet << 2) + (tmpc >> 4);
282 *c = ((state->lastoctet & 0xF) << 4) + (tmpc >> 2);
285 *c = ((state->lastoctet & 3) << 6) + tmpc;
289 state->curoctet %= 3;
290 state->lastoctet = tmpc;
293 state->crc24 ^= *c << 16;
294 for (i = 0; i < 8; i++) {
296 if (state->crc24 & 0x1000000) {
297 state->crc24 ^= CRC24_POLY;
305 static int dearmor_getchar_c(void *ctx, size_t count, void *c)
309 for (i = 0; i < count && rc == 0; i++) {
310 rc = dearmor_getchar(ctx, &((unsigned char *) c)[i]);
317 * armor_openpgp_stream - Takes a list of OpenPGP packets and armors it.
318 * @putchar_func: The function to output the next armor character.
319 * @ctx: The context pointer for putchar_func.
320 * @packets: The list of packets to output.
322 * This function ASCII armors a list of OpenPGP packets and outputs it
323 * using putchar_func.
325 int armor_openpgp_stream(int (*putchar_func)(void *ctx, size_t count,
328 struct openpgp_packet_list *packets)
330 struct armor_context armor_ctx;
335 putchar_func(ctx, sizeof("-----BEGIN PGP PUBLIC KEY BLOCK-----\n") - 1,
336 (unsigned char *) "-----BEGIN PGP PUBLIC KEY BLOCK-----\n");
337 putchar_func(ctx, sizeof("Version: onak " ONAK_VERSION "\n\n") - 1,
338 (unsigned char *) "Version: onak " ONAK_VERSION "\n\n");
340 armor_init(&armor_ctx);
341 armor_ctx.putchar_func = putchar_func;
343 write_openpgp_stream(armor_putchar, &armor_ctx, packets);
344 armor_finish(&armor_ctx);
349 putchar_func(ctx, sizeof("-----END PGP PUBLIC KEY BLOCK-----\n") - 1,
350 (unsigned char *) "-----END PGP PUBLIC KEY BLOCK-----\n");
356 * dearmor_openpgp_stream - Reads & decodes an ACSII armored OpenPGP msg.
357 * @getchar_func: The function to get the next character from the stream.
358 * @ctx: The context pointer for getchar_func.
359 * @packets: The list of packets.
361 * This function uses getchar_func to read characters from an ASCII
362 * armored OpenPGP stream and outputs the data as a linked list of
365 int dearmor_openpgp_stream(int (*getchar_func)(void *ctx, size_t count,
368 struct openpgp_packet_list **packets)
370 struct dearmor_context dearmor_ctx;
371 unsigned char curchar;
376 * Look for armor header. We want "-----BEGIN.*\n", then some headers
377 * with :s in them, then a blank line, then the data.
380 while (state != 4 && !getchar_func(ctx, 1, &curchar)) {
383 if (curchar == '\n') {
389 if (curchar == '-') {
394 } else if (curchar != '\n') {
399 if (curchar == 'B') {
407 if (curchar == '\n') {
412 } else if (curchar != '\r') {
420 dearmor_init(&dearmor_ctx);
421 dearmor_ctx.getchar_func = getchar_func;
422 dearmor_ctx.ctx = ctx;
423 read_openpgp_stream(dearmor_getchar_c, &dearmor_ctx,
425 dearmor_finish(&dearmor_ctx);
427 * TODO: Look for armor footer