PostgreSQL Source Code  git master
pgp-pubenc.c
Go to the documentation of this file.
1 /*
2  * pgp-pubenc.c
3  * Encrypt session key with public key.
4  *
5  * Copyright (c) 2005 Marko Kreen
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * contrib/pgcrypto/pgp-pubenc.c
30  */
31 #include "postgres.h"
32 
33 #include "px.h"
34 #include "pgp.h"
35 
36 /*
37  * padded msg: 02 || non-zero pad bytes || 00 || msg
38  */
39 static int
40 pad_eme_pkcs1_v15(uint8 *data, int data_len, int res_len, uint8 **res_p)
41 {
42  uint8 *buf,
43  *p;
44  int pad_len = res_len - 2 - data_len;
45 
46  if (pad_len < 8)
47  return PXE_BUG;
48 
49  buf = px_alloc(res_len);
50  buf[0] = 0x02;
51 
52  if (!pg_strong_random(buf + 1, pad_len))
53  {
54  px_free(buf);
55  return PXE_NO_RANDOM;
56  }
57 
58  /* pad must not contain zero bytes */
59  p = buf + 1;
60  while (p < buf + 1 + pad_len)
61  {
62  if (*p == 0)
63  {
64  if (!pg_strong_random(p, 1))
65  {
66  px_memset(buf, 0, res_len);
67  px_free(buf);
68  return PXE_NO_RANDOM;
69  }
70  }
71  if (*p != 0)
72  p++;
73  }
74 
75  buf[pad_len + 1] = 0;
76  memcpy(buf + pad_len + 2, data, data_len);
77  *res_p = buf;
78 
79  return 0;
80 }
81 
82 static int
83 create_secmsg(PGP_Context *ctx, PGP_MPI **msg_p, int full_bytes)
84 {
85  uint8 *secmsg;
86  int res,
87  i;
88  unsigned cksum = 0;
89  int klen = ctx->sess_key_len;
90  uint8 *padded = NULL;
91  PGP_MPI *m = NULL;
92 
93  /* calc checksum */
94  for (i = 0; i < klen; i++)
95  cksum += ctx->sess_key[i];
96 
97  /*
98  * create "secret message"
99  */
100  secmsg = px_alloc(klen + 3);
101  secmsg[0] = ctx->cipher_algo;
102  memcpy(secmsg + 1, ctx->sess_key, klen);
103  secmsg[klen + 1] = (cksum >> 8) & 0xFF;
104  secmsg[klen + 2] = cksum & 0xFF;
105 
106  /*
107  * now create a large integer of it
108  */
109  res = pad_eme_pkcs1_v15(secmsg, klen + 3, full_bytes, &padded);
110  if (res >= 0)
111  {
112  /* first byte will be 0x02 */
113  int full_bits = full_bytes * 8 - 6;
114 
115  res = pgp_mpi_create(padded, full_bits, &m);
116  }
117 
118  if (padded)
119  {
120  px_memset(padded, 0, full_bytes);
121  px_free(padded);
122  }
123  px_memset(secmsg, 0, klen + 3);
124  px_free(secmsg);
125 
126  if (res >= 0)
127  *msg_p = m;
128 
129  return res;
130 }
131 
132 static int
134 {
135  int res;
136  PGP_MPI *m = NULL,
137  *c1 = NULL,
138  *c2 = NULL;
139 
140  /* create padded msg */
141  res = create_secmsg(ctx, &m, pk->pub.elg.p->bytes - 1);
142  if (res < 0)
143  goto err;
144 
145  /* encrypt it */
146  res = pgp_elgamal_encrypt(pk, m, &c1, &c2);
147  if (res < 0)
148  goto err;
149 
150  /* write out */
151  res = pgp_mpi_write(pkt, c1);
152  if (res < 0)
153  goto err;
154  res = pgp_mpi_write(pkt, c2);
155 
156 err:
157  pgp_mpi_free(m);
158  pgp_mpi_free(c1);
159  pgp_mpi_free(c2);
160  return res;
161 }
162 
163 static int
165 {
166  int res;
167  PGP_MPI *m = NULL,
168  *c = NULL;
169 
170  /* create padded msg */
171  res = create_secmsg(ctx, &m, pk->pub.rsa.n->bytes - 1);
172  if (res < 0)
173  goto err;
174 
175  /* encrypt it */
176  res = pgp_rsa_encrypt(pk, m, &c);
177  if (res < 0)
178  goto err;
179 
180  /* write out */
181  res = pgp_mpi_write(pkt, c);
182 
183 err:
184  pgp_mpi_free(m);
185  pgp_mpi_free(c);
186  return res;
187 }
188 
189 int
191 {
192  int res;
193  PGP_PubKey *pk = ctx->pub_key;
194  uint8 ver = 3;
195  PushFilter *pkt = NULL;
196  uint8 algo;
197 
198  if (pk == NULL)
199  {
200  px_debug("no pubkey?\n");
201  return PXE_BUG;
202  }
203 
204  algo = pk->algo;
205 
206  /*
207  * now write packet
208  */
210  if (res < 0)
211  goto err;
212  res = pushf_write(pkt, &ver, 1);
213  if (res < 0)
214  goto err;
215  res = pushf_write(pkt, pk->key_id, 8);
216  if (res < 0)
217  goto err;
218  res = pushf_write(pkt, &algo, 1);
219  if (res < 0)
220  goto err;
221 
222  switch (algo)
223  {
224  case PGP_PUB_ELG_ENCRYPT:
225  res = encrypt_and_write_elgamal(ctx, pk, pkt);
226  break;
227  case PGP_PUB_RSA_ENCRYPT:
229  res = encrypt_and_write_rsa(ctx, pk, pkt);
230  break;
231  }
232  if (res < 0)
233  goto err;
234 
235  /*
236  * done, signal packet end
237  */
238  res = pushf_flush(pkt);
239 err:
240  if (pkt)
241  pushf_free(pkt);
242 
243  return res;
244 }
void pushf_free(PushFilter *mp)
Definition: mbuf.c:412
struct PGP_PubKey::@5::@7 elg
int cipher_algo
Definition: pgp.h:144
int pushf_flush(PushFilter *mp)
Definition: mbuf.c:516
int pgp_write_pubenc_sesskey(PGP_Context *ctx, PushFilter *dst)
Definition: pgp-pubenc.c:190
#define px_free(p)
Definition: px.h:46
unsigned char uint8
Definition: c.h:356
int pgp_mpi_write(PushFilter *dst, PGP_MPI *n)
Definition: pgp-mpi.c:105
#define PXE_NO_RANDOM
Definition: px.h:75
static int encrypt_and_write_rsa(PGP_Context *ctx, PGP_PubKey *pk, PushFilter *pkt)
Definition: pgp-pubenc.c:164
int pgp_create_pkt_writer(PushFilter *dst, int tag, PushFilter **res_p)
Definition: pgp-encrypt.c:313
static int pad_eme_pkcs1_v15(uint8 *data, int data_len, int res_len, uint8 **res_p)
Definition: pgp-pubenc.c:40
static int create_secmsg(PGP_Context *ctx, PGP_MPI **msg_p, int full_bytes)
Definition: pgp-pubenc.c:83
static int encrypt_and_write_elgamal(PGP_Context *ctx, PGP_PubKey *pk, PushFilter *pkt)
Definition: pgp-pubenc.c:133
uint8 sess_key[PGP_MAX_KEY]
Definition: pgp.h:171
struct PGP_PubKey::@5::@8 rsa
int pgp_elgamal_encrypt(PGP_PubKey *pk, PGP_MPI *_m, PGP_MPI **c1_p, PGP_MPI **c2_p)
char * c
static char * buf
Definition: pg_test_fsync.c:68
int pgp_rsa_encrypt(PGP_PubKey *pk, PGP_MPI *_m, PGP_MPI **c_p)
#define PXE_BUG
Definition: px.h:70
Definition: pgp.h:179
int pgp_mpi_free(PGP_MPI *mpi)
Definition: pgp-mpi.c:70
bool pg_strong_random(void *buf, size_t len)
unsigned sess_key_len
Definition: pgp.h:172
void px_debug(const char *fmt,...)
Definition: px.c:152
uint8 key_id[8]
Definition: pgp.h:235
union PGP_PubKey::@5 pub
uint8 algo
Definition: pgp.h:190
#define px_alloc(s)
Definition: px.h:44
int i
PGP_PubKey * pub_key
Definition: pgp.h:164
int pgp_mpi_create(uint8 *data, int bits, PGP_MPI **mpi)
Definition: pgp-mpi.c:56
int pushf_write(PushFilter *mp, const uint8 *data, int len)
Definition: mbuf.c:456
void px_memset(void *ptr, int c, size_t len)
Definition: px.c:126