edit-key is now complete
[gnupg.git] / g10 / seckey-cert.c
1 /* seckey-cert.c -  secret key certifucate packet handling
2  *      Copyright (C) 1998 Free Software Foundation, Inc.
3  *
4  * This file is part of GNUPG.
5  *
6  * GNUPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GNUPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26 #include "util.h"
27 #include "memory.h"
28 #include "packet.h"
29 #include "mpi.h"
30 #include "keydb.h"
31 #include "cipher.h"
32 #include "main.h"
33 #include "options.h"
34 #include "i18n.h"
35
36
37 static int
38 do_check( PKT_secret_key *sk )
39 {
40     byte *buffer;
41     u16 csum=0;
42     int i, res;
43     unsigned nbytes;
44
45     if( sk->is_protected ) { /* remove the protection */
46         DEK *dek = NULL;
47         u32 keyid[2];
48         CIPHER_HANDLE cipher_hd=NULL;
49         PKT_secret_key *save_sk;
50         char save_iv[8];
51
52         if( sk->protect.algo == CIPHER_ALGO_NONE )
53             BUG();
54         if( check_cipher_algo( sk->protect.algo ) )
55             return G10ERR_CIPHER_ALGO; /* unsupported protection algorithm */
56         if( cipher_get_blocksize( sk->protect.algo ) != 8 )
57             return G10ERR_CIPHER_ALGO; /* unsupported protection algorithm */
58         keyid_from_sk( sk, keyid );
59         dek = passphrase_to_dek( keyid, sk->protect.algo,
60                                  &sk->protect.s2k, 0 );
61         cipher_hd = cipher_open( sk->protect.algo,
62                                  CIPHER_MODE_AUTO_CFB, 1);
63         cipher_setkey( cipher_hd, dek->key, dek->keylen );
64         cipher_setiv( cipher_hd, NULL );
65         m_free(dek);
66         save_sk = copy_secret_key( NULL, sk );
67         memcpy(save_iv, sk->protect.iv, 8 );
68         cipher_decrypt( cipher_hd, sk->protect.iv, sk->protect.iv, 8 );
69         csum = 0;
70         for(i=pubkey_get_npkey(sk->pubkey_algo);
71                 i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
72             buffer = mpi_get_secure_buffer( sk->skey[i], &nbytes, NULL );
73             cipher_sync( cipher_hd );
74             assert( mpi_is_protected(sk->skey[i]) );
75             cipher_decrypt( cipher_hd, buffer, buffer, nbytes );
76             mpi_set_buffer( sk->skey[i], buffer, nbytes, 0 );
77             mpi_clear_protect_flag( sk->skey[i] );
78             csum += checksum_mpi( sk->skey[i] );
79             m_free( buffer );
80         }
81         if( opt.emulate_bugs & EMUBUG_GPGCHKSUM ) {
82            csum = sk->csum;
83         }
84         cipher_close( cipher_hd );
85         /* now let's see whether we have used the right passphrase */
86         if( csum != sk->csum ) {
87             copy_secret_key( sk, save_sk );
88             free_secret_key( save_sk );
89             memcpy( sk->protect.iv, save_iv, 8 );
90             return G10ERR_BAD_PASS;
91         }
92         /* the checksum may fail, so we also check the key itself */
93         res = pubkey_check_secret_key( sk->pubkey_algo, sk->skey );
94         if( res ) {
95             copy_secret_key( sk, save_sk );
96             free_secret_key( save_sk );
97             memcpy( sk->protect.iv, save_iv, 8 );
98             return G10ERR_BAD_PASS;
99         }
100         free_secret_key( save_sk );
101         sk->is_protected = 0;
102     }
103     else { /* not protected, assume it is okay if the checksum is okay */
104         csum = 0;
105         for(i=pubkey_get_npkey(sk->pubkey_algo);
106                 i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
107             csum += checksum_mpi( sk->skey[i] );
108         }
109         if( csum != sk->csum )
110             return G10ERR_CHECKSUM;
111     }
112
113     return 0;
114 }
115
116
117
118 /****************
119  * Check the secret key
120  * Ask up to 3 times for a correct passphrase
121  */
122 int
123 check_secret_key( PKT_secret_key *sk )
124 {
125     int rc = G10ERR_BAD_PASS;
126     int i;
127
128     for(i=0; i < 3 && rc == G10ERR_BAD_PASS; i++ ) {
129         if( i )
130             log_error(_("Invalid passphrase; please try again ...\n"));
131         rc = do_check( sk );
132       #if 0 /* set to 1 to enable the workaround */
133         if( rc == G10ERR_BAD_PASS && sk->is_protected
134             && sk->protect.algo == CIPHER_ALGO_BLOWFISH
135             && sk->pubkey_algo != PUBKEY_ALGO_ELGAMAL ) {
136             /* Workaround for a bug in 0.2.16 which still used
137              * a 160 bit key for BLOWFISH. */
138             log_info("trying workaround for 0.2.16 passphrase bug ...\n");
139             log_info("If you don't need this, uncomment it in g10/seckey-cert.c\n\n");
140             sk->protect.algo = CIPHER_ALGO_BLOWFISH160;
141             rc = do_check( sk );
142             if( rc )
143                 rc = G10ERR_BAD_PASS;
144             sk->protect.algo = CIPHER_ALGO_BLOWFISH;
145         }
146       #endif
147         if( get_passphrase_fd() != -1 )
148             break;
149     }
150
151     return rc;
152 }
153
154 /****************
155  * check whether the secret key is protected.
156  * Returns: 0 not protected, -1 on error or the protection algorithm
157  */
158 int
159 is_secret_key_protected( PKT_secret_key *sk )
160 {
161     return sk->is_protected? sk->protect.algo : 0;
162 }
163
164
165
166 /****************
167  * Protect the secret key with the passphrase from DEK
168  */
169 int
170 protect_secret_key( PKT_secret_key *sk, DEK *dek )
171 {
172     int i, rc = 0;
173     byte *buffer;
174     unsigned nbytes;
175     u16 csum;
176
177     if( !dek )
178         return 0;
179
180     if( !sk->is_protected ) { /* okay, apply the protection */
181         CIPHER_HANDLE cipher_hd=NULL;
182
183         if( check_cipher_algo( sk->protect.algo ) )
184             rc = G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
185         else if( cipher_get_blocksize( sk->protect.algo ) != 8 )
186             rc = G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
187         else {
188             cipher_hd = cipher_open( sk->protect.algo,
189                                      CIPHER_MODE_AUTO_CFB, 1 );
190             cipher_setkey( cipher_hd, dek->key, dek->keylen );
191             cipher_setiv( cipher_hd, NULL );
192             cipher_encrypt( cipher_hd, sk->protect.iv, sk->protect.iv, 8 );
193             /* NOTE: we always recalculate the checksum because there are some
194              * test releases which calculated it wrong */
195             csum = 0;
196             for(i=pubkey_get_npkey(sk->pubkey_algo);
197                     i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
198                 csum += checksum_mpi_counted_nbits( sk->skey[i] );
199                 buffer = mpi_get_buffer( sk->skey[i], &nbytes, NULL );
200                 cipher_sync( cipher_hd );
201                 assert( !mpi_is_protected(sk->skey[i]) );
202                 cipher_encrypt( cipher_hd, buffer, buffer, nbytes );
203                 mpi_set_buffer( sk->skey[i], buffer, nbytes, 0 );
204                 mpi_set_protect_flag( sk->skey[i] );
205                 m_free( buffer );
206             }
207             sk->csum = csum;
208             sk->is_protected = 1;
209             cipher_close( cipher_hd );
210         }
211     }
212     return rc;
213 }
214