Header And Logo

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

Data Structures | Defines | Functions | Variables

pgp-encrypt.c File Reference

#include "postgres.h"
#include <time.h>
#include "mbuf.h"
#include "px.h"
#include "pgp.h"
Include dependency graph for pgp-encrypt.c:

Go to the source code of this file.

Data Structures

struct  EncStat
struct  PktStreamStat

Defines

#define MDC_DIGEST_LEN   20
#define STREAM_ID   0xE0
#define STREAM_BLOCK_SHIFT   14
#define ENCBUF   8192

Functions

static uint8render_newlen (uint8 *h, int len)
static int write_tag_only (PushFilter *dst, int tag)
static int write_normal_header (PushFilter *dst, int tag, int len)
static int mdc_init (PushFilter *dst, void *init_arg, void **priv_p)
static int mdc_write (PushFilter *dst, void *priv, const uint8 *data, int len)
static int mdc_flush (PushFilter *dst, void *priv)
static void mdc_free (void *priv)
static int encrypt_init (PushFilter *next, void *init_arg, void **priv_p)
static int encrypt_process (PushFilter *next, void *priv, const uint8 *data, int len)
static void encrypt_free (void *priv)
static int pkt_stream_init (PushFilter *next, void *init_arg, void **priv_p)
static int pkt_stream_process (PushFilter *next, void *priv, const uint8 *data, int len)
static int pkt_stream_flush (PushFilter *next, void *priv)
static void pkt_stream_free (void *priv)
int pgp_create_pkt_writer (PushFilter *dst, int tag, PushFilter **res_p)
static int crlf_process (PushFilter *dst, void *priv, const uint8 *data, int len)
static int init_litdata_packet (PushFilter **pf_res, PGP_Context *ctx, PushFilter *dst)
static int init_compress (PushFilter **pf_res, PGP_Context *ctx, PushFilter *dst)
static int init_encdata_packet (PushFilter **pf_res, PGP_Context *ctx, PushFilter *dst)
static int write_prefix (PGP_Context *ctx, PushFilter *dst)
static int symencrypt_sesskey (PGP_Context *ctx, uint8 *dst)
static int write_symenc_sesskey (PGP_Context *ctx, PushFilter *dst)
static int init_s2k_key (PGP_Context *ctx)
static int init_sess_key (PGP_Context *ctx)
int pgp_encrypt (PGP_Context *ctx, MBuf *src, MBuf *dst)

Variables

static const PushFilterOps mdc_filter
static const PushFilterOps encrypt_filter
static const PushFilterOps pkt_stream_filter
static const PushFilterOps crlf_filter

Define Documentation

#define ENCBUF   8192

Definition at line 151 of file pgp-encrypt.c.

Referenced by encrypt_process().

#define MDC_DIGEST_LEN   20

Definition at line 41 of file pgp-encrypt.c.

Referenced by mdc_flush().

#define STREAM_BLOCK_SHIFT   14

Definition at line 43 of file pgp-encrypt.c.

#define STREAM_ID   0xE0

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

Referenced by pkt_stream_process().


Function Documentation

static int crlf_process ( PushFilter dst,
void *  priv,
const uint8 data,
int  len 
) [static]

Definition at line 327 of file pgp-encrypt.c.

References NULL, and pushf_write().

{
    const uint8 *data_end = data + len;
    const uint8 *p2,
               *p1 = data;
    int         line_len;
    static const uint8 crlf[] = {'\r', '\n'};
    int         res = 0;

    while (p1 < data_end)
    {
        p2 = memchr(p1, '\n', data_end - p1);
        if (p2 == NULL)
            p2 = data_end;

        line_len = p2 - p1;

        /* write data */
        res = 0;
        if (line_len > 0)
        {
            res = pushf_write(dst, p1, line_len);
            if (res < 0)
                break;
            p1 += line_len;
        }

        /* write crlf */
        while (p1 < data_end && *p1 == '\n')
        {
            res = pushf_write(dst, crlf, 2);
            if (res < 0)
                break;
            p1++;
        }
    }
    return res;
}

static void encrypt_free ( void *  priv  )  [static]

Definition at line 216 of file pgp-encrypt.c.

References px_free.

{
    struct EncStat *st = priv;

    memset(st, 0, sizeof(*st));
    px_free(st);
}

static int encrypt_init ( PushFilter next,
void *  init_arg,
void **  priv_p 
) [static]

Definition at line 159 of file pgp-encrypt.c.

