textual changes
[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         keyid_from_sk( sk, keyid );
57         dek = passphrase_to_dek( keyid, sk->protect.algo,
58                                  &sk->protect.s2k, 0 );
59         cipher_hd = cipher_open( sk->protect.algo,
60                                  CIPHER_MODE_AUTO_CFB, 1);
61         cipher_setkey( cipher_hd, dek->key, dek->keylen );
62         cipher_setiv( cipher_hd, NULL );
63         m_free(dek);
64         save_sk = copy_secret_key( NULL, sk );
65         memcpy(save_iv, sk->protect.iv, 8 );
66         cipher_decrypt( cipher_hd, sk->protect.iv, sk->protect.iv, 8 );
67         csum = 0;
68         for(i=pubkey_get_npkey(sk->pubkey_algo);
69                 i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
70             buffer = mpi_get_secure_buffer( sk->skey[i], &nbytes, NULL );
71             cipher_sync( cipher_hd );
72             assert( mpi_is_protected(sk->skey[i]) );
73             cipher_decrypt( cipher_hd, buffer, buffer, nbytes );
74             mpi_set_buffer( sk->skey[i], buffer, nbytes, 0 );
75             mpi_clear_protect_flag( sk->skey[i] );
76             csum += checksum_mpi( sk->skey[i] );
77             m_free( buffer );
78         }
79         if( opt.emulate_bugs & 1 ) {
80            csum = sk->csum;
81         }
82         cipher_close( cipher_hd );
83         /* now let's see whether we have used the right passphrase */
84         if( csum != sk->csum ) {
85             copy_secret_key( sk, save_sk );
86             free_secret_key( save_sk );
87             memcpy( sk->protect.iv, save_iv, 8 );
88             return G10ERR_BAD_PASS;
89         }
90         /* the checksum may fail, so we also check the key itself */
91         res = pubkey_check_secret_key( sk->pubkey_algo, sk->skey );
92         if( res ) {
93             copy_secret_key( sk, save_sk );
94             free_secret_key( save_sk );
95             memcpy( sk->protect.iv, save_iv, 8 );
96             return G10ERR_BAD_PASS;
97         }
98         free_secret_key( save_sk );
99         sk->is_protected = 0;
100     }
101     else { /* not protected, assume it is okay if the checksum is okay */
102         csum = 0;
103         for(i=pubkey_get_npkey(sk->pubkey_algo);
104                 i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
105             csum += checksum_mpi( sk->skey[i] );
106         }
107         if( csum != sk->csum )
108             return G10ERR_CHECKSUM;
109     }
110
111     return 0;
112 }
113
114
115
116 /****************
117  * Check the secret key
118  * Ask up to 3 times for a correct passphrase
119  */
120 int
121 check_secret_key( PKT_secret_key *sk )
122 {
123     int rc = G10ERR_BAD_PASS;
124     int i;
125
126     for(i=0; i < 3 && rc == G10ERR_BAD_PASS; i++ ) {
127         if( i )
128             log_error(_("Invalid passphrase; please try again ...\n"));
129         rc = do_check( sk );
130       #if 0 /* set to 1 to enable the workaround */
131         if( rc == G10ERR_BAD_PASS && sk->is_protected
132             && sk->protect.algo == CIPHER_ALGO_BLOWFISH
133             && sk->pubkey_algo != PUBKEY_ALGO_ELGAMAL ) {
134             /* Workaround for a bug in 0.2.16 which still used
135              * a 160 bit key for BLOWFISH. */
136             log_info("trying workaround for 0.2.16 passphrase bug ...\n");
137             log_info("If you don't need this, uncomment it in g10/seckey-cert.c\n\n");
138             sk->protect.algo = CIPHER_ALGO_BLOWFISH160;
139             rc = do_check( sk );
140             if( rc )
141                 rc = G10ERR_BAD_PASS;
142             sk->protect.algo = CIPHER_ALGO_BLOWFISH;
143         }
144       #endif
145         if( get_passphrase_fd() != -1 )
146             break;
147     }
148
149     return rc;
150 }
151
152 /****************
153  * check whether the secret key is protected.
154  * Returns: 0 not protected, -1 on error or the protection algorithm
155  */
156 int
157 is_secret_key_protected( PKT_secret_key *sk )
158 {
159     return sk->is_protected? sk->protect.algo : 0;
160 }
161
162
163
164 /****************
165  * Protect the secret key with the passphrase from DEK
166  */
167 int
168 protect_secret_key( PKT_secret_key *sk, DEK *dek )
169 {
170     int i, rc = 0;
171     byte *buffer;
172     unsigned nbytes;
173     u16 csum;
174
175     if( !dek )
176         return 0;
177
178     if( !sk->is_protected ) { /* okay, apply the protection */
179         CIPHER_HANDLE cipher_hd=NULL;
180
181         if( check_cipher_algo( sk->protect.algo ) )
182             rc = G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
183         else {
184             cipher_hd = cipher_open( sk->protect.algo,
185                                      CIPHER_MODE_AUTO_CFB, 1 );
186             cipher_setkey( cipher_hd, dek->key, dek->keylen );
187             cipher_setiv( cipher_hd, NULL );
188             cipher_encrypt( cipher_hd, sk->protect.iv, sk->protect.iv, 8 );
189             /* NOTE: we always recalculate the checksum because there are some
190              * test releases which calculated it wrong */
191             csum = 0;
192             for(i=pubkey_get_npkey(sk->pubkey_algo);
193                     i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
194                 csum += checksum_mpi_counted_nbits( sk->skey[i] );
195                 buffer = mpi_get_buffer( sk->skey[i], &nbytes, NULL );
196                 cipher_sync( cipher_hd );
197                 assert( !mpi_is_protected(sk->skey[i]) );
198                 cipher_encrypt( cipher_hd, buffer, buffer, nbytes );
199                 mpi_set_buffer( sk->skey[i], buffer, nbytes, 0 );
200                 mpi_set_protect_flag( sk->skey[i] );
201                 m_free( buffer );
202             }
203             sk->csum = csum;
204             sk->is_protected = 1;
205             cipher_close( cipher_hd );
206         }
207     }
208     return rc;
209 }
210