5 * Copyright (c) 2005 Marko Kreen
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * contrib/pgcrypto/pgp-armor.c
38 * BASE64 - duplicated :(
42"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
52 unsigned long buf = 0;
59 buf |= *s << (pos << 3);
86 *p++ = (pos == 0) ?
_base64[(
buf >> 6) & 0x3f] :
'=';
93/* probably should use lookup table */
102 unsigned long buf = 0;
109 if (
c >=
'A' &&
c <=
'Z')
111 else if (
c >=
'a' &&
c <=
'z')
113 else if (
c >=
'0' &&
c <=
'9')
135 else if (
c ==
' ' ||
c ==
'\t' ||
c ==
'\n' ||
c ==
'\r')
147 *p++ = (
buf >> 16) & 255;
148 if (end == 0 || end > 1)
149 *p++ = (
buf >> 8) & 255;
150 if (end == 0 || end > 2)
166 * 3 bytes will be converted to 4, linefeed after 76 chars
168 return (srclen + 2) / 3 * 4 + srclen / (76 * 3 / 4);
174 return (srclen * 3) >> 2;
181 static const char *
const armor_header =
"-----BEGIN PGP MESSAGE-----\n";
182 static const char *
const armor_footer =
"\n-----END PGP MESSAGE-----\n";
184/* CRC24 implementation from rfc2440 */
185 #define CRC24_INIT 0x00b704ceL
186 #define CRC24_POLY 0x01864cfbL
196 for (
i = 0;
i < 8;
i++)
203 return crc & 0xffffffL;
208 int num_headers,
char **keys,
char **
values)
217 for (n = 0; n < num_headers; n++)
221 /* make sure we have enough room to pg_base64_encode() */
227 elog(
FATAL,
"overflow - encode estimate too small");
230 if (*(dst->
data + dst->
len - 1) !=
'\n')
249 if (data_end -
data < strlen)
253 p = memchr(p,
str[0], data_end - p);
256 if (p + strlen > data_end)
258 if (memcmp(p,
str, strlen) == 0)
267 const uint8 **start_p,
int is_end)
270 static const char *start_sep =
"-----BEGIN";
271 static const char *end_sep =
"-----END";
272 const char *sep = is_end ? end_sep : start_sep;
274 /* find header line */
277 p =
find_str(p, datend, sep, strlen(sep));
280 /* it must start at beginning of line */
281 if (p ==
data || *(p - 1) ==
'\n')
288 /* check if header text ok */
289 for (; p < datend && *p !=
'-'; p++)
291 /* various junk can be there, but definitely not line-feed */
296 if (datend - p < 5 || memcmp(p, sep, 5) != 0)
300 /* check if at end of line */
303 if (*p !=
'\n' && *p !=
'\r')
307 if (p < datend && *p ==
'\n')
316 const uint8 *p = src;
319 const uint8 *base64_start,
321 const uint8 *base64_end = NULL;
338 /* skip comments - find empty line */
339 while (p < armor_end && *p !=
'\n' && *p !=
'\r')
341 p = memchr(p,
'\n', armor_end - p);
345 /* step to start of next line */
351 for (p = armor_end; p >= base64_start; p--)
357 if (base64_end == NULL)
363 crc = (((long)
buf[0]) << 16) + (((
long)
buf[1]) << 8) + (long)
buf[2];
370 elog(
FATAL,
"overflow - decode estimate too small");
383 * Extracts all armor headers from an ASCII-armored input.
385 * Returns 0 on success, or PXE_* error code on error. On success, the
386 * number of headers and their keys and values are returned in *nheaders,
387 * *nkeys and *nvalues.
391 int *nheaders,
char ***keys,
char ***
values)
395 const uint8 *base64_start;
396 const uint8 *armor_start;
397 const uint8 *armor_end;
409 hlen =
find_header(src, data_end, &armor_start, 0);
415 hlen =
find_header(armor_start, data_end, &armor_end, 1);
419 /* Count the number of armor header lines. */
422 while (p < armor_end && *p !=
'\n' && *p !=
'\r')
424 p = memchr(p,
'\n', armor_end - p);
428 /* step to start of next line */
435 * Make a modifiable copy of the part of the input that contains the
436 * headers. The returned key/value pointers will point inside the buffer.
438 armor_len = base64_start - armor_start;
440 memcpy(
buf, armor_start, armor_len);
441 buf[armor_len] =
'0円';
443 /* Allocate return arrays */
444 *keys = (
char **)
palloc(hdrlines *
sizeof(
char *));
448 * Split the header lines at newlines and ": " separators, and collect
449 * pointers to the keys and values in the return arrays.
455 /* find end of line */
456 eol = strchr(line,
'\n');
460 /* if the line ends in CR + LF, strip the CR */
461 if (eol > line && *(eol - 1) ==
'\r')
465 /* find colon+space separating the key and value */
466 colon = strstr(line,
": ");
471 /* shouldn't happen, we counted the number of lines beforehand */
473 elog(
ERROR,
"unexpected number of armor header lines");
476 (*values)[n] =
colon + 2;
479 /* step to start of next line */
484 elog(
ERROR,
"unexpected number of armor header lines");
static Datum values[MAXATTR]
static long crc24(const uint8 *data, unsigned len)
int pgp_extract_armor_headers(const uint8 *src, unsigned len, int *nheaders, char ***keys, char ***values)
static int find_header(const uint8 *data, const uint8 *datend, const uint8 **start_p, int is_end)
static const char *const armor_footer
static unsigned pg_base64_enc_len(unsigned srclen)
int pgp_armor_decode(const uint8 *src, int len, StringInfo dst)
static int pg_base64_decode(const uint8 *src, unsigned len, uint8 *dst)
void pgp_armor_encode(const uint8 *src, unsigned len, StringInfo dst, int num_headers, char **keys, char **values)
static const char *const armor_header
static unsigned pg_base64_dec_len(unsigned srclen)
static int pg_base64_encode(const uint8 *src, unsigned len, uint8 *dst)
static const uint8 * find_str(const uint8 *data, const uint8 *data_end, const char *str, int strlen)
static const unsigned char _base64[]
#define PXE_PGP_CORRUPT_ARMOR
void appendStringInfo(StringInfo str, const char *fmt,...)
void enlargeStringInfo(StringInfo str, int needed)
void appendStringInfoString(StringInfo str, const char *s)
void appendStringInfoChar(StringInfo str, char ch)