References EncStat::ciph, PGP_Context::cipher_algo, PGP_Context::disable_mdc, NULL, pgp_cfb_create(), pushf_write(), px_alloc, PGP_Context::sess_key, and PGP_Context::sess_key_len.

{
    struct EncStat *st;
    PGP_Context *ctx = init_arg;
    PGP_CFB    *ciph;
    int         resync = 1;
    int         res;

    /* should we use newer packet format? */
    if (ctx->disable_mdc == 0)
    {
        uint8       ver = 1;

        resync = 0;
        res = pushf_write(next, &ver, 1);
        if (res < 0)
            return res;
    }
    res = pgp_cfb_create(&ciph, ctx->cipher_algo,
                         ctx->sess_key, ctx->sess_key_len, resync, NULL);
    if (res < 0)
        return res;

    st = px_alloc(sizeof(*st));
    memset(st, 0, sizeof(*st));
    st->ciph = ciph;

    *priv_p = st;
    return ENCBUF;
}

static int encrypt_process ( PushFilter next,
void *  priv,
const uint8 data,
int  len 
) [static]

Definition at line 191 of file pgp-encrypt.c.

References EncStat::buf, EncStat::ciph, ENCBUF, pgp_cfb_encrypt(), and pushf_write().

{
    int         res;
    struct EncStat *st = priv;
    int         avail = len;

    while (avail > 0)
    {
        int         tmplen = avail > ENCBUF ? ENCBUF : avail;

        res = pgp_cfb_encrypt(st->ciph, data, tmplen, st->buf);
        if (res < 0)
            return res;

        res = pushf_write(next, st->buf, tmplen);
        if (res < 0)
            return res;

        data += tmplen;
        avail -= tmplen;
    }
    return 0;
}

static int init_compress ( PushFilter **  pf_res,
PGP_Context ctx,
PushFilter dst 
) [static]

Definition at line 429 of file pgp-encrypt.c.

References PGP_Context::compress_algo, pgp_compress_filter(), PGP_PKT_COMPRESSED_DATA, pushf_create(), pushf_free(), pushf_write(), and write_tag_only().

Referenced by pgp_encrypt().

{
    int         res;
    uint8       type = ctx->compress_algo;
    PushFilter *pkt;

    res = write_tag_only(dst, PGP_PKT_COMPRESSED_DATA);
    if (res < 0)
        return res;

    res = pushf_create(&pkt, &pkt_stream_filter, ctx, dst);
    if (res < 0)
        return res;

    res = pushf_write(pkt, &type, 1);
    if (res >= 0)
        res = pgp_compress_filter(pf_res, ctx, pkt);

    if (res < 0)
        pushf_free(pkt);

    return res;
}

static int init_encdata_packet ( PushFilter **  pf_res,
PGP_Context ctx,
PushFilter dst 
) [static]

Definition at line 457 of file pgp-encrypt.c.

References PGP_Context::disable_mdc, pushf_create(), and write_tag_only().

Referenced by pgp_encrypt().

{
    int         res;
    int         tag;

    if (ctx->disable_mdc)
        tag = PGP_PKT_SYMENCRYPTED_DATA;
    else
        tag = PGP_PKT_SYMENCRYPTED_DATA_MDC;

    res = write_tag_only(dst, tag);
    if (res < 0)
        return res;

    return pushf_create(pf_res, &pkt_stream_filter, ctx, dst);
}

static int init_litdata_packet ( PushFilter **  pf_res,
PGP_Context ctx,
PushFilter dst 
) [static]

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

References NULL, PGP_PKT_LITERAL_DATA, pushf_create(), pushf_free(), pushf_write(), PGP_Context::text_mode, PGP_Context::unicode_mode, and write_tag_only().

Referenced by pgp_encrypt().

{
    int         res;
    int         hdrlen;
    uint8       hdr[6];
    uint32      t;
    PushFilter *pkt;
    int         type;

    /*
     * Create header
     */

    if (ctx->text_mode)
        type = ctx->unicode_mode ? 'u' : 't';
    else
        type = 'b';

    /*
     * Store the creation time into packet. The goal is to have as few known
     * bytes as possible.
     */
    t = (uint32) time(NULL);

    hdr[0] = type;
    hdr[1] = 0;
    hdr[2] = (t >> 24) & 255;
    hdr[3] = (t >> 16) & 255;
    hdr[4] = (t >> 8) & 255;
    hdr[5] = t & 255;
    hdrlen = 6;

    res = write_tag_only(dst, PGP_PKT_LITERAL_DATA);
    if (res < 0)
        return res;

    res = pushf_create(&pkt, &pkt_stream_filter, ctx, dst);
    if (res < 0)
        return res;

    res = pushf_write(pkt, hdr, hdrlen);
    if (res < 0)
    {
        pushf_free(pkt);
        return res;
    }

    *pf_res = pkt;
    return 0;
}

