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, see <https://www.gnu.org/licenses/>.
22 #include "build-config.h"
25 #include "keystructs.h"
29 * @brief Line length we'll use for armored output
31 #define ARMOR_WIDTH 64
34 * @brief CRC24 initialisation value
36 #define CRC24_INIT 0xb704ceL
38 * @brief CRC24 polynomial value
40 #define CRC24_POLY 0x1864cfbL
45 static unsigned char encode64(unsigned char c) {
48 } else if (c >= 26 && c <= 51) {
50 } else if (c >= 52 && c <= 61) {
66 static unsigned char decode64(unsigned char c) {
67 if (c >= 'A' && c <= 'Z') {
69 } else if (c >= 'a' && c <= 'z') {
71 } else if (c >= '0' && c <= '9') {
73 } else if (c == '+') {
75 } else if (c == '/') {
77 } else if (c == '=' || c == '-') {
87 * @brief Holds the context of an ongoing ASCII armor operation
89 struct armor_context {
90 /** The last octet we got. */
91 unsigned char lastoctet;
92 /** The current octet we're expecting (0, 1 or 2). */
94 /** The number of octets we've seen. */
96 /** A running CRC24 of the data we've seen. */
98 /** The function to output a character. */
99 size_t (*putchar_func)(void *ctx, size_t count, void *c);
100 /** Context for putchar_func. */
104 static void armor_init(struct armor_context *ctx)
109 ctx->crc24 = CRC24_INIT;
112 static void armor_finish(struct armor_context *state)
116 switch (state->curoctet++) {
120 c = encode64((state->lastoctet & 3) << 4);
121 state->putchar_func(state->ctx, 1, &c);
122 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
123 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
125 if ((state->count % ARMOR_WIDTH) == 0) {
126 state->putchar_func(state->ctx, 1,
127 (unsigned char *) "\n");
131 c = encode64((state->lastoctet & 0xF) << 2);
132 state->putchar_func(state->ctx, 1, &c);
133 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
135 if ((state->count % ARMOR_WIDTH) == 0) {
136 state->putchar_func(state->ctx, 1,
137 (unsigned char *) "\n");
142 state->crc24 &= 0xffffffL;
143 if ((state->count % ARMOR_WIDTH) != 0) {
144 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
146 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
147 c = encode64(state->crc24 >> 18);
148 state->putchar_func(state->ctx, 1, &c);
149 c = encode64((state->crc24 >> 12) & 0x3F);
150 state->putchar_func(state->ctx, 1, &c);
151 c = encode64((state->crc24 >> 6) & 0x3F);
152 state->putchar_func(state->ctx, 1, &c);
153 c = encode64(state->crc24 & 0x3F);
154 state->putchar_func(state->ctx, 1, &c);
155 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
160 static int armor_putchar_int(void *ctx, unsigned char c)
162 struct armor_context *state;
166 state = (struct armor_context *) ctx;
168 switch (state->curoctet++) {
170 t = encode64(c >> 2);
171 state->putchar_func(state->ctx, 1, &t);
175 t = encode64(((state->lastoctet & 3) << 4) + (c >> 4));
176 state->putchar_func(state->ctx, 1, &t);
180 t = encode64(((state->lastoctet & 0xF) << 2) + (c >> 6));
181 state->putchar_func(state->ctx, 1, &t);
182 t = encode64(c & 0x3F);
183 state->putchar_func(state->ctx, 1, &t);
187 state->curoctet %= 3;
188 state->lastoctet = c;
190 state->crc24 ^= c << 16;
191 for (i = 0; i < 8; i++) {
193 if (state->crc24 & 0x1000000) {
194 state->crc24 ^= CRC24_POLY;
198 if ((state->count % ARMOR_WIDTH) == 0) {
199 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
206 static size_t armor_putchar(void *ctx, size_t count, void *c)
211 for (i = 0; i < count; i++) {
212 armor_putchar_int(ctx, ((char *) c)[i]);
219 * @brief Holds the context of an ongoing ASCII dearmor operation
221 struct dearmor_context {
222 /** The last octet we got. */
223 unsigned char lastoctet;
224 /** The current octet we're expecting (0, 1 or 2). */
226 /** The number of octets we've seen. */
228 /** A running CRC24 of the data we've seen. */
230 /** The function to get the next character. */
231 size_t (*getchar_func)(void *ctx, size_t count, void *c);
232 /** Context for getchar_func. */
236 static void dearmor_init(struct dearmor_context *ctx)
241 ctx->crc24 = CRC24_INIT;
244 static void dearmor_finish(struct dearmor_context *state)
250 state->crc24 &= 0xffffffL;
252 state->putchar_func(state->ctx, '\n');
253 state->putchar_func(state->ctx, '=');
254 state->putchar_func(state->ctx, encode64(state->crc24 >> 18));
255 state->putchar_func(state->ctx, encode64((state->crc24 >> 12) & 0x3F));
256 state->putchar_func(state->ctx, encode64((state->crc24 >> 6) & 0x3F));
257 state->putchar_func(state->ctx, encode64(state->crc24 & 0x3F));
262 static int dearmor_getchar(void *ctx, unsigned char *c)
264 struct dearmor_context *state;
268 state = (struct dearmor_context *) ctx;
273 state->getchar_func(state->ctx, 1, &tmpc);
274 tmpc = decode64(tmpc);
278 switch (state->curoctet++) {
280 state->lastoctet = tmpc;
283 state->getchar_func(state->ctx, 1, &tmpc);
284 tmpc = decode64(tmpc);
286 *c = (state->lastoctet << 2) + (tmpc >> 4);
289 *c = ((state->lastoctet & 0xF) << 4) + (tmpc >> 2);
292 *c = ((state->lastoctet & 3) << 6) + tmpc;
296 state->curoctet %= 3;
297 state->lastoctet = tmpc;
300 state->crc24 ^= *c << 16;
301 for (i = 0; i < 8; i++) {
303 if (state->crc24 & 0x1000000) {
304 state->crc24 ^= CRC24_POLY;
312 static size_t dearmor_getchar_c(void *ctx, size_t count, void *c)
316 for (i = 0; i < count && rc == 0; i++) {
317 rc = dearmor_getchar(ctx, &((unsigned char *) c)[i]);
320 return (rc == 0) ? i : 0;
323 int armor_openpgp_stream(size_t (*putchar_func)(void *ctx, size_t count,
326 struct openpgp_packet_list *packets)
328 struct armor_context armor_ctx;
333 putchar_func(ctx, sizeof("-----BEGIN PGP PUBLIC KEY BLOCK-----\n\n") - 1,
334 (unsigned char *) "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\n");
336 armor_init(&armor_ctx);
337 armor_ctx.putchar_func = putchar_func;
339 write_openpgp_stream(armor_putchar, &armor_ctx, packets);
340 armor_finish(&armor_ctx);
345 putchar_func(ctx, sizeof("-----END PGP PUBLIC KEY BLOCK-----\n") - 1,
346 (unsigned char *) "-----END PGP PUBLIC KEY BLOCK-----\n");
351 int dearmor_openpgp_stream(size_t (*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) == 1) {
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