~ubuntu-branches/ubuntu/precise/gnupg2/precise-proposed

« back to all changes in this revision

Viewing changes to g10/seckey-cert.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Mueller
  • Date: 2005-03-29 10:30:32 UTC
  • Revision ID: james.westby@ubuntu.com-20050329103032-sj42n2ain3ipx310
Tags: upstream-1.9.15
ImportĀ upstreamĀ versionĀ 1.9.15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* seckey-cert.c -  secret key certificate packet handling
 
2
 * Copyright (C) 1998, 1999, 2000, 2001, 2002,
 
3
 *               2003 Free Software Foundation, Inc.
 
4
 *
 
5
 * This file is part of GnuPG.
 
6
 *
 
7
 * GnuPG is free software; you can redistribute it and/or modify
 
8
 * it under the terms of the GNU General Public License as published by
 
9
 * the Free Software Foundation; either version 2 of the License, or
 
10
 * (at your option) any later version.
 
11
 *
 
12
 * GnuPG is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program; if not, write to the Free Software
 
19
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 
20
 */
 
21
 
 
22
#include <config.h>
 
23
#include <stdio.h>
 
24
#include <stdlib.h>
 
25
#include <string.h>
 
26
#include <assert.h>
 
27
 
 
28
#include "gpg.h"
 
29
#include "util.h"
 
30
#include "memory.h"
 
31
#include "packet.h"
 
32
#include "mpi.h"
 
33
#include "keydb.h"
 
34
#include "cipher.h"
 
35
#include "main.h"
 
36
#include "options.h"
 
37
#include "i18n.h"
 
38
#include "status.h"
 
39
#include "pkglue.h"
 
40
 
 
41
static int
 
42
do_check( PKT_secret_key *sk, const char *tryagain_text, int mode,
 
43
          int *canceled )
 
