/contrib/pgcrypto/pgp-pubenc.c
https://gitlab.com/kush/jarulraj-postgresql-cpp · C · 249 lines · 162 code · 33 blank · 54 comment · 27 complexity · 2334c2015b237e1a763b4999ed28487e MD5 · raw file
- /*
- * pgp-pubenc.c
- * Encrypt session key with public key.
- *
- * Copyright (c) 2005 Marko Kreen
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * contrib/pgcrypto/pgp-pubenc.c
- */
- #include "postgres.h"
- #include "px.h"
- #include "pgp.h"
- /*
- * padded msg: 02 || non-zero pad bytes || 00 || msg
- */
- static int
- pad_eme_pkcs1_v15(uint8 *data, int data_len, int res_len, uint8 **res_p)
- {
- 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)
- {
- px_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;
- }
- static int
- create_secmsg(PGP_Context *ctx, PGP_MPI **msg_p, int full_bytes)
- {
- 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)
- {
- px_memset(padded, 0, full_bytes);
- px_free(padded);
- }
- px_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)
- {
- 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)
- {
- 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;
- }
- int
- pgp_write_pubenc_sesskey(PGP_Context *ctx, PushFilter *dst)
- {
- 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;
- }