int main (int argc, char **argv) { gpgme_ctx_t ctx; gpgme_error_t err; gpgme_data_t sig, text; gpgme_verify_result_t result; init_gpgme (GPGME_PROTOCOL_CMS); err = gpgme_new (&ctx); fail_if_err (err); gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); /* Checking a valid message. */ err = gpgme_data_new_from_mem (&text, test_text1, strlen (test_text1), 0); fail_if_err (err); err = gpgme_data_new_from_mem (&sig, test_sig1, strlen (test_sig1), 0); fail_if_err (err); err = gpgme_op_verify (ctx, sig, text, NULL); fail_if_err (err); result = gpgme_op_verify_result (ctx); check_result (result, GPGME_SIGSUM_VALID | GPGME_SIGSUM_GREEN, "3CF405464F66ED4A7DF45BBDD1E4282E33BDB76E", GPG_ERR_NO_ERROR, GPGME_VALIDITY_FULL); show_auditlog (ctx); /* Checking a manipulated message. */ gpgme_data_release (text); err = gpgme_data_new_from_mem (&text, test_text1f, strlen (test_text1f), 0); fail_if_err (err); gpgme_data_seek (sig, 0, SEEK_SET); err = gpgme_op_verify (ctx, sig, text, NULL); fail_if_err (err); result = gpgme_op_verify_result (ctx); check_result (result, GPGME_SIGSUM_RED, "3CF405464F66ED4A7DF45BBDD1E4282E33BDB76E", GPG_ERR_BAD_SIGNATURE, GPGME_VALIDITY_UNKNOWN); show_auditlog (ctx); gpgme_data_release (text); gpgme_data_release (sig); gpgme_release (ctx); return got_errors? 1 : 0; }
static gboolean verify_done (SeahorseToolMode *mode, const gchar *uri, gpgme_data_t uridata, SeahorsePGPOperation *pop, GError **err) { const gchar *orig; gpgme_verify_result_t status; status = gpgme_op_verify_result (pop->gctx); if (status && status->signatures) { orig = g_object_get_data (G_OBJECT (pop), "original-file"); if (!orig) orig = uri; seahorse_notify_signatures (orig, status); } else { /* * TODO: What should happen with multiple files at this point. * The last thing we want to do is cascade a big pile of error * dialogs at the user. */ g_set_error (err, SEAHORSE_ERROR, -1, _("No valid signatures found")); return FALSE; } return TRUE; }
const char * gpgme_get_sig_string_attr (gpgme_ctx_t ctx, int idx, _gpgme_attr_t what, int whatidx) { gpgme_verify_result_t result; gpgme_signature_t sig; result = gpgme_op_verify_result (ctx); sig = result->signatures; while (sig && idx) { sig = sig->next; idx--; } if (!sig || idx) return NULL; switch (what) { case GPGME_ATTR_FPR: return sig->fpr; case GPGME_ATTR_ERRTOK: if (whatidx == 1) return sig->wrong_key_usage ? "Wrong_Key_Usage" : ""; else return ""; default: break; } return NULL; }
GPGWrapperDecryptedData GPGWrapper::decrypt(const std::string& message) { init(); ScopedGPGData clear_text, sign_text, encrypted_text; gpgme_error_t error = encrypted_text.init(message.c_str(), message.length()); fail_if_err(error, L"Nie uda³o siê zainicjowaæ danych do odszyfrowania (encrypted_text)."); error = sign_text.init(); fail_if_err(error, L"Nie uda³o siê zainicjowaæ danych do odszyfrowania (sign_text)."); error = gpgme_op_decrypt(context, encrypted_text.get(), sign_text.get()); fail_if_err(error, L"Nie uda³o siê odszyfrowaæ wiadomoœci."); error = gpgme_data_rewind(sign_text.get()); fail_if_err(error, L"Nie uda³o siê przewin¹æ na pocz¹tek podpisanego strumienia, aby go póŸniej zweryfikowaæ."); error = clear_text.init(); fail_if_err(error, L"Nie uda³o siê zainicjowaæ danych do odszyfrowania (clear_text)."); error = gpgme_op_verify(context, sign_text.get(), NULL, clear_text.get()); fail_if_err(error, L"Nie powiod³a siê próba potwierdzenia podpisu nadawcy."); GPGWrapperDecryptedData result; gpgme_verify_result_t verifyResult = gpgme_op_verify_result(context); if (verifyResult != NULL && verifyResult->signatures != NULL && verifyResult->signatures->summary & GPGME_SIGSUM_VALID) result.isSignValid = true; result.data = copyData(clear_text.get()); return result; }
/* ------------------ * verify a signed string with the key found with fingerprint fpr * FREE MEMORY AFTER USAGE OF RETURN VALUE! * ------------------ */ static char* verify(const char* sig_str) { gpgme_error_t error; gpgme_ctx_t ctx; gpgme_data_t plain,sig,sig_text; gpgme_verify_result_t result; char* fpr = NULL; char* armored_sig_str = NULL; if (sig_str == NULL) { purple_debug_error(PLUGIN_ID,"verify got null parameter\n"); return NULL; } // connect to gpgme gpgme_check_version (NULL); error = gpgme_new(&ctx); if (error) { purple_debug_error(PLUGIN_ID,"gpgme_new failed: %s %s\n",gpgme_strsource (error), gpgme_strerror (error)); return NULL; } // armor sig_str armored_sig_str = str_armor(sig_str); // create data containers gpgme_data_new_from_mem (&sig, armored_sig_str,strlen(armored_sig_str),1); gpgme_data_new(&plain); // try to verify error = gpgme_op_verify(ctx,sig,NULL,plain); if (error) { purple_debug_error(PLUGIN_ID,"gpgme_op_verify failed: %s %s\n",gpgme_strsource (error), gpgme_strerror (error)); gpgme_release (ctx); return NULL; } // get result result = gpgme_op_verify_result (ctx); if (result != NULL) { if (result->signatures != NULL) { // return the fingerprint of the key that made the signature fpr = g_strdup(result->signatures->fpr); } } // release memory for data containers gpgme_data_release(sig); gpgme_data_release(plain); return fpr; }
/* Retrieve the signature status of signature IDX in CTX after a successful verify operation in R_STAT (if non-null). The creation time stamp of the signature is returned in R_CREATED (if non-null). The function returns a string containing the fingerprint. */ const char * gpgme_get_sig_status (gpgme_ctx_t ctx, int idx, _gpgme_sig_stat_t *r_stat, time_t *r_created) { gpgme_verify_result_t result; gpgme_signature_t sig; result = gpgme_op_verify_result (ctx); sig = result->signatures; while (sig && idx) { sig = sig->next; idx--; } if (!sig || idx) return NULL; if (r_stat) { switch (gpg_err_code (sig->status)) { case GPG_ERR_NO_ERROR: *r_stat = GPGME_SIG_STAT_GOOD; break; case GPG_ERR_BAD_SIGNATURE: *r_stat = GPGME_SIG_STAT_BAD; break; case GPG_ERR_NO_PUBKEY: *r_stat = GPGME_SIG_STAT_NOKEY; break; case GPG_ERR_NO_DATA: *r_stat = GPGME_SIG_STAT_NOSIG; break; case GPG_ERR_SIG_EXPIRED: *r_stat = GPGME_SIG_STAT_GOOD_EXP; break; case GPG_ERR_KEY_EXPIRED: *r_stat = GPGME_SIG_STAT_GOOD_EXPKEY; break; default: *r_stat = GPGME_SIG_STAT_ERROR; break; } } if (r_created) *r_created = sig->timestamp; return sig->fpr; }
void p_gpg_verify(const char *const barejid, const char *const sign) { if (!sign) { return; } gpgme_ctx_t ctx; gpgme_error_t error = gpgme_new(&ctx); if (error) { log_error("GPG: Failed to create gpgme context. %s %s", gpgme_strsource(error), gpgme_strerror(error)); return; } char *sign_with_header_footer = _add_header_footer(sign, PGP_SIGNATURE_HEADER, PGP_SIGNATURE_FOOTER); gpgme_data_t sign_data; gpgme_data_new_from_mem(&sign_data, sign_with_header_footer, strlen(sign_with_header_footer), 1); free(sign_with_header_footer); gpgme_data_t plain_data; gpgme_data_new(&plain_data); error = gpgme_op_verify(ctx, sign_data, NULL, plain_data); gpgme_data_release(sign_data); gpgme_data_release(plain_data); if (error) { log_error("GPG: Failed to verify. %s %s", gpgme_strsource(error), gpgme_strerror(error)); gpgme_release(ctx); return; } gpgme_verify_result_t result = gpgme_op_verify_result(ctx); if (result) { if (result->signatures) { gpgme_key_t key = NULL; error = gpgme_get_key(ctx, result->signatures->fpr, &key, 0); if (error) { log_debug("Could not find PGP key with ID %s for %s", result->signatures->fpr, barejid); } else { log_debug("Fingerprint found for %s: %s ", barejid, key->subkeys->fpr); ProfPGPPubKeyId *pubkeyid = malloc(sizeof(ProfPGPPubKeyId)); pubkeyid->id = strdup(key->subkeys->keyid); pubkeyid->received = TRUE; g_hash_table_replace(pubkeys, strdup(barejid), pubkeyid); } gpgme_key_unref(key); } } gpgme_release(ctx); }
static gboolean decrypt_done (SeahorseToolMode *mode, const gchar *uri, gpgme_data_t uridata, SeahorsePGPOperation *pop, GError **err) { gpgme_verify_result_t status; status = gpgme_op_verify_result (pop->gctx); if (status && status->signatures) seahorse_notify_signatures (uri, status); return TRUE; }
int main (int argc, char *argv[]) { gpgme_ctx_t ctx; gpgme_error_t err; gpgme_data_t in, out; gpgme_verify_result_t result; char *agent_info; int i; init_gpgme (GPGME_PROTOCOL_OpenPGP); err = gpgme_new (&ctx); fail_if_err (err); agent_info = getenv ("GPG_AGENT_INFO"); if (!(agent_info && strchr (agent_info, ':'))) gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL); err = gpgme_data_new_from_mem (&in, "Hallo Leute\n", 12, 0); fail_if_err (err); err = gpgme_data_new (&out); fail_if_err (err); for (i = 0; i < sizeof (expected_notations) / sizeof (expected_notations[0]); i++) { err = gpgme_sig_notation_add (ctx, expected_notations[i].name, expected_notations[i].value, expected_notations[i].flags); fail_if_err (err); } err = gpgme_op_sign (ctx, in, out, GPGME_SIG_MODE_NORMAL); fail_if_err (err); gpgme_data_release (in); err = gpgme_data_new (&in); fail_if_err (err); gpgme_data_seek (out, 0, SEEK_SET); err = gpgme_op_verify (ctx, out, NULL, in); fail_if_err (err); result = gpgme_op_verify_result (ctx); check_result (result); gpgme_data_release (in); gpgme_data_release (out); gpgme_release (ctx); return 0; }
static inline retvalue verify_signature(const struct signature_requirement *requirements, const char *releasegpg, const char *releasename) { gpgme_verify_result_t result; int i; const struct signature_requirement *req; result = gpgme_op_verify_result(context); if (result == NULL) { fprintf(stderr, "Internal error communicating with libgpgme: no result record!\n\n"); return RET_ERROR_GPGME; } for (req = requirements ; req != NULL ; req = req->next) { bool fullfilled = false; /* check first for good signatures, and then for good enough signatures, to not pester the user with warnings of one of the alternate keys, if the last one is good enough */ for (i = 0 ; (size_t)i < req->num_keys ; i++) { if (key_good(&req->keys[i], result->signatures)) { fullfilled = true; break; } } for (i = 0 ; !fullfilled && (size_t)i < req->num_keys ; i++) { if (key_good_enough(&req->keys[i], result->signatures, releasegpg, releasename)) { fullfilled = true; break; } } if (!fullfilled) { fprintf(stderr, "ERROR: Condition '%s' not fullfilled for '%s'.\n", req->condition, releasegpg); print_signatures(stderr, result->signatures, releasegpg); return RET_ERROR_BADSIG; } if (verbose > 10) { fprintf(stdout, "Condition '%s' fullfilled for '%s'.\n", req->condition, releasegpg); } } if (verbose > 20) print_signatures(stdout, result->signatures, releasegpg); return RET_OK; }
/* Not that this closure is called in the context of the waiter_thread. */ static void verify_closure (closure_data_t cld, gpgme_ctx_t ctx, gpg_error_t err) { if (!err) { gpgme_verify_result_t res; res = gpgme_op_verify_result (ctx); if (res) verify_dialog_box (gpgme_get_protocol (ctx), res, NULL); } gpgme_data_release (cld->sigobj); engine_private_finished (cld->filter, err); }
/* int main(int argc, char** argv) { gpgme_ctx_t ctx; gpgme_error_t err; init_gpgme(GPGME_PROTOCOL_OpenPGP); err = gpgme_new(&ctx); check_errors(err,"error with gpgme_new"); verify_signature(ctx,"signature.c.sig","signature.c"); return 0; } */ bool verify_signature(gpgme_ctx_t ctx, char* sig_path,char* file_path) { gpgme_error_t err; FILE* fp_sig = NULL; FILE* fp_msg = NULL; gpgme_data_t sig = NULL; gpgme_data_t msg = NULL; gpgme_verify_result_t result; fp_sig = fopen(sig_path,"rb"); //open file with signature if(!fp_sig) { err = gpg_error_from_syserror(); fprintf (stderr, PGM ": can't open `%s': %s\n", sig_path, gpg_strerror(err)); return false; } fp_msg = fopen(file_path,"rb"); //open file which want to check if(!fp_msg) { err = gpg_error_from_syserror(); fprintf(stderr,PGM ": cant open `%s`: %s\n", file_path, gpg_strerror(err)); return false; } err = gpgme_data_new_from_stream(&sig,fp_sig); //write to gpgme_data object from fp_sig stream(signature) if(err) { fprintf (stderr, PGM ": error allocating data object: %s\n",gpg_strerror (err)); return false; } if(fp_msg) { err = gpgme_data_new_from_stream(&msg,fp_msg); //write to gpgme_data object from fp_msg(file) if(err) { fprintf(stderr,PGM ": error allocation data object: %s\n",gpg_strerror(err)); return false; } } err = gpgme_op_verify(ctx,sig,msg,NULL); //verify signature check_errors(err,"error with verify"); result = gpgme_op_verify_result(ctx); //get result of checking signature if(result) { print_result_of_checking(result); //printf checking information } fclose(fp_sig); fclose(fp_msg); gpgme_data_release (msg); gpgme_data_release (sig); return true; }
int main (int argc, char *argv[]) { gpgme_ctx_t ctx; gpgme_error_t err; gpgme_data_t in, out; gpgme_decrypt_result_t decrypt_result; gpgme_verify_result_t verify_result; char *cipher_2_asc = make_filename ("cipher-2.asc"); char *agent_info; init_gpgme (GPGME_PROTOCOL_OpenPGP); err = gpgme_new (&ctx); fail_if_err (err); agent_info = getenv("GPG_AGENT_INFO"); if (!(agent_info && strchr (agent_info, ':'))) gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL); err = gpgme_data_new_from_file (&in, cipher_2_asc, 1); free (cipher_2_asc); fail_if_err (err); err = gpgme_data_new (&out); fail_if_err (err); err = gpgme_op_decrypt_verify (ctx, in, out); fail_if_err (err); decrypt_result = gpgme_op_decrypt_result (ctx); if (decrypt_result->unsupported_algorithm) { fprintf (stderr, "%s:%i: unsupported algorithm: %s\n", __FILE__, __LINE__, decrypt_result->unsupported_algorithm); exit (1); } print_data (out); verify_result = gpgme_op_verify_result (ctx); check_verify_result (verify_result, 0, "A0FF4590BB6122EDEF6E3C542D727CC768697734", GPG_ERR_NO_ERROR); gpgme_data_release (in); gpgme_data_release (out); gpgme_release (ctx); return 0; }
/* Get the key used to create signature IDX in CTX and return it in R_KEY. */ gpgme_error_t gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key) { gpgme_verify_result_t result; gpgme_signature_t sig; result = gpgme_op_verify_result (ctx); sig = result->signatures; while (sig && idx) { sig = sig->next; idx--; } if (!sig || idx) return gpg_error (GPG_ERR_EOF); return gpgme_get_key (ctx, sig->fpr, r_key, 0); }
gpgme_verify_result_t sgpgme_verify_signature(gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t plain, gpgme_data_t dummy) { gpgme_verify_result_t status = NULL; gpgme_error_t err; if ((err = gpgme_op_verify(ctx, sig, plain, dummy)) != GPG_ERR_NO_ERROR) { debug_print("op_verify err %s\n", gpgme_strerror(err)); privacy_set_error("%s", gpgme_strerror(err)); return GINT_TO_POINTER(-GPG_ERR_SYSTEM_ERROR); } status = gpgme_op_verify_result(ctx); if (status && status->signatures == NULL) { debug_print("no signature found\n"); privacy_set_error(_("No signature found")); return GINT_TO_POINTER(-GPG_ERR_SYSTEM_ERROR); } return status; }
void geanypg_handle_signatures(encrypt_data * ed) { int verified = 0; gpgme_verify_result_t vres = gpgme_op_verify_result(ed->ctx); if (vres) { gpgme_signature_t sig = vres->signatures; while (sig) { geanypg_check_sig(ed, sig); sig = sig->next; verified = 1; } } if (!verified) { fprintf(stderr, "GEANYPG: could not find verification results\n"); dialogs_show_msgbox(GTK_MESSAGE_ERROR, "Error, could not find verification results"); } }
/* Not that this closure is called in the context of the waiter_thread. */ static void decrypt_closure (closure_data_t cld, gpgme_ctx_t ctx, gpg_error_t err) { update_passphrase_cache (err, &cld->pw_cb); if (!err && !cld->with_verify) ; else if (!err) { gpgme_verify_result_t res; /* Decryption succeeded. Now check the state of the signatures. */ res = gpgme_op_verify_result (ctx); if (res && res->signatures) verify_dialog_box (gpgme_get_protocol (ctx), res, NULL); } else if (gpg_err_code (err) == GPG_ERR_DECRYPT_FAILED) { /* The decryption failed. See whether we can figure out a more suitable error code. */ gpgme_decrypt_result_t res; res = gpgme_op_decrypt_result (ctx); if (res && res->recipients && gpgme_err_code (res->recipients->status) == GPG_ERR_NO_SECKEY) err = gpg_error (GPG_ERR_NO_SECKEY); /* Fixme: return the keyids */ } else { /* Decryption failed for other reasons. */ } /* If the passphrase callback indicated a cancel operation, change the the error code accordingly. */ if (err && (cld->pw_cb.opts & OPT_FLAG_CANCEL)) err = gpg_error (GPG_ERR_CANCELED); engine_private_finished (cld->filter, err); }
void crypto_asym::fill_signing_result() { gpgme_verify_result_t inter = gpgme_op_verify_result(context); gpgme_signature_t res = NULL; signator tmp; signing_result.clear(); if(inter != NULL) res = inter->signatures; else res = NULL; while(res != NULL) { if(res->summary & (GPGME_SIGSUM_VALID|GPGME_SIGSUM_GREEN)) tmp.result = signator::good; else if(res->summary & GPGME_SIGSUM_RED) tmp.result = signator::bad; else if(res->summary & GPGME_SIGSUM_KEY_MISSING) tmp.result = signator::unknown_key; else tmp.result = signator::error; if(res->summary & GPGME_SIGSUM_KEY_REVOKED) tmp.key_validity = signator::revoked; else if(res->summary & GPGME_SIGSUM_KEY_EXPIRED) tmp.key_validity = signator::expired; else tmp.key_validity = signator::valid; tmp.fingerprint = res->fpr; tmp.signing_date = datetime(res->timestamp); tmp.signature_expiration_date = datetime(res->exp_timestamp); res = res->next; signing_result.push_back(tmp); } }
bool c_gpgme::verify_detached_signature ( const std::string &sig_file, const std::string &clear_data_file, const std::string &expected_fpr ) { auto sig_file_ptr = load_file(sig_file); auto clear_data_file_ptr = load_file(clear_data_file); m_error_code = gpgme_op_verify(m_ctx, *sig_file_ptr, *clear_data_file_ptr, nullptr); if (m_error_code) return false; gpgme_verify_result_t result = gpgme_op_verify_result(m_ctx); if (result == nullptr) return false; gpgme_signature_t sig = result->signatures; if (!sig) return false; for (; sig; sig = sig->next) { if ((sig->summary & GPGME_SIGSUM_VALID) || (sig->summary & GPGME_SIGSUM_GREEN)) { // Valid if (expected_fpr == sig->fpr) return true; else return false; } else if (sig->summary == 0 && sig->status == GPG_ERR_NO_ERROR) { // Valid but key is not certified with a trusted signature if (expected_fpr == sig->fpr) return true; else return false; } } return false; }
/* Loop through all files in metalink structure and retrieve them. Returns RETROK if all files were downloaded. Returns last retrieval error (from retrieve_url) if some files could not be downloaded. */ uerr_t retrieve_from_metalink (const metalink_t* metalink) { metalink_file_t **mfile_ptr; uerr_t last_retr_err = RETROK; /* Store last encountered retrieve error. */ FILE *_output_stream = output_stream; bool _output_stream_regular = output_stream_regular; char *_output_document = opt.output_document; DEBUGP (("Retrieving from Metalink\n")); /* No files to download. */ if (!metalink->files) return RETROK; if (opt.output_document) { /* We cannot support output_document as we need to compute checksum of downloaded file, and to remove it if the checksum is bad. */ logputs (LOG_NOTQUIET, _("-O not supported for metalink download. Ignoring.\n")); } for (mfile_ptr = metalink->files; *mfile_ptr; mfile_ptr++) { metalink_file_t *mfile = *mfile_ptr; metalink_resource_t **mres_ptr; char *filename = NULL; bool hash_ok = false; uerr_t retr_err = METALINK_MISSING_RESOURCE; /* -1 -> file should be rejected 0 -> could not verify 1 -> verified successfully */ char sig_status = 0; output_stream = NULL; DEBUGP (("Processing metalink file %s...\n", quote (mfile->name))); /* Resources are sorted by priority. */ for (mres_ptr = mfile->resources; *mres_ptr; mres_ptr++) { metalink_resource_t *mres = *mres_ptr; metalink_checksum_t **mchksum_ptr, *mchksum; struct iri *iri; struct url *url; int url_err; if (!RES_TYPE_SUPPORTED (mres->type)) { logprintf (LOG_VERBOSE, _("Resource type %s not supported, ignoring...\n"), quote (mres->type)); continue; } retr_err = METALINK_RETR_ERROR; /* If output_stream is not NULL, then we have failed on previous resource and are retrying. Thus, remove the file. */ if (output_stream) { fclose (output_stream); output_stream = NULL; if (unlink (filename)) logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno)); xfree (filename); } /* Parse our resource URL. */ iri = iri_new (); set_uri_encoding (iri, opt.locale, true); url = url_parse (mres->url, &url_err, iri, false); if (!url) { char *error = url_error (mres->url, url_err); logprintf (LOG_NOTQUIET, "%s: %s.\n", mres->url, error); xfree (error); inform_exit_status (URLERROR); iri_free (iri); continue; } else { /* Avoid recursive Metalink from HTTP headers. */ bool _metalink_http = opt.metalink_over_http; /* Assure proper local file name regardless of the URL of particular Metalink resource. To do that we create the local file here and put it as output_stream. We restore the original configuration after we are finished with the file. */ output_stream = unique_create (mfile->name, true, &filename); output_stream_regular = true; /* Store the real file name for displaying in messages. */ opt.output_document = filename; opt.metalink_over_http = false; DEBUGP (("Storing to %s\n", filename)); retr_err = retrieve_url (url, mres->url, NULL, NULL, NULL, NULL, opt.recursive, iri, false); opt.metalink_over_http = _metalink_http; } url_free (url); iri_free (iri); if (retr_err == RETROK) { FILE *local_file; /* Check the digest. */ local_file = fopen (filename, "rb"); if (!local_file) { logprintf (LOG_NOTQUIET, _("Could not open downloaded file.\n")); continue; } for (mchksum_ptr = mfile->checksums; *mchksum_ptr; mchksum_ptr++) { char sha256[SHA256_DIGEST_SIZE]; char sha256_txt[2 * SHA256_DIGEST_SIZE + 1]; mchksum = *mchksum_ptr; /* I have seen both variants... */ if (strcasecmp (mchksum->type, "sha256") && strcasecmp (mchksum->type, "sha-256")) { DEBUGP (("Ignoring unsupported checksum type %s.\n", quote (mchksum->type))); continue; } logprintf (LOG_VERBOSE, _("Computing checksum for %s\n"), quote (mfile->name)); sha256_stream (local_file, sha256); wg_hex_to_string (sha256_txt, sha256, SHA256_DIGEST_SIZE); DEBUGP (("Declared hash: %s\n", mchksum->hash)); DEBUGP (("Computed hash: %s\n", sha256_txt)); if (!strcmp (sha256_txt, mchksum->hash)) { logputs (LOG_VERBOSE, _("Checksum matches.\n")); hash_ok = true; } else { logprintf (LOG_NOTQUIET, _("Checksum mismatch for file %s.\n"), quote (mfile->name)); hash_ok = false; } /* Stop as soon as we checked the supported checksum. */ break; } /* Iterate over available checksums. */ fclose (local_file); local_file = NULL; if (!hash_ok) continue; sig_status = 0; /* Not verified. */ #ifdef HAVE_GPGME /* Check the crypto signature. Note that the signtures from Metalink in XML will not be parsed when using libmetalink version older than 0.1.3. Metalink-over-HTTP is not affected by this problem. */ if (mfile->signature) { metalink_signature_t *msig = mfile->signature; gpgme_error_t gpgerr; gpgme_ctx_t gpgctx; gpgme_data_t gpgsigdata, gpgdata; gpgme_verify_result_t gpgres; gpgme_signature_t gpgsig; gpgme_protocol_t gpgprot = GPGME_PROTOCOL_UNKNOWN; int fd = -1; /* Initialize the library - as name suggests. */ gpgme_check_version (NULL); /* Open data file. */ fd = open (filename, O_RDONLY); if (fd == -1) { logputs (LOG_NOTQUIET, _("Could not open downloaded file for signature " "verification.\n")); goto gpg_skip_verification; } /* Assign file descriptor to GPG data structure. */ gpgerr = gpgme_data_new_from_fd (&gpgdata, fd); if (gpgerr != GPG_ERR_NO_ERROR) { logprintf (LOG_NOTQUIET, "GPGME data_new_from_fd: %s\n", gpgme_strerror (gpgerr)); goto gpg_skip_verification; } /* Prepare new GPGME context. */ gpgerr = gpgme_new (&gpgctx); if (gpgerr != GPG_ERR_NO_ERROR) { logprintf (LOG_NOTQUIET, "GPGME new: %s\n", gpgme_strerror (gpgerr)); gpgme_data_release (gpgdata); goto gpg_skip_verification; } DEBUGP (("Verifying signature %s:\n%s\n", quote (msig->mediatype), msig->signature)); /* Check signature type. */ if (!strcmp (msig->mediatype, "application/pgp-signature")) gpgprot = GPGME_PROTOCOL_OpenPGP; else /* Unsupported signature type. */ { gpgme_release (gpgctx); gpgme_data_release (gpgdata); goto gpg_skip_verification; } gpgerr = gpgme_set_protocol (gpgctx, gpgprot); if (gpgerr != GPG_ERR_NO_ERROR) { logprintf (LOG_NOTQUIET, "GPGME set_protocol: %s\n", gpgme_strerror (gpgerr)); gpgme_release (gpgctx); gpgme_data_release (gpgdata); goto gpg_skip_verification; } /* Load the signature. */ gpgerr = gpgme_data_new_from_mem (&gpgsigdata, msig->signature, strlen (msig->signature), 0); if (gpgerr != GPG_ERR_NO_ERROR) { logprintf (LOG_NOTQUIET, _("GPGME data_new_from_mem: %s\n"), gpgme_strerror (gpgerr)); gpgme_release (gpgctx); gpgme_data_release (gpgdata); goto gpg_skip_verification; } /* Verify the signature. */ gpgerr = gpgme_op_verify (gpgctx, gpgsigdata, gpgdata, NULL); if (gpgerr != GPG_ERR_NO_ERROR) { logprintf (LOG_NOTQUIET, _("GPGME op_verify: %s\n"), gpgme_strerror (gpgerr)); gpgme_data_release (gpgsigdata); gpgme_release (gpgctx); gpgme_data_release (gpgdata); goto gpg_skip_verification; } /* Check the results. */ gpgres = gpgme_op_verify_result (gpgctx); if (!gpgres) { logputs (LOG_NOTQUIET, _("GPGME op_verify_result: NULL\n")); gpgme_data_release (gpgsigdata); gpgme_release (gpgctx); gpgme_data_release (gpgdata); goto gpg_skip_verification; } /* The list is null-terminated. */ for (gpgsig = gpgres->signatures; gpgsig; gpgsig = gpgsig->next) { DEBUGP (("Checking signature %s\n", gpgsig->fpr)); if (gpgsig->summary & (GPGME_SIGSUM_VALID | GPGME_SIGSUM_GREEN)) { logputs (LOG_VERBOSE, _("Signature validation suceeded.\n")); sig_status = 1; break; } if (gpgsig->summary & GPGME_SIGSUM_RED) { logputs (LOG_NOTQUIET, _("Invalid signature. Rejecting resource.\n")); sig_status = -1; break; } if (gpgsig->summary == 0 && (gpgsig->status & 0xFFFF) == GPG_ERR_NO_ERROR) { logputs (LOG_VERBOSE, _("Data matches signature, but signature " "is not trusted.\n")); } if ((gpgsig->status & 0xFFFF) != GPG_ERR_NO_ERROR) { logprintf (LOG_NOTQUIET, "GPGME: %s\n", gpgme_strerror (gpgsig->status & 0xFFFF)); } } gpgme_data_release (gpgsigdata); gpgme_release (gpgctx); gpgme_data_release (gpgdata); gpg_skip_verification: if (fd != -1) close (fd); } /* endif (mfile->signature) */ #endif /* Stop if file was downloaded with success. */ if (sig_status >= 0) break; } /* endif RETR_OK. */ } /* Iterate over resources. */ if (retr_err != RETROK) { logprintf (LOG_VERBOSE, _("Failed to download %s. Skipping resource.\n"), quote (mfile->name)); } else if (!hash_ok) { retr_err = METALINK_CHKSUM_ERROR; logprintf (LOG_NOTQUIET, _("File %s retrieved but checksum does not match. " "\n"), quote (mfile->name)); } #ifdef HAVE_GPGME /* Signature will be only validated if hash check was successful. */ else if (sig_status < 0) { retr_err = METALINK_SIG_ERROR; logprintf (LOG_NOTQUIET, _("File %s retrieved but signature does not match. " "\n"), quote (mfile->name)); } #endif last_retr_err = retr_err == RETROK ? last_retr_err : retr_err; /* Remove the file if error encountered or if option specified. Note: the file has been downloaded using *_loop. Therefore, it is not necessary to keep the file for continuated download. */ if ((retr_err != RETROK || opt.delete_after) && filename != NULL && file_exists_p (filename)) { logprintf (LOG_VERBOSE, _("Removing %s.\n"), quote (filename)); if (unlink (filename)) logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno)); } if (output_stream) { fclose (output_stream); output_stream = NULL; } xfree (filename); } /* Iterate over files. */ /* Restore original values. */ opt.output_document = _output_document; output_stream_regular = _output_stream_regular; output_stream = _output_stream; return last_retr_err; }
gpgme_data_t sgpgme_decrypt_verify(gpgme_data_t cipher, gpgme_verify_result_t *status, gpgme_ctx_t ctx) { struct passphrase_cb_info_s info; gpgme_data_t plain; gpgme_error_t err; memset (&info, 0, sizeof info); if ((err = gpgme_data_new(&plain)) != GPG_ERR_NO_ERROR) { gpgme_release(ctx); privacy_set_error(_("Couldn't initialize data, %s"), gpgme_strerror(err)); return NULL; } if (gpgme_get_protocol(ctx) == GPGME_PROTOCOL_OpenPGP) { prefs_gpg_enable_agent(prefs_gpg_get_config()->use_gpg_agent); if (!getenv("GPG_AGENT_INFO") || !prefs_gpg_get_config()->use_gpg_agent) { info.c = ctx; gpgme_set_passphrase_cb (ctx, gpgmegtk_passphrase_cb, &info); } } else { prefs_gpg_enable_agent(TRUE); info.c = ctx; gpgme_set_passphrase_cb (ctx, NULL, &info); } if (gpgme_get_protocol(ctx) == GPGME_PROTOCOL_OpenPGP) { err = gpgme_op_decrypt_verify(ctx, cipher, plain); if (err != GPG_ERR_NO_ERROR) { debug_print("can't decrypt (%s)\n", gpgme_strerror(err)); privacy_set_error("%s", gpgme_strerror(err)); gpgmegtk_free_passphrase(); gpgme_data_release(plain); return NULL; } err = cm_gpgme_data_rewind(plain); if (err) { debug_print("can't seek (%d %d %s)\n", err, errno, strerror(errno)); } debug_print("decrypted.\n"); *status = gpgme_op_verify_result (ctx); } else { err = gpgme_op_decrypt(ctx, cipher, plain); if (err != GPG_ERR_NO_ERROR) { debug_print("can't decrypt (%s)\n", gpgme_strerror(err)); privacy_set_error("%s", gpgme_strerror(err)); gpgmegtk_free_passphrase(); gpgme_data_release(plain); return NULL; } err = cm_gpgme_data_rewind(plain); if (err) { debug_print("can't seek (%d %d %s)\n", err, errno, strerror(errno)); } debug_print("decrypted.\n"); *status = gpgme_op_verify_result (ctx); } return plain; }
/** * Check the PGP signature for the given file path. * If base64_sig is provided, it will be used as the signature data after * decoding. If base64_sig is NULL, expect a signature file next to path * (e.g. "%s.sig"). * * The return value will be 0 if nothing abnormal happened during the signature * check, and -1 if an error occurred while checking signatures or if a * signature could not be found; pm_errno will be set. Note that "abnormal" * does not include a failed signature; the value in siglist should be checked * to determine if the signature(s) are good. * @param handle the context handle * @param path the full path to a file * @param base64_sig optional PGP signature data in base64 encoding * @param siglist a pointer to storage for signature results * @return 0 in normal cases, -1 if the something failed in the check process */ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path, const char *base64_sig, alpm_siglist_t *siglist) { int ret = -1, sigcount; gpgme_error_t gpg_err = 0; gpgme_ctx_t ctx; gpgme_data_t filedata, sigdata; gpgme_verify_result_t verify_result; gpgme_signature_t gpgsig; char *sigpath = NULL; unsigned char *decoded_sigdata = NULL; FILE *file = NULL, *sigfile = NULL; if(!path || _alpm_access(handle, NULL, path, R_OK) != 0) { RET_ERR(handle, ALPM_ERR_NOT_A_FILE, -1); } if(!siglist) { RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1); } siglist->count = 0; if(!base64_sig) { sigpath = _alpm_sigpath(handle, path); if(_alpm_access(handle, NULL, sigpath, R_OK) != 0 || (sigfile = fopen(sigpath, "rb")) == NULL) { _alpm_log(handle, ALPM_LOG_DEBUG, "sig path %s could not be opened\n", sigpath); handle->pm_errno = ALPM_ERR_SIG_MISSING; goto error; } } /* does the file we are verifying exist? */ file = fopen(path, "rb"); if(file == NULL) { handle->pm_errno = ALPM_ERR_NOT_A_FILE; goto error; } if(init_gpgme(handle)) { /* pm_errno was set in gpgme_init() */ goto error; } _alpm_log(handle, ALPM_LOG_DEBUG, "checking signature for %s\n", path); memset(&ctx, 0, sizeof(ctx)); memset(&sigdata, 0, sizeof(sigdata)); memset(&filedata, 0, sizeof(filedata)); gpg_err = gpgme_new(&ctx); CHECK_ERR(); /* create our necessary data objects to verify the signature */ gpg_err = gpgme_data_new_from_stream(&filedata, file); CHECK_ERR(); /* next create data object for the signature */ if(base64_sig) { /* memory-based, we loaded it from a sync DB */ size_t data_len; int decode_ret = alpm_decode_signature(base64_sig, &decoded_sigdata, &data_len); if(decode_ret) { handle->pm_errno = ALPM_ERR_SIG_INVALID; goto gpg_error; } gpg_err = gpgme_data_new_from_mem(&sigdata, (char *)decoded_sigdata, data_len, 0); } else { /* file-based, it is on disk */ gpg_err = gpgme_data_new_from_stream(&sigdata, sigfile); } CHECK_ERR(); /* here's where the magic happens */ gpg_err = gpgme_op_verify(ctx, sigdata, filedata, NULL); CHECK_ERR(); verify_result = gpgme_op_verify_result(ctx); CHECK_ERR(); if(!verify_result || !verify_result->signatures) { _alpm_log(handle, ALPM_LOG_DEBUG, "no signatures returned\n"); handle->pm_errno = ALPM_ERR_SIG_MISSING; goto gpg_error; } for(gpgsig = verify_result->signatures, sigcount = 0; gpgsig; gpgsig = gpgsig->next, sigcount++); _alpm_log(handle, ALPM_LOG_DEBUG, "%d signatures returned\n", sigcount); CALLOC(siglist->results, sigcount, sizeof(alpm_sigresult_t), handle->pm_errno = ALPM_ERR_MEMORY; goto gpg_error); siglist->count = sigcount; for(gpgsig = verify_result->signatures, sigcount = 0; gpgsig; gpgsig = gpgsig->next, sigcount++) { alpm_list_t *summary_list, *summary; alpm_sigstatus_t status; alpm_sigvalidity_t validity; gpgme_key_t key; alpm_sigresult_t *result; _alpm_log(handle, ALPM_LOG_DEBUG, "fingerprint: %s\n", gpgsig->fpr); summary_list = list_sigsum(gpgsig->summary); for(summary = summary_list; summary; summary = summary->next) { _alpm_log(handle, ALPM_LOG_DEBUG, "summary: %s\n", (const char *)summary->data); } alpm_list_free(summary_list); _alpm_log(handle, ALPM_LOG_DEBUG, "status: %s\n", gpgme_strerror(gpgsig->status)); _alpm_log(handle, ALPM_LOG_DEBUG, "timestamp: %lu\n", gpgsig->timestamp); if((time_t)gpgsig->timestamp > time(NULL)) { _alpm_log(handle, ALPM_LOG_DEBUG, "signature timestamp is greater than system time.\n"); } _alpm_log(handle, ALPM_LOG_DEBUG, "exp_timestamp: %lu\n", gpgsig->exp_timestamp); _alpm_log(handle, ALPM_LOG_DEBUG, "validity: %s; reason: %s\n", string_validity(gpgsig->validity), gpgme_strerror(gpgsig->validity_reason)); result = siglist->results + sigcount; gpg_err = gpgme_get_key(ctx, gpgsig->fpr, &key, 0); if(gpg_err_code(gpg_err) == GPG_ERR_EOF) { _alpm_log(handle, ALPM_LOG_DEBUG, "key lookup failed, unknown key\n"); gpg_err = GPG_ERR_NO_ERROR; /* we dupe the fpr in this case since we have no key to point at */ STRDUP(result->key.fingerprint, gpgsig->fpr, handle->pm_errno = ALPM_ERR_MEMORY; goto gpg_error); } else {
gboolean lr_gpg_check_signature_fd(int signature_fd, int data_fd, const char *home_dir, GError **err) { gpgme_error_t gpgerr; gpgme_ctx_t context; gpgme_data_t signature_data; gpgme_data_t data_data; gpgme_verify_result_t result; gpgme_signature_t sig; assert(!err || *err == NULL); // Initialization gpgme_check_version(NULL); gpgerr = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP); if (gpgerr != GPG_ERR_NO_ERROR) { g_debug("%s: gpgme_engine_check_version: %s", __func__, gpgme_strerror(gpgerr)); g_set_error(err, LR_GPG_ERROR, LRE_GPGNOTSUPPORTED, "gpgme_engine_check_version() error: %s", gpgme_strerror(gpgerr)); return FALSE; } gpgerr = gpgme_new(&context); if (gpgerr != GPG_ERR_NO_ERROR) { g_debug("%s: gpgme_new: %s", __func__, gpgme_strerror(gpgerr)); g_set_error(err, LR_GPG_ERROR, LRE_GPGERROR, "gpgme_new() error: %s", gpgme_strerror(gpgerr)); return FALSE; } gpgerr = gpgme_set_protocol(context, GPGME_PROTOCOL_OpenPGP); if (gpgerr != GPG_ERR_NO_ERROR) { g_debug("%s: gpgme_set_protocol: %s", __func__, gpgme_strerror(gpgerr)); g_set_error(err, LR_GPG_ERROR, LRE_GPGERROR, "gpgme_set_protocol() error: %s", gpgme_strerror(gpgerr)); gpgme_release(context); return FALSE; } if (home_dir) { gpgerr = gpgme_ctx_set_engine_info(context, GPGME_PROTOCOL_OpenPGP, NULL, home_dir); if (gpgerr != GPG_ERR_NO_ERROR) { g_debug("%s: gpgme_ctx_set_engine_info: %s", __func__, gpgme_strerror(gpgerr)); g_set_error(err, LR_GPG_ERROR, LRE_GPGERROR, "gpgme_ctx_set_engine_info() error: %s", gpgme_strerror(gpgerr)); gpgme_release(context); return FALSE; } } gpgme_set_armor(context, 1); gpgerr = gpgme_data_new_from_fd(&signature_data, signature_fd); if (gpgerr != GPG_ERR_NO_ERROR) { g_debug("%s: gpgme_data_new_from_fd: %s", __func__, gpgme_strerror(gpgerr)); g_set_error(err, LR_GPG_ERROR, LRE_GPGERROR, "gpgme_data_new_from_fd(_, %d) error: %s", signature_fd, gpgme_strerror(gpgerr)); gpgme_release(context); return FALSE; } gpgerr = gpgme_data_new_from_fd(&data_data, data_fd); if (gpgerr != GPG_ERR_NO_ERROR) { g_debug("%s: gpgme_data_new_from_fd: %s", __func__, gpgme_strerror(gpgerr)); g_set_error(err, LR_GPG_ERROR, LRE_GPGERROR, "gpgme_data_new_from_fd(_, %d) error: %s", data_fd, gpgme_strerror(gpgerr)); gpgme_data_release(signature_data); gpgme_release(context); return FALSE; } // Verify gpgerr = gpgme_op_verify(context, signature_data, data_data, NULL); gpgme_data_release(signature_data); gpgme_data_release(data_data); if (gpgerr != GPG_ERR_NO_ERROR) { g_debug("%s: gpgme_op_verify: %s", __func__, gpgme_strerror(gpgerr)); g_set_error(err, LR_GPG_ERROR, LRE_GPGERROR, "gpgme_op_verify() error: %s", gpgme_strerror(gpgerr)); gpgme_release(context); return FALSE; } result = gpgme_op_verify_result(context); if (!result) { g_debug("%s: gpgme_op_verify_result: error", __func__); g_set_error(err, LR_GPG_ERROR, LRE_GPGERROR, "gpgme_op_verify_result() error: %s", gpgme_strerror(gpgerr)); gpgme_release(context); return FALSE; } // Check result of verification sig = result->signatures; if(!sig) { g_debug("%s: signature verify error (no signatures)", __func__); g_set_error(err, LR_GPG_ERROR, LRE_BADGPG, "Signature verify error - no signatures"); gpgme_release(context); return FALSE; } // Example of signature usage could be found in gpgme git repository // in the gpgme/tests/run-verify.c for (; sig; sig = sig->next) { if ((sig->summary & GPGME_SIGSUM_VALID) || // Valid (sig->summary & GPGME_SIGSUM_GREEN) || // Valid (sig->summary == 0 && sig->status == GPG_ERR_NO_ERROR)) // Valid but key is not certified with a trusted signature { gpgme_release(context); return TRUE; } } gpgme_release(context); g_debug("%s: Bad GPG signature", __func__); g_set_error(err, LR_GPG_ERROR, LRE_BADGPG, "Bad GPG signature"); return FALSE; }
/* ############################################################################# * * Description encrypt the given buffer and return the encrypted data with * an updated size information * Author Harry Brueckner * Date 2005-03-31 * Arguments char* buffer - buffer to encrypt * int size - size of the buffer * char** newbuffer - pointer to the new buffer which holds the * encrypted data * int* newsize - size of the returned buffer * PASSPHRASE_FN password_cb - callback function pointer used * to get the current passphrase * SHOWERROR_FN showerror_cb - callback function pointer used * to display errors * Return 0 if ok, otherwise 1 */ int gpgDecrypt(char* buffer, int size, char** newbuffer, int* newsize, PASSPHRASE_FN password_cb, SHOWERROR_FN showerror_cb) { gpgme_ctx_t context; gpgme_error_t error; gpgme_data_t input, output; gpgme_decrypt_result_t decrypt_result = NULL; gpgme_verify_result_t verify_result; int showerror = 1; char* agent; char* tmpbuffer = NULL; TRACE(99, "gpgDecrypt()", NULL); /* we set our passphrase callback function */ passphrase_callback = password_cb; *newbuffer = NULL; *newsize = 0; error = gpgme_new(&context); if (error) { (showerror_cb)(_("GpgMe context error"), gpgme_strerror(error)); return 1; } else { /* we got a context, we set the passphrase callback */ /* Flawfinder: ignore */ agent = getenv("GPG_AGENT_INFO"); if (!(agent && strchr(agent, ':'))) { retries = 0; gpgme_set_passphrase_cb(context, gpgRequestPassphrase, NULL); } } if (!error) { error = gpgme_data_new_from_mem(&input, buffer, size, 0); } if (!error) { error = gpgme_data_new(&output); } if (!error) { error = gpgme_op_decrypt_verify(context, input, output); } if (!error) { decrypt_result = gpgme_op_decrypt_result(context); } if (!error && decrypt_result && decrypt_result -> unsupported_algorithm) { tmpbuffer = memAlloc(__FILE__, __LINE__, STDBUFFERLENGTH); snprintf(tmpbuffer, STDBUFFERLENGTH, _("unsupported algorithm: %s\n"), decrypt_result -> unsupported_algorithm); (showerror_cb)(_("GpgMe error"), tmpbuffer); memFree(__FILE__, __LINE__, tmpbuffer, STDBUFFERLENGTH); showerror = 0; error = 1; } if (!error) { verify_result = gpgme_op_verify_result(context); error = gpgCheckVerifyResult(showerror_cb, verify_result, GPG_ERR_NO_ERROR); showerror = !error; } /* we don't need the passphrase any longer */ clearPassphrase(0); if (!error) { tmpbuffer = gpgData2Char(output, newsize); } #ifdef GPGME_HAS_RECIPIENT /* we get the recipients of the message for the further re-encryption of * the file */ if (!error && decrypt_result && decrypt_result -> recipients) { error = gpgGetRecipients(decrypt_result -> recipients, showerror_cb); showerror = 0; } #endif gpgme_data_release(input); gpgme_data_release(output); gpgme_release(context); *newbuffer = tmpbuffer; if (error) { if (showerror) { (showerror_cb)(_("GpgMe decrypt error"), gpgme_strerror(error)); } return 1; } else return 0; }
int opkg_verify_file (char *text_file, char *sig_file) { #if defined HAVE_GPGME if (conf->check_signature == 0 ) return 0; int status = -1; gpgme_ctx_t ctx; gpgme_data_t sig, text, key; gpgme_error_t err; gpgme_verify_result_t result; gpgme_signature_t s; char *trusted_path = NULL; gpgme_check_version (NULL); err = gpgme_new (&ctx); if (err) return -1; sprintf_alloc(&trusted_path, "%s/%s", conf->offline_root, "/etc/opkg/trusted.gpg"); err = gpgme_data_new_from_file (&key, trusted_path, 1); free (trusted_path); if (err) { return -1; } err = gpgme_op_import (ctx, key); if (err) { gpgme_data_release (key); return -1; } gpgme_data_release (key); err = gpgme_data_new_from_file (&sig, sig_file, 1); if (err) { gpgme_release (ctx); return -1; } err = gpgme_data_new_from_file (&text, text_file, 1); if (err) { gpgme_data_release (sig); gpgme_release (ctx); return -1; } err = gpgme_op_verify (ctx, sig, text, NULL); result = gpgme_op_verify_result (ctx); if (!result) return -1; /* see if any of the signitures matched */ s = result->signatures; while (s) { status = gpg_err_code (s->status); if (status == GPG_ERR_NO_ERROR) break; s = s->next; } gpgme_data_release (sig); gpgme_data_release (text); gpgme_release (ctx); return status; #elif defined HAVE_OPENSSL X509_STORE *store = NULL; PKCS7 *p7 = NULL; BIO *in = NULL, *indata = NULL; // Sig check failed by default ! int status = -1; openssl_init(); // Set-up the key store if(!(store = setup_verify(conf->signature_ca_file, conf->signature_ca_path))){ opkg_msg(ERROR, "Can't open CA certificates.\n"); goto verify_file_end; } // Open a BIO to read the sig file if (!(in = BIO_new_file(sig_file, "rb"))){ opkg_msg(ERROR, "Can't open signature file %s.\n", sig_file); goto verify_file_end; } // Read the PKCS7 block contained in the sig file p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); if(!p7){ opkg_msg(ERROR, "Can't read signature file %s (Corrupted ?).\n", sig_file); goto verify_file_end; } #if defined(HAVE_PATHFINDER) if(conf->check_x509_path){ if(!pkcs7_pathfinder_verify_signers(p7)){ opkg_msg(ERROR, "pkcs7_pathfinder_verify_signers: " "Path verification failed.\n"); goto verify_file_end; } } #endif // Open the Package file to authenticate if (!(indata = BIO_new_file(text_file, "rb"))){ opkg_msg(ERROR, "Can't open file %s.\n", text_file); goto verify_file_end; } // Let's verify the autenticity ! if (PKCS7_verify(p7, NULL, store, indata, NULL, PKCS7_BINARY) != 1){ // Get Off My Lawn! opkg_msg(ERROR, "Verification failure.\n"); }else{ // Victory ! status = 0; } verify_file_end: BIO_free(in); BIO_free(indata); PKCS7_free(p7); X509_STORE_free(store); return status; #else /* mute `unused variable' warnings. */ (void) sig_file; (void) text_file; (void) conf; return 0; #endif }
retvalue signature_check(const struct signature_requirement *requirements, const char *releasegpg, const char *release) { gpg_error_t err; int fd, gpgfd; gpgme_data_t dh, dh_gpg; gpgme_verify_result_t result; int i; const struct signature_requirement *req; assert (requirements != NULL); if (FAILEDTOALLOC(release) || FAILEDTOALLOC(releasegpg)) return RET_ERROR_OOM; assert (context != NULL); /* Read the file and its signature into memory: */ gpgfd = open(releasegpg, O_RDONLY|O_NOCTTY); if (gpgfd < 0) { int e = errno; fprintf(stderr, "Error opening '%s': %s\n", releasegpg, strerror(e)); return RET_ERRNO(e); } fd = open(release, O_RDONLY|O_NOCTTY); if (fd < 0) { int e = errno; (void)close(gpgfd); fprintf(stderr, "Error opening '%s': %s\n", release, strerror(e)); return RET_ERRNO(e); } err = gpgme_data_new_from_fd(&dh_gpg, gpgfd); if (err != 0) { (void)close(gpgfd); (void)close(fd); fprintf(stderr, "Error reading '%s':\n", releasegpg); return gpgerror(err); } err = gpgme_data_new_from_fd(&dh, fd); if (err != 0) { gpgme_data_release(dh_gpg); (void)close(gpgfd); (void)close(fd); fprintf(stderr, "Error reading '%s':\n", release); return gpgerror(err); } /* Verify the signature */ err = gpgme_op_verify(context, dh_gpg, dh, NULL); gpgme_data_release(dh_gpg); gpgme_data_release(dh); close(gpgfd); close(fd); if (err != 0) { fprintf(stderr, "Error verifying '%s':\n", releasegpg); return gpgerror(err); } result = gpgme_op_verify_result(context); if (result == NULL) { fprintf(stderr, "Internal error communicating with libgpgme: no result record!\n\n"); return RET_ERROR_GPGME; } for (req = requirements ; req != NULL ; req = req->next) { bool fullfilled = false; /* check first for good signatures, and then for good enough signatures, to not pester the user with warnings of one of the alternate keys, if the last one is good enough */ for (i = 0 ; (size_t)i < req->num_keys ; i++) { if (key_good(&req->keys[i], result->signatures)) { fullfilled = true; break; } } for (i = 0 ; !fullfilled && (size_t)i < req->num_keys ; i++) { if (key_good_enough(&req->keys[i], result->signatures, releasegpg, release)) { fullfilled = true; break; } } if (!fullfilled) { fprintf(stderr, "ERROR: Condition '%s' not fullfilled for '%s'.\n", req->condition, releasegpg); print_signatures(stderr, result->signatures, releasegpg); return RET_ERROR_BADSIG; } if (verbose > 10) { fprintf(stdout, "Condition '%s' fullfilled for '%s'.\n", req->condition, releasegpg); } } if (verbose > 20) print_signatures(stdout, result->signatures, releasegpg); return RET_OK; }
/* The main GPG decryption routine for libfko. */ int gpgme_decrypt(fko_ctx_t fko_ctx, unsigned char *indata, size_t in_len, const char *pw, unsigned char **out, size_t *out_len) { char *tmp_buf; int res; gpgme_ctx_t gpg_ctx = NULL; gpgme_data_t cipher = NULL; gpgme_data_t plaintext = NULL; gpgme_error_t err; gpgme_decrypt_result_t decrypt_res; gpgme_verify_result_t verify_res; /* Initialize gpgme */ res = init_gpgme(fko_ctx); if(res != FKO_SUCCESS) return(res); gpg_ctx = fko_ctx->gpg_ctx; err = gpgme_data_new(&plaintext); if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; fko_ctx->gpg_err = err; return(FKO_ERROR_GPGME_PLAINTEXT_DATA_OBJ); } /* Initialize the cipher data (place into gpgme_data object) */ err = gpgme_data_new_from_mem(&cipher, (char*)indata, in_len, 0); if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { gpgme_data_release(plaintext); gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; fko_ctx->gpg_err = err; return(FKO_ERROR_GPGME_CIPHER_DATA_OBJ); } /* Set the passphrase callback. */ gpgme_set_passphrase_cb(gpg_ctx, my_passphrase_cb, (void*)pw); /* Now decrypt and verify. */ err = gpgme_op_decrypt_verify(gpg_ctx, cipher, plaintext); if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { gpgme_data_release(plaintext); gpgme_data_release(cipher); gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; fko_ctx->gpg_err = err; return(FKO_ERROR_GPGME_DECRYPT_FAILED); } /* Done with the cipher text. */ gpgme_data_release(cipher); /* We check the "usupported_algorithm" flag in the decrypt result. */ decrypt_res = gpgme_op_decrypt_result(gpg_ctx); if(decrypt_res->unsupported_algorithm) { gpgme_data_release(plaintext); gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; return(FKO_ERROR_GPGME_DECRYPT_UNSUPPORTED_ALGORITHM); } /* Now verify the signatures if so configured. */ if(fko_ctx->verify_gpg_sigs) { verify_res = gpgme_op_verify_result(gpg_ctx); res = process_sigs(fko_ctx, verify_res); if(res != FKO_SUCCESS) { gpgme_data_release(plaintext); gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; return(res); } } /* Get the encrypted data and its length from the gpgme data object. */ tmp_buf = gpgme_data_release_and_get_mem(plaintext, out_len); /* Use calloc here with an extra byte because I am not sure if all systems * will include the terminating NULL with the decrypted data (which is * expected to be a string). */ *out = calloc(1, *out_len+1); /* This is freed upon fko_ctx destruction. */ if(*out == NULL) res = FKO_ERROR_MEMORY_ALLOCATION; else { memcpy(*out, tmp_buf, *out_len); res = FKO_SUCCESS; } gpgme_free(tmp_buf); return(res); }
/** * seahorse_service_crypto_verify_text: * @crypto: #SeahorseServiceCrypto context * @ktype: "openpgp" * @flags: FLAG_QUIET for no notification * @crypttext: the text to decrypt * @cleartext: the plaintext after verification (out) * @signer: the signer if the text is signed (out) * @error: a potential error (out) * * DBus: VerifyText * * Decrypts the @crypttext and returns it in @cleartext. If the text * was signed, the signed is returned. * * Returns: TRUE on success */ gboolean seahorse_service_crypto_verify_text (SeahorseServiceCrypto *crypto, const gchar *ktype, int flags, const gchar *crypttext, gchar **cleartext, char **signer, GError **error) { gpgme_verify_result_t status; gpgme_error_t gerr; SeahorseGpgmeOperation *pop; gpgme_data_t plain, cipher; gboolean ret = TRUE; GQuark keyid; if (!g_str_equal (ktype, g_quark_to_string (SEAHORSE_PGP))) { g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID, _("Invalid key type for verifying: %s"), ktype); return FALSE; } /* * TODO: Once we support different kinds of keys that support encryption * then all this logic will need to change. */ pop = seahorse_gpgme_operation_new (NULL); /* new data from text */ gerr = gpgme_data_new_from_mem (&cipher, crypttext, strlen (crypttext), FALSE); g_return_val_if_fail (GPG_IS_OK (gerr), FALSE); gerr = gpgme_data_new (&plain); g_return_val_if_fail (GPG_IS_OK (gerr), FALSE); /* encrypt with armor */ gpgme_set_textmode (pop->gctx, TRUE); gpgme_set_armor (pop->gctx, TRUE); /* Do the decryption */ gerr = gpgme_op_verify_start (pop->gctx, cipher, NULL, plain); /* Frees plain */ ret = process_crypto_result (pop, gerr, plain, cleartext, NULL, error); if (ret) { *signer = NULL; status = gpgme_op_verify_result (pop->gctx); if (status->signatures) { if (!(flags & FLAG_QUIET)) notify_signatures (NULL, status); if (status->signatures->summary & GPGME_SIGSUM_GREEN || status->signatures->summary & GPGME_SIGSUM_VALID || status->signatures->summary & GPGME_SIGSUM_KEY_MISSING) { keyid = seahorse_pgp_key_canonize_id (status->signatures->fpr); *signer = seahorse_context_id_to_dbus (SCTX_APP (), keyid); } } } g_object_unref (pop); gpgme_data_release (cipher); return TRUE; }
/* Retrieve certain attributes of a signature. IDX is the index number of the signature after a successful verify operation. WHAT is an attribute where GPGME_ATTR_EXPIRE is probably the most useful one. WHATIDX is to be passed as 0 for most attributes . */ unsigned long gpgme_get_sig_ulong_attr (gpgme_ctx_t ctx, int idx, _gpgme_attr_t what, int whatidx) { gpgme_verify_result_t result; gpgme_signature_t sig; result = gpgme_op_verify_result (ctx); sig = result->signatures; while (sig && idx) { sig = sig->next; idx--; } if (!sig || idx) return 0; switch (what) { case GPGME_ATTR_CREATED: return sig->timestamp; case GPGME_ATTR_EXPIRE: return sig->exp_timestamp; case GPGME_ATTR_VALIDITY: return (unsigned long) sig->validity; case GPGME_ATTR_SIG_STATUS: switch (gpg_err_code (sig->status)) { case GPG_ERR_NO_ERROR: return GPGME_SIG_STAT_GOOD; case GPG_ERR_BAD_SIGNATURE: return GPGME_SIG_STAT_BAD; case GPG_ERR_NO_PUBKEY: return GPGME_SIG_STAT_NOKEY; case GPG_ERR_NO_DATA: return GPGME_SIG_STAT_NOSIG; case GPG_ERR_SIG_EXPIRED: return GPGME_SIG_STAT_GOOD_EXP; case GPG_ERR_KEY_EXPIRED: return GPGME_SIG_STAT_GOOD_EXPKEY; default: return GPGME_SIG_STAT_ERROR; } case GPGME_ATTR_SIG_SUMMARY: return sig->summary; default: break; } return 0; }
static GMimeSignatureList * pkcs7_get_signatures (Pkcs7Ctx *pkcs7, gboolean verify) { GMimeSignatureList *signatures; GMimeSignature *signature; gpgme_verify_result_t result; gpgme_subkey_t subkey; gpgme_signature_t sig; gpgme_user_id_t uid; gpgme_key_t key; /* get the signature verification results from GpgMe */ if (!(result = gpgme_op_verify_result (pkcs7->ctx)) || !result->signatures) return verify ? g_mime_signature_list_new () : NULL; /* create a new signature list to return */ signatures = g_mime_signature_list_new (); sig = result->signatures; while (sig != NULL) { signature = g_mime_signature_new (); g_mime_signature_list_add (signatures, signature); if (sig->status != GPG_ERR_NO_ERROR) g_mime_signature_set_status (signature, GMIME_SIGNATURE_STATUS_ERROR); else g_mime_signature_set_status (signature, GMIME_SIGNATURE_STATUS_GOOD); g_mime_certificate_set_pubkey_algo (signature->cert, sig->pubkey_algo); g_mime_certificate_set_digest_algo (signature->cert, sig->hash_algo); g_mime_certificate_set_fingerprint (signature->cert, sig->fpr); g_mime_signature_set_expires (signature, sig->exp_timestamp); g_mime_signature_set_created (signature, sig->timestamp); if (sig->exp_timestamp != 0 && sig->exp_timestamp <= time (NULL)) { /* signature expired, automatically results in a BAD signature */ signature->errors |= GMIME_SIGNATURE_ERROR_EXPSIG; signature->status = GMIME_SIGNATURE_STATUS_BAD; } if (gpgme_get_key (pkcs7->ctx, sig->fpr, &key, 0) == GPG_ERR_NO_ERROR && key) { /* get more signer info from their signing key */ g_mime_certificate_set_trust (signature->cert, pkcs7_trust (key->owner_trust)); g_mime_certificate_set_issuer_serial (signature->cert, key->issuer_serial); g_mime_certificate_set_issuer_name (signature->cert, key->issuer_name); /* get the keyid, name, and email address */ uid = key->uids; while (uid) { if (uid->name && *uid->name) g_mime_certificate_set_name (signature->cert, uid->name); if (uid->email && *uid->email) g_mime_certificate_set_email (signature->cert, uid->email); if (uid->uid && *uid->uid) g_mime_certificate_set_key_id (signature->cert, uid->uid); if (signature->cert->name && signature->cert->email && signature->cert->keyid) break; uid = uid->next; } /* get the subkey used for signing */ subkey = key->subkeys; while (subkey && !subkey->can_sign) subkey = subkey->next; if (subkey) { g_mime_certificate_set_created (signature->cert, subkey->timestamp); g_mime_certificate_set_expires (signature->cert, subkey->expires); if (subkey->revoked) { /* signer's key has been revoked, automatic BAD status */ signature->errors |= GMIME_SIGNATURE_ERROR_REVKEYSIG; signature->status = GMIME_SIGNATURE_STATUS_BAD; } if (subkey->expired) { /* signer's key has expired, automatic BAD status */ signature->errors |= GMIME_SIGNATURE_ERROR_EXPKEYSIG; signature->status = GMIME_SIGNATURE_STATUS_BAD; } } else { /* If we don't have the subkey used by the signer, then we can't * tell what the status is, so set to ERROR if it hasn't already * been designated as BAD. */ if (signature->status != GMIME_SIGNATURE_STATUS_BAD) signature->status = GMIME_SIGNATURE_STATUS_ERROR; signature->errors |= GMIME_SIGNATURE_ERROR_NO_PUBKEY; } gpgme_key_unref (key); } else { /* If we don't have the signer's public key, then we can't tell what * the status is, so set it to ERROR if it hasn't already been * designated as BAD. */ g_mime_certificate_set_trust (signature->cert, GMIME_CERTIFICATE_TRUST_UNDEFINED); if (signature->status != GMIME_SIGNATURE_STATUS_BAD) signature->status = GMIME_SIGNATURE_STATUS_ERROR; signature->errors |= GMIME_SIGNATURE_ERROR_NO_PUBKEY; } sig = sig->next; } return signatures; }