OSDN Git Service

Merge branch 'REL9_0_STABLE' into pgrex90-base
[pg-rex/syncrep.git] / contrib / pgcrypto / pgp-pubkey.c
1 /*
2  * pgp-pubkey.c
3  *        Read public or secret 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  * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pubkey.c,v 1.5 2009/06/11 14:48:52 momjian Exp $
30  */
31 #include "postgres.h"
32
33 #include "px.h"
34 #include "mbuf.h"
35 #include "pgp.h"
36
37 int
38 pgp_key_alloc(PGP_PubKey **pk_p)
39 {
40         PGP_PubKey *pk;
41
42         pk = px_alloc(sizeof(*pk));
43         memset(pk, 0, sizeof(*pk));
44         *pk_p = pk;
45         return 0;
46 }
47
48 void
49 pgp_key_free(PGP_PubKey *pk)
50 {
51         if (pk == NULL)
52                 return;
53
54         switch (pk->algo)
55         {
56                 case PGP_PUB_ELG_ENCRYPT:
57                         pgp_mpi_free(pk->pub.elg.p);
58                         pgp_mpi_free(pk->pub.elg.g);
59                         pgp_mpi_free(pk->pub.elg.y);
60                         pgp_mpi_free(pk->sec.elg.x);
61                         break;
62                 case PGP_PUB_RSA_SIGN:
63                 case PGP_PUB_RSA_ENCRYPT:
64                 case PGP_PUB_RSA_ENCRYPT_SIGN:
65                         pgp_mpi_free(pk->pub.rsa.n);
66                         pgp_mpi_free(pk->pub.rsa.e);
67                         pgp_mpi_free(pk->sec.rsa.d);
68                         pgp_mpi_free(pk->sec.rsa.p);
69                         pgp_mpi_free(pk->sec.rsa.q);
70                         pgp_mpi_free(pk->sec.rsa.u);
71                         break;
72                 case PGP_PUB_DSA_SIGN:
73                         pgp_mpi_free(pk->pub.dsa.p);
74                         pgp_mpi_free(pk->pub.dsa.q);
75                         pgp_mpi_free(pk->pub.dsa.g);
76                         pgp_mpi_free(pk->pub.dsa.y);
77                         pgp_mpi_free(pk->sec.dsa.x);
78                         break;
79         }
80         memset(pk, 0, sizeof(*pk));
81         px_free(pk);
82 }
83
84 static int
85 calc_key_id(PGP_PubKey *pk)
86 {
87         int                     res;
88         PX_MD      *md;
89         int                     len;
90         uint8           hdr[3];
91         uint8           hash[20];
92
93         res = pgp_load_digest(PGP_DIGEST_SHA1, &md);
94         if (res < 0)
95                 return res;
96
97         len = 1 + 4 + 1;
98         switch (pk->algo)
99         {
100                 case PGP_PUB_ELG_ENCRYPT:
101                         len += 2 + pk->pub.elg.p->bytes;
102                         len += 2 + pk->pub.elg.g->bytes;
103                         len += 2 + pk->pub.elg.y->bytes;
104                         break;
105                 case PGP_PUB_RSA_SIGN:
106                 case PGP_PUB_RSA_ENCRYPT:
107                 case PGP_PUB_RSA_ENCRYPT_SIGN:
108                         len += 2 + pk->pub.rsa.n->bytes;
109                         len += 2 + pk->pub.rsa.e->bytes;
110                         break;
111                 case PGP_PUB_DSA_SIGN:
112                         len += 2 + pk->pub.dsa.p->bytes;
113                         len += 2 + pk->pub.dsa.q->bytes;
114                         len += 2 + pk->pub.dsa.g->bytes;
115                         len += 2 + pk->pub.dsa.y->bytes;
116                         break;
117         }
118
119         hdr[0] = 0x99;
120         hdr[1] = len >> 8;
121         hdr[2] = len & 0xFF;
122         px_md_update(md, hdr, 3);
123
124         px_md_update(md, &pk->ver, 1);
125         px_md_update(md, pk->time, 4);
126         px_md_update(md, &pk->algo, 1);
127
128         switch (pk->algo)
129         {
130                 case PGP_PUB_ELG_ENCRYPT:
131                         pgp_mpi_hash(md, pk->pub.elg.p);
132                         pgp_mpi_hash(md, pk->pub.elg.g);
133                         pgp_mpi_hash(md, pk->pub.elg.y);
134                         break;
135                 case PGP_PUB_RSA_SIGN:
136                 case PGP_PUB_RSA_ENCRYPT:
137                 case PGP_PUB_RSA_ENCRYPT_SIGN:
138                         pgp_mpi_hash(md, pk->pub.rsa.n);
139                         pgp_mpi_hash(md, pk->pub.rsa.e);
140                         break;
141                 case PGP_PUB_DSA_SIGN:
142                         pgp_mpi_hash(md, pk->pub.dsa.p);
143                         pgp_mpi_hash(md, pk->pub.dsa.q);
144                         pgp_mpi_hash(md, pk->pub.dsa.g);
145                         pgp_mpi_hash(md, pk->pub.dsa.y);
146                         break;
147         }
148
149         px_md_finish(md, hash);
150         px_md_free(md);
151
152         memcpy(pk->key_id, hash + 12, 8);
153         memset(hash, 0, 20);
154
155         return 0;
156 }
157
158 int
159 _pgp_read_public_key(PullFilter *pkt, PGP_PubKey **pk_p)
160 {
161         int                     res;
162         PGP_PubKey *pk;
163
164         res = pgp_key_alloc(&pk);
165         if (res < 0)
166                 return res;
167
168         /* get version */
169         GETBYTE(pkt, pk->ver);
170         if (pk->ver != 4)
171         {
172                 res = PXE_PGP_NOT_V4_KEYPKT;
173                 goto out;
174         }
175
176         /* read time */
177         res = pullf_read_fixed(pkt, 4, pk->time);
178         if (res < 0)
179                 goto out;
180
181         /* pubkey algorithm */
182         GETBYTE(pkt, pk->algo);
183
184         switch (pk->algo)
185         {
186                 case PGP_PUB_DSA_SIGN:
187                         res = pgp_mpi_read(pkt, &pk->pub.dsa.p);
188                         if (res < 0)
189                                 break;
190                         res = pgp_mpi_read(pkt, &pk->pub.dsa.q);
191                         if (res < 0)
192                                 break;
193                         res = pgp_mpi_read(pkt, &pk->pub.dsa.g);
194                         if (res < 0)
195                                 break;
196                         res = pgp_mpi_read(pkt, &pk->pub.dsa.y);
197                         if (res < 0)
198                                 break;
199
200                         res = calc_key_id(pk);
201                         break;
202
203                 case PGP_PUB_RSA_SIGN:
204                 case PGP_PUB_RSA_ENCRYPT:
205                 case PGP_PUB_RSA_ENCRYPT_SIGN:
206                         res = pgp_mpi_read(pkt, &pk->pub.rsa.n);
207                         if (res < 0)
208                                 break;
209                         res = pgp_mpi_read(pkt, &pk->pub.rsa.e);
210                         if (res < 0)
211                                 break;
212
213                         res = calc_key_id(pk);
214
215                         if (pk->algo != PGP_PUB_RSA_SIGN)
216                                 pk->can_encrypt = 1;
217                         break;
218
219                 case PGP_PUB_ELG_ENCRYPT:
220                         res = pgp_mpi_read(pkt, &pk->pub.elg.p);
221                         if (res < 0)
222                                 break;
223                         res = pgp_mpi_read(pkt, &pk->pub.elg.g);
224                         if (res < 0)
225                                 break;
226                         res = pgp_mpi_read(pkt, &pk->pub.elg.y);
227                         if (res < 0)
228                                 break;
229
230                         res = calc_key_id(pk);
231
232                         pk->can_encrypt = 1;
233                         break;
234
235                 default:
236                         px_debug("unknown public algo: %d", pk->algo);
237                         res = PXE_PGP_UNKNOWN_PUBALGO;
238         }
239
240 out:
241         if (res < 0)
242                 pgp_key_free(pk);
243         else
244                 *pk_p = pk;
245
246         return res;
247 }
248
249 #define HIDE_CLEAR 0
250 #define HIDE_CKSUM 255
251 #define HIDE_SHA1 254
252
253 static int
254 check_key_sha1(PullFilter *src, PGP_PubKey *pk)
255 {
256         int                     res;
257         uint8           got_sha1[20];
258         uint8           my_sha1[20];
259         PX_MD      *md;
260
261         res = pullf_read_fixed(src, 20, got_sha1);
262         if (res < 0)
263                 return res;
264
265         res = pgp_load_digest(PGP_DIGEST_SHA1, &md);
266         if (res < 0)
267                 goto err;
268         switch (pk->algo)
269         {
270                 case PGP_PUB_ELG_ENCRYPT:
271                         pgp_mpi_hash(md, pk->sec.elg.x);
272                         break;
273                 case PGP_PUB_RSA_SIGN:
274                 case PGP_PUB_RSA_ENCRYPT:
275                 case PGP_PUB_RSA_ENCRYPT_SIGN:
276                         pgp_mpi_hash(md, pk->sec.rsa.d);
277                         pgp_mpi_hash(md, pk->sec.rsa.p);
278                         pgp_mpi_hash(md, pk->sec.rsa.q);
279                         pgp_mpi_hash(md, pk->sec.rsa.u);
280                         break;
281                 case PGP_PUB_DSA_SIGN:
282                         pgp_mpi_hash(md, pk->sec.dsa.x);
283                         break;
284         }
285         px_md_finish(md, my_sha1);
286         px_md_free(md);
287
288         if (memcmp(my_sha1, got_sha1, 20) != 0)
289         {
290                 px_debug("key sha1 check failed");
291                 res = PXE_PGP_KEYPKT_CORRUPT;
292         }
293 err:
294         memset(got_sha1, 0, 20);
295         memset(my_sha1, 0, 20);
296         return res;
297 }
298
299 static int
300 check_key_cksum(PullFilter *src, PGP_PubKey *pk)
301 {
302         int                     res;
303         unsigned        got_cksum,
304                                 my_cksum = 0;
305         uint8           buf[2];
306
307         res = pullf_read_fixed(src, 2, buf);
308         if (res < 0)
309                 return res;
310
311         got_cksum = ((unsigned) buf[0] << 8) + buf[1];
312         switch (pk->algo)
313         {
314                 case PGP_PUB_ELG_ENCRYPT:
315                         my_cksum = pgp_mpi_cksum(0, pk->sec.elg.x);
316                         break;
317                 case PGP_PUB_RSA_SIGN:
318                 case PGP_PUB_RSA_ENCRYPT:
319                 case PGP_PUB_RSA_ENCRYPT_SIGN:
320                         my_cksum = pgp_mpi_cksum(0, pk->sec.rsa.d);
321                         my_cksum = pgp_mpi_cksum(my_cksum, pk->sec.rsa.p);
322                         my_cksum = pgp_mpi_cksum(my_cksum, pk->sec.rsa.q);
323                         my_cksum = pgp_mpi_cksum(my_cksum, pk->sec.rsa.u);
324                         break;
325                 case PGP_PUB_DSA_SIGN:
326                         my_cksum = pgp_mpi_cksum(0, pk->sec.dsa.x);
327                         break;
328         }
329         if (my_cksum != got_cksum)
330         {
331                 px_debug("key cksum check failed");
332                 return PXE_PGP_KEYPKT_CORRUPT;
333         }
334         return 0;
335 }
336
337 static int
338 process_secret_key(PullFilter *pkt, PGP_PubKey **pk_p,
339                                    const uint8 *key, int key_len)
340 {
341         int                     res;
342         int                     hide_type;
343         int                     cipher_algo;
344         int                     bs;
345         uint8           iv[512];
346         PullFilter *pf_decrypt = NULL,
347                            *pf_key;
348         PGP_CFB    *cfb = NULL;
349         PGP_S2K         s2k;
350         PGP_PubKey *pk;
351
352         /* first read public key part */
353         res = _pgp_read_public_key(pkt, &pk);
354         if (res < 0)
355                 return res;
356
357         /*
358          * is secret key encrypted?
359          */
360         GETBYTE(pkt, hide_type);
361         if (hide_type == HIDE_SHA1 || hide_type == HIDE_CKSUM)
362         {
363                 if (key == NULL)
364                         return PXE_PGP_NEED_SECRET_PSW;
365                 GETBYTE(pkt, cipher_algo);
366                 res = pgp_s2k_read(pkt, &s2k);
367                 if (res < 0)
368                         return res;
369
370                 res = pgp_s2k_process(&s2k, cipher_algo, key, key_len);
371                 if (res < 0)
372                         return res;
373
374                 bs = pgp_get_cipher_block_size(cipher_algo);
375                 if (bs == 0)
376                 {
377                         px_debug("unknown cipher algo=%d", cipher_algo);
378                         return PXE_PGP_UNSUPPORTED_CIPHER;
379                 }
380                 res = pullf_read_fixed(pkt, bs, iv);
381                 if (res < 0)
382                         return res;
383
384                 /*
385                  * create decrypt filter
386                  */
387                 res = pgp_cfb_create(&cfb, cipher_algo, s2k.key, s2k.key_len, 0, iv);
388                 if (res < 0)
389                         return res;
390                 res = pullf_create(&pf_decrypt, &pgp_decrypt_filter, cfb, pkt);
391                 if (res < 0)
392                         return res;
393                 pf_key = pf_decrypt;
394         }
395         else if (hide_type == HIDE_CLEAR)
396         {
397                 pf_key = pkt;
398         }
399         else
400         {
401                 px_debug("unknown hide type");
402                 return PXE_PGP_KEYPKT_CORRUPT;
403         }
404
405         /* read secret key */
406         switch (pk->algo)
407         {
408                 case PGP_PUB_RSA_SIGN:
409                 case PGP_PUB_RSA_ENCRYPT:
410                 case PGP_PUB_RSA_ENCRYPT_SIGN:
411                         res = pgp_mpi_read(pkt, &pk->sec.rsa.d);
412                         if (res < 0)
413                                 break;
414                         res = pgp_mpi_read(pkt, &pk->sec.rsa.p);
415                         if (res < 0)
416                                 break;
417                         res = pgp_mpi_read(pkt, &pk->sec.rsa.q);
418                         if (res < 0)
419                                 break;
420                         res = pgp_mpi_read(pkt, &pk->sec.rsa.u);
421                         if (res < 0)
422                                 break;
423                         break;
424                 case PGP_PUB_ELG_ENCRYPT:
425                         res = pgp_mpi_read(pf_key, &pk->sec.elg.x);
426                         break;
427                 case PGP_PUB_DSA_SIGN:
428                         res = pgp_mpi_read(pf_key, &pk->sec.dsa.x);
429                         break;
430                 default:
431                         px_debug("unknown public algo: %d", pk->algo);
432                         res = PXE_PGP_KEYPKT_CORRUPT;
433         }
434         /* read checksum / sha1 */
435         if (res >= 0)
436         {
437                 if (hide_type == HIDE_SHA1)
438                         res = check_key_sha1(pf_key, pk);
439                 else
440                         res = check_key_cksum(pf_key, pk);
441         }
442         if (res >= 0)
443                 res = pgp_expect_packet_end(pf_key);
444
445         if (pf_decrypt)
446                 pullf_free(pf_decrypt);
447         if (cfb)
448                 pgp_cfb_free(cfb);
449
450         if (res < 0)
451                 pgp_key_free(pk);
452         else
453                 *pk_p = pk;
454
455         return res;
456 }
457
458 static int
459 internal_read_key(PullFilter *src, PGP_PubKey **pk_p,
460                                   const uint8 *psw, int psw_len, int pubtype)
461 {
462         PullFilter *pkt = NULL;
463         int                     res;
464         uint8           tag;
465         int                     len;
466         PGP_PubKey *enc_key = NULL;
467         PGP_PubKey *pk = NULL;
468         int                     got_main_key = 0;
469
470         /*
471          * Search for encryption key.
472          *
473          * Error out on anything fancy.
474          */
475         while (1)
476         {
477                 res = pgp_parse_pkt_hdr(src, &tag, &len, 0);
478                 if (res <= 0)
479                         break;
480                 res = pgp_create_pkt_reader(&pkt, src, len, res, NULL);
481                 if (res < 0)
482                         break;
483
484                 switch (tag)
485                 {
486                         case PGP_PKT_PUBLIC_KEY:
487                         case PGP_PKT_SECRET_KEY:
488                                 if (got_main_key)
489                                 {
490                                         res = PXE_PGP_MULTIPLE_KEYS;
491                                         break;
492                                 }
493                                 got_main_key = 1;
494                                 res = pgp_skip_packet(pkt);
495                                 break;
496
497                         case PGP_PKT_PUBLIC_SUBKEY:
498                                 if (pubtype != 0)
499                                         res = PXE_PGP_EXPECT_SECRET_KEY;
500                                 else
501                                         res = _pgp_read_public_key(pkt, &pk);
502                                 break;
503
504                         case PGP_PKT_SECRET_SUBKEY:
505                                 if (pubtype != 1)
506                                         res = PXE_PGP_EXPECT_PUBLIC_KEY;
507                                 else
508                                         res = process_secret_key(pkt, &pk, psw, psw_len);
509                                 break;
510
511                         case PGP_PKT_SIGNATURE:
512                         case PGP_PKT_MARKER:
513                         case PGP_PKT_TRUST:
514                         case PGP_PKT_USER_ID:
515                         case PGP_PKT_USER_ATTR:
516                         case PGP_PKT_PRIV_61:
517                                 res = pgp_skip_packet(pkt);
518                                 break;
519                         default:
520                                 px_debug("unknown/unexpected packet: %d", tag);
521                                 res = PXE_PGP_UNEXPECTED_PKT;
522                 }
523                 pullf_free(pkt);
524                 pkt = NULL;
525
526                 if (pk != NULL)
527                 {
528                         if (res >= 0 && pk->can_encrypt)
529                         {
530                                 if (enc_key == NULL)
531                                 {
532                                         enc_key = pk;
533                                         pk = NULL;
534                                 }
535                                 else
536                                         res = PXE_PGP_MULTIPLE_SUBKEYS;
537                         }
538
539                         if (pk)
540                                 pgp_key_free(pk);
541                         pk = NULL;
542                 }
543
544                 if (res < 0)
545                         break;
546         }
547
548         if (pkt)
549                 pullf_free(pkt);
550
551         if (res < 0)
552         {
553                 if (enc_key)
554                         pgp_key_free(enc_key);
555                 return res;
556         }
557
558         if (!enc_key)
559                 res = PXE_PGP_NO_USABLE_KEY;
560         else
561                 *pk_p = enc_key;
562         return res;
563 }
564
565 int
566 pgp_set_pubkey(PGP_Context *ctx, MBuf *keypkt,
567                            const uint8 *key, int key_len, int pubtype)
568 {
569         int                     res;
570         PullFilter *src;
571         PGP_PubKey *pk = NULL;
572
573         res = pullf_create_mbuf_reader(&src, keypkt);
574         if (res < 0)
575                 return res;
576
577         res = internal_read_key(src, &pk, key, key_len, pubtype);
578         pullf_free(src);
579
580         if (res >= 0)
581                 ctx->pub_key = pk;
582
583         return res < 0 ? res : 0;
584 }