1 /* 2 * pgp-info.c 3 * Provide info about PGP data. 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-info.c 30 */ 31 #include "postgres.h" 32 33 #include "px.h" 34 #include "mbuf.h" 35 #include "pgp.h" 36 37 static int 38 read_pubkey_keyid(PullFilter *pkt, uint8 *keyid_buf) 39 { 40 int res; 41 PGP_PubKey *pk = NULL; 42 43 res = _pgp_read_public_key(pkt, &pk); 44 if (res < 0) 45 goto err; 46 47 /* skip secret key part, if it exists */ 48 res = pgp_skip_packet(pkt); 49 if (res < 0) 50 goto err; 51 52 /* is it encryption key */ 53 switch (pk->algo) 54 { 55 case PGP_PUB_ELG_ENCRYPT: 56 case PGP_PUB_RSA_ENCRYPT: 57 case PGP_PUB_RSA_ENCRYPT_SIGN: 58 memcpy(keyid_buf, pk->key_id, 8); 59 res = 1; 60 break; 61 default: 62 res = 0; 63 } 64 65 err: 66 pgp_key_free(pk); 67 return res; 68 } 69 70 static int 71 read_pubenc_keyid(PullFilter *pkt, uint8 *keyid_buf) 72 { 73 uint8 ver; 74 int res; 75 76 GETBYTE(pkt, ver); 77 if (ver != 3) 78 return -1; 79 80 res = pullf_read_fixed(pkt, 8, keyid_buf); 81 if (res < 0) 82 return res; 83 84 return pgp_skip_packet(pkt); 85 } 86 87 static const char hextbl[] = "0123456789ABCDEF"; 88 89 static int 90 print_key(uint8 *keyid, char *dst) 91 { 92 int i; 93 unsigned c; 94 95 for (i = 0; i < 8; i++) 96 { 97 c = keyid[i]; 98 *dst++ = hextbl[(c >> 4) & 0x0F]; 99 *dst++ = hextbl[c & 0x0F]; 100 } 101 *dst = 0; 102 return 8 * 2; 103 } 104 105 static const uint8 any_key[] = 106 {0, 0, 0, 0, 0, 0, 0, 0}; 107 108 /* 109 * dst should have room for 17 bytes 110 */ 111 int 112 pgp_get_keyid(MBuf *pgp_data, char *dst) 113 { 114 int res; 115 PullFilter *src; 116 PullFilter *pkt = NULL; 117 int len; 118 uint8 tag; 119 int got_pub_key = 0, 120 got_symenc_key = 0, 121 got_pubenc_key = 0; 122 int got_data = 0; 123 uint8 keyid_buf[8]; 124 int got_main_key = 0; 125 126 127 res = pullf_create_mbuf_reader(&src, pgp_data); 128 if (res < 0) 129 return res; 130 131 while (1) 132 { 133 res = pgp_parse_pkt_hdr(src, &tag, &len, 0); 134 if (res <= 0) 135 break; 136 res = pgp_create_pkt_reader(&pkt, src, len, res, NULL); 137 if (res < 0) 138 break; 139 140 switch (tag) 141 { 142 case PGP_PKT_SECRET_KEY: 143 case PGP_PKT_PUBLIC_KEY: 144 /* main key is for signing, so ignore it */ 145 if (!got_main_key) 146 { 147 got_main_key = 1; 148 res = pgp_skip_packet(pkt); 149 } 150 else 151 res = PXE_PGP_MULTIPLE_KEYS; 152 break; 153 case PGP_PKT_SECRET_SUBKEY: 154 case PGP_PKT_PUBLIC_SUBKEY: 155 res = read_pubkey_keyid(pkt, keyid_buf); 156 if (res < 0) 157 break; 158 if (res > 0) 159 got_pub_key++; 160 break; 161 case PGP_PKT_PUBENCRYPTED_SESSKEY: 162 got_pubenc_key++; 163 res = read_pubenc_keyid(pkt, keyid_buf); 164 break; 165 case PGP_PKT_SYMENCRYPTED_DATA: 166 case PGP_PKT_SYMENCRYPTED_DATA_MDC: 167 /* don't skip it, just stop */ 168 got_data = 1; 169 break; 170 case PGP_PKT_SYMENCRYPTED_SESSKEY: 171 got_symenc_key++; 172 /* fallthru */ 173 case PGP_PKT_SIGNATURE: 174 case PGP_PKT_MARKER: 175 case PGP_PKT_TRUST: 176 case PGP_PKT_USER_ID: 177 case PGP_PKT_USER_ATTR: 178 case PGP_PKT_PRIV_61: 179 res = pgp_skip_packet(pkt); 180 break; 181 default: 182 res = PXE_PGP_CORRUPT_DATA; 183 } 184 185 if (pkt) 186 pullf_free(pkt); 187 pkt = NULL; 188 189 if (res < 0 || got_data) 190 break; 191 } 192 193 pullf_free(src); 194 if (pkt) 195 pullf_free(pkt); 196 197 if (res < 0) 198 return res; 199 200 /* now check sanity */ 201 if (got_pub_key && got_pubenc_key) 202 res = PXE_PGP_CORRUPT_DATA; 203 204 if (got_pub_key > 1) 205 res = PXE_PGP_MULTIPLE_KEYS; 206 207 if (got_pubenc_key > 1) 208 res = PXE_PGP_MULTIPLE_KEYS; 209 210 /* 211 * if still ok, look what we got 212 */ 213 if (res >= 0) 214 { 215 if (got_pubenc_key || got_pub_key) 216 { 217 if (memcmp(keyid_buf, any_key, 8) == 0) 218 { 219 memcpy(dst, "ANYKEY", 7); 220 res = 6; 221 } 222 else 223 res = print_key(keyid_buf, dst); 224 } 225 else if (got_symenc_key) 226 { 227 memcpy(dst, "SYMKEY", 7); 228 res = 6; 229 } 230 else 231 res = PXE_PGP_NO_USABLE_KEY; 232 } 233 234 return res; 235 } 236