dada0fd207d5b7d2dd644134dc410ae9fc9286aa
[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
33 #if  BLOWFISH_BLOCKSIZE != 8
34   #error unsupported blocksize
35 #endif
36 #if  CAST5_BLOCKSIZE != 8
37   #error unsupported blocksize
38 #endif
39
40 static u16
41 checksum_u16( unsigned n )
42 {
43     u16 a;
44
45     a  = (n >> 8) & 0xff;
46     a |= n & 0xff;
47     return a;
48 }
49
50 static u16
51 checksum( byte *p, unsigned n )
52 {
53     u16 a;
54
55     for(a=0; n; n-- )
56         a += *p++;
57     return a;
58 }
59
60
61
62 static int
63 check_elg( PKT_secret_cert *cert )
64 {
65     byte *buffer;
66     u16 csum=0;
67     int res;
68     unsigned nbytes;
69     u32 keyid[2];
70     ELG_secret_key skey;
71     char save_iv[8];
72
73     if( cert->is_protected ) { /* remove the protection */
74         DEK *dek = NULL;
75         MPI test_x;
76         BLOWFISH_context *blowfish_ctx=NULL;
77         CAST5_context *cast5_ctx=NULL;
78
79         switch( cert->protect.algo ) {
80           case CIPHER_ALGO_NONE: BUG(); break;
81           case CIPHER_ALGO_BLOWFISH:
82           case CIPHER_ALGO_CAST:
83             keyid_from_skc( cert, keyid );
84             if( cert->protect.s2k == 1 || cert->protect.s2k == 3 )
85                 dek = get_passphrase_hash( keyid, NULL,
86                                                  cert->protect.salt );
87             else
88                 dek = get_passphrase_hash( keyid, NULL, NULL );
89
90             if( cert->protect.algo == CIPHER_ALGO_CAST )
91                 cast5_ctx = m_alloc_secure( sizeof *cast5_ctx );
92             else
93                 blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
94
95             if( blowfish_ctx ) {
96                 blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
97                 blowfish_setiv( blowfish_ctx, NULL );
98             }
99             else {
100                 cast5_setkey( cast5_ctx, dek->key, dek->keylen );
101                 cast5_setiv( cast5_ctx, NULL );
102             }
103             m_free(dek); /* pw is in secure memory, so m_free() burns it */
104             memcpy(save_iv, cert->protect.iv, 8 );
105             if( blowfish_ctx )
106                 blowfish_decode_cfb( blowfish_ctx, cert->protect.iv,
107                                                    cert->protect.iv, 8 );
108             else
109                 cast5_decode_cfb( cast5_ctx, cert->protect.iv,
110                                                 cert->protect.iv, 8 );
111             mpi_set_secure(cert->d.elg.x );
112             /*fixme: maybe it is better to set the buffer secure with a
113              * new get_buffer_secure() function */
114             buffer = mpi_get_buffer( cert->d.elg.x, &nbytes, NULL );
115             csum = checksum_u16( nbytes*8 );
116             if( blowfish_ctx )
117                 blowfish_decode_cfb( blowfish_ctx, buffer, buffer, nbytes );
118             else
119                 cast5_decode_cfb( cast5_ctx, buffer, buffer, nbytes );
120             csum += checksum( buffer, nbytes );
121             test_x = mpi_alloc_secure( mpi_get_nlimbs(cert->d.elg.x) );
122             mpi_set_buffer( test_x, buffer, nbytes, 0 );
123             m_free( buffer );
124             m_free( cast5_ctx );
125             m_free( blowfish_ctx );
126             /* now let's see wether we have used the right passphrase */
127             if( csum != cert->csum ) {
128                 mpi_free(test_x);
129                 memcpy( cert->protect.iv, save_iv, 8 );
130                 return G10ERR_BAD_PASS;
131             }
132
133             skey.p = cert->d.elg.p;
134             skey.g = cert->d.elg.g;
135             skey.y = cert->d.elg.y;
136             skey.x = test_x;
137             res = elg_check_secret_key( &skey );
138             memset( &skey, 0, sizeof skey );
139             if( !res ) {
140                 mpi_free(test_x);
141                 memcpy( cert->protect.iv, save_iv, 8 );
142                 return G10ERR_BAD_PASS;
143             }
144             mpi_set(cert->d.elg.x, test_x);
145             mpi_free(test_x);
146             cert->is_protected = 0;
147             break;
148
149           default:
150             return G10ERR_CIPHER_ALGO; /* unsupported protection algorithm */
151         }
152     }
153     else { /* not protected */
154         buffer = mpi_get_buffer( cert->d.elg.x, &nbytes, NULL );
155         csum = checksum_u16( nbytes*8 );
156         csum += checksum( buffer, nbytes );
157         m_free( buffer );
158         if( csum != cert->csum )
159             return G10ERR_CHECKSUM;
160     }
161
162     return 0;
163 }
164
165
166 static int
167 check_dsa( PKT_secret_cert *cert )
168 {
169     byte *buffer;
170     u16 csum=0;
171     int res;
172     unsigned nbytes;
173     u32 keyid[2];
174     DSA_secret_key skey;
175     char save_iv[8];
176
177     if( cert->is_protected ) { /* remove the protection */
178         DEK *dek = NULL;
179         MPI test_x;
180         BLOWFISH_context *blowfish_ctx=NULL;
181         CAST5_context *cast5_ctx=NULL;
182
183         switch( cert->protect.algo ) {
184           case CIPHER_ALGO_NONE: BUG(); break;
185           case CIPHER_ALGO_BLOWFISH:
186           case CIPHER_ALGO_CAST:
187             keyid_from_skc( cert, keyid );
188             if( cert->protect.s2k == 1 || cert->protect.s2k == 3 )
189                 dek = get_passphrase_hash( keyid, NULL,
190                                                  cert->protect.salt );
191             else
192                 dek = get_passphrase_hash( keyid, NULL, NULL );
193
194             if( cert->protect.algo == CIPHER_ALGO_CAST ) {
195                 cast5_ctx = m_alloc_secure( sizeof *cast5_ctx );
196                 cast5_setkey( cast5_ctx, dek->key, dek->keylen );
197                 cast5_setiv( cast5_ctx, NULL );
198             }
199             else {
200                 blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
201                 blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
202                 blowfish_setiv( blowfish_ctx, NULL );
203             }
204             m_free(dek); /* pw is in secure memory, so m_free() burns it */
205             memcpy(save_iv, cert->protect.iv, 8 );
206             if( blowfish_ctx )
207                 blowfish_decode_cfb( blowfish_ctx, cert->protect.iv,
208                                                    cert->protect.iv, 8 );
209             else
210                 cast5_decode_cfb( cast5_ctx, cert->protect.iv,
211                                              cert->protect.iv, 8 );
212             mpi_set_secure(cert->d.dsa.x );
213             /*fixme: maybe it is better to set the buffer secure with a
214              * new get_buffer_secure() function */
215             buffer = mpi_get_buffer( cert->d.dsa.x, &nbytes, NULL );
216             csum = checksum_u16( nbytes*8 );
217             if( blowfish_ctx )
218                 blowfish_decode_cfb( blowfish_ctx, buffer, buffer, nbytes );
219             else
220                 cast5_decode_cfb( cast5_ctx, buffer, buffer, nbytes );
221             csum += checksum( buffer, nbytes );
222             test_x = mpi_alloc_secure( mpi_get_nlimbs(cert->d.dsa.x) );
223             mpi_set_buffer( test_x, buffer, nbytes, 0 );
224             m_free( buffer );
225             m_free( cast5_ctx );
226             m_free( blowfish_ctx );
227             /* now let's see wether we have used the right passphrase */
228             if( csum != cert->csum ) {
229                 mpi_free(test_x);
230                 memcpy( cert->protect.iv, save_iv, 8 );
231                 return G10ERR_BAD_PASS;
232             }
233
234             skey.p = cert->d.dsa.p;
235             skey.q = cert->d.dsa.q;
236             skey.g = cert->d.dsa.g;
237             skey.y = cert->d.dsa.y;
238             skey.x = test_x;
239             res = dsa_check_secret_key( &skey );
240             memset( &skey, 0, sizeof skey );
241             if( !res ) {
242                 mpi_free(test_x);
243                 memcpy( cert->protect.iv, save_iv, 8 );
244                 return G10ERR_BAD_PASS;
245             }
246             mpi_set(cert->d.dsa.x, test_x);
247             mpi_free(test_x);
248             cert->is_protected = 0;
249             break;
250
251           default:
252             return G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
253         }
254     }
255     else { /* not protected */
256         buffer = mpi_get_buffer( cert->d.dsa.x, &nbytes, NULL );
257         csum = checksum_u16( nbytes*8 );
258         csum += checksum( buffer, nbytes );
259         m_free( buffer );
260         if( csum != cert->csum )
261             return G10ERR_CHECKSUM;
262     }
263
264     return 0;
265 }
266
267
268
269 #ifdef HAVE_RSA_CIPHER
270 static int
271 check_rsa( PKT_secret_cert *cert )
272 {
273     byte *buffer;
274     u16 csum=0;
275     int res;
276     unsigned nbytes;
277     u32 keyid[2];
278     RSA_secret_key skey;
279
280     if( cert->is_protected ) { /* remove the protection */
281         DEK *dek = NULL;
282         BLOWFISH_context *blowfish_ctx=NULL;
283
284         switch( cert->protect.algo ) {
285             /* FIXME: use test variables to check for the correct key */
286           case CIPHER_ALGO_NONE: BUG(); break;
287           case CIPHER_ALGO_BLOWFISH:
288             keyid_from_skc( cert, keyid );
289             dek = get_passphrase_hash( keyid, NULL, NULL );
290             blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
291             blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
292             m_free(dek); /* pw is in secure memory, so m_free() burns it */
293             blowfish_setiv( blowfish_ctx, NULL );
294             blowfish_decode_cfb( blowfish_ctx, cert->protect.iv,
295                                                cert->protect.iv, 8 );
296             csum = 0;
297             #define X(a) do { \
298                 mpi_set_secure(cert->d.rsa.rsa_##a); \
299                 buffer = mpi_get_buffer( cert->d.rsa.rsa_##a, &nbytes, NULL );\
300                 csum += checksum_u16( nbytes*8 );                            \
301                 blowfish_decode_cfb( blowfish_ctx, buffer, buffer, nbytes ); \
302                 csum += checksum( buffer, nbytes );                          \
303                 mpi_set_buffer(cert->d.rsa.rsa_##a, buffer, nbytes, 0 );     \
304                 m_free( buffer );                                            \
305                } while(0)
306             X(d);
307             X(p);
308             X(q);
309             X(u);
310             #undef X
311             cert->is_protected = 0;
312             m_free( blowfish_ctx );
313             /* now let's see wether we have used the right passphrase */
314             if( csum != cert->csum )
315                 return G10ERR_BAD_PASS;
316
317             skey.d = cert->d.rsa.rsa_d;
318             skey.p = cert->d.rsa.rsa_p;
319             skey.q = cert->d.rsa.rsa_q;
320             skey.u = cert->d.rsa.rsa_u;
321             res = rsa_check_secret_key( &skey );
322             memset( &skey, 0, sizeof skey );
323             if( !res )
324                 return G10ERR_BAD_PASS;
325             break;
326
327           default:
328             return G10ERR_CIPHER_ALGO; /* unsupported protection algorithm */
329         }
330     }
331     else { /* not protected */
332         csum =0;
333         buffer = mpi_get_buffer( cert->d.rsa.rsa_d, &nbytes, NULL );
334         csum += checksum_u16( nbytes*8 );
335         csum += checksum( buffer, nbytes );
336         m_free( buffer );
337         buffer = mpi_get_buffer( cert->d.rsa.rsa_p, &nbytes, NULL );
338         csum += checksum_u16( nbytes*8 );
339         csum += checksum( buffer, nbytes );
340         m_free( buffer );
341         buffer = mpi_get_buffer( cert->d.rsa.rsa_q, &nbytes, NULL );
342         csum += checksum_u16( nbytes*8 );
343         csum += checksum( buffer, nbytes );
344         m_free( buffer );
345         buffer = mpi_get_buffer( cert->d.rsa.rsa_u, &nbytes, NULL );
346         csum += checksum_u16( nbytes*8 );
347         csum += checksum( buffer, nbytes );
348         m_free( buffer );
349         if( csum != cert->csum )
350             return G10ERR_CHECKSUM;
351     }
352
353     return 0;
354 }
355 #endif /*HAVE_RSA_CIPHER*/
356
357
358
359
360 /****************
361  * Check the secret key certificate
362  * Ask up to 3 time for a correct passphrase
363  */
364 int
365 check_secret_key( PKT_secret_cert *cert )
366 {
367     int rc = G10ERR_BAD_PASS;
368     int i;
369
370     for(i=0; i < 3 && rc == G10ERR_BAD_PASS; i++ ) {
371         if( i )
372             log_error("Invalid passphrase; please try again ...\n");
373         if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL )
374             rc = check_elg( cert );
375         else if( cert->pubkey_algo == PUBKEY_ALGO_DSA )
376             rc = check_dsa( cert );
377       #ifdef HAVE_RSA_CIPHER
378         else if( cert->pubkey_algo == PUBKEY_ALGO_RSA )
379             rc = check_rsa( cert );
380       #endif
381         else
382             rc = G10ERR_PUBKEY_ALGO;
383         if( get_passphrase_fd() != -1 )
384             break;
385     }
386     return rc;
387 }
388
389 /****************
390  * check wether the secret key is protected.
391  * Returns: 0 not protected, -1 on error or the protection algorithm
392  */
393 int
394 is_secret_key_protected( PKT_secret_cert *cert )
395 {
396     return cert->is_protected? cert->protect.algo : 0;
397 }
398
399
400 static int
401 do_protect( void (*fnc)(void *, byte *, byte *, unsigned),
402             void *fncctx, PKT_secret_cert *cert )
403 {
404     byte *buffer;
405     unsigned nbytes;
406
407     switch( cert->pubkey_algo ) {
408       case PUBKEY_ALGO_ELGAMAL:
409         buffer = mpi_get_buffer( cert->d.elg.x, &nbytes, NULL );
410         (*fnc)( fncctx, buffer, buffer, nbytes );
411         mpi_set_buffer( cert->d.elg.x, buffer, nbytes, 0 );
412         m_free( buffer );
413         break;
414
415       case PUBKEY_ALGO_DSA:
416         buffer = mpi_get_buffer( cert->d.dsa.x, &nbytes, NULL );
417         (*fnc)( fncctx, buffer, buffer, nbytes );
418         mpi_set_buffer( cert->d.dsa.x, buffer, nbytes, 0 );
419         m_free( buffer );
420         break;
421
422       default: return G10ERR_PUBKEY_ALGO;
423     }
424     return 0;
425 }
426
427
428 /****************
429  * Protect the secret key certificate with the passphrase from DEK
430  */
431 int
432 protect_secret_key( PKT_secret_cert *cert, DEK *dek )
433 {
434     int rc=0;
435
436     if( !dek )
437         return 0;
438
439     if( !cert->is_protected ) { /* okay, apply the protection */
440         BLOWFISH_context *blowfish_ctx=NULL;
441         CAST5_context *cast5_ctx=NULL;
442
443         switch( cert->protect.algo ) {
444           case CIPHER_ALGO_NONE: BUG(); break;
445           case CIPHER_ALGO_BLOWFISH:
446             blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
447             blowfish_setkey( blowfish_ctx, dek->key, dek->keylen );
448             blowfish_setiv( blowfish_ctx, NULL );
449             blowfish_encode_cfb( blowfish_ctx, cert->protect.iv,
450                                                cert->protect.iv, 8 );
451             if( !do_protect( (void (*)(void*,byte*,byte*,unsigned))
452                              &blowfish_encode_cfb, blowfish_ctx, cert ) )
453                 cert->is_protected = 1;
454             m_free( blowfish_ctx );
455             break;
456
457           case CIPHER_ALGO_CAST:
458             cast5_ctx = m_alloc_secure( sizeof *cast5_ctx );
459             cast5_setkey( cast5_ctx, dek->key, dek->keylen );
460             cast5_setiv( cast5_ctx, NULL );
461             cast5_encode_cfb( cast5_ctx, cert->protect.iv,
462                                                cert->protect.iv, 8 );
463             if( !do_protect( (void (*)(void*,byte*,byte*,unsigned))
464                              &cast5_encode_cfb, cast5_ctx, cert ) )
465                 cert->is_protected = 1;
466             m_free( cast5_ctx );
467             break;
468
469           default:
470             rc = G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
471             break;
472         }
473     }
474     return rc;
475 }
476