static int init_s2k_key ( PGP_Context ctx  )  [static]
static int init_sess_key ( PGP_Context ctx  )  [static]
static int mdc_flush ( PushFilter dst,
void *  priv 
) [static]

Definition at line 116 of file pgp-encrypt.c.

References MDC_DIGEST_LEN, pushf_write(), px_md_finish, and px_md_update.

{
    int         res;
    uint8       pkt[2 + MDC_DIGEST_LEN];
    PX_MD      *md = priv;

    /*
     * create mdc pkt
     */
    pkt[0] = 0xD3;
    pkt[1] = 0x14;              /* MDC_DIGEST_LEN */
    px_md_update(md, pkt, 2);
    px_md_finish(md, pkt + 2);

    res = pushf_write(dst, pkt, 2 + MDC_DIGEST_LEN);
    memset(pkt, 0, 2 + MDC_DIGEST_LEN);
    return res;
}

static void mdc_free ( void *  priv  )  [static]

Definition at line 136 of file pgp-encrypt.c.

References px_md_free.

{
    PX_MD      *md = priv;

    px_md_free(md);
}

static int mdc_init ( PushFilter dst,
void *  init_arg,
void **  priv_p 
) [static]

Definition at line 93 of file pgp-encrypt.c.

References PGP_DIGEST_SHA1, and pgp_load_digest().

{
    int         res;
    PX_MD      *md;

    res = pgp_load_digest(PGP_DIGEST_SHA1, &md);
    if (res < 0)
        return res;

    *priv_p = md;
    return 0;
}

static int mdc_write ( PushFilter dst,
void *  priv,
const uint8 data,
int  len 
) [static]

Definition at line 107 of file pgp-encrypt.c.

References pushf_write(), and px_md_update.

{
    PX_MD      *md = priv;

    px_md_update(md, data, len);
    return pushf_write(dst, data, len);
}

int pgp_create_pkt_writer ( PushFilter dst,
int  tag,
PushFilter **  res_p 
)

Definition at line 311 of file pgp-encrypt.c.

References NULL, pushf_create(), and write_tag_only().

Referenced by pgp_write_pubenc_sesskey().

{
    int         res;

    res = write_tag_only(dst, tag);
    if (res < 0)
        return res;

    return pushf_create(res_p, &pkt_stream_filter, NULL, dst);
}

int pgp_encrypt ( PGP_Context ctx,
MBuf src,
MBuf dst 
)

Definition at line 603 of file pgp-encrypt.c.

References buf, PGP_Context::compress_algo, PGP_Context::compress_level, PGP_Context::convert_crlf, PGP_Context::disable_mdc, init_compress(), init_encdata_packet(), init_litdata_packet(), init_s2k_key(), init_sess_key(), mbuf_avail(), mbuf_grab(), pgp_write_pubenc_sesskey(), PGP_Context::pub_key, pushf_create(), pushf_create_mbuf_writer(), pushf_flush(), pushf_free_all(), pushf_write(), PGP_Context::sym_key, PGP_Context::text_mode, write_prefix(), and write_symenc_sesskey().

Referenced by encrypt_internal().

{
    int         res;
    int         len;
    uint8      *buf;
    PushFilter *pf,
               *pf_tmp;

    /*
     * do we have any key
     */
    if (!ctx->sym_key && !ctx->pub_key)
        return PXE_ARGUMENT_ERROR;

    /* MBuf writer */
    res = pushf_create_mbuf_writer(&pf, dst);
    if (res < 0)
        goto out;

    /*
     * initialize symkey
     */
    if (ctx->sym_key)
    {
        res = init_s2k_key(ctx);
        if (res < 0)
            goto out;
    }

    res = init_sess_key(ctx);
    if (res < 0)
        goto out;

    /*
     * write keypkt
     */
    if (ctx->pub_key)
        res = pgp_write_pubenc_sesskey(ctx, pf);
    else
        res = write_symenc_sesskey(ctx, pf);
    if (res < 0)
        goto out;

    /* encrypted data pkt */
    res = init_encdata_packet(&pf_tmp, ctx, pf);
    if (res < 0)
        goto out;
    pf = pf_tmp;

    /* encrypter */
    res = pushf_create(&pf_tmp, &encrypt_filter, ctx, pf);
    if (res < 0)
        goto out;
    pf = pf_tmp;

    /* hasher */
    if (ctx->disable_mdc == 0)
    {
        res = pushf_create(&pf_tmp, &mdc_filter, ctx, pf);
        if (res < 0)
            goto out;
        pf = pf_tmp;
    }

    /* prefix */
    res = write_prefix(ctx, pf);
    if (res < 0)
        goto out;

    /* compressor */
    if (ctx->compress_algo > 0 && ctx->compress_level > 0)
    {
        res = init_compress(&pf_tmp, ctx, pf);
        if (res < 0)
            goto out;
        pf = pf_tmp;
    }

    /* data streamer */
    res = init_litdata_packet(&pf_tmp, ctx, pf);
    if (res < 0)
        goto out;
    pf = pf_tmp;


    /* text conversion? */
    if (ctx->text_mode && ctx->convert_crlf)
    {
        res = pushf_create(&pf_tmp, &crlf_filter, ctx, pf);
        if (res < 0)
            goto out;
        pf = pf_tmp;
    }

    /*
     * chain complete
     */

    len = mbuf_grab(src, mbuf_avail(src), &buf);
    res = pushf_write(pf, buf, len);
    if (res >= 0)
        res = pushf_flush(pf);
out:
    pushf_free_all(pf);
    return res;
}

