*** a/contrib/pgcrypto/pgp-armor.c --- b/contrib/pgcrypto/pgp-armor.c *************** *** 31,36 **** --- 31,38 ---- #include "postgres.h" + #include "lib/stringinfo.h" + #include "px.h" #include "pgp.h" *************** *** 38,58 **** * BASE64 - duplicated :( */ ! static const unsigned char _base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; ! static int ! b64_encode(const uint8 *src, unsigned len, uint8 *dst) { - uint8 *p, - *lend = dst + 76; const uint8 *s, *end = src + len; int pos = 2; unsigned long buf = 0; s = src; - p = dst; while (s < end) { --- 40,58 ---- * BASE64 - duplicated :( */ ! static const char _base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; ! static void ! b64_encode(const uint8 *src, unsigned len, StringInfo dst) { const uint8 *s, *end = src + len; int pos = 2; unsigned long buf = 0; + int linepos = 0; s = src; while (s < end) { *************** *** 65,93 **** b64_encode(const uint8 *src, unsigned len, uint8 *dst) */ if (pos < 0) { ! *p++ = _base64[(buf >> 18) & 0x3f]; ! *p++ = _base64[(buf >> 12) & 0x3f]; ! *p++ = _base64[(buf >> 6) & 0x3f]; ! *p++ = _base64[buf & 0x3f]; pos = 2; buf = 0; } ! if (p >= lend) { ! *p++ = '\n'; ! lend = p + 76; } } if (pos != 2) { ! *p++ = _base64[(buf >> 18) & 0x3f]; ! *p++ = _base64[(buf >> 12) & 0x3f]; ! *p++ = (pos == 0) ? _base64[(buf >> 6) & 0x3f] : '='; ! *p++ = '='; } - - return p - dst; } /* probably should use lookup table */ --- 65,92 ---- */ if (pos < 0) { ! appendStringInfoCharMacro(dst, _base64[(buf >> 18) & 0x3f]); ! appendStringInfoCharMacro(dst, _base64[(buf >> 12) & 0x3f]); ! appendStringInfoCharMacro(dst, _base64[(buf >> 6) & 0x3f]); ! appendStringInfoCharMacro(dst, _base64[buf & 0x3f]); + linepos += 4; pos = 2; buf = 0; } ! if (linepos >= 76) { ! appendStringInfoCharMacro(dst, '\n'); ! linepos = 0; } } if (pos != 2) { ! appendStringInfoCharMacro(dst, _base64[(buf >> 18) & 0x3f]); ! appendStringInfoCharMacro(dst, _base64[(buf >> 12) & 0x3f]); ! appendStringInfoCharMacro(dst, (pos == 0) ? _base64[(buf >> 6) & 0x3f] : '='); ! appendStringInfoCharMacro(dst, '='); } } /* probably should use lookup table */ *************** *** 160,174 **** b64_decode(const uint8 *src, unsigned len, uint8 *dst) } static unsigned - b64_enc_len(unsigned srclen) - { - /* - * 3 bytes will be converted to 4, linefeed after 76 chars - */ - return (srclen + 2) * 4 / 3 + srclen / (76 * 3 / 4); - } - - static unsigned b64_dec_len(unsigned srclen) { return (srclen * 3) >> 2; --- 159,164 ---- *************** *** 203,240 **** crc24(const uint8 *data, unsigned len) return crc & 0xffffffL; } ! int ! pgp_armor_encode(const uint8 *src, unsigned len, uint8 *dst) { - int n; - uint8 *pos = dst; unsigned crc = crc24(src, len); ! n = strlen(armor_header); ! memcpy(pos, armor_header, n); ! pos += n; ! n = b64_encode(src, len, pos); ! pos += n; ! if (*(pos - 1) != '\n') ! *pos++ = '\n'; ! *pos++ = '='; ! pos[3] = _base64[crc & 0x3f]; ! crc >>= 6; ! pos[2] = _base64[crc & 0x3f]; ! crc >>= 6; ! pos[1] = _base64[crc & 0x3f]; ! crc >>= 6; ! pos[0] = _base64[crc & 0x3f]; ! pos += 4; ! n = strlen(armor_footer); ! memcpy(pos, armor_footer, n); ! pos += n; ! ! return pos - dst; } static const uint8 * --- 193,217 ---- return crc & 0xffffffL; } ! void ! pgp_armor_encode(const uint8 *src, unsigned len, StringInfo dst) { unsigned crc = crc24(src, len); ! appendStringInfoString(dst, armor_header); ! b64_encode(src, len, dst); ! if (*(dst->data + dst->len - 1) != '\n') ! appendStringInfoChar(dst, '\n'); ! appendStringInfoChar(dst, '='); ! appendStringInfoChar(dst, _base64[(crc >> 18) & 0x3f]); ! appendStringInfoChar(dst, _base64[(crc >> 12) & 0x3f]); ! appendStringInfoChar(dst, _base64[(crc >> 6) & 0x3f]); ! appendStringInfoChar(dst, _base64[crc & 0x3f]); ! appendStringInfoString(dst, armor_footer); } static const uint8 * *************** *** 370,381 **** out: } unsigned - pgp_armor_enc_len(unsigned len) - { - return b64_enc_len(len) + strlen(armor_header) + strlen(armor_footer) + 16; - } - - unsigned pgp_armor_dec_len(unsigned len) { return b64_dec_len(len); --- 347,352 ---- *** a/contrib/pgcrypto/pgp-pgsql.c --- b/contrib/pgcrypto/pgp-pgsql.c *************** *** 820,842 **** pg_armor(PG_FUNCTION_ARGS) { bytea *data; text *res; ! int data_len, ! res_len, ! guess_len; data = PG_GETARG_BYTEA_P(0); data_len = VARSIZE(data) - VARHDRSZ; ! guess_len = pgp_armor_enc_len(data_len); ! res = palloc(VARHDRSZ + guess_len); ! res_len = pgp_armor_encode((uint8 *) VARDATA(data), data_len, ! (uint8 *) VARDATA(res)); ! if (res_len > guess_len) ! ereport(ERROR, ! (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION), ! errmsg("Overflow - encode estimate too small"))); ! SET_VARSIZE(res, VARHDRSZ + res_len); PG_FREE_IF_COPY(data, 0); PG_RETURN_TEXT_P(res); --- 820,839 ---- { bytea *data; text *res; ! int data_len; ! StringInfoData buf; data = PG_GETARG_BYTEA_P(0); data_len = VARSIZE(data) - VARHDRSZ; ! initStringInfo(&buf); ! pgp_armor_encode((uint8 *) VARDATA(data), data_len, &buf); ! ! res = palloc(VARHDRSZ + buf.len); ! SET_VARSIZE(res, VARHDRSZ + buf.len); ! memcpy(VARDATA(res), buf.data, buf.len); ! pfree(buf.data); PG_FREE_IF_COPY(data, 0); PG_RETURN_TEXT_P(res); *** a/contrib/pgcrypto/pgp.h --- b/contrib/pgcrypto/pgp.h *************** *** 29,34 **** --- 29,35 ---- * contrib/pgcrypto/pgp.h */ + #include "lib/stringinfo.h" #include "mbuf.h" #include "px.h" *************** *** 274,280 **** void pgp_cfb_free(PGP_CFB *ctx); int pgp_cfb_encrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst); int pgp_cfb_decrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst); ! int pgp_armor_encode(const uint8 *src, unsigned len, uint8 *dst); int pgp_armor_decode(const uint8 *src, unsigned len, uint8 *dst); unsigned pgp_armor_enc_len(unsigned len); unsigned pgp_armor_dec_len(unsigned len); --- 275,281 ---- int pgp_cfb_encrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst); int pgp_cfb_decrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst); ! void pgp_armor_encode(const uint8 *src, unsigned len, StringInfo dst); int pgp_armor_decode(const uint8 *src, unsigned len, uint8 *dst); unsigned pgp_armor_enc_len(unsigned len); unsigned pgp_armor_dec_len(unsigned len);