diff options
author | Werner Koch <[email protected]> | 2003-07-03 18:08:16 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2003-07-03 18:08:16 +0000 |
commit | 1753a2f3b0ec8c1eda54d9de7b17fa62c43fef39 (patch) | |
tree | ec11dfed93129b924a14e921ea110ddcc7506d64 /g10/pubkey-enc.c | |
parent | * app-openpgp.c (store_fpr): Fixed fingerprint calculation. (diff) | |
download | gnupg-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.c | 286 |
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; } |