#include #include #include #include #include "libnpass/gpg.h" #include "libnpass/util.h" #include "util.h" #define gpg_err_ret(err) \ do { \ if (err) { \ gpg_cleanup(); \ err_ret(1, "%s: %s", gpgme_strsource(err), \ gpgme_strerror(err)); \ } \ } while (0) static gpgme_ctx_t ctx = NULL; static gpgme_key_t key[2] = {0}; static int gpg_init(void); static void gpg_cleanup(void); static int gpg_init(void) { gpgme_error_t err; const char *local = setlocale(LC_ALL, ""); gpgme_check_version(NULL); gpgme_set_locale(NULL, LC_CTYPE, local); #ifdef LC_MESSAGES gpgme_set_locale(NULL, LC_MESSAGES, local); #endif err = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP); gpg_err_ret(err); err = gpgme_new(&ctx); gpg_err_ret(err); return 0; } static void gpg_cleanup(void) { if (ctx) gpgme_release(ctx); if (*key) gpgme_key_release(*key); } int gpg_key_validate(const char *fpr) { int r; gpgme_error_t err; r = gpg_init(); if (r) return r; err = gpgme_get_key(ctx, fpr, key, 1); gpg_err_ret(err); gpg_cleanup(); return 0; } int gpg_decrypt(FILE *pass_out, const char *pass_path) { int r; char buf[BUFSIZ]; gpgme_data_t in, out; gpgme_error_t err; r = gpg_init(); if (r) return r; err = gpgme_data_new_from_file(&in, pass_path, 1); gpg_err_ret(err); err = gpgme_data_new(&out); gpg_err_ret(err); err = gpgme_op_decrypt(ctx, in, out); gpg_err_ret(err); r = gpgme_data_seek(out, 0, SEEK_SET); if (r) gpg_err_ret(gpgme_err_code_from_errno(errno)); while ((r = gpgme_data_read(out, buf, sizeof(buf)))) fwrite(buf, r, 1, pass_out); if (r < 0) gpg_err_ret(gpgme_err_code_from_errno(errno)); gpg_cleanup(); return 0; } int gpg_encrypt(FILE *stream, const char *fpr, const char *pass, size_t n) { int r; char buf[BUFSIZ]; gpgme_data_t in, out; gpgme_error_t err; r = gpg_init(); if (r) return r; err = gpgme_get_key(ctx, fpr, key, 1); gpg_err_ret(err); err = gpgme_data_new_from_mem(&in, pass, n, 0); gpg_err_ret(err); err = gpgme_data_new(&out); gpg_err_ret(err); err = gpgme_op_encrypt(ctx, key, GPGME_ENCRYPT_ALWAYS_TRUST, in, out); gpg_err_ret(err); r = gpgme_data_seek(out, 0, SEEK_SET); if (r) gpg_err_ret(gpgme_err_code_from_errno(errno)); while ((r = gpgme_data_read(out, buf, sizeof(buf)))) fwrite(buf, r, 1, stream); gpg_cleanup(); if (r < 0) gpg_err_ret(gpgme_err_code_from_errno(errno)); return 0; }