Header And Logo

PostgreSQL
| The world's most advanced open source database.

Defines | Functions | Variables

pgp-armor.c File Reference

#include "postgres.h"
#include "px.h"
#include "mbuf.h"
#include "pgp.h"
Include dependency graph for pgp-armor.c:

Go to the source code of this file.

Defines

#define CRC24_INIT   0x00b704ceL
#define CRC24_POLY   0x01864cfbL

Functions

static int b64_encode (const uint8 *src, unsigned len, uint8 *dst)
static int b64_decode (const uint8 *src, unsigned len, uint8 *dst)
static unsigned b64_enc_len (unsigned srclen)
static unsigned b64_dec_len (unsigned srclen)
static long crc24 (const uint8 *data, unsigned len)
int pgp_armor_encode (const uint8 *src, unsigned len, uint8 *dst)
static const uint8find_str (const uint8 *data, const uint8 *data_end, const char *str, int strlen)
static int find_header (const uint8 *data, const uint8 *datend, const uint8 **start_p, int is_end)
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)

Variables

static const unsigned char _base64 [] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
static const char * armor_header = "-----BEGIN PGP MESSAGE-----\n\n"
static const char * armor_footer = "\n-----END PGP MESSAGE-----\n"

Define Documentation

#define CRC24_INIT   0x00b704ceL

Definition at line 186 of file pgp-armor.c.

#define CRC24_POLY   0x01864cfbL

Definition at line 187 of file pgp-armor.c.


Function Documentation

static unsigned b64_dec_len ( unsigned  srclen  )  [static]

Definition at line 173 of file pgp-armor.c.

Referenced by pgp_armor_dec_len().

{
    return (srclen * 3) >> 2;
}

static int b64_decode ( const uint8 src,
unsigned  len,
uint8 dst 
) [static]

Definition at line 96 of file pgp-armor.c.

References buf, and end.

Referenced by pgp_armor_decode().

{
    const uint8 *srcend = src + len,
               *s = src;
    uint8      *p = dst;
    char        c;
    unsigned    b = 0;
    unsigned long buf = 0;
    int         pos = 0,
                end = 0;

    while (s < srcend)
    {
        c = *s++;
        if (c >= 'A' && c <= 'Z')
            b = c - 'A';
        else if (c >= 'a' && c <= 'z')
            b = c - 'a' + 26;
        else if (c >= '0' && c <= '9')
            b = c - '0' + 52;
        else if (c == '+')
            b = 62;
        else if (c == '/')
            b = 63;
        else if (c == '=')
        {
            /*
             * end sequence
             */
            if (!end)
            {
                if (pos == 2)
                    end = 1;
                else if (pos == 3)
                    end = 2;
                else
                    return PXE_PGP_CORRUPT_ARMOR;
            }
            b = 0;
        }
        else if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
            continue;
        else
            return PXE_PGP_CORRUPT_ARMOR;

        /*
         * add it to buffer
         */
        buf = (buf << 6) + b;
        pos++;
        if (pos == 4)
        {
            *p++ = (buf >> 16) & 255;
            if (end == 0 || end > 1)
                *p++ = (buf >> 8) & 255;
            if (end == 0 || end > 2)
                *p++ = buf & 255;
            buf = 0;
            pos = 0;
        }
    }

    if (pos != 0)
        return PXE_PGP_CORRUPT_ARMOR;
    return p - dst;
}

static unsigned b64_enc_len ( unsigned  srclen  )  [static]

Definition at line 164 of file pgp-armor.c.

Referenced by pgp_armor_enc_len().

{
    /*
     * 3 bytes will be converted to 4, linefeed after 76 chars
     */
    return (srclen + 2) * 4 / 3 + srclen / (76 * 3 / 4);
}

static int b64_encode ( const uint8 src,
unsigned  len,
uint8 dst 
) [static]

Definition at line 46 of file pgp-armor.c.

References _base64, buf, and end.

Referenced by pgp_armor_encode().

{
    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)
    {
        buf |= *s << (pos << 3);
        pos--;
        s++;

        /*
         * write it out
         */
        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;
}

static long crc24 ( const uint8 data,
unsigned  len 
) [static]

Definition at line 189 of file pgp-armor.c.

References i.

Referenced by pgp_armor_decode(), and pgp_armor_encode().

{
    unsigned    crc = CRC24_INIT;
    int         i;

    while (len--)
    {
        crc ^= (*data++) << 16;
        for (i = 0; i < 8; i++)
        {
            crc <<= 1;
            if (crc & 0x1000000)
                crc ^= CRC24_POLY;
        }
    }
    return crc & 0xffffffL;
}

static int find_header ( const uint8 data,
const uint8 datend,
const uint8 **  start_p,
int  is_end 
) [static]

Definition at line 265 of file pgp-armor.c.

References find_str(), memcmp(), and NULL.

Referenced by pgp_armor_decode().

