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
00032 #include "postgres.h"
00033
00034 #include "px.h"
00035
00036 struct error_desc
00037 {
00038 int err;
00039 const char *desc;
00040 };
00041
00042 static const struct error_desc px_err_list[] = {
00043 {PXE_OK, "Everything ok"},
00044 {PXE_ERR_GENERIC, "Some PX error (not specified)"},
00045 {PXE_NO_HASH, "No such hash algorithm"},
00046 {PXE_NO_CIPHER, "No such cipher algorithm"},
00047 {PXE_NOTBLOCKSIZE, "Data not a multiple of block size"},
00048 {PXE_BAD_OPTION, "Unknown option"},
00049 {PXE_BAD_FORMAT, "Badly formatted type"},
00050 {PXE_KEY_TOO_BIG, "Key was too big"},
00051 {PXE_CIPHER_INIT, "Cipher cannot be initalized ?"},
00052 {PXE_HASH_UNUSABLE_FOR_HMAC, "This hash algorithm is unusable for HMAC"},
00053 {PXE_DEV_READ_ERROR, "Error reading from random device"},
00054 {PXE_OSSL_RAND_ERROR, "OpenSSL PRNG error"},
00055 {PXE_BUG, "pgcrypto bug"},
00056 {PXE_ARGUMENT_ERROR, "Illegal argument to function"},
00057 {PXE_UNKNOWN_SALT_ALGO, "Unknown salt algorithm"},
00058 {PXE_BAD_SALT_ROUNDS, "Incorrect number of rounds"},
00059 {PXE_MCRYPT_INTERNAL, "mcrypt internal error"},
00060 {PXE_NO_RANDOM, "No strong random source"},
00061 {PXE_DECRYPT_FAILED, "Decryption failed"},
00062 {PXE_PGP_CORRUPT_DATA, "Wrong key or corrupt data"},
00063 {PXE_PGP_CORRUPT_ARMOR, "Corrupt ascii-armor"},
00064 {PXE_PGP_UNSUPPORTED_COMPR, "Unsupported compression algorithm"},
00065 {PXE_PGP_UNSUPPORTED_CIPHER, "Unsupported cipher algorithm"},
00066 {PXE_PGP_UNSUPPORTED_HASH, "Unsupported digest algorithm"},
00067 {PXE_PGP_COMPRESSION_ERROR, "Compression error"},
00068 {PXE_PGP_NOT_TEXT, "Not text data"},
00069 {PXE_PGP_UNEXPECTED_PKT, "Unexpected packet in key data"},
00070 {PXE_PGP_NO_BIGNUM,
00071 "public-key functions disabled - "
00072 "pgcrypto needs OpenSSL for bignums"},
00073 {PXE_PGP_MATH_FAILED, "Math operation failed"},
00074 {PXE_PGP_SHORT_ELGAMAL_KEY, "Elgamal keys must be at least 1024 bits long"},
00075 {PXE_PGP_RSA_UNSUPPORTED, "pgcrypto does not support RSA keys"},
00076 {PXE_PGP_UNKNOWN_PUBALGO, "Unknown public-key encryption algorithm"},
00077 {PXE_PGP_WRONG_KEY, "Wrong key"},
00078 {PXE_PGP_MULTIPLE_KEYS,
00079 "Several keys given - pgcrypto does not handle keyring"},
00080 {PXE_PGP_EXPECT_PUBLIC_KEY, "Refusing to encrypt with secret key"},
00081 {PXE_PGP_EXPECT_SECRET_KEY, "Cannot decrypt with public key"},
00082 {PXE_PGP_NOT_V4_KEYPKT, "Only V4 key packets are supported"},
00083 {PXE_PGP_KEYPKT_CORRUPT, "Corrupt key packet"},
00084 {PXE_PGP_NO_USABLE_KEY, "No encryption key found"},
00085 {PXE_PGP_NEED_SECRET_PSW, "Need password for secret key"},
00086 {PXE_PGP_BAD_S2K_MODE, "Bad S2K mode"},
00087 {PXE_PGP_UNSUPPORTED_PUBALGO, "Unsupported public key algorithm"},
00088 {PXE_PGP_MULTIPLE_SUBKEYS, "Several subkeys not supported"},
00089
00090
00091 {PXE_MBUF_SHORT_READ, "Corrupt data"},
00092
00093 {0, NULL},
00094 };
00095
00096 const char *
00097 px_strerror(int err)
00098 {
00099 const struct error_desc *e;
00100
00101 for (e = px_err_list; e->desc; e++)
00102 if (e->err == err)
00103 return e->desc;
00104 return "Bad error code";
00105 }
00106
00107
00108 const char *
00109 px_resolve_alias(const PX_Alias *list, const char *name)
00110 {
00111 while (list->name)
00112 {
00113 if (pg_strcasecmp(list->alias, name) == 0)
00114 return list->name;
00115 list++;
00116 }
00117 return name;
00118 }
00119
00120 static void (*debug_handler) (const char *) = NULL;
00121
00122 void
00123 px_set_debug_handler(void (*handler) (const char *))
00124 {
00125 debug_handler = handler;
00126 }
00127
00128 void
00129 px_debug(const char *fmt,...)
00130 {
00131 va_list ap;
00132
00133 va_start(ap, fmt);
00134 if (debug_handler)
00135 {
00136 char buf[512];
00137
00138 vsnprintf(buf, sizeof(buf), fmt, ap);
00139 debug_handler(buf);
00140 }
00141 va_end(ap);
00142 }
00143
00144
00145
00146
00147
00148 static unsigned
00149 combo_encrypt_len(PX_Combo *cx, unsigned dlen)
00150 {
00151 return dlen + 512;
00152 }
00153
00154 static unsigned
00155 combo_decrypt_len(PX_Combo *cx, unsigned dlen)
00156 {
00157 return dlen;
00158 }
00159
00160 static int
00161 combo_init(PX_Combo *cx, const uint8 *key, unsigned klen,
00162 const uint8 *iv, unsigned ivlen)
00163 {
00164 int err;
00165 unsigned ks,
00166 ivs;
00167 PX_Cipher *c = cx->cipher;
00168 uint8 *ivbuf = NULL;
00169 uint8 *keybuf;
00170
00171 ks = px_cipher_key_size(c);
00172
00173 ivs = px_cipher_iv_size(c);
00174 if (ivs > 0)
00175 {
00176 ivbuf = px_alloc(ivs);
00177 memset(ivbuf, 0, ivs);
00178 if (ivlen > ivs)
00179 memcpy(ivbuf, iv, ivs);
00180 else
00181 memcpy(ivbuf, iv, ivlen);
00182 }
00183
00184 if (klen > ks)
00185 klen = ks;
00186 keybuf = px_alloc(ks);
00187 memset(keybuf, 0, ks);
00188 memcpy(keybuf, key, klen);
00189
00190 err = px_cipher_init(c, keybuf, klen, ivbuf);
00191
00192 if (ivbuf)
00193 px_free(ivbuf);
00194 px_free(keybuf);
00195
00196 return err;
00197 }
00198
00199 static int
00200 combo_encrypt(PX_Combo *cx, const uint8 *data, unsigned dlen,
00201 uint8 *res, unsigned *rlen)
00202 {
00203 int err = 0;
00204 uint8 *bbuf;
00205 unsigned bs,
00206 bpos,
00207 i,
00208 pad;
00209
00210 PX_Cipher *c = cx->cipher;
00211
00212 bbuf = NULL;
00213 bs = px_cipher_block_size(c);
00214
00215
00216 if (bs > 1)
00217 {
00218 bbuf = px_alloc(bs * 4);
00219 bpos = dlen % bs;
00220 *rlen = dlen - bpos;
00221 memcpy(bbuf, data + *rlen, bpos);
00222
00223
00224 if (*rlen)
00225 {
00226 err = px_cipher_encrypt(c, data, *rlen, res);
00227 if (err)
00228 goto out;
00229 }
00230
00231
00232 if (cx->padding)
00233 {
00234 pad = bs - (bpos % bs);
00235 for (i = 0; i < pad; i++)
00236 bbuf[bpos++] = pad;
00237 }
00238 else if (bpos % bs)
00239 {
00240
00241 pad = bs - (bpos % bs);
00242 for (i = 0; i < pad; i++)
00243 bbuf[bpos++] = 0;
00244 }
00245
00246
00247 if (bpos)
00248 {
00249 err = px_cipher_encrypt(c, bbuf, bpos, res + *rlen);
00250 *rlen += bpos;
00251 }
00252 }
00253 else
00254 {
00255
00256 err = px_cipher_encrypt(c, data, dlen, res);
00257 if (err)
00258 goto out;
00259 *rlen = dlen;
00260 }
00261 out:
00262 if (bbuf)
00263 px_free(bbuf);
00264
00265 return err;
00266 }
00267
00268 static int
00269 combo_decrypt(PX_Combo *cx, const uint8 *data, unsigned dlen,
00270 uint8 *res, unsigned *rlen)
00271 {
00272 unsigned bs,
00273 i,
00274 pad;
00275 unsigned pad_ok;
00276
00277 PX_Cipher *c = cx->cipher;
00278
00279
00280 if (dlen == 0)
00281 {
00282
00283 if (cx->padding)
00284 return PXE_DECRYPT_FAILED;
00285
00286
00287 *rlen = 0;
00288 return 0;
00289 }
00290
00291 bs = px_cipher_block_size(c);
00292 if (bs > 1 && (dlen % bs) != 0)
00293 goto block_error;
00294
00295
00296 *rlen = dlen;
00297 px_cipher_decrypt(c, data, dlen, res);
00298
00299
00300 if (bs > 1 && cx->padding)
00301 {
00302 pad = res[*rlen - 1];
00303 pad_ok = 0;
00304 if (pad > 0 && pad <= bs && pad <= *rlen)
00305 {
00306 pad_ok = 1;
00307 for (i = *rlen - pad; i < *rlen; i++)
00308 if (res[i] != pad)
00309 {
00310 pad_ok = 0;
00311 break;
00312 }
00313 }
00314
00315 if (pad_ok)
00316 *rlen -= pad;
00317 }
00318
00319 return 0;
00320
00321 block_error:
00322 return PXE_NOTBLOCKSIZE;
00323 }
00324
00325 static void
00326 combo_free(PX_Combo *cx)
00327 {
00328 if (cx->cipher)
00329 px_cipher_free(cx->cipher);
00330 memset(cx, 0, sizeof(*cx));
00331 px_free(cx);
00332 }
00333
00334
00335
00336 static int
00337 parse_cipher_name(char *full, char **cipher, char **pad)
00338 {
00339 char *p,
00340 *p2,
00341 *q;
00342
00343 *cipher = full;
00344 *pad = NULL;
00345
00346 p = strchr(full, '/');
00347 if (p != NULL)
00348 *p++ = 0;
00349 while (p != NULL)
00350 {
00351 if ((q = strchr(p, '/')) != NULL)
00352 *q++ = 0;
00353
00354 if (!*p)
00355 {
00356 p = q;
00357 continue;
00358 }
00359 p2 = strchr(p, ':');
00360 if (p2 != NULL)
00361 {
00362 *p2++ = 0;
00363 if (strcmp(p, "pad") == 0)
00364 *pad = p2;
00365 else
00366 return PXE_BAD_OPTION;
00367 }
00368 else
00369 return PXE_BAD_FORMAT;
00370
00371 p = q;
00372 }
00373 return 0;
00374 }
00375
00376
00377
00378 int
00379 px_find_combo(const char *name, PX_Combo **res)
00380 {
00381 int err;
00382 char *buf,
00383 *s_cipher,
00384 *s_pad;
00385
00386 PX_Combo *cx;
00387
00388 cx = px_alloc(sizeof(*cx));
00389 memset(cx, 0, sizeof(*cx));
00390
00391 buf = px_alloc(strlen(name) + 1);
00392 strcpy(buf, name);
00393
00394 err = parse_cipher_name(buf, &s_cipher, &s_pad);
00395 if (err)
00396 {
00397 px_free(buf);
00398 px_free(cx);
00399 return err;
00400 }
00401
00402 err = px_find_cipher(s_cipher, &cx->cipher);
00403 if (err)
00404 goto err1;
00405
00406 if (s_pad != NULL)
00407 {
00408 if (strcmp(s_pad, "pkcs") == 0)
00409 cx->padding = 1;
00410 else if (strcmp(s_pad, "none") == 0)
00411 cx->padding = 0;
00412 else
00413 goto err1;
00414 }
00415 else
00416 cx->padding = 1;
00417
00418 cx->init = combo_init;
00419 cx->encrypt = combo_encrypt;
00420 cx->decrypt = combo_decrypt;
00421 cx->encrypt_len = combo_encrypt_len;
00422 cx->decrypt_len = combo_decrypt_len;
00423 cx->free = combo_free;
00424
00425 px_free(buf);
00426
00427 *res = cx;
00428
00429 return 0;
00430
00431 err1:
00432 if (cx->cipher)
00433 px_cipher_free(cx->cipher);
00434 px_free(cx);
00435 px_free(buf);
00436 return PXE_NO_CIPHER;
00437 }