static int pkt_stream_flush ( PushFilter next,
void *  priv 
) [static]

Definition at line 278 of file pgp-encrypt.c.

References PktStreamStat::final_done, pushf_write(), and render_newlen().

{
    int         res;
    uint8       hdr[8];
    uint8      *h = hdr;
    struct PktStreamStat *st = priv;

    /* stream MUST end with normal packet. */
    if (!st->final_done)
    {
        h = render_newlen(h, 0);
        res = pushf_write(next, hdr, h - hdr);
        if (res < 0)
            return res;
        st->final_done = 1;
    }
    return 0;
}

static void pkt_stream_free ( void *  priv  )  [static]

Definition at line 298 of file pgp-encrypt.c.

References px_free.

{
    struct PktStreamStat *st = priv;

    memset(st, 0, sizeof(*st));
    px_free(st);
}

static int pkt_stream_init ( PushFilter next,
void *  init_arg,
void **  priv_p 
) [static]

Definition at line 239 of file pgp-encrypt.c.

References PktStreamStat::final_done, PktStreamStat::pkt_block, and px_alloc.

{
    struct PktStreamStat *st;

    st = px_alloc(sizeof(*st));
    st->final_done = 0;
    st->pkt_block = 1 << STREAM_BLOCK_SHIFT;
    *priv_p = st;

    return st->pkt_block;
}

static int pkt_stream_process ( PushFilter next,
void *  priv,
const uint8 data,
int  len 
) [static]

Definition at line 252 of file pgp-encrypt.c.

References PktStreamStat::final_done, PktStreamStat::pkt_block, pushf_write(), render_newlen(), and STREAM_ID.

{
    int         res;
    uint8       hdr[8];
    uint8      *h = hdr;
    struct PktStreamStat *st = priv;

    if (st->final_done)
        return PXE_BUG;

    if (len == st->pkt_block)
        *h++ = STREAM_ID | STREAM_BLOCK_SHIFT;
    else
    {
        h = render_newlen(h, len);
        st->final_done = 1;
    }

    res = pushf_write(next, hdr, h - hdr);
    if (res < 0)
        return res;

    return pushf_write(next, data, len);
}

static uint8* render_newlen ( uint8 h,
int  len 
) [static]

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

Referenced by pkt_stream_flush(), pkt_stream_process(), and write_normal_header().

{
    if (len <= 191)
    {
        *h++ = len & 255;
    }
    else if (len > 191 && len <= 8383)
    {
        *h++ = ((len - 192) >> 8) + 192;
        *h++ = (len - 192) & 255;
    }
    else
    {
        *h++ = 255;
        *h++ = (len >> 24) & 255;
        *h++ = (len >> 16) & 255;
        *h++ = (len >> 8) & 255;
        *h++ = len & 255;
    }
    return h;
}

static int symencrypt_sesskey ( PGP_Context ctx,
uint8 dst 
) [static]

Definition at line 502 of file pgp-encrypt.c.

References PGP_Context::cipher_algo, PGP_S2K::key, PGP_S2K::key_len, NULL, pgp_cfb_create(), pgp_cfb_encrypt(), pgp_cfb_free(), PGP_Context::s2k, PGP_Context::s2k_cipher_algo, PGP_Context::sess_key, and PGP_Context::sess_key_len.

Referenced by write_symenc_sesskey().

