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"
25 #include "onak-conf.h"
30 * @brief Line length we'll use for armored output
32 #define ARMOR_WIDTH 64
35 * @brief CRC24 initialisation value
37 #define CRC24_INIT 0xb704ceL
39 * @brief CRC24 polynomial value
41 #define CRC24_POLY 0x1864cfbL
46 static unsigned char encode64(unsigned char c) {
49 } else if (c >= 26 && c <= 51) {
51 } else if (c >= 52 && c <= 61) {
67 static unsigned char decode64(unsigned char c) {
68 if (c >= 'A' && c <= 'Z') {
70 } else if (c >= 'a' && c <= 'z') {
72 } else if (c >= '0' && c <= '9') {
74 } else if (c == '+') {
76 } else if (c == '/') {
78 } else if (c == '=' || c == '-') {
88 * @brief Holds the context of an ongoing ASCII armor operation
90 struct armor_context {
91 /** The last octet we got. */
92 unsigned char lastoctet;
93 /** The current octet we're expecting (0, 1 or 2). */
95 /** The number of octets we've seen. */
97 /** A running CRC24 of the data we've seen. */
99 /** The function to output a character. */
100 int (*putchar_func)(void *ctx, size_t count, void *c);
101 /** Context for putchar_func. */
105 static void armor_init(struct armor_context *ctx)
110 ctx->crc24 = CRC24_INIT;
113 static void armor_finish(struct armor_context *state)
117 switch (state->curoctet++) {
121 c = encode64((state->lastoctet & 3) << 4);
122 state->putchar_func(state->ctx, 1, &c);
123 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
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");
132 c = encode64((state->lastoctet & 0xF) << 2);
133 state->putchar_func(state->ctx, 1, &c);
134 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
136 if ((state->count % ARMOR_WIDTH) == 0) {
137 state->putchar_func(state->ctx, 1,
138 (unsigned char *) "\n");
143 state->crc24 &= 0xffffffL;
144 if ((state->count % ARMOR_WIDTH) != 0) {
145 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
147 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
148 c = encode64(state->crc24 >> 18);
149 state->putchar_func(state->ctx, 1, &c);
150 c = encode64((state->crc24 >> 12) & 0x3F);
151 state->putchar_func(state->ctx, 1, &c);
152 c = encode64((state->crc24 >> 6) & 0x3F);
153 state->putchar_func(state->ctx, 1, &c);
154 c = encode64(state->crc24 & 0x3F);
155 state->putchar_func(state->ctx, 1, &c);
156 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
161 static int armor_putchar_int(void *ctx, unsigned char c)
163 struct armor_context *state;
167 state = (struct armor_context *) ctx;
169 switch (state->curoctet++) {
171 t = encode64(c >> 2);
172 state->putchar_func(state->ctx, 1, &t);
176 t = encode64(((state->lastoctet & 3) << 4) + (c >> 4));
177 state->putchar_func(state->ctx, 1, &t);
181 t = encode64(((state->lastoctet & 0xF) << 2) + (c >> 6));
182 state->putchar_func(state->ctx, 1, &t);
183 t = encode64(c & 0x3F);
184 state->putchar_func(state->ctx, 1, &t);
188 state->curoctet %= 3;
189 state->lastoctet = c;
191 state->crc24 ^= c << 16;
192 for (i = 0; i < 8; i++) {
194 if (state->crc24 & 0x1000000) {
195 state->crc24 ^= CRC24_POLY;
199 if ((state->count % ARMOR_WIDTH) == 0) {
200 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
207 static int armor_putchar(void *ctx, size_t count, void *c)
212 for (i = 0; i < count; i++) {
213 armor_putchar_int(ctx, ((char *) c)[i]);
220 * @brief Holds the context of an ongoing ASCII dearmor operation
222 struct dearmor_context {
223 /** The last octet we got. */
224 unsigned char lastoctet;
225 /** The current octet we're expecting (0, 1 or 2). */
227 /** The number of octets we've seen. */
229 /** A running CRC24 of the data we've seen. */
231 /** The function to get the next character. */
232 int (*getchar_func)(void *ctx, size_t count, void *c);
233 /** Context for getchar_func. */
237 static void dearmor_init(struct dearmor_context *ctx)
242 ctx->crc24 = CRC24_INIT;
245 static void dearmor_finish(struct dearmor_context *state)
251 state->crc24 &= 0xffffffL;
253 state->putchar_func(state->ctx, '\n');
254 state->putchar_func(state->ctx, '=');
255 state->putchar_func(state->ctx, encode64(state->crc24 >> 18));
256 state->putchar_func(state->ctx, encode64((state->crc24 >> 12) & 0x3F));
257 state->putchar_func(state->ctx, encode64((state->crc24 >> 6) & 0x3F));
258 state->putchar_func(state->ctx, encode64(state->crc24 & 0x3F));
263 static int dearmor_getchar(void *ctx, unsigned char *c)
265 struct dearmor_context *state;
269 state = (struct dearmor_context *) ctx;
274 state->getchar_func(state->ctx, 1, &tmpc);
275 tmpc = decode64(tmpc);
279 switch (state->curoctet++) {
281 state->lastoctet = tmpc;
284 state->getchar_func(state->ctx, 1, &tmpc);
285 tmpc = decode64(tmpc);
287 *c = (state->lastoctet << 2) + (tmpc >> 4);
290 *c = ((state->lastoctet & 0xF) << 4) + (tmpc >> 2);
293 *c = ((state->lastoctet & 3) << 6) + tmpc;
297 state->curoctet %= 3;
298 state->lastoctet = tmpc;
301 state->crc24 ^= *c << 16;
302 for (i = 0; i < 8; i++) {
304 if (state->crc24 & 0x1000000) {
305 state->crc24 ^= CRC24_POLY;
313 static int dearmor_getchar_c(void *ctx, size_t count, void *c)
317 for (i = 0; i < count && rc == 0; i++) {
318 rc = dearmor_getchar(ctx, &((unsigned char *) c)[i]);
324 int armor_openpgp_stream(int (*putchar_func)(void *ctx, size_t count,
327 struct openpgp_packet_list *packets)
329 struct armor_context armor_ctx;
334 putchar_func(ctx, sizeof("-----BEGIN PGP PUBLIC KEY BLOCK-----\n") - 1,
335 (unsigned char *) "-----BEGIN PGP PUBLIC KEY BLOCK-----\n");
336 putchar_func(ctx, sizeof("Version: onak " ONAK_VERSION "\n\n") - 1,
337 (unsigned char *) "Version: onak " ONAK_VERSION "\n\n");
339 armor_init(&armor_ctx);
340 armor_ctx.putchar_func = putchar_func;
342 write_openpgp_stream(armor_putchar, &armor_ctx, packets);
343 armor_finish(&armor_ctx);
348 putchar_func(ctx, sizeof("-----END PGP PUBLIC KEY BLOCK-----\n") - 1,
349 (unsigned char *) "-----END PGP PUBLIC KEY BLOCK-----\n");
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