44
{
 
45
    byte *buffer;
 
46
    u16 csum=0;
 
47
    int i, res;
 
48
    unsigned nbytes;
 
49
    gpg_error_t rc;
 
50
 
 
51
    if( sk->is_protected ) { /* remove the protection */
 
52
        DEK *dek = NULL;
 
53
        u32 keyid[4]; /* 4! because we need two of them */
 
54
        CIPHER_HANDLE cipher_hd=NULL;
 
55
        PKT_secret_key *save_sk;
 
56
 
 
57
        if( sk->protect.s2k.mode == 1001 ) {
 
58
            log_info(_("secret key parts are not available\n"));
 
59
            return GPG_ERR_GENERAL;
 
60
        }
 
61
        if( sk->protect.algo == CIPHER_ALGO_NONE )
 
62
            BUG();
 
63
        if( openpgp_cipher_test_algo( sk->protect.algo ) ) {
 
64
            log_info(_("protection algorithm %d%s is not supported\n"),
 
65
                        sk->protect.algo,sk->protect.algo==1?" (IDEA)":"" );
 
66
            if (sk->protect.algo==CIPHER_ALGO_IDEA)
 
67
              {
 
68
                write_status (STATUS_RSA_OR_IDEA);
 
69
                idea_cipher_warn (0);
 
70
              }
 
71
            return GPG_ERR_CIPHER_ALGO;
 
72
        }
 
73
        keyid_from_sk( sk, keyid );
 
74
        keyid[2] = keyid[3] = 0;
 
75
        if( !sk->is_primary ) {
 
76
            keyid[2] = sk->main_keyid[0];
 
77
            keyid[3] = sk->main_keyid[1];
 
78
        }
 
79
        dek = passphrase_to_dek( keyid, sk->pubkey_algo, sk->protect.algo,
 
80
                                 &sk->protect.s2k, mode,
 
81
                                 tryagain_text, canceled );
 
82
        if (!dek && canceled && *canceled)
 
83
            return GPG_ERR_GENERAL;
 
84
 
 
85
        rc = gcry_cipher_open (&cipher_hd, sk->protect.algo,
 
86
                               GCRY_CIPHER_MODE_CFB,
 
87
                               GCRY_CIPHER_SECURE
 
88
                               | (sk->protect.algo >= 100 ?
 
89
                                  0 : GCRY_CIPHER_ENABLE_SYNC));
 
90
        if (rc)
 
91
          log_fatal ("cipher open failed: %s\n", gpg_strerror (rc) );
 
92
 
 
93
        rc = gcry_cipher_setkey (cipher_hd, dek->key, dek->keylen);
 
94
        if (rc)
 
95
          log_fatal ("set key failed: %s\n", gpg_strerror (rc) );
 
96
 
 
97
        xfree (dek);
 
98
        save_sk = copy_secret_key( NULL, sk );
 
99
        gcry_cipher_setiv (cipher_hd, sk->protect.iv, sk->protect.ivlen);
 
100
        csum = 0;
 
101
        if( sk->version >= 4 ) {
 
102
            int ndata;
 
103
            unsigned int ndatabits;
 
104
            byte *p, *data;
 
105
            u16 csumc = 0;
 
106
 
 
107
            i = pubkey_get_npkey(sk->pubkey_algo);
 
108
            assert( gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE ));
 
109
            p = gcry_mpi_get_opaque( sk->skey[i], &ndatabits );
 
110
            ndata = (ndatabits+7)/8;
 
111
            if ( ndata > 1 )
 
112
                csumc = p[ndata-2] << 8 | p[ndata-1];
 
113
            data = gcry_xmalloc_secure ( ndata );
 
114
            gcry_cipher_decrypt( cipher_hd, data, ndata, p, ndata );
 
115
            gcry_mpi_release ( sk->skey[i] ); sk->skey[i] = NULL ;
 
116
            p = data;
 
117
            if (sk->protect.sha1chk) {
 
118
                /* This is the new SHA1 checksum method to detect
 
119
                   tampering with the key as used by the Klima/Rosa
 
120
                   attack */
 
121
                sk->csum = 0;
 
122
                csum = 1;
 
123
                if( ndata < 20 ) 
 
124
                    log_error("not enough bytes for SHA-1 checksum\n");
 
125
                else {
 
126
                    gcry_md_hd_t h;
 
127
 
 
128
                    if ( gcry_md_open (&h, DIGEST_ALGO_SHA1, 1))
 
129
                        BUG(); /* algo not available */
 
130
                    gcry_md_write (h, data, ndata - 20);
 
131
                    gcry_md_final (h);
 
132
                    if (!memcmp (gcry_md_read (h, DIGEST_ALGO_SHA1),
 
133
                                 data + ndata - 20, 20) ) {
 
134
                        /* digest does match.  We have to keep the old
 
135
                           style checksum in sk->csum, so that the
 
136
                           test used for unprotected keys does work.
 
137
                           This test gets used when we are adding new
 
138
                           keys. */
 
139
                        sk->csum = csum = checksum (data, ndata-20);
 
140
                    }
 
141
                    gcry_md_close (h);
 
142
                }
 
143
            }
 
144
            else {
 
145
                if( ndata < 2 ) {
 
146
                    log_error("not enough bytes for checksum\n");
 
147
                    sk->csum = 0;
 
148
                    csum = 1;
 
149
                }
 
150
                else {
 
151
                    csum = checksum( data, ndata-2);
 
152
                    sk->csum = data[ndata-2] << 8 | data[ndata-1];
 
153
                    if ( sk->csum != csum ) {
 
154
                        /* This is a PGP 7.0.0 workaround */
 
155
                        sk->csum = csumc; /* take the encrypted one */
 
156
                    }
 
157
                }
 
158
            }
 
159
                
 
160
            /* must check it here otherwise the mpi_read_xx would fail
 
161
               because the length may have an arbitrary value */
 
162
            if( sk->csum == csum ) {
 
163
                for( ; i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
 
164
                    assert( gcry_is_secure( p ) );
 
165
                    res = gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_PGP,
 
166
                                         p, ndata, &nbytes);
 
167
                    if( res )
 
168
                        log_bug ("gcry_mpi_scan failed in do_check: %s\n",
 
169
                                 gpg_strerror (res));
 
170
                    ndata -= nbytes;
 
171
                    p += nbytes;
 
172
                }
 
173
                /* Note: at this point ndata should be 2 for a simple
 
174
                   checksum or 20 for the sha1 digest */
 
175
            }
 
176
            xfree (data);
 
177
        }
 