{
    const uint8 *p = data;
    static const char *start_sep = "-----BEGIN";
    static const char *end_sep = "-----END";
    const char *sep = is_end ? end_sep : start_sep;

    /* find header line */
    while (1)
    {
        p = find_str(p, datend, sep, strlen(sep));
        if (p == NULL)
            return PXE_PGP_CORRUPT_ARMOR;
        /* it must start at beginning of line */
        if (p == data || *(p - 1) == '\n')
            break;
        p += strlen(sep);
    }
    *start_p = p;
    p += strlen(sep);

    /* check if header text ok */
    for (; p < datend && *p != '-'; p++)
    {
        /* various junk can be there, but definitely not line-feed  */
        if (*p >= ' ')
            continue;
        return PXE_PGP_CORRUPT_ARMOR;
    }
    if (datend - p < 5 || memcmp(p, sep, 5) != 0)
        return PXE_PGP_CORRUPT_ARMOR;
    p += 5;

    /* check if at end of line */
    if (p < datend)
    {
        if (*p != '\n' && *p != '\r')
            return PXE_PGP_CORRUPT_ARMOR;
        if (*p == '\r')
            p++;
        if (p < datend && *p == '\n')
            p++;
    }
    return p - *start_p;
}

static const uint8* find_str ( const uint8 data,
const uint8 data_end,
const char *  str,
int  strlen 
) [static]

Definition at line 242 of file pgp-armor.c.

References memcmp(), and NULL.

Referenced by find_header().

{
    const uint8 *p = data;

    if (!strlen)
        return NULL;
    if (data_end - data < strlen)
        return NULL;
    while (p < data_end)
    {
        p = memchr(p, str[0], data_end - p);
        if (p == NULL)
            return NULL;
        if (p + strlen > data_end)
            return NULL;
        if (memcmp(p, str, strlen) == 0)
            return p;
        p++;
    }
    return NULL;
}

unsigned pgp_armor_dec_len ( unsigned  len  ) 

Definition at line 380 of file pgp-armor.c.

References b64_dec_len().

Referenced by pg_dearmor().

{
    return b64_dec_len(len);
}

int pgp_armor_decode ( const uint8 src,
unsigned  len,
uint8 dst 
)

Definition at line 313 of file pgp-armor.c.

References b64_decode(), buf, crc24(), find_header(), and NULL.

Referenced by pg_dearmor().

{
    const uint8 *p = src;
    const uint8 *data_end = src + len;
    long        crc;
    const uint8 *base64_start,
               *armor_end;
    const uint8 *base64_end = NULL;
    uint8       buf[4];
    int         hlen;
    int         res = PXE_PGP_CORRUPT_ARMOR;

    /* armor start */
    hlen = find_header(src, data_end, &p, 0);
    if (hlen <= 0)
        goto out;
    p += hlen;

    /* armor end */
    hlen = find_header(p, data_end, &armor_end, 1);
    if (hlen <= 0)
        goto out;

    /* skip comments - find empty line */
    while (p < armor_end && *p != '\n' && *p != '\r')
    {
        p = memchr(p, '\n', armor_end - p);
        if (!p)
            goto out;

        /* step to start of next line */
        p++;
    }
    base64_start = p;

    /* find crc pos */
    for (p = armor_end; p >= base64_start; p--)
        if (*p == '=')
        {
            base64_end = p - 1;
            break;
        }
    if (base64_end == NULL)
        goto out;

    /* decode crc */
    if (b64_decode(p + 1, 4, buf) != 3)
        goto out;
    crc = (((long) buf[0]) << 16) + (((long) buf[1]) << 8) + (long) buf[2];

    /* decode data */
    res = b64_decode(base64_start, base64_end - base64_start, dst);

    /* check crc */
    if (res >= 0 && crc24(dst, res) != crc)
        res = PXE_PGP_CORRUPT_ARMOR;
out:
    return res;
}

unsigned pgp_armor_enc_len ( unsigned  len  ) 

Definition at line 374 of file pgp-armor.c.

References armor_footer, armor_header, and b64_enc_len().

Referenced by pg_armor().

{
    return b64_enc_len(len) + strlen(armor_header) + strlen(armor_footer) + 16;
}

int pgp_armor_encode ( const uint8 src,
unsigned  len,
uint8 dst 
)

Definition at line 208 of file pgp-armor.c.

References _base64, armor_footer, armor_header, b64_encode(), and crc24().

Referenced by pg_armor().

{
    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;
}


Variable Documentation

const unsigned char _base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" [static]

Definition at line 42 of file pgp-armor.c.

Referenced by b64_encode(), and pgp_armor_encode().

const char* armor_footer = "\n-----END PGP MESSAGE-----\n" [static]

Definition at line 183 of file pgp-armor.c.

Referenced by pgp_armor_enc_len(), and pgp_armor_encode().

const char* armor_header = "-----BEGIN PGP MESSAGE-----\n\n" [static]

Definition at line 182 of file pgp-armor.c.

Referenced by pgp_armor_enc_len(), and pgp_armor_encode().