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/>.
23 #include "keystructs.h"
28 * @brief Line length we'll use for armored output
30 #define ARMOR_WIDTH 64
33 * @brief CRC24 initialisation value
35 #define CRC24_INIT 0xb704ceL
37 * @brief CRC24 polynomial value
39 #define CRC24_POLY 0x1864cfbL
44 static unsigned char encode64(unsigned char c) {
47 } else if (c >= 26 && c <= 51) {
49 } else if (c >= 52 && c <= 61) {
65 static unsigned char decode64(unsigned char c) {
66 if (c >= 'A' && c <= 'Z') {
68 } else if (c >= 'a' && c <= 'z') {
70 } else if (c >= '0' && c <= '9') {
72 } else if (c == '+') {
74 } else if (c == '/') {
76 } else if (c == '=' || c == '-') {
86 * @brief Holds the context of an ongoing ASCII armor operation
88 struct armor_context {
89 /** The last octet we got. */
90 unsigned char lastoctet;
91 /** The current octet we're expecting (0, 1 or 2). */
93 /** The number of octets we've seen. */
95 /** A running CRC24 of the data we've seen. */
97 /** The function to output a character. */
98 int (*putchar_func)(void *ctx, size_t count, void *c);
99 /** Context for putchar_func. */
103 static void armor_init(struct armor_context *ctx)
108 ctx->crc24 = CRC24_INIT;
111 static void armor_finish(struct armor_context *state)
115 switch (state->curoctet++) {
119 c = encode64((state->lastoctet & 3) << 4);
120 state->putchar_func(state->ctx, 1, &c);
121 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
122 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
124 if ((state->count % ARMOR_WIDTH) == 0) {
125 state->putchar_func(state->ctx, 1,
126 (unsigned char *) "\n");
130 c = encode64((state->lastoctet & 0xF) << 2);
131 state->putchar_func(state->ctx, 1, &c);
132 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
134 if ((state->count % ARMOR_WIDTH) == 0) {
135 state->putchar_func(state->ctx, 1,
136 (unsigned char *) "\n");
141 state->crc24 &= 0xffffffL;
142 if ((state->count % ARMOR_WIDTH) != 0) {
143 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
145 state->putchar_func(state->ctx, 1, (unsigned char *) "=");
146 c = encode64(state->crc24 >> 18);
147 state->putchar_func(state->ctx, 1, &c);
148 c = encode64((state->crc24 >> 12) & 0x3F);
149 state->putchar_func(state->ctx, 1, &c);
150 c = encode64((state->crc24 >> 6) & 0x3F);
151 state->putchar_func(state->ctx, 1, &c);
152 c = encode64(state->crc24 & 0x3F);
153 state->putchar_func(state->ctx, 1, &c);
154 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
159 static int armor_putchar_int(void *ctx, unsigned char c)
161 struct armor_context *state;
165 state = (struct armor_context *) ctx;
167 switch (state->curoctet++) {
169 t = encode64(c >> 2);
170 state->putchar_func(state->ctx, 1, &t);
174 t = encode64(((state->lastoctet & 3) << 4) + (c >> 4));
175 state->putchar_func(state->ctx, 1, &t);
179 t = encode64(((state->lastoctet & 0xF) << 2) + (c >> 6));
180 state->putchar_func(state->ctx, 1, &t);
181 t = encode64(c & 0x3F);
182 state->putchar_func(state->ctx, 1, &t);
186 state->curoctet %= 3;
187 state->lastoctet = c;
189 state->crc24 ^= c << 16;
190 for (i = 0; i < 8; i++) {
192 if (state->crc24 & 0x1000000) {
193 state->crc24 ^= CRC24_POLY;
197 if ((state->count % ARMOR_WIDTH) == 0) {
198 state->putchar_func(state->ctx, 1, (unsigned char *) "\n");
205 static int armor_putchar(void *ctx, size_t count, void *c)
210 for (i = 0; i < count; i++) {
211 armor_putchar_int(ctx, ((char *) c)[i]);
218 * @brief Holds the context of an ongoing ASCII dearmor operation
220 struct dearmor_context {
221 /** The last octet we got. */
222 unsigned char lastoctet;
223 /** The current octet we're expecting (0, 1 or 2). */
225 /** The number of octets we've seen. */
227 /** A running CRC24 of the data we've seen. */
229 /** The function to get the next character. */
230 int (*getchar_func)(void *ctx, size_t count, void *c);
231 /** Context for getchar_func. */
235 static void dearmor_init(struct dearmor_context *ctx)
240 ctx->crc24 = CRC24_INIT;
243 static void dearmor_finish(struct dearmor_context *state)
249 state->crc24 &= 0xffffffL;
251 state->putchar_func(state->ctx, '\n');
252 state->putchar_func(state->ctx, '=');
253 state->putchar_func(state->ctx, encode64(state->crc24 >> 18));
254 state->putchar_func(state->ctx, encode64((state->crc24 >> 12) & 0x3F));
255 state->putchar_func(state->ctx, encode64((state->crc24 >> 6) & 0x3F));
256 state->putchar_func(state->ctx, encode64(state->crc24 & 0x3F));
261 static int dearmor_getchar(void *ctx, unsigned char *c)
263 struct dearmor_context *state;
267 state = (struct dearmor_context *) ctx;
272 state->getchar_func(state->ctx, 1, &tmpc);
273 tmpc = decode64(tmpc);
277 switch (state->curoctet++) {
279 state->lastoctet = tmpc;
282 state->getchar_func(state->ctx, 1, &tmpc);
283 tmpc = decode64(tmpc);
285 *c = (state->lastoctet << 2) + (tmpc >> 4);
288 *c = ((state->lastoctet & 0xF) << 4) + (tmpc >> 2);
291 *c = ((state->lastoctet & 3) << 6) + tmpc;
295 state->curoctet %= 3;
296 state->lastoctet = tmpc;
299 state->crc24 ^= *c << 16;
300 for (i = 0; i < 8; i++) {
302 if (state->crc24 & 0x1000000) {
303 state->crc24 ^= CRC24_POLY;
311 static int dearmor_getchar_c(void *ctx, size_t count, void *c)
315 for (i = 0; i < count && rc == 0; i++) {
316 rc = dearmor_getchar(ctx, &((unsigned char *) c)[i]);
322 int armor_openpgp_stream(int (*putchar_func)(void *ctx, size_t count,
325 struct openpgp_packet_list *packets)
327 struct armor_context armor_ctx;
332 putchar_func(ctx, sizeof("-----BEGIN PGP PUBLIC KEY BLOCK-----\n") - 1,
333 (unsigned char *) "-----BEGIN PGP PUBLIC KEY BLOCK-----\n");
334 putchar_func(ctx, sizeof("Version: onak " ONAK_VERSION "\n\n") - 1,
335 (unsigned char *) "Version: onak " ONAK_VERSION "\n\n");
337 armor_init(&armor_ctx);
338 armor_ctx.putchar_func = putchar_func;
340 write_openpgp_stream(armor_putchar, &armor_ctx, packets);
341 armor_finish(&armor_ctx);
346 putchar_func(ctx, sizeof("-----END PGP PUBLIC KEY BLOCK-----\n") - 1,
347 (unsigned char *) "-----END PGP PUBLIC KEY BLOCK-----\n");
352 int dearmor_openpgp_stream(int (*getchar_func)(void *ctx, size_t count,
355 struct openpgp_packet_list **packets)
357 struct dearmor_context dearmor_ctx;
358 unsigned char curchar;
363 * Look for armor header. We want "-----BEGIN.*\n", then some headers
364 * with :s in them, then a blank line, then the data.
367 while (state != 4 && !getchar_func(ctx, 1, &curchar)) {
370 if (curchar == '\n') {
376 if (curchar == '-') {
381 } else if (curchar != '\n') {
386 if (curchar == 'B') {
394 if (curchar == '\n') {
399 } else if (curchar != '\r') {
407 dearmor_init(&dearmor_ctx);
408 dearmor_ctx.getchar_func = getchar_func;
409 dearmor_ctx.ctx = ctx;
410 read_openpgp_stream(dearmor_getchar_c, &dearmor_ctx,
412 dearmor_finish(&dearmor_ctx);
414 * TODO: Look for armor footer