{
    int         res;
    PGP_CFB    *cfb;
    uint8       algo = ctx->cipher_algo;

    res = pgp_cfb_create(&cfb, ctx->s2k_cipher_algo,
                         ctx->s2k.key, ctx->s2k.key_len, 0, NULL);
    if (res < 0)
        return res;

    pgp_cfb_encrypt(cfb, &algo, 1, dst);
    pgp_cfb_encrypt(cfb, ctx->sess_key, ctx->sess_key_len, dst + 1);

    pgp_cfb_free(cfb);
    return ctx->sess_key_len + 1;
}

static int write_normal_header ( PushFilter dst,
int  tag,
int  len 
) [static]

Definition at line 77 of file pgp-encrypt.c.

References pushf_write(), and render_newlen().

Referenced by write_symenc_sesskey().

{
    uint8       hdr[8];
    uint8      *h = hdr;

    *h++ = 0xC0 | tag;
    h = render_newlen(h, len);
    return pushf_write(dst, hdr, h - hdr);
}

static int write_prefix ( PGP_Context ctx,
PushFilter dst 
) [static]

Definition at line 478 of file pgp-encrypt.c.

References PGP_Context::cipher_algo, pgp_get_cipher_block_size(), PGP_MAX_BLOCK, pushf_write(), and px_get_random_bytes().

Referenced by pgp_encrypt().

{
    uint8       prefix[PGP_MAX_BLOCK + 2];
    int         res,
                bs;

    bs = pgp_get_cipher_block_size(ctx->cipher_algo);
    res = px_get_random_bytes(prefix, bs);
    if (res < 0)
        return res;

    prefix[bs + 0] = prefix[bs - 2];
    prefix[bs + 1] = prefix[bs - 1];

    res = pushf_write(dst, prefix, bs + 2);
    memset(prefix, 0, bs + 2);
    return res < 0 ? res : 0;
}

static int write_symenc_sesskey ( PGP_Context ctx,
PushFilter dst 
) [static]

Definition at line 522 of file pgp-encrypt.c.

References PGP_S2K::digest_algo, PGP_S2K::iter, PGP_S2K::mode, PGP_PKT_SYMENCRYPTED_SESSKEY, pushf_write(), PGP_Context::s2k, PGP_Context::s2k_cipher_algo, PGP_S2K::salt, symencrypt_sesskey(), PGP_Context::use_sess_key, and write_normal_header().

Referenced by pgp_encrypt().

{
    uint8       pkt[256];
    int         pktlen;
    int         res;
    uint8      *p = pkt;

    *p++ = 4;                   /* 5.3 - version number  */
    *p++ = ctx->s2k_cipher_algo;

    *p++ = ctx->s2k.mode;
    *p++ = ctx->s2k.digest_algo;
    if (ctx->s2k.mode > 0)
    {
        memcpy(p, ctx->s2k.salt, 8);
        p += 8;
    }
    if (ctx->s2k.mode == 3)
        *p++ = ctx->s2k.iter;

    if (ctx->use_sess_key)
    {
        res = symencrypt_sesskey(ctx, p);
        if (res < 0)
            return res;
        p += res;
    }

    pktlen = p - pkt;
    res = write_normal_header(dst, PGP_PKT_SYMENCRYPTED_SESSKEY, pktlen);
    if (res >= 0)
        res = pushf_write(dst, pkt, pktlen);

    memset(pkt, 0, pktlen);
    return res;
}

static int write_tag_only ( PushFilter dst,
int  tag 
) [static]

Definition at line 69 of file pgp-encrypt.c.

References pushf_write().

Referenced by init_compress(), init_encdata_packet(), init_litdata_packet(), and pgp_create_pkt_writer().

{
    uint8       hdr = 0xC0 | tag;

    return pushf_write(dst, &hdr, 1);
}


Variable Documentation

const PushFilterOps crlf_filter [static]
Initial value:
 {
    NULL, crlf_process, NULL, NULL
}

Definition at line 366 of file pgp-encrypt.c.

const PushFilterOps encrypt_filter [static]
Initial value:
 {
    encrypt_init, encrypt_process, NULL, encrypt_free
}

Definition at line 224 of file pgp-encrypt.c.

const PushFilterOps mdc_filter [static]
Initial value:
 {
    mdc_init, mdc_write, mdc_flush, mdc_free
}

Definition at line 143 of file pgp-encrypt.c.

Initial value:
 {
    pkt_stream_init, pkt_stream_process, pkt_stream_flush, pkt_stream_free
}

Definition at line 306 of file pgp-encrypt.c.