Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "postgres.h"
00032
00033 #include "px.h"
00034 #include "mbuf.h"
00035 #include "pgp.h"
00036
00037
00038
00039
00040
00041
00042 static uint8 *
00043 check_eme_pkcs1_v15(uint8 *data, int len)
00044 {
00045 uint8 *data_end = data + len;
00046 uint8 *p = data;
00047 int rnd = 0;
00048
00049 if (len < 1 + 8 + 1)
00050 return NULL;
00051
00052 if (*p++ != 2)
00053 return NULL;
00054
00055 while (p < data_end && *p)
00056 {
00057 p++;
00058 rnd++;
00059 }
00060
00061 if (p == data_end)
00062 return NULL;
00063 if (*p != 0)
00064 return NULL;
00065 if (rnd < 8)
00066 return NULL;
00067 return p + 1;
00068 }
00069
00070
00071
00072
00073
00074 static int
00075 control_cksum(uint8 *msg, int msglen)
00076 {
00077 int i;
00078 unsigned my_cksum,
00079 got_cksum;
00080
00081 if (msglen < 3)
00082 return PXE_PGP_WRONG_KEY;
00083
00084 my_cksum = 0;
00085 for (i = 1; i < msglen - 2; i++)
00086 my_cksum += msg[i];
00087 my_cksum &= 0xFFFF;
00088 got_cksum = ((unsigned) (msg[msglen - 2]) << 8) + msg[msglen - 1];
00089 if (my_cksum != got_cksum)
00090 {
00091 px_debug("pubenc cksum failed");
00092 return PXE_PGP_WRONG_KEY;
00093 }
00094 return 0;
00095 }
00096
00097 static int
00098 decrypt_elgamal(PGP_PubKey *pk, PullFilter *pkt, PGP_MPI **m_p)
00099 {
00100 int res;
00101 PGP_MPI *c1 = NULL;
00102 PGP_MPI *c2 = NULL;
00103
00104 if (pk->algo != PGP_PUB_ELG_ENCRYPT)
00105 return PXE_PGP_WRONG_KEY;
00106
00107
00108 res = pgp_mpi_read(pkt, &c1);
00109 if (res < 0)
00110 goto out;
00111 res = pgp_mpi_read(pkt, &c2);
00112 if (res < 0)
00113 goto out;
00114
00115
00116 res = pgp_elgamal_decrypt(pk, c1, c2, m_p);
00117
00118 out:
00119 pgp_mpi_free(c1);
00120 pgp_mpi_free(c2);
00121 return res;
00122 }
00123
00124 static int
00125 decrypt_rsa(PGP_PubKey *pk, PullFilter *pkt, PGP_MPI **m_p)
00126 {
00127 int res;
00128 PGP_MPI *c;
00129
00130 if (pk->algo != PGP_PUB_RSA_ENCRYPT
00131 && pk->algo != PGP_PUB_RSA_ENCRYPT_SIGN)
00132 return PXE_PGP_WRONG_KEY;
00133
00134
00135 res = pgp_mpi_read(pkt, &c);
00136 if (res < 0)
00137 return res;
00138
00139
00140 res = pgp_rsa_decrypt(pk, c, m_p);
00141
00142 pgp_mpi_free(c);
00143 return res;
00144 }
00145
00146
00147 static const uint8
00148 any_key[] = {0, 0, 0, 0, 0, 0, 0, 0};
00149
00150 int
00151 pgp_parse_pubenc_sesskey(PGP_Context *ctx, PullFilter *pkt)
00152 {
00153 int ver;
00154 int algo;
00155 int res;
00156 uint8 key_id[8];
00157 PGP_PubKey *pk;
00158 uint8 *msg;
00159 int msglen;
00160 PGP_MPI *m;
00161
00162 pk = ctx->pub_key;
00163 if (pk == NULL)
00164 {
00165 px_debug("no pubkey?");
00166 return PXE_BUG;
00167 }
00168
00169 GETBYTE(pkt, ver);
00170 if (ver != 3)
00171 {
00172 px_debug("unknown pubenc_sesskey pkt ver=%d", ver);
00173 return PXE_PGP_CORRUPT_DATA;
00174 }
00175
00176
00177
00178
00179 res = pullf_read_fixed(pkt, 8, key_id);
00180 if (res < 0)
00181 return res;
00182 if (memcmp(key_id, any_key, 8) != 0
00183 && memcmp(key_id, pk->key_id, 8) != 0)
00184 {
00185 px_debug("key_id's does not match");
00186 return PXE_PGP_WRONG_KEY;
00187 }
00188
00189
00190
00191
00192 GETBYTE(pkt, algo);
00193 switch (algo)
00194 {
00195 case PGP_PUB_ELG_ENCRYPT:
00196 res = decrypt_elgamal(pk, pkt, &m);
00197 break;
00198 case PGP_PUB_RSA_ENCRYPT:
00199 case PGP_PUB_RSA_ENCRYPT_SIGN:
00200 res = decrypt_rsa(pk, pkt, &m);
00201 break;
00202 default:
00203 res = PXE_PGP_UNKNOWN_PUBALGO;
00204 }
00205 if (res < 0)
00206 return res;
00207
00208
00209
00210
00211 msg = check_eme_pkcs1_v15(m->data, m->bytes);
00212 if (msg == NULL)
00213 {
00214 px_debug("check_eme_pkcs1_v15 failed");
00215 res = PXE_PGP_WRONG_KEY;
00216 goto out;
00217 }
00218 msglen = m->bytes - (msg - m->data);
00219
00220 res = control_cksum(msg, msglen);
00221 if (res < 0)
00222 goto out;
00223
00224
00225
00226
00227 ctx->cipher_algo = *msg;
00228 ctx->sess_key_len = msglen - 3;
00229 memcpy(ctx->sess_key, msg + 1, ctx->sess_key_len);
00230
00231 out:
00232 pgp_mpi_free(m);
00233 if (res < 0)
00234 return res;
00235 return pgp_expect_packet_end(pkt);
00236 }