178
        else {
 
179
            for(i=pubkey_get_npkey(sk->pubkey_algo);
 
180
                    i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
 
181
                byte *p;
 
182
                int ndata;
 
183
                unsigned int ndatabits;
 
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
                assert (ndata >= 2);
 
189
                assert (ndata == ((p[0] << 8 | p[1]) + 7)/8 + 2);
 
190
                buffer = gcry_xmalloc_secure (ndata);
 
191
                gcry_cipher_sync (cipher_hd);
 
192
                buffer[0] = p[0];
 
193
                buffer[1] = p[1];
 
194
                gcry_cipher_decrypt (cipher_hd, buffer+2, ndata-2,
 
195
                                     p+2, ndata-2);
 
196
                csum += checksum (buffer, ndata);
 
197
                gcry_mpi_release (sk->skey[i]);
 
198
                res = gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_USG,
 
199
                                     buffer, ndata, &ndata );
 
200
                if( res )
 
201
                    log_bug ("gcry_mpi_scan failed in do_check: %s\n", 
 
202
                             gpg_strerror (res));
 
203
 
 
204
                assert (sk->skey[i]);
 
205
                xfree (buffer);
 
206
/*              csum += checksum_mpi (sk->skey[i]); */
 
207
            }
 
208
        }
 
209
        gcry_cipher_close (cipher_hd);
 
210
        /* now let's see whether we have used the right passphrase */
 
211
        if( csum != sk->csum ) {
 
212
            copy_secret_key( sk, save_sk );
 
213
            passphrase_clear_cache ( keyid, sk->pubkey_algo );
 
214
            free_secret_key( save_sk );
 
215
            return gpg_error (GPG_ERR_BAD_PASSPHRASE);
 
216
        }
 
217
        /* the checksum may fail, so we also check the key itself */
 
218
        res = pk_check_secret_key (sk->pubkey_algo, sk->skey);
 
219
        if (res) {
 
220
            copy_secret_key( sk, save_sk );
 
221
            passphrase_clear_cache ( keyid, sk->pubkey_algo );
 
222
            free_secret_key( save_sk );
 
223
            return gpg_error (GPG_ERR_BAD_PASSPHRASE);
 
224
        }
 
225
        free_secret_key( save_sk );
 
226
        sk->is_protected = 0;
 
227
    }
 
228
    else { /* not protected, assume it is okay if the checksum is okay */
 
229
        csum = 0;
 
230
        for(i=pubkey_get_npkey(sk->pubkey_algo);
 
231
                i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
 
232
            csum += checksum_mpi( sk->skey[i] );
 
233
        }
 
234
        if( csum != sk->csum )
 
235
            return GPG_ERR_CHECKSUM;
 
236
    }
 
237
 
 
238
    return 0;
 
239
}
 
240
 
 
241
 
 
242
 
 
243
/****************
 
244
 * Check the secret key
 
245
 * Ask up to 3 (or n) times for a correct passphrase
 
246
 * If n is negative, disable the key info prompt and make n=abs(n)
 
247
 */
 
248
int
 
249
check_secret_key( PKT_secret_key *sk, int n )
 
250
{
 
251
    int rc = gpg_error (GPG_ERR_BAD_PASSPHRASE);
 
252
    int i,mode;
 
253
 
 
254
    if (sk && sk->is_protected && sk->protect.s2k.mode == 1002)
 
255
      return 0; /* Let the scdaemon handle it. */
 
256
 
 
257
    if(n<0)
 
258
      {
 
259
        n=abs(n);
 
260
        mode=1;
 
261
      }
 
262
    else
 
263
      mode=0;
 
264
 
 
265
    if( n < 1 )
 
266
        n = (opt.batch && !opt.use_agent)? 1 : 3; /* use the default value */
 
267
 
 
268
    for(i=0; i < n && gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE; i++ ) {
 
269
        int canceled = 0;
 
270
        const char *tryagain = NULL;
 
271
        if (i) {
 
272
            tryagain = N_("Invalid passphrase; please try again");
 
273
            log_info (_("%s ...\n"), _(tryagain));
 
274
        }
 
275
        rc = do_check( sk, tryagain, mode, &canceled );
 
276
        if( gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
 
277
            && is_status_enabled() ) {
 
278
            u32 kid[2];
 
279
            char buf[50];
 
280
 
 
281
            keyid_from_sk( sk, kid );
 
282
            sprintf(buf, "%08lX%08lX", (ulong)kid[0], (ulong)kid[1]);
 
283
            write_status_text( STATUS_BAD_PASSPHRASE, buf );
 
284
        }
 
285
        if( have_static_passphrase() || canceled)
 
286
            break;
 
287
    }
 
288
 
 
289
    if( !rc )
 
290
        write_status( STATUS_GOOD_PASSPHRASE );
 
291
 
 
292
    return rc;
 
293
}
 
