Header And Logo

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

Functions

pgp-pubenc.c File Reference

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

Go to the source code of this file.

Functions

static int pad_eme_pkcs1_v15 (uint8 *data, int data_len, int res_len, uint8 **res_p)
static int create_secmsg (PGP_Context *ctx, PGP_MPI **msg_p, int full_bytes)
static int encrypt_and_write_elgamal (PGP_Context *ctx, PGP_PubKey *pk, PushFilter *pkt)
static int encrypt_and_write_rsa (PGP_Context *ctx, PGP_PubKey *pk, PushFilter *pkt)
int pgp_write_pubenc_sesskey (PGP_Context *ctx, PushFilter *dst)

Function Documentation

static int create_secmsg ( PGP_Context ctx,
PGP_MPI **  msg_p,
int  full_bytes 
) [static]

Definition at line 89 of file pgp-pubenc.c.

References PGP_Context::cipher_algo, i, pad_eme_pkcs1_v15(), pgp_mpi_create(), px_alloc, px_free, PGP_Context::sess_key, and PGP_Context::sess_key_len.

Referenced by encrypt_and_write_elgamal(), and encrypt_and_write_rsa().

{
    uint8      *secmsg;
    int         res,
                i;
    unsigned    cksum = 0;
    int         klen = ctx->sess_key_len;
    uint8      *padded = NULL;
    PGP_MPI    *m = NULL;

    /* calc checksum */
    for (i = 0; i < klen; i++)
        cksum += ctx->sess_key[i];

    /*
     * create "secret message"
     */
    secmsg = px_alloc(klen + 3);
    secmsg[0] = ctx->cipher_algo;
    memcpy(secmsg + 1, ctx->sess_key, klen);
    secmsg[klen + 1] = (cksum >> 8) & 0xFF;
    secmsg[klen + 2] = cksum & 0xFF;

    /*
     * now create a large integer of it
     */
    res = pad_eme_pkcs1_v15(secmsg, klen + 3, full_bytes, &padded);
    if (res >= 0)
    {
        /* first byte will be 0x02 */
        int         full_bits = full_bytes * 8 - 6;

        res = pgp_mpi_create(padded, full_bits, &m);
    }

    if (padded)
    {
        memset(padded, 0, full_bytes);
        px_free(padded);
    }
    memset(secmsg, 0, klen + 3);
    px_free(secmsg);

    if (res >= 0)
        *msg_p = m;

    return res;
}

static int encrypt_and_write_elgamal ( PGP_Context ctx,
PGP_PubKey pk,
PushFilter pkt 
) [static]

Definition at line 139 of file pgp-pubenc.c.

References create_secmsg(), PGP_PubKey::elg, pgp_elgamal_encrypt(), pgp_mpi_free(), pgp_mpi_write(), and PGP_PubKey::pub.

Referenced by pgp_write_pubenc_sesskey().

{
    int         res;
    PGP_MPI    *m = NULL,
               *c1 = NULL,
               *c2 = NULL;

    /* create padded msg */
    res = create_secmsg(ctx, &m, pk->pub.elg.p->bytes - 1);
    if (res < 0)
        goto err;

    /* encrypt it */
    res = pgp_elgamal_encrypt(pk, m, &c1, &c2);
    if (res < 0)
        goto err;

    /* write out */
    res = pgp_mpi_write(pkt, c1);
    if (res < 0)
        goto err;
    res = pgp_mpi_write(pkt, c2);

err:
    pgp_mpi_free(m);
    pgp_mpi_free(c1);
    pgp_mpi_free(c2);
    return res;
}

static int encrypt_and_write_rsa ( PGP_Context ctx,
PGP_PubKey pk,
PushFilter pkt 
) [static]

Definition at line 170 of file pgp-pubenc.c.

References create_secmsg(), pgp_mpi_free(), pgp_mpi_write(), pgp_rsa_encrypt(), PGP_PubKey::pub, and PGP_PubKey::rsa.

