3 * @brief Routines to (de)armor OpenPGP packet streams.
5 * Copyright 2002-2004, 2011 Jonathan McDowell <noodles@earth.li>
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; version 2 of the License.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 51
18 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 #include "keystructs.h"
26 #include "onak-conf.h"
31 * @brief Line length we'll use for armored output
33 #define ARMOR_WIDTH 64
36 * @brief CRC24 initialisation value
38 #define CRC24_INIT 0xb704ceL
40 * @brief CRC24 polynomial value
42 #define CRC24_POLY 0x1864cfbL
47 static unsigned char encode64(unsigned char c) {
50 } else if (c >= 26 && c <= 51) {
52 } else if (c >= 52 && c <= 61) {
68 static unsigned char decode64(unsigned char c) {
69 if (c >= 'A' && c <= 'Z') {
71 } else if (c >= 'a' && c <= 'z') {
73 } else if (c >= '0' && c <= '9') {
75 } else if (c == '+') {
77 } else if (c == '/') {
79 } else if (c == '=' || c == '-') {
89 * @brief Holds the context of an ongoing ASCII armor operation
91 struct armor_context {
92 /** The last octet we got. */
93 unsigned char lastoctet;
94 /** The current octet we're expecting (0, 1 or 2). */
96 /** The number of octets we've seen. */
98 /** A running CRC24 of the data we've seen. */
100 /** The function to output a character. */
101 int (*putchar_func)(void *ctx, size_t count, void *c);
102 /** Context for putchar_func. */
106 static void armor_init(struct armor_context *ctx)
111 ctx->crc24 = CRC24_INIT;
114 static void armor_finish(struct armor_context *state)
118 switch (state->curoctet++) {
122 c = encode64((state->lastoctet & 3) << 4);
123 state->putchar_func(state->ctx, 1, &c);
124 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
125 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
127 if ((state->count % ARMOR_WIDTH) == 0) {
128 state->putchar_func(state->ctx, 1,
129 (unsigned char *) "\n");
133 c = encode64((state->lastoctet & 0xF) << 2);
134 state->putchar_func(state->ctx, 1, &c);
135 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
137 if ((state->count % ARMOR_WIDTH) == 0) {
138 state->putchar_func(state->ctx, 1,
139 (unsigned char *) "\n");
144 state->crc24 &= 0xffffffL;
145 if ((state->count % ARMOR_WIDTH) != 0) {
146 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
148 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
149 c = encode64(state->crc24 >> 18);
150 state->putchar_func(state->ctx, 1, &c);
151 c = encode64((state->crc24 >> 12) & 0x3F);
152 state->putchar_func(state->ctx, 1, &c);
153 c = encode64((state->crc24 >> 6) & 0x3F);
154 state->putchar_func(state->ctx, 1, &c);
155 c = encode64(state->crc24 & 0x3F);
156 state->putchar_func(state->ctx, 1, &c);
157 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
162 static int armor_putchar_int(void *ctx, unsigned char c)
164 struct armor_context *state;
168 log_assert(ctx != NULL);
169 state = (struct armor_context *) ctx;
171 switch (state->curoctet++) {
173 t = encode64(c >> 2);
174 state->putchar_func(state->ctx, 1, &t);
178 t = encode64(((state->lastoctet & 3) << 4) + (c >> 4));
179 state->putchar_func(state->ctx, 1, &t);
183 t = encode64(((state->lastoctet & 0xF) << 2) + (c >> 6));
184 state->putchar_func(state->ctx, 1, &t);
185 t = encode64(c & 0x3F);
186 state->putchar_func(state->ctx, 1, &t);
190 state->curoctet %= 3;
191 state->lastoctet = c;
193 state->crc24 ^= c << 16;
194 for (i = 0; i < 8; i++) {
196 if (state->crc24 & 0x1000000) {
197 state->crc24 ^= CRC24_POLY;
201 if ((state->count % ARMOR_WIDTH) == 0) {
202 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
209 static int armor_putchar(void *ctx, size_t count, void *c)
213 log_assert(c != NULL);
215 for (i = 0; i < count; i++) {
216 armor_putchar_int(ctx, ((char *) c)[i]);
223 * @brief Holds the context of an ongoing ASCII dearmor operation
225 struct dearmor_context {
226 /** The last octet we got. */
227 unsigned char lastoctet;
228 /** The current octet we're expecting (0, 1 or 2). */
230 /** The number of octets we've seen. */
232 /** A running CRC24 of the data we've seen. */
234 /** The function to get the next character. */
235 int (*getchar_func)(void *ctx, size_t count, void *c);
236 /** Context for getchar_func. */
240 static void dearmor_init(struct dearmor_context *ctx)
245 ctx->crc24 = CRC24_INIT;
248 static void dearmor_finish(struct dearmor_context *state)
254 state->crc24 &= 0xffffffL;
256 state->putchar_func(state->ctx, '\n');
257 state->putchar_func(state->ctx, '=');
258 state->putchar_func(state->ctx, encode64(state->crc24 >> 18));
259 state->putchar_func(state->ctx, encode64((state->crc24 >> 12) & 0x3F));
260 state->putchar_func(state->ctx, encode64((state->crc24 >> 6) & 0x3F));
261 state->putchar_func(state->ctx, encode64(state->crc24 & 0x3F));
266 static int dearmor_getchar(void *ctx, unsigned char *c)
268 struct dearmor_context *state;
272 log_assert(ctx != NULL);
273 state = (struct dearmor_context *) ctx;
278 state->getchar_func(state->ctx, 1, &tmpc);
279 tmpc = decode64(tmpc);
283 switch (state->curoctet++) {
285 state->lastoctet = tmpc;
288 state->getchar_func(state->ctx, 1, &tmpc);
289 tmpc = decode64(tmpc);
291 *c = (state->lastoctet << 2) + (tmpc >> 4);
294 *c = ((state->lastoctet & 0xF) << 4) + (tmpc >> 2);
297 *c = ((state->lastoctet & 3) << 6) + tmpc;
301 state->curoctet %= 3;
302 state->lastoctet = tmpc;
305 state->crc24 ^= *c << 16;
306 for (i = 0; i < 8; i++) {
308 if (state->crc24 & 0x1000000) {
309 state->crc24 ^= CRC24_POLY;
317 static int dearmor_getchar_c(void *ctx, size_t count, void *c)
321 for (i = 0; i < count && rc == 0; i++) {
322 rc = dearmor_getchar(ctx, &((unsigned char *) c)[i]);
328 int armor_openpgp_stream(int (*putchar_func)(void *ctx, size_t count,
331 struct openpgp_packet_list *packets)
333 struct armor_context armor_ctx;
338 putchar_func(ctx, sizeof("-----BEGIN PGP PUBLIC KEY BLOCK-----\n") - 1,
339 (unsigned char *) "-----BEGIN PGP PUBLIC KEY BLOCK-----\n");
340 putchar_func(ctx, sizeof("Version: onak " ONAK_VERSION "\n\n") - 1,
341 (unsigned char *) "Version: onak " ONAK_VERSION "\n\n");
343 armor_init(&armor_ctx);
344 armor_ctx.putchar_func = putchar_func;
346 write_openpgp_stream(armor_putchar, &armor_ctx, packets);
347 armor_finish(&armor_ctx);
352 putchar_func(ctx, sizeof("-----END PGP PUBLIC KEY BLOCK-----\n") - 1,
353 (unsigned char *) "-----END PGP PUBLIC KEY BLOCK-----\n");
358 int dearmor_openpgp_stream(int (*getchar_func)(void *ctx, size_t count,
361 struct openpgp_packet_list **packets)
363 struct dearmor_context dearmor_ctx;
364 unsigned char curchar;
369 * Look for armor header. We want "-----BEGIN.*\n", then some headers
370 * with :s in them, then a blank line, then the data.
373 while (state != 4 && !getchar_func(ctx, 1, &curchar)) {
376 if (curchar == '\n') {
382 if (curchar == '-') {
387 } else if (curchar != '\n') {
392 if (curchar == 'B') {
400 if (curchar == '\n') {
405 } else if (curchar != '\r') {
413 dearmor_init(&dearmor_ctx);
414 dearmor_ctx.getchar_func = getchar_func;
415 dearmor_ctx.ctx = ctx;
416 read_openpgp_stream(dearmor_getchar_c, &dearmor_ctx,
418 dearmor_finish(&dearmor_ctx);
420 * TODO: Look for armor footer