See ChangeLog: Fri Jul 14 19:38:23 CEST 2000 Werner Koch
[gnupg.git] / g10 / seckey-cert.c
1 /* seckey-cert.c -  secret key certificate packet handling
2  *      Copyright (C) 1998, 1999, 2000 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
27 #include <gcrypt.h>
28 #include "util.h"
29 #include "packet.h"
30 #include "keydb.h"
31 #include "main.h"
32 #include "options.h"
33 #include "i18n.h"
34 #include "status.h"
35
36
37 /****************
38  * Emulate our old PK interface here - sometime in the future we might
39  * change the internal design to directly fit to libgcrypt.
40  */
41 static int
42 pk_check_secret_key( int algo, MPI *skey )
43 {
44     GCRY_SEXP s_skey;
45     int rc;
46
47     /* make a sexp from skey */
48     if( algo == GCRY_PK_DSA ) {
49         s_skey = SEXP_CONS( SEXP_NEW( "private-key", 0 ),
50                           gcry_sexp_vlist( SEXP_NEW( "dsa", 0 ),
51                           gcry_sexp_new_name_mpi( "p", skey[0] ),
52                           gcry_sexp_new_name_mpi( "q", skey[1] ),
53                           gcry_sexp_new_name_mpi( "g", skey[2] ),
54                           gcry_sexp_new_name_mpi( "y", skey[3] ),
55                           gcry_sexp_new_name_mpi( "x", skey[4] ),
56                           NULL ));
57     }
58     else if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E ) {
59         s_skey = SEXP_CONS( SEXP_NEW( "private-key", 0 ),
60                           gcry_sexp_vlist( SEXP_NEW( "elg", 0 ),
61                           gcry_sexp_new_name_mpi( "p", skey[0] ),
62                           gcry_sexp_new_name_mpi( "g", skey[1] ),
63                           gcry_sexp_new_name_mpi( "y", skey[2] ),
64                           gcry_sexp_new_name_mpi( "x", skey[3] ),
65                           NULL ));
66     }
67     else if( algo == GCRY_PK_RSA ) {
68         s_skey = SEXP_CONS( SEXP_NEW( "private-key", 0 ),
69                           gcry_sexp_vlist( SEXP_NEW( "rsa", 0 ),
70                           gcry_sexp_new_name_mpi( "n", skey[0] ),
71                           gcry_sexp_new_name_mpi( "e", skey[1] ),
72                           gcry_sexp_new_name_mpi( "d", skey[2] ),
73                           gcry_sexp_new_name_mpi( "p", skey[3] ),
74                           gcry_sexp_new_name_mpi( "q", skey[4] ),
75                           gcry_sexp_new_name_mpi( "u", skey[5] ),
76                           NULL ));
77     }
78     else
79         return GPGERR_PUBKEY_ALGO;
80
81     rc = gcry_pk_testkey( s_skey );
82     gcry_sexp_release( s_skey );
83     return rc;
84 }
85
86
87 static int
88 do_check( PKT_secret_key *sk )
89 {
90     byte *buffer;
91     u16 csum=0;
92     int i, res;
93     unsigned nbytes;
94
95     if( sk->is_protected ) { /* remove the protection */
96         DEK *dek = NULL;
97         u32 keyid[4]; /* 4! because we need two of them */
98         GCRY_CIPHER_HD cipher_hd=NULL;
99         PKT_secret_key *save_sk;
100
101         if( sk->protect.s2k.mode == 1001 ) {
102             log_info(_("secret key parts are not available\n"));
103             return GPGERR_GENERAL;
104         }
105         if( sk->protect.algo == GCRY_CIPHER_NONE )
106             BUG();
107         if( openpgp_cipher_test_algo( sk->protect.algo ) ) {
108             log_info(_("protection algorithm %d is not supported\n"),
109                         sk->protect.algo );
110             return GPGERR_CIPHER_ALGO;
111         }
112         keyid_from_sk( sk, keyid );
113         keyid[2] = keyid[3] = 0;
114         if( !sk->is_primary ) {
115             PKT_secret_key *sk2 = gcry_xcalloc( 1, sizeof *sk2 );
116             if( !get_primary_seckey( sk2, keyid ) )
117                 keyid_from_sk( sk2, keyid+2 );
118             free_secret_key( sk2 );
119         }
120         dek = passphrase_to_dek( keyid, sk->pubkey_algo, sk->protect.algo,
121                                  &sk->protect.s2k, 0 );
122         /* Hmmm: Do we use sync mode here even for Twofish? */
123         if( !(cipher_hd = gcry_cipher_open( sk->protect.algo,
124                                       GCRY_CIPHER_MODE_CFB,
125                                       GCRY_CIPHER_SECURE
126                                       | (sk->protect.algo >= 100 ?
127                                            0 : GCRY_CIPHER_ENABLE_SYNC) ) )
128                                     ) {
129             BUG();
130         }
131
132         if( gcry_cipher_setkey( cipher_hd, dek->key, dek->keylen ) )
133             log_fatal("set key failed: %s\n", gcry_strerror(-1) );
134         gcry_free(dek);
135         save_sk = copy_secret_key( NULL, sk );
136         if( gcry_cipher_setiv( cipher_hd, sk->protect.iv, sk->protect.ivlen ))
137             log_fatal("set IV failed: %s\n", gcry_strerror(-1) );
138         csum = 0;
139         if( sk->version >= 4 ) {
140             size_t ndata;
141             unsigned int ndatabits;
142             byte *p, *data;
143
144             i = pubkey_get_npkey(sk->pubkey_algo);
145             assert( gcry_mpi_get_flag( sk->skey[i], GCRYMPI_FLAG_OPAQUE ) );
146             p = gcry_mpi_get_opaque( sk->skey[i], &ndatabits );
147             ndata = (ndatabits+7)/8;
148             data = gcry_xmalloc_secure( ndata );
149             gcry_cipher_decrypt( cipher_hd, data, ndata, p, ndata );
150             mpi_release( sk->skey[i] ); sk->skey[i] = NULL ;
151             p = data;
152             if( ndata < 2 ) {
153                 log_error("not enough bytes for checksum\n");
154                 sk->csum = 0;
155                 csum = 1;
156             }
157             else {
158                 csum = checksum( data, ndata-2);
159                 sk->csum = data[ndata-2] << 8 | data[ndata-1];
160             }
161             /* must check it here otherwise the mpi_read_xx would fail
162              * because the length may have an arbitrary value */
163             if( sk->csum == csum ) {
164                 for( ; i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
165                     nbytes = ndata;
166                     assert( gcry_is_secure( p ) );
167                     res = gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_PGP,
168                                                              p, &nbytes);
169                     if( res )
170                         log_bug("gcry_mpi_scan failed in do_check: rc=%d\n", res);
171
172                     ndata -= nbytes;
173                     p += nbytes;
174                 }
175             }
176             gcry_free(data);
177         }
178         else {
179             for(i=pubkey_get_npkey(sk->pubkey_algo);
180                     i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
181                 size_t ndata;
182                 unsigned int ndatabits;
183                 byte *p, *data;
184
185                 assert( gcry_mpi_get_flag( sk->skey[i], GCRYMPI_FLAG_OPAQUE ) );
186                 p = gcry_mpi_get_opaque( sk->skey[i], &ndatabits );
187                 ndata = (ndatabits+7)/8;
188                 data = gcry_xmalloc_secure( ndata );
189                 gcry_cipher_sync( cipher_hd );
190                 gcry_cipher_decrypt( cipher_hd, data, ndata, p, ndata );
191                 mpi_release( sk->skey[i] ); sk->skey[i] = NULL ;
192
193                 res = gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_USG,
194                                      data, &ndata );
195                 if( res )
196                     log_bug("gcry_mpi_scan failed in do_check: rc=%d\n", res);
197
198                 csum += checksum_mpi( sk->skey[i] );
199                 gcry_free( data );
200             }
201         }
202         gcry_cipher_close( cipher_hd );
203         /* now let's see whether we have used the right passphrase */
204         if( csum != sk->csum ) {
205             copy_secret_key( sk, save_sk );
206             free_secret_key( save_sk );
207             return GPGERR_BAD_PASS;
208         }
209         /* the checksum may be correct in some cases,
210          * so we also check the key itself */
211         res = pk_check_secret_key( sk->pubkey_algo, sk->skey );
212         if( res ) {
213             copy_secret_key( sk, save_sk );
214             free_secret_key( save_sk );
215             return GPGERR_BAD_PASS;
216         }
217         free_secret_key( save_sk );
218         sk->is_protected = 0;
219     }
220     else { /* not protected, assume it is okay if the checksum is okay */
221         csum = 0;
222         for(i=pubkey_get_npkey(sk->pubkey_algo);
223                 i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
224             assert( !gcry_mpi_get_flag( sk->skey[i], GCRYMPI_FLAG_OPAQUE ) );
225             csum += checksum_mpi( sk->skey[i] );
226         }
227         if( csum != sk->csum )
228             return GPGERR_CHECKSUM;
229     }
230
231     return 0;
232 }
233
234
235
236 /****************
237  * Check the secret key
238  * Ask up to 3 (or n) times for a correct passphrase
239  */
240 int
241 check_secret_key( PKT_secret_key *sk, int n )
242 {
243     int rc = GPGERR_BAD_PASS;
244     int i;
245
246     if( n < 1 )
247         n = opt.batch? 1 : 3; /* use the default value */
248
249     for(i=0; i < n && rc == GPGERR_BAD_PASS; i++ ) {
250         if( i )
251             log_info(_("Invalid passphrase; please try again ...\n"));
252         rc = do_check( sk );
253         if( rc == GPGERR_BAD_PASS && is_status_enabled() ) {
254             u32 kid[2];
255             char buf[50];
256
257             keyid_from_sk( sk, kid );
258             sprintf(buf, "%08lX%08lX", (ulong)kid[0], (ulong)kid[1]);
259             write_status_text( STATUS_BAD_PASSPHRASE, buf );
260         }
261         if( have_static_passphrase() )
262             break;
263     }
264
265     if( !rc )
266         write_status( STATUS_GOOD_PASSPHRASE );
267
268     return rc;
269 }
270
271 /****************
272  * check whether the secret key is protected.
273  * Returns: 0 not protected, -1 on error or the protection algorithm
274  */
275 int
276 is_secret_key_protected( PKT_secret_key *sk )
277 {
278     return sk->is_protected? sk->protect.algo : 0;
279 }
280
281
282
283 /****************
284  * Protect the secret key with the passphrase from DEK
285  */
286 int
287 protect_secret_key( PKT_secret_key *sk, DEK *dek )
288 {
289     int i,j, rc = 0;
290     byte *buffer;
291     unsigned nbytes;
292     u16 csum;
293
294     if( !dek )
295         return 0;
296
297     if( !sk->is_protected ) { /* okay, apply the protection */
298         GCRY_CIPHER_HD cipher_hd=NULL;
299
300         if( openpgp_cipher_test_algo( sk->protect.algo ) )
301             rc = GPGERR_CIPHER_ALGO; /* unsupport protection algorithm */
302         else {
303             print_cipher_algo_note( sk->protect.algo );
304             if( !(cipher_hd = gcry_cipher_open( sk->protect.algo,
305                                           GCRY_CIPHER_MODE_CFB,
306                                           GCRY_CIPHER_SECURE
307                                           | (sk->protect.algo >= 100 ?
308                                               0 : GCRY_CIPHER_ENABLE_SYNC) ))
309                                          ) {
310                 BUG();
311             }
312             rc = gcry_cipher_setkey( cipher_hd, dek->key, dek->keylen );
313             if( rc == GCRYERR_WEAK_KEY ) {
314                 log_info(_("WARNING: Weak key detected"
315                            " - please change passphrase again.\n"));
316                 rc = 0;
317             }
318             else if( rc )
319                 BUG();
320
321             /* set the IV length */
322             {   int blocksize = gcry_cipher_get_algo_blklen( sk->protect.algo );
323                 if( blocksize != 8 && blocksize != 16 )
324                     log_fatal("unsupported blocksize %d\n", blocksize );
325                 sk->protect.ivlen = blocksize;
326                 assert( sk->protect.ivlen <= DIM(sk->protect.iv) );
327             }
328             gcry_randomize(sk->protect.iv, sk->protect.ivlen,
329                                                          GCRY_STRONG_RANDOM);
330             gcry_cipher_setiv( cipher_hd, sk->protect.iv, sk->protect.ivlen );
331
332             #warning FIXME: replace set/get buffer
333             if( sk->version >= 4 ) {
334                 /* FIXME: There is a bug in this function for all algorithms
335                  * where the secret MPIs are more than 1 */
336                 byte *bufarr[GNUPG_MAX_NSKEY];
337                 unsigned narr[GNUPG_MAX_NSKEY];
338                 unsigned nbits[GNUPG_MAX_NSKEY];
339                 int ndata=0;
340                 byte *p, *data;
341
342                 for(j=0, i = pubkey_get_npkey(sk->pubkey_algo);
343                         i < pubkey_get_nskey(sk->pubkey_algo); i++, j++ ) {
344                     assert( !gcry_mpi_get_flag( sk->skey[i], GCRYMPI_FLAG_OPAQUE ) );
345
346                     if( gcry_mpi_aprint( GCRYMPI_FMT_USG, (char*)bufarr+j,
347                                                           narr+j, sk->skey[i]))
348                         BUG();
349
350                     nbits[j]  = gcry_mpi_get_nbits( sk->skey[i] );
351                     ndata += narr[j] + 2;
352                 }
353                 for( ; j < GNUPG_MAX_NSKEY; j++ )
354                     bufarr[j] = NULL;
355                 ndata += 2; /* for checksum */
356
357                 data = gcry_xmalloc_secure( ndata );
358                 p = data;
359                 for(j=0; j < GNUPG_MAX_NSKEY && bufarr[j]; j++ ) {
360                     p[0] = nbits[j] >> 8 ;
361                     p[1] = nbits[j];
362                     p += 2;
363                     memcpy(p, bufarr[j], narr[j] );
364                     p += narr[j];
365                     gcry_free(bufarr[j]);
366                 }
367                 csum = checksum( data, ndata-2);
368                 sk->csum = csum;
369                 *p++ =  csum >> 8;
370                 *p++ =  csum;
371                 assert( p == data+ndata );
372                 gcry_cipher_encrypt( cipher_hd, data, ndata, NULL, 0 );
373                 for(i = pubkey_get_npkey(sk->pubkey_algo);
374                         i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
375                     mpi_release( sk->skey[i] );
376                     sk->skey[i] = NULL;
377                 }
378                 i = pubkey_get_npkey(sk->pubkey_algo);
379                 sk->skey[i] = gcry_mpi_set_opaque(NULL, data, ndata*8 );
380             }
381             else {
382                 /* NOTE: we always recalculate the checksum because there
383                  * are some test releases which calculated it wrong */
384                #warning FIXME:  Replace this code
385                 csum = 0;
386                 for(i=pubkey_get_npkey(sk->pubkey_algo);
387                         i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
388                     csum += checksum_mpi( sk->skey[i] );
389
390                     if( gcry_mpi_aprint( GCRYMPI_FMT_USG,
391                                          &buffer, &nbytes, sk->skey[i] ) )
392                         BUG();
393
394                     gcry_cipher_sync( cipher_hd );
395                     assert( !gcry_mpi_get_flag( sk->skey[i], GCRYMPI_FLAG_OPAQUE ) );
396                     gcry_cipher_encrypt( cipher_hd, buffer, nbytes, NULL, 0 );
397                     gcry_mpi_release( sk->skey[i] );
398                     if( gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_USG,
399                                        buffer,&nbytes ) )
400                         BUG();
401
402                     gcry_free( buffer );
403                 }
404                 sk->csum = csum;
405             }
406             sk->is_protected = 1;
407             gcry_cipher_close( cipher_hd );
408         }
409     }
410     return rc;
411 }
412