Referenced by pgp_write_pubenc_sesskey().

{
    int         res;
    PGP_MPI    *m = NULL,
               *c = NULL;

    /* create padded msg */
    res = create_secmsg(ctx, &m, pk->pub.rsa.n->bytes - 1);
    if (res < 0)
        goto err;

    /* encrypt it */
    res = pgp_rsa_encrypt(pk, m, &c);
    if (res < 0)
        goto err;

    /* write out */
    res = pgp_mpi_write(pkt, c);

err:
    pgp_mpi_free(m);
    pgp_mpi_free(c);
    return res;
}

static int pad_eme_pkcs1_v15 ( uint8 data,
int  data_len,
int  res_len,
uint8 **  res_p 
) [static]

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

References buf, px_alloc, px_free, and px_get_random_bytes().

Referenced by create_secmsg().

{
    int         res;
    uint8      *buf,
               *p;
    int         pad_len = res_len - 2 - data_len;

    if (pad_len < 8)
        return PXE_BUG;

    buf = px_alloc(res_len);
    buf[0] = 0x02;
    res = px_get_random_bytes(buf + 1, pad_len);
    if (res < 0)
    {
        px_free(buf);
        return res;
    }

    /* pad must not contain zero bytes */
    p = buf + 1;
    while (p < buf + 1 + pad_len)
    {
        if (*p == 0)
        {
            res = px_get_random_bytes(p, 1);
            if (res < 0)
                break;
        }
        if (*p != 0)
            p++;
    }

    if (res < 0)
    {
        memset(buf, 0, res_len);
        px_free(buf);
        return res;
    }

    buf[pad_len + 1] = 0;
    memcpy(buf + pad_len + 2, data, data_len);
    *res_p = buf;

    return 0;
}

int pgp_write_pubenc_sesskey ( PGP_Context ctx,
PushFilter dst 
)

Definition at line 196 of file pgp-pubenc.c.

References PGP_PubKey::algo, encrypt_and_write_elgamal(), encrypt_and_write_rsa(), PGP_PubKey::key_id, NULL, pgp_create_pkt_writer(), PGP_PKT_PUBENCRYPTED_SESSKEY, PGP_PUB_ELG_ENCRYPT, PGP_PUB_RSA_ENCRYPT, PGP_PUB_RSA_ENCRYPT_SIGN, PGP_Context::pub_key, pushf_flush(), pushf_free(), pushf_write(), and px_debug().

Referenced by pgp_encrypt().

{
    int         res;
    PGP_PubKey *pk = ctx->pub_key;
    uint8       ver = 3;
    PushFilter *pkt = NULL;
    uint8       algo;

    if (pk == NULL)
    {
        px_debug("no pubkey?\n");
        return PXE_BUG;
    }

    algo = pk->algo;

    /*
     * now write packet
     */
    res = pgp_create_pkt_writer(dst, PGP_PKT_PUBENCRYPTED_SESSKEY, &pkt);
    if (res < 0)
        goto err;
    res = pushf_write(pkt, &ver, 1);
    if (res < 0)
        goto err;
    res = pushf_write(pkt, pk->key_id, 8);
    if (res < 0)
        goto err;
    res = pushf_write(pkt, &algo, 1);
    if (res < 0)
        goto err;

    switch (algo)
    {
        case PGP_PUB_ELG_ENCRYPT:
            res = encrypt_and_write_elgamal(ctx, pk, pkt);
            break;
        case PGP_PUB_RSA_ENCRYPT:
        case PGP_PUB_RSA_ENCRYPT_SIGN:
            res = encrypt_and_write_rsa(ctx, pk, pkt);
            break;
    }
    if (res < 0)
        goto err;

    /*
     * done, signal packet end
     */
    res = pushf_flush(pkt);
err:
    if (pkt)
        pushf_free(pkt);

    return res;
}