aboutsummaryrefslogtreecommitdiffstats
path: root/g10/pubkey-enc.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2003-07-03 18:08:16 +0000
committerWerner Koch <[email protected]>2003-07-03 18:08:16 +0000
commit1753a2f3b0ec8c1eda54d9de7b17fa62c43fef39 (patch)
treeec11dfed93129b924a14e921ea110ddcc7506d64 /g10/pubkey-enc.c
parent* app-openpgp.c (store_fpr): Fixed fingerprint calculation. (diff)
downloadgnupg-1753a2f3b0ec8c1eda54d9de7b17fa62c43fef39.tar.gz
gnupg-1753a2f3b0ec8c1eda54d9de7b17fa62c43fef39.zip
* options.h (DBG_CIPHER): Reintroduced it.
* seskey.c (encode_session_key): Debug output of the session key. * pubkey-enc.c (get_it): Handle card case. * call-agent.c (agent_scd_pkdecrypt): New. * pkglue.c (pk_encrypt): Add RSA support. * g10.c (main): Default to --use-agent. * keygen.c (show_smartcard): Print info about the public key. (check_smartcard): Check for existing key here. (gen_card_key): And not anymore here. (fpr_is_zero): New. (generate_keypair): Generate both keys for a card. (smartcard_change_url): Nw.
Diffstat (limited to 'g10/pubkey-enc.c')
-rw-r--r--g10/pubkey-enc.c286
1 files changed, 161 insertions, 125 deletions
diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c
index b08394e4a..d052546e3 100644
--- a/g10/pubkey-enc.c
+++ b/g10/pubkey-enc.c
@@ -38,6 +38,7 @@
#include "main.h"
#include "i18n.h"
#include "pkglue.h"
+#include "call-agent.h"
static int get_it( PKT_pubkey_enc *k,
DEK *dek, PKT_secret_key *sk, u32 *keyid );
@@ -136,146 +137,181 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
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 n, nframe;
- u16 csum, csum2;
+ int rc;
+ gcry_mpi_t plain_dek = NULL;
+ byte *frame = NULL;
+ unsigned n, nframe;
+ u16 csum, csum2;
+ int card = 0;
- 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( n + 7 > nframe )
- { rc = 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"));
- rc = GPG_ERR_CIPHER_ALGO;
- goto leave;
+ if (sk->is_protected && sk->protect.s2k.mode == 1002)
+ { /* FIXME: Note that we do only support RSA for now. */
+ char *rbuf;
+ size_t rbuflen;
+ char *snbuf;
+ void *indata = NULL;
+ unsigned int 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;
}
- if( frame[n] != 2 ) /* somethink is wrong */
- { rc = GPG_ERR_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 = 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);
- 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;
+ else
+ {
+ void *indata;
+
+ rc = pk_decrypt (sk->pubkey_algo, &plain_dek, enc->data, sk->skey);
+ if( rc )
+ goto leave;
+ if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &indata, &nframe, plain_dek))
+ BUG();
+ frame = indata;
+ gcry_mpi_release (plain_dek); plain_dek = NULL;
}
- if( dek->keylen != gcry_cipher_get_algo_keylen (dek->algo) ) {
- rc = GPG_ERR_WRONG_SECKEY;
- 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 (!card)
+ {
+ if( n + 7 > nframe )
+ { rc = 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"));
+ rc = GPG_ERR_CIPHER_ALGO;
+ goto leave;
+ }
+ if( frame[n] != 2 ) /* somethink is wrong */
+ { rc = GPG_ERR_WRONG_SECKEY; goto leave; }
+ for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */
+ ;
+ n++; /* and the zero byte */
}
- /* 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 = GPG_ERR_WRONG_SECKEY;
- goto leave;
+ if( n + 4 > nframe )
+ { rc = 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);
+ 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);
}
- 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);
+ dek->algo = 0;
+ goto leave;
+ }
+ if( dek->keylen != gcry_cipher_get_algo_keylen (dek->algo) ) {
+ rc = GPG_ERR_WRONG_SECKEY;
+ goto leave;
+ }
- 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
- && !is_algo_in_prefs( pkb, PREFTYPE_SYM, dek->algo ) ) {
- /* Don't print a note while we are not on verbose mode,
- * the cipher is blowfish and the preferences have twofish
- * listed */
- if( opt.verbose || dek->algo != CIPHER_ALGO_BLOWFISH
- || !is_algo_in_prefs( pkb, PREFTYPE_SYM, CIPHER_ALGO_TWOFISH))
- log_info(_(
- "NOTE: cipher algorithm %d not found in preferences\n"),
- dek->algo );
- }
+ /* 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 = 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 ) {
+ 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
+ && !is_algo_in_prefs( pkb, PREFTYPE_SYM, dek->algo ) ) {
+ /* Don't print a note while we are not on verbose mode,
+ * the cipher is blowfish and the preferences have twofish
+ * listed */
+ if( opt.verbose || dek->algo != CIPHER_ALGO_BLOWFISH
+ || !is_algo_in_prefs( pkb, PREFTYPE_SYM, CIPHER_ALGO_TWOFISH))
+ log_info(_(
+ "NOTE: cipher algorithm %d not found in preferences\n"),
+ dek->algo );
+ }
- if (!rc) {
- KBNODE k;
+ 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 %08lX expired at %s\n"),
- (ulong)keyid[1], asctimestamp( pk->expiredate) );
- }
- }
+ 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 ( pk && pk->is_revoked ) {
- log_info( _("NOTE: key has been revoked") );
- putc( '\n', log_get_stream() );
- show_revocation_reason( pk, 1 );
+ 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 %08lX expired at %s\n"),
+ (ulong)keyid[1], asctimestamp( pk->expiredate) );
+ }
+ }
- release_kbnode (pkb);
- rc = 0;
+ if ( pk && pk->is_revoked ) {
+ log_info( _("NOTE: key has been revoked") );
+ putc( '\n', log_get_stream() );
+ show_revocation_reason( pk, 1 );
}
+ release_kbnode (pkb);
+ rc = 0;
+ }
- leave:
- gcry_mpi_release (plain_dek);
- xfree (frame);
- return rc;
+
+ leave:
+ gcry_mpi_release (plain_dek);
+ xfree (frame);
+ return rc;
}