294
 
 
295
/****************
 
296
 * check whether the secret key is protected.
 
297
 * Returns: 0 not protected, -1 on error or the protection algorithm
 
298
 *                           -2 indicates a card stub.
 
299
 */
 
300
int
 
301
is_secret_key_protected( PKT_secret_key *sk )
 
302
{
 
303
    return sk->is_protected?
 
304
               sk->protect.s2k.mode == 1002? -2
 
305
                                           : sk->protect.algo : 0;
 
306
}
 
307
 
 
308
 
 
309
 
 
310
/****************
 
311
 * Protect the secret key with the passphrase from DEK
 
312
 */
 
313
int
 
314
protect_secret_key( PKT_secret_key *sk, DEK *dek )
 
315
{
 
316
    int i,j, rc = 0;
 
317
    byte *buffer;
 
318
    unsigned nbytes;
 
319
    u16 csum;
 
320
 
 
321
    if( !dek )
 
322
        return 0;
 
323
 
 
324
    if( !sk->is_protected ) { /* okay, apply the protection */
 
325
        gcry_cipher_hd_t cipher_hd=NULL;
 
326
 
 
327
        if( openpgp_cipher_test_algo( sk->protect.algo ) )
 
328
          {
 
329
            rc = gpg_error (GPG_ERR_CIPHER_ALGO); /* unsupport
 
330
                                                     protection
 
331
                                                     algorithm */
 
332
          }
 
333
        else {
 
334
            print_cipher_algo_note( sk->protect.algo );
 
335
            rc = gcry_cipher_open (&cipher_hd, sk->protect.algo,
 
336
                                   GCRY_CIPHER_MODE_CFB,
 
337
                                   GCRY_CIPHER_SECURE
 
338
                                   | (sk->protect.algo >= 100 ?
 
339
                                      0 : GCRY_CIPHER_ENABLE_SYNC) );
 
340
            if (rc)
 
341
              BUG();
 
342
            if( gcry_cipher_setkey( cipher_hd, dek->key, dek->keylen ) )
 
343
                log_info(_("WARNING: Weak key detected"
 
344
                           " - please change passphrase again.\n"));
 
345
            sk->protect.ivlen = gcry_cipher_get_algo_blklen(sk->protect.algo);
 
346
            assert( sk->protect.ivlen <= DIM(sk->protect.iv) );
 
347
            if( sk->protect.ivlen != 8 && sk->protect.ivlen != 16 )
 
348
                BUG(); /* yes, we are very careful */
 
349
            gcry_create_nonce (sk->protect.iv, sk->protect.ivlen);
 
350
            gcry_cipher_setiv( cipher_hd, sk->protect.iv, sk->protect.ivlen );
 
351
            if( sk->version >= 4 ) {
 
352
                unsigned char *bufarr[PUBKEY_MAX_NSKEY];
 
353
                unsigned narr[PUBKEY_MAX_NSKEY];
 
354
                unsigned nbits[PUBKEY_MAX_NSKEY];
 
355
                int ndata=0;
 
356
                byte *p, *data;
 
357
 
 
358
                for(j=0, i = pubkey_get_npkey(sk->pubkey_algo);
 
359
                        i < pubkey_get_nskey(sk->pubkey_algo); i++, j++ ) {
 
360
                    assert( !gcry_mpi_get_flag( sk->skey[i],
 
361
                                                GCRYMPI_FLAG_OPAQUE ));
 
362
 
 
363
                    if( gcry_mpi_aprint( GCRYMPI_FMT_USG, bufarr+j,
 
364
                                         narr+j, sk->skey[i]))
 
365
                        BUG();
 
366
 
 
367
                    nbits[j]  = gcry_mpi_get_nbits( sk->skey[i] );
 
368
                    ndata += narr[j] + 2;
 
369
                }
 
370
                for( ; j < PUBKEY_MAX_NSKEY; j++ )
 
371
                    bufarr[j] = NULL;
 
372
                ndata += opt.simple_sk_checksum? 2 : 20; /* for checksum */
 
373
 
 
374
                data = xmalloc_secure ( ndata );
 
375
                p = data;
 
376
                for(j=0; j < PUBKEY_MAX_NSKEY && bufarr[j]; j++ ) {
 
377
                    p[0] = nbits[j] >> 8 ;
 
378
                    p[1] = nbits[j];
 
379
                    p += 2;
 
380
                    memcpy(p, bufarr[j], narr[j] );
 
381
                    p += narr[j];
 
382
                    xfree (bufarr[j]);
 
383
                }
 
384
                
 
385
                if (opt.simple_sk_checksum) {
 
386
                    log_info (_("generating the deprecated 16-bit checksum"
 
387
                              " for secret key protection\n")); 
 
388
                    csum = checksum( data, ndata-2);
 
389
                    sk->csum = csum;
 
390
                    *p++ =      csum >> 8;
 
391
                    *p++ =      csum;
 
392
                    sk->protect.sha1chk = 0;
 
393
                }
 
394
                else {
 
395
                    gcry_md_hd_t h;
 
396
 
 
397
                    if (gcry_md_open (&h, GCRY_MD_SHA1, 1))
 
398
                        BUG(); /* algo not available */
 
399
                    gcry_md_write (h, data, ndata - 20);
 
400
                    gcry_md_final (h);
 
401
                    memcpy (p, gcry_md_read (h, GCRY_MD_SHA1), 20);
 
402
                    p += 20;
 
403
                    gcry_md_close (h);
 
404
                    sk->csum = csum = 0;
 
405
                    sk->protect.sha1chk = 1;
 
406
                }
 
407
                assert( p == data+ndata );
 
408
 
 
409
                gcry_cipher_encrypt( cipher_hd, data, ndata, NULL, 0 );
 
410
                for(i = pubkey_get_npkey(sk->pubkey_algo);
 
411
                        i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
 
412
                    gcry_mpi_release ( sk->skey[i] );
 
413
                    sk->skey[i] = NULL;
 
414
                }
 
415
                i = pubkey_get_npkey(sk->pubkey_algo);
 
416
                sk->skey[i] = gcry_mpi_set_opaque(NULL, data, ndata*8);
 
417
            }
 
418
            else {
 
419
                csum = 0;
 
420
                for(i=pubkey_get_npkey(sk->pubkey_algo);
 
421
                        i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
 
422
                    byte *data;
 
423
                    unsigned int nbits;
 
424
 
 
425
                    csum += checksum_mpi (sk->skey[i]);
 
426
                    if( gcry_mpi_aprint( GCRYMPI_FMT_USG, &buffer,
 
427
                                         &nbytes, sk->skey[i] ) )
 
428
                        BUG();
 
429
                    gcry_cipher_sync (cipher_hd);
 
430
                    assert (!gcry_mpi_get_flag( sk->skey[i],
 
431
                                                GCRYMPI_FLAG_OPAQUE ));
 
432
                    data = xmalloc (nbytes+2);
 
433
                    nbits  = gcry_mpi_get_nbits (sk->skey[i]);
 
434
                    assert (nbytes == (nbits + 7)/8);
 
435
                    data[0] = nbits >> 8;
 
436
                    data[1] = nbits;
 
437
                    gcry_cipher_encrypt (cipher_hd, data+2, nbytes,
 
438
                                         buffer, nbytes);
 
439
                    xfree ( buffer );
 
440
                    
 
441
                    gcry_mpi_release (sk->skey[i]);
 
442
                    sk->skey[i] = gcry_mpi_set_opaque (NULL, data,
 
443
                                                       (nbytes+2)*8);
 
444
                }
 
445
                sk->csum = csum;
 
446
            }
 
447
            sk->is_protected = 1;
 
448
            gcry_cipher_close( cipher_hd );
 
449
        }
 
450
    }
 
451
    return rc;
 
452
}