aboutsummaryrefslogtreecommitdiffstats
path: root/g10/seckey-cert.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/seckey-cert.c')
-rw-r--r--g10/seckey-cert.c127
1 files changed, 127 insertions, 0 deletions
diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c
index 85b0ed7af..f126ba01b 100644
--- a/g10/seckey-cert.c
+++ b/g10/seckey-cert.c
@@ -141,6 +141,7 @@ check_elg( PKT_secret_cert *cert )
return 0;
}
+
static int
protect_elg( PKT_secret_cert *cert, DEK *dek )
{
@@ -174,6 +175,126 @@ protect_elg( PKT_secret_cert *cert, DEK *dek )
return 0;
}
+static int
+check_dsa( PKT_secret_cert *cert )
+{
+ byte *buffer;
+ u16 csum=0;
+ int res;
+ unsigned nbytes;
+ u32 keyid[2];
+ DSA_secret_key skey;
+ char save_iv[8];
+
+ if( cert->d.dsa.is_protected ) { /* remove the protection */
+ DEK *dek = NULL;
+ MPI test_x;
+ BLOWFISH_context *blowfish_ctx=NULL;
+
+ switch( cert->d.dsa.protect.algo ) {
+ case CIPHER_ALGO_NONE: BUG(); break;
+ case CIPHER_ALGO_BLOWFISH:
+ keyid_from_skc( cert, keyid );
+ if( cert->d.dsa.protect.s2k == 1
+ || cert->d.dsa.protect.s2k == 3 )
+ dek = get_passphrase_hash( keyid, NULL,
+ cert->d.dsa.protect.salt );
+ else
+ dek = get_passphrase_hash( keyid, NULL, NULL );
+
+ blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
+ blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
+ m_free(dek); /* pw is in secure memory, so m_free() burns it */
+ blowfish_setiv( blowfish_ctx, NULL );
+ memcpy(save_iv, cert->d.dsa.protect.iv, 8 );
+ blowfish_decode_cfb( blowfish_ctx,
+ cert->d.dsa.protect.iv,
+ cert->d.dsa.protect.iv, 8 );
+ mpi_set_secure(cert->d.dsa.x );
+ /*fixme: maybe it is better to set the buffer secure with a
+ * new get_buffer_secure() function */
+ buffer = mpi_get_buffer( cert->d.dsa.x, &nbytes, NULL );
+ csum = checksum_u16( nbytes*8 );
+ blowfish_decode_cfb( blowfish_ctx, buffer, buffer, nbytes );
+ csum += checksum( buffer, nbytes );
+ test_x = mpi_alloc_secure( mpi_get_nlimbs(cert->d.dsa.x) );
+ mpi_set_buffer( test_x, buffer, nbytes, 0 );
+ m_free( buffer );
+ m_free( blowfish_ctx );
+ /* now let's see wether we have used the right passphrase */
+ if( csum != cert->d.dsa.csum ) {
+ mpi_free(test_x);
+ memcpy( cert->d.dsa.protect.iv, save_iv, 8 );
+ return G10ERR_BAD_PASS;
+ }
+
+ skey.p = cert->d.dsa.p;
+ skey.q = cert->d.dsa.q;
+ skey.g = cert->d.dsa.g;
+ skey.y = cert->d.dsa.y;
+ skey.x = test_x;
+ res = dsa_check_secret_key( &skey );
+ memset( &skey, 0, sizeof skey );
+ if( !res ) {
+ mpi_free(test_x);
+ memcpy( cert->d.dsa.protect.iv, save_iv, 8 );
+ return G10ERR_BAD_PASS;
+ }
+ mpi_set(cert->d.dsa.x, test_x);
+ mpi_free(test_x);
+ cert->d.dsa.is_protected = 0;
+ break;
+
+ default:
+ return G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
+ }
+ }
+ else { /* not protected */
+ buffer = mpi_get_buffer( cert->d.dsa.x, &nbytes, NULL );
+ csum = checksum_u16( nbytes*8 );
+ csum += checksum( buffer, nbytes );
+ m_free( buffer );
+ if( csum != cert->d.dsa.csum )
+ return G10ERR_CHECKSUM;
+ }
+
+ return 0;
+}
+
+
+static int
+protect_dsa( PKT_secret_cert *cert, DEK *dek )
+{
+ byte *buffer;
+ unsigned nbytes;
+
+ if( !cert->d.dsa.is_protected ) { /* add the protection */
+ BLOWFISH_context *blowfish_ctx=NULL;
+
+ switch( cert->d.dsa.protect.algo ) {
+ case CIPHER_ALGO_NONE: BUG(); break;
+ case CIPHER_ALGO_BLOWFISH:
+ blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
+ blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
+ blowfish_setiv( blowfish_ctx, NULL );
+ blowfish_encode_cfb( blowfish_ctx,
+ cert->d.dsa.protect.iv,
+ cert->d.dsa.protect.iv, 8 );
+ buffer = mpi_get_buffer( cert->d.dsa.x, &nbytes, NULL );
+ blowfish_encode_cfb( blowfish_ctx, buffer, buffer, nbytes );
+ mpi_set_buffer( cert->d.dsa.x, buffer, nbytes, 0 );
+ m_free( buffer );
+ m_free( blowfish_ctx );
+ cert->d.dsa.is_protected = 1;
+ break;
+
+ default:
+ return G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
+ }
+ }
+ return 0;
+}
+
#ifdef HAVE_RSA_CIPHER
static int
@@ -282,6 +403,8 @@ check_secret_key( PKT_secret_cert *cert )
log_error("Invalid passphrase; please try again ...\n");
if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
rc = check_elg( cert );
+ else if( cert->pubkey_algo == PUBKEY_ALGO_DSA )
+ rc = check_dsa( cert );
#ifdef HAVE_RSA_CIPHER
else if( cert->pubkey_algo == PUBKEY_ALGO_RSA )
rc = check_rsa( cert );
@@ -303,6 +426,8 @@ is_secret_key_protected( PKT_secret_cert *cert )
{
if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
return cert->d.elg.is_protected? cert->d.elg.protect.algo : 0;
+ else if( cert->pubkey_algo == PUBKEY_ALGO_DSA )
+ return cert->d.dsa.is_protected? cert->d.dsa.protect.algo : 0;
#ifdef HAVE_RSA_CIPHER
else if( cert->pubkey_algo == PUBKEY_ALGO_RSA )
return cert->d.rsa.is_protected? cert->d.rsa.protect_algo : 0;
@@ -323,6 +448,8 @@ protect_secret_key( PKT_secret_cert *cert, DEK *dek )
if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
return protect_elg( cert, dek );
+ else if( cert->pubkey_algo == PUBKEY_ALGO_DSA )
+ return protect_dsa( cert, dek );
else
return G10ERR_PUBKEY_ALGO;
}