void show_revocation_reason( PKT_public_key *pk, int mode ) { /* Hmmm, this is not so easy becuase we have to duplicate the code * used in the trustbd to calculate the keyflags. We need to find * a clean way to check revocation certificates on keys and * signatures. And there should be no duplicate code. Because we * enter this function only when the trustdb told us that we have * a revoked key, we could simply look for a revocation cert and * display this one, when there is only one. Let's try to do this * until we have a better solution. */ KBNODE node, keyblock = NULL; byte fingerprint[MAX_FINGERPRINT_LEN]; size_t fingerlen; int rc; /* get the keyblock */ fingerprint_from_pk( pk, fingerprint, &fingerlen ); rc = get_keyblock_byfprint( &keyblock, fingerprint, fingerlen ); if( rc ) { /* that should never happen */ log_debug( "failed to get the keyblock\n"); return; } for( node=keyblock; node; node = node->next ) { if( (mode && node->pkt->pkttype == PKT_PUBLIC_KEY) || ( ( node->pkt->pkttype == PKT_PUBLIC_KEY || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) && !cmp_public_keys( node->pkt->pkt.public_key, pk ) ) ) break; } if( !node ) { log_debug("Oops, PK not in keyblock\n"); release_kbnode( keyblock ); return; } /* now find the revocation certificate */ for( node = node->next; node ; node = node->next ) { if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) break; if( node->pkt->pkttype == PKT_SIGNATURE && (node->pkt->pkt.signature->sig_class == 0x20 || node->pkt->pkt.signature->sig_class == 0x28 ) ) { /* FIXME: we should check the signature here */ do_show_revocation_reason ( node->pkt->pkt.signature ); break; } } /* We didn't find it, so check if the whole key is revoked */ if(!node && !mode) show_revocation_reason(pk,1); release_kbnode( keyblock ); }
static int get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid ) { int rc; gcry_mpi_t plain_dek = NULL; byte *frame = NULL; unsigned int n; size_t nframe; u16 csum, csum2; int card = 0; if (sk->is_protected && sk->protect.s2k.mode == 1002) { /* Note, that we only support RSA for now. */ #ifdef ENABLE_CARD_SUPPORT unsigned char *rbuf; size_t rbuflen; char *snbuf; unsigned char *indata = NULL; size_t indatalen; snbuf = serialno_and_fpr_from_sk (sk->protect.iv, sk->protect.ivlen, sk); if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &indata, &indatalen, enc->data[0])) BUG (); rc = agent_scd_pkdecrypt (snbuf, indata, indatalen, &rbuf, &rbuflen); xfree (snbuf); xfree (indata); if (rc) goto leave; frame = rbuf; nframe = rbuflen; card = 1; #else rc = gpg_error (GPG_ERR_NOT_SUPPORTED); goto leave; #endif /*!ENABLE_CARD_SUPPORT*/ } else { rc = pk_decrypt (sk->pubkey_algo, &plain_dek, enc->data, sk->skey ); if( rc ) goto leave; if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &frame, &nframe, plain_dek)) BUG(); gcry_mpi_release (plain_dek); plain_dek = NULL; } /* Now get the DEK (data encryption key) from the frame * * Old versions encode the DEK in in this format (msb is left): * * 0 1 DEK(16 bytes) CSUM(2 bytes) 0 RND(n bytes) 2 * * Later versions encode the DEK like this: * * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes) * * (mpi_get_buffer already removed the leading zero). * * RND are non-zero randow bytes. * A is the cipher algorithm * DEK is the encryption key (session key) with length k * CSUM */ if (DBG_CIPHER) log_printhex ("DEK frame:", frame, nframe ); n=0; if (!card) { if( n + 7 > nframe ) { rc = G10ERR_WRONG_SECKEY; goto leave; } if( frame[n] == 1 && frame[nframe-1] == 2 ) { log_info(_("old encoding of the DEK is not supported\n")); rc = G10ERR_CIPHER_ALGO; goto leave; } if( frame[n] != 2 ) /* somethink is wrong */ { rc = G10ERR_WRONG_SECKEY; goto leave; } for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */ ; n++; /* and the zero byte */ } if( n + 4 > nframe ) { rc = G10ERR_WRONG_SECKEY; goto leave; } dek->keylen = nframe - (n+1) - 2; dek->algo = frame[n++]; if( dek->algo == CIPHER_ALGO_IDEA ) write_status(STATUS_RSA_OR_IDEA); rc = openpgp_cipher_test_algo (dek->algo); if( rc ) { if( !opt.quiet && gpg_err_code (rc) == GPG_ERR_CIPHER_ALGO ) { log_info(_("cipher algorithm %d%s is unknown or disabled\n"), dek->algo, dek->algo == CIPHER_ALGO_IDEA? " (IDEA)":""); if(dek->algo==CIPHER_ALGO_IDEA) idea_cipher_warn (0); } dek->algo = 0; goto leave; } if ( dek->keylen != openpgp_cipher_get_algo_keylen (dek->algo) ) { rc = GPG_ERR_WRONG_SECKEY; goto leave; } /* copy the key to DEK and compare the checksum */ csum = frame[nframe-2] << 8; csum |= frame[nframe-1]; memcpy( dek->key, frame+n, dek->keylen ); for( csum2=0, n=0; n < dek->keylen; n++ ) csum2 += dek->key[n]; if( csum != csum2 ) { rc = G10ERR_WRONG_SECKEY; goto leave; } if( DBG_CIPHER ) log_printhex ("DEK is:", dek->key, dek->keylen ); /* check that the algo is in the preferences and whether it has expired */ { PKT_public_key *pk = NULL; KBNODE pkb = get_pubkeyblock (keyid); if( !pkb ) { rc = -1; log_error("oops: public key not found for preference check\n"); } else if(pkb->pkt->pkt.public_key->selfsigversion > 3 && dek->algo != CIPHER_ALGO_3DES && !opt.quiet && !is_algo_in_prefs( pkb, PREFTYPE_SYM, dek->algo )) log_info (_("WARNING: cipher algorithm %s not found in recipient" " preferences\n"), openpgp_cipher_algo_name (dek->algo)); if (!rc) { KBNODE k; for (k=pkb; k; k = k->next) { if (k->pkt->pkttype == PKT_PUBLIC_KEY || k->pkt->pkttype == PKT_PUBLIC_SUBKEY){ u32 aki[2]; keyid_from_pk(k->pkt->pkt.public_key, aki); if (aki[0]==keyid[0] && aki[1]==keyid[1]) { pk = k->pkt->pkt.public_key; break; } } } if (!pk) BUG (); if ( pk->expiredate && pk->expiredate <= make_timestamp() ) { log_info(_("NOTE: secret key %s expired at %s\n"), keystr(keyid), asctimestamp( pk->expiredate) ); } } if ( pk && pk->is_revoked ) { log_info( _("NOTE: key has been revoked") ); log_printf ("\n"); show_revocation_reason( pk, 1 ); } release_kbnode (pkb); rc = 0; } leave: gcry_mpi_release (plain_dek); xfree (frame); return rc; }
/**************** * Check whether we can trust this signature. * Returns: Error if we shall not trust this signatures. */ int check_signatures_trust( PKT_signature *sig ) { PKT_public_key *pk = xmalloc_clear( sizeof *pk ); unsigned int trustlevel; int rc=0; rc = get_pubkey( pk, sig->keyid ); if (rc) { /* this should not happen */ log_error("Ooops; the key vanished - can't check the trust\n"); rc = G10ERR_NO_PUBKEY; goto leave; } if ( opt.trust_model==TM_ALWAYS ) { if( !opt.quiet ) log_info(_("WARNING: Using untrusted key!\n")); if (opt.with_fingerprint) print_fingerprint (pk, NULL, 1); goto leave; } if(pk->maybe_revoked && !pk->is_revoked) log_info(_("WARNING: this key might be revoked (revocation key" " not present)\n")); trustlevel = get_validity (pk, NULL); if ( (trustlevel & TRUST_FLAG_REVOKED) ) { write_status( STATUS_KEYREVOKED ); if(pk->is_revoked==2) log_info(_("WARNING: This key has been revoked by its" " designated revoker!\n")); else log_info(_("WARNING: This key has been revoked by its owner!\n")); log_info(_(" This could mean that the signature is forged.\n")); show_revocation_reason( pk, 0 ); } else if ((trustlevel & TRUST_FLAG_SUB_REVOKED) ) { write_status( STATUS_KEYREVOKED ); log_info(_("WARNING: This subkey has been revoked by its owner!\n")); show_revocation_reason( pk, 0 ); } if ((trustlevel & TRUST_FLAG_DISABLED)) log_info (_("Note: This key has been disabled.\n")); /* If we have PKA information adjust the trustlevel. */ if (sig->pka_info && sig->pka_info->valid) { unsigned char fpr[MAX_FINGERPRINT_LEN]; PKT_public_key *primary_pk; size_t fprlen; int okay; primary_pk = xmalloc_clear (sizeof *primary_pk); get_pubkey (primary_pk, pk->main_keyid); fingerprint_from_pk (primary_pk, fpr, &fprlen); free_public_key (primary_pk); if ( fprlen == 20 && !memcmp (sig->pka_info->fpr, fpr, 20) ) { okay = 1; write_status_text (STATUS_PKA_TRUST_GOOD, sig->pka_info->email); log_info (_("Note: Verified signer's address is `%s'\n"), sig->pka_info->email); } else { okay = 0; write_status_text (STATUS_PKA_TRUST_BAD, sig->pka_info->email); log_info (_("Note: Signer's address `%s' " "does not match DNS entry\n"), sig->pka_info->email); } switch ( (trustlevel & TRUST_MASK) ) { case TRUST_UNKNOWN: case TRUST_UNDEFINED: case TRUST_MARGINAL: if (okay && opt.verify_options&VERIFY_PKA_TRUST_INCREASE) { trustlevel = ((trustlevel & ~TRUST_MASK) | TRUST_FULLY); log_info (_("trustlevel adjusted to FULL" " due to valid PKA info\n")); } /* (fall through) */ case TRUST_FULLY: if (!okay) { trustlevel = ((trustlevel & ~TRUST_MASK) | TRUST_NEVER); log_info (_("trustlevel adjusted to NEVER" " due to bad PKA info\n")); } break; } } /* Now let the user know what up with the trustlevel. */ switch ( (trustlevel & TRUST_MASK) ) { case TRUST_EXPIRED: log_info(_("Note: This key has expired!\n")); print_fingerprint (pk, NULL, 1); break; default: log_error ("invalid trustlevel %u returned from validation layer\n", trustlevel); /* fall thru */ case TRUST_UNKNOWN: case TRUST_UNDEFINED: write_status( STATUS_TRUST_UNDEFINED ); log_info(_("WARNING: This key is not certified with" " a trusted signature!\n")); log_info(_(" There is no indication that the " "signature belongs to the owner.\n" )); print_fingerprint (pk, NULL, 1); break; case TRUST_NEVER: /* currently we won't get that status */ write_status( STATUS_TRUST_NEVER ); log_info(_("WARNING: We do NOT trust this key!\n")); log_info(_(" The signature is probably a FORGERY.\n")); if (opt.with_fingerprint) print_fingerprint (pk, NULL, 1); rc = G10ERR_BAD_SIGN; break; case TRUST_MARGINAL: write_status( STATUS_TRUST_MARGINAL ); log_info(_("WARNING: This key is not certified with" " sufficiently trusted signatures!\n")); log_info(_(" It is not certain that the" " signature belongs to the owner.\n" )); print_fingerprint (pk, NULL, 1); break; case TRUST_FULLY: write_status( STATUS_TRUST_FULLY ); if (opt.with_fingerprint) print_fingerprint (pk, NULL, 1); break; case TRUST_ULTIMATE: write_status( STATUS_TRUST_ULTIMATE ); if (opt.with_fingerprint) print_fingerprint (pk, NULL, 1); break; } leave: free_public_key( pk ); return rc; }
static gpg_error_t get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid) { gpg_error_t err; byte *frame = NULL; unsigned int n; size_t nframe; u16 csum, csum2; int card = 0; gcry_sexp_t s_data; char *desc; char *keygrip; byte fp[MAX_FINGERPRINT_LEN]; size_t fpn; const int pkalgo = map_pk_openpgp_to_gcry (sk->pubkey_algo); /* Get the keygrip. */ err = hexkeygrip_from_pk (sk, &keygrip); if (err) goto leave; /* Convert the data to an S-expression. */ if (pkalgo == GCRY_PK_ELG || pkalgo == GCRY_PK_ELG_E) { if (!enc->data[0] || !enc->data[1]) err = gpg_error (GPG_ERR_BAD_MPI); else err = gcry_sexp_build (&s_data, NULL, "(enc-val(elg(a%m)(b%m)))", enc->data[0], enc->data[1]); } else if (pkalgo == GCRY_PK_RSA || pkalgo == GCRY_PK_RSA_E) { if (!enc->data[0]) err = gpg_error (GPG_ERR_BAD_MPI); else err = gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))", enc->data[0]); } else if (pkalgo == GCRY_PK_ECDH) { if (!enc->data[0] || !enc->data[1]) err = gpg_error (GPG_ERR_BAD_MPI); else err = gcry_sexp_build (&s_data, NULL, "(enc-val(ecdh(s%m)(e%m)))", enc->data[0], enc->data[1]); } else err = gpg_error (GPG_ERR_BUG); if (err) goto leave; if (sk->pubkey_algo == PUBKEY_ALGO_ECDH) { fingerprint_from_pk (sk, fp, &fpn); assert (fpn == 20); } /* Decrypt. */ desc = gpg_format_keydesc (sk, 0, 1); err = agent_pkdecrypt (NULL, keygrip, desc, s_data, &frame, &nframe); xfree (desc); gcry_sexp_release (s_data); if (err) goto leave; /* Now get the DEK (data encryption key) from the frame * * Old versions encode the DEK in in this format (msb is left): * * 0 1 DEK(16 bytes) CSUM(2 bytes) 0 RND(n bytes) 2 * * Later versions encode the DEK like this: * * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes) * * (mpi_get_buffer already removed the leading zero). * * RND are non-zero randow bytes. * A is the cipher algorithm * DEK is the encryption key (session key) with length k * CSUM */ if (DBG_CIPHER) log_printhex ("DEK frame:", frame, nframe); n = 0; if (sk->pubkey_algo == PUBKEY_ALGO_ECDH) { gcry_mpi_t shared_mpi; gcry_mpi_t decoded; /* At the beginning the frame are the bytes of shared point MPI. */ err = gcry_mpi_scan (&shared_mpi, GCRYMPI_FMT_USG, frame, nframe, NULL); if (err) { err = gpg_error (GPG_ERR_WRONG_SECKEY); goto leave; } err = pk_ecdh_decrypt (&decoded, fp, enc->data[1]/*encr data as an MPI*/, shared_mpi, sk->pkey); mpi_release (shared_mpi); if(err) goto leave; /* Reuse NFRAME, which size is sufficient to include the session key. */ err = gcry_mpi_print (GCRYMPI_FMT_USG, frame, nframe, &nframe, decoded); mpi_release (decoded); if (err) goto leave; /* Now the frame are the bytes decrypted but padded session key. */ /* Allow double padding for the benefit of DEK size concealment. Higher than this is wasteful. */ if (!nframe || frame[nframe-1] > 8*2 || nframe <= 8 || frame[nframe-1] > nframe) { err = gpg_error (GPG_ERR_WRONG_SECKEY); goto leave; } nframe -= frame[nframe-1]; /* Remove padding. */ assert (!n); /* (used just below) */ } else { if (!card) { if (n + 7 > nframe) { err = gpg_error (GPG_ERR_WRONG_SECKEY); goto leave; } if (frame[n] == 1 && frame[nframe - 1] == 2) { log_info (_("old encoding of the DEK is not supported\n")); err = gpg_error (GPG_ERR_CIPHER_ALGO); goto leave; } if (frame[n] != 2) /* Something went wrong. */ { err = gpg_error (GPG_ERR_WRONG_SECKEY); goto leave; } for (n++; n < nframe && frame[n]; n++) /* Skip the random bytes. */ ; n++; /* Skip the zero byte. */ } } if (n + 4 > nframe) { err = gpg_error (GPG_ERR_WRONG_SECKEY); goto leave; } dek->keylen = nframe - (n + 1) - 2; dek->algo = frame[n++]; if (dek->algo == CIPHER_ALGO_IDEA) write_status (STATUS_RSA_OR_IDEA); err = openpgp_cipher_test_algo (dek->algo); if (err) { if (!opt.quiet && gpg_err_code (err) == GPG_ERR_CIPHER_ALGO) { log_info (_("cipher algorithm %d%s is unknown or disabled\n"), dek->algo, dek->algo == CIPHER_ALGO_IDEA ? " (IDEA)" : ""); if (dek->algo == CIPHER_ALGO_IDEA) idea_cipher_warn (0); } dek->algo = 0; goto leave; } if (dek->keylen != openpgp_cipher_get_algo_keylen (dek->algo)) { err = gpg_error (GPG_ERR_WRONG_SECKEY); goto leave; } /* Copy the key to DEK and compare the checksum. */ csum = frame[nframe - 2] << 8; csum |= frame[nframe - 1]; memcpy (dek->key, frame + n, dek->keylen); for (csum2 = 0, n = 0; n < dek->keylen; n++) csum2 += dek->key[n]; if (csum != csum2) { err = gpg_error (GPG_ERR_WRONG_SECKEY); goto leave; } if (DBG_CIPHER) log_printhex ("DEK is:", dek->key, dek->keylen); /* Check that the algo is in the preferences and whether it has expired. */ { PKT_public_key *pk = NULL; KBNODE pkb = get_pubkeyblock (keyid); if (!pkb) { err = -1; log_error ("oops: public key not found for preference check\n"); } else if (pkb->pkt->pkt.public_key->selfsigversion > 3 && dek->algo != CIPHER_ALGO_3DES && !opt.quiet && !is_algo_in_prefs (pkb, PREFTYPE_SYM, dek->algo)) log_info (_("WARNING: cipher algorithm %s not found in recipient" " preferences\n"), openpgp_cipher_algo_name (dek->algo)); if (!err) { KBNODE k; for (k = pkb; k; k = k->next) { if (k->pkt->pkttype == PKT_PUBLIC_KEY || k->pkt->pkttype == PKT_PUBLIC_SUBKEY) { u32 aki[2]; keyid_from_pk (k->pkt->pkt.public_key, aki); if (aki[0] == keyid[0] && aki[1] == keyid[1]) { pk = k->pkt->pkt.public_key; break; } } } if (!pk) BUG (); if (pk->expiredate && pk->expiredate <= make_timestamp ()) { log_info (_("NOTE: secret key %s expired at %s\n"), keystr (keyid), asctimestamp (pk->expiredate)); } } if (pk && pk->flags.revoked) { log_info (_("NOTE: key has been revoked")); log_printf ("\n"); show_revocation_reason (pk, 1); } release_kbnode (pkb); err = 0; } leave: xfree (frame); xfree (keygrip); return err; }
static gpg_error_t get_it (ctrl_t ctrl, PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid) { gpg_error_t err; byte *frame = NULL; unsigned int n; size_t nframe; u16 csum, csum2; int padding; gcry_sexp_t s_data; char *desc; char *keygrip; byte fp[MAX_FINGERPRINT_LEN]; size_t fpn; if (DBG_CLOCK) log_clock ("decryption start"); /* Get the keygrip. */ err = hexkeygrip_from_pk (sk, &keygrip); if (err) goto leave; /* Convert the data to an S-expression. */ if (sk->pubkey_algo == PUBKEY_ALGO_ELGAMAL || sk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E) { if (!enc->data[0] || !enc->data[1]) err = gpg_error (GPG_ERR_BAD_MPI); else err = gcry_sexp_build (&s_data, NULL, "(enc-val(elg(a%m)(b%m)))", enc->data[0], enc->data[1]); } else if (sk->pubkey_algo == PUBKEY_ALGO_RSA || sk->pubkey_algo == PUBKEY_ALGO_RSA_E) { if (!enc->data[0]) err = gpg_error (GPG_ERR_BAD_MPI); else err = gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))", enc->data[0]); } else if (sk->pubkey_algo == PUBKEY_ALGO_ECDH) { if (!enc->data[0] || !enc->data[1]) err = gpg_error (GPG_ERR_BAD_MPI); else err = gcry_sexp_build (&s_data, NULL, "(enc-val(ecdh(s%m)(e%m)))", enc->data[1], enc->data[0]); } else err = gpg_error (GPG_ERR_BUG); if (err) goto leave; if (sk->pubkey_algo == PUBKEY_ALGO_ECDH) { fingerprint_from_pk (sk, fp, &fpn); log_assert (fpn == 20); } /* Decrypt. */ desc = gpg_format_keydesc (ctrl, sk, FORMAT_KEYDESC_NORMAL, 1); err = agent_pkdecrypt (NULL, keygrip, desc, sk->keyid, sk->main_keyid, sk->pubkey_algo, s_data, &frame, &nframe, &padding); xfree (desc); gcry_sexp_release (s_data); if (err) goto leave; /* Now get the DEK (data encryption key) from the frame * * Old versions encode the DEK in this format (msb is left): * * 0 1 DEK(16 bytes) CSUM(2 bytes) 0 RND(n bytes) 2 * * Later versions encode the DEK like this: * * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes) * * (mpi_get_buffer already removed the leading zero). * * RND are non-zero randow bytes. * A is the cipher algorithm * DEK is the encryption key (session key) with length k * CSUM */ if (DBG_CRYPTO) log_printhex (frame, nframe, "DEK frame:"); n = 0; if (sk->pubkey_algo == PUBKEY_ALGO_ECDH) { gcry_mpi_t shared_mpi; gcry_mpi_t decoded; /* At the beginning the frame are the bytes of shared point MPI. */ err = gcry_mpi_scan (&shared_mpi, GCRYMPI_FMT_USG, frame, nframe, NULL); if (err) { err = gpg_error (GPG_ERR_WRONG_SECKEY); goto leave; } err = pk_ecdh_decrypt (&decoded, fp, enc->data[1]/*encr data as an MPI*/, shared_mpi, sk->pkey); mpi_release (shared_mpi); if(err) goto leave; xfree (frame); err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &frame, &nframe, decoded); mpi_release (decoded); if (err) goto leave; /* Now the frame are the bytes decrypted but padded session key. */ /* Allow double padding for the benefit of DEK size concealment. Higher than this is wasteful. */ if (!nframe || frame[nframe-1] > 8*2 || nframe <= 8 || frame[nframe-1] > nframe) { err = gpg_error (GPG_ERR_WRONG_SECKEY); goto leave; } nframe -= frame[nframe-1]; /* Remove padding. */ log_assert (!n); /* (used just below) */ } else { if (padding) { if (n + 7 > nframe) { err = gpg_error (GPG_ERR_WRONG_SECKEY); goto leave; } if (frame[n] == 1 && frame[nframe - 1] == 2) { log_info (_("old encoding of the DEK is not supported\n")); err = gpg_error (GPG_ERR_CIPHER_ALGO); goto leave; } if (frame[n] != 2) /* Something went wrong. */ { err = gpg_error (GPG_ERR_WRONG_SECKEY); goto leave; } for (n++; n < nframe && frame[n]; n++) /* Skip the random bytes. */ ; n++; /* Skip the zero byte. */ } } if (n + 4 > nframe) { err = gpg_error (GPG_ERR_WRONG_SECKEY); goto leave; } dek->keylen = nframe - (n + 1) - 2; dek->algo = frame[n++]; err = openpgp_cipher_test_algo (dek->algo); if (err) { if (!opt.quiet && gpg_err_code (err) == GPG_ERR_CIPHER_ALGO) { log_info (_("cipher algorithm %d%s is unknown or disabled\n"), dek->algo, dek->algo == CIPHER_ALGO_IDEA ? " (IDEA)" : ""); } dek->algo = 0; goto leave; } if (dek->keylen != openpgp_cipher_get_algo_keylen (dek->algo)) { err = gpg_error (GPG_ERR_WRONG_SECKEY); goto leave; } /* Copy the key to DEK and compare the checksum. */ csum = buf16_to_u16 (frame+nframe-2); memcpy (dek->key, frame + n, dek->keylen); for (csum2 = 0, n = 0; n < dek->keylen; n++) csum2 += dek->key[n]; if (csum != csum2) { err = gpg_error (GPG_ERR_WRONG_SECKEY); goto leave; } if (DBG_CLOCK) log_clock ("decryption ready"); if (DBG_CRYPTO) log_printhex (dek->key, dek->keylen, "DEK is:"); /* Check that the algo is in the preferences and whether it has * expired. Also print a status line with the key's fingerprint. */ { PKT_public_key *pk = NULL; PKT_public_key *mainpk = NULL; KBNODE pkb = get_pubkeyblock (ctrl, keyid); if (!pkb) { err = -1; log_error ("oops: public key not found for preference check\n"); } else if (pkb->pkt->pkt.public_key->selfsigversion > 3 && dek->algo != CIPHER_ALGO_3DES && !opt.quiet && !is_algo_in_prefs (pkb, PREFTYPE_SYM, dek->algo)) log_info (_("WARNING: cipher algorithm %s not found in recipient" " preferences\n"), openpgp_cipher_algo_name (dek->algo)); if (!err) { kbnode_t k; int first = 1; for (k = pkb; k; k = k->next) { if (k->pkt->pkttype == PKT_PUBLIC_KEY || k->pkt->pkttype == PKT_PUBLIC_SUBKEY) { u32 aki[2]; if (first) { first = 0; mainpk = k->pkt->pkt.public_key; } keyid_from_pk (k->pkt->pkt.public_key, aki); if (aki[0] == keyid[0] && aki[1] == keyid[1]) { pk = k->pkt->pkt.public_key; break; } } } if (!pk) BUG (); if (pk->expiredate && pk->expiredate <= make_timestamp ()) { log_info (_("Note: secret key %s expired at %s\n"), keystr (keyid), asctimestamp (pk->expiredate)); } } if (pk && pk->flags.revoked) { log_info (_("Note: key has been revoked")); log_printf ("\n"); show_revocation_reason (ctrl, pk, 1); } if (is_status_enabled () && pk && mainpk) { char pkhex[MAX_FINGERPRINT_LEN*2+1]; char mainpkhex[MAX_FINGERPRINT_LEN*2+1]; hexfingerprint (pk, pkhex, sizeof pkhex); hexfingerprint (mainpk, mainpkhex, sizeof mainpkhex); /* Note that we do not want to create a trustdb just for * getting the ownertrust: If there is no trustdb there can't * be ulitmately trusted key anyway and thus the ownertrust * value is irrelevant. */ write_status_printf (STATUS_DECRYPTION_KEY, "%s %s %c", pkhex, mainpkhex, get_ownertrust_info (ctrl, mainpk, 1)); } release_kbnode (pkb); err = 0; } leave: xfree (frame); xfree (keygrip); return err; }