~ubuntu-branches/ubuntu/oneiric/gnupg2/oneiric-updates

« back to all changes in this revision

Viewing changes to g10/seskey.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-10-04 10:25:53 UTC
  • mfrom: (5.1.15 intrepid)
  • Revision ID: james.westby@ubuntu.com-20081004102553-fv62pp8dsitxli47
Tags: 2.0.9-3.1
* Non-maintainer upload.
* agent/gpg-agent.c: Deinit the threading library before exec'ing
  the command to run in --daemon mode. And because that still doesn't
  restore the sigprocmask, do that manually. Closes: #499569

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* seskey.c -  make sesssion keys etc.
2
 
 * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
 
2
 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 
3
 *               2006 Free Software Foundation, Inc.
3
4
 *
4
5
 * This file is part of GnuPG.
5
6
 *
6
7
 * GnuPG is free software; you can redistribute it and/or modify
7
8
 * 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
 * the Free Software Foundation; either version 3 of the License, or
9
10
 * (at your option) any later version.
10
11
 *
11
12
 * GnuPG is distributed in the hope that it will be useful,
14
15
 * GNU General Public License for more details.
15
16
 *
16
17
 * 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
 
18
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19
19
 */
20
20
 
21
21
#include <config.h>
27
27
#include "gpg.h"
28
28
#include "util.h"
29
29
#include "cipher.h"
30
 
#include "mpi.h"
31
30
#include "main.h"
32
31
#include "i18n.h"
33
 
#include "options.h"
 
32
 
34
33
 
35
34
/****************
36
35
 * Make a session key and put it into DEK
38
37
void
39
38
make_session_key( DEK *dek )
40
39
{
41
 
  gcry_cipher_hd_t chd;
42
 
  int i, rc;
43
 
 
44
 
  dek->keylen = gcry_cipher_get_algo_keylen (dek->algo);
45
 
 
46
 
  if (gcry_cipher_open (&chd, dek->algo, GCRY_CIPHER_MODE_CFB,
 
40
    gcry_cipher_hd_t chd;
 
41
    int i, rc;
 
42
 
 
43
    dek->keylen = gcry_cipher_get_algo_keylen (dek->algo);
 
44
 
 
45
    if (gcry_cipher_open (&chd, dek->algo, GCRY_CIPHER_MODE_CFB,
47
46
                          (GCRY_CIPHER_SECURE
48
47
                           | (dek->algo >= 100 ?
49
48
                              0 : GCRY_CIPHER_ENABLE_SYNC))) )
50
 
    BUG();
51
 
 
52
 
  gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM );
53
 
  for (i=0; i < 16; i++ )
54
 
    {
55
 
      rc = gcry_cipher_setkey (chd, dek->key, dek->keylen);
56
 
      if (!rc)
57
 
        {
58
 
          gcry_cipher_close (chd);
59
 
          return;
60
 
        }
61
 
      if (gpg_err_code (rc) != GPG_ERR_WEAK_KEY)
62
 
        BUG();
63
 
      log_info (_("weak key created - retrying\n") );
64
 
      /* Renew the session key until we get a non-weak key. */
65
 
      gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM );
66
 
    }
67
 
  
68
 
  log_fatal (_("cannot avoid weak key for symmetric cipher; "
69
 
               "tried %d times!\n"), i);
 
49
      BUG();
 
50
    gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM );
 
51
    for (i=0; i < 16; i++ ) 
 
52
      {
 
53
        rc = gcry_cipher_setkey (chd, dek->key, dek->keylen);
 
54
        if (!rc) 
 
55
          {
 
56
            gcry_cipher_close (chd);
 
57
            return;
 
58
          }
 
59
        if (gpg_err_code (rc) != GPG_ERR_WEAK_KEY)
 
60
          BUG();
 
61
        log_info(_("weak key created - retrying\n") );
 
62
        /* Renew the session key until we get a non-weak key. */
 
63
        gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM);
 
64
      }
 
65
    log_fatal (_("cannot avoid weak key for symmetric cipher; "
 
66
                 "tried %d times!\n"), i);
70
67
}
71
68
 
72
69
 
78
75
gcry_mpi_t
79
76
encode_session_key (DEK *dek, unsigned int nbits)
80
77
{
81
 
    int nframe = (nbits+7) / 8;
 
78
    size_t nframe = (nbits+7) / 8;
82
79
    byte *p;
83
80
    byte *frame;
84
81
    int i,n;
85
82
    u16 csum;
86
83
    gcry_mpi_t a;
87
84
 
88
 
    /* the current limitation is that we can only use a session key
 
85
    /* The current limitation is that we can only use a session key
89
86
     * whose length is a multiple of BITS_PER_MPI_LIMB
90
87
     * I think we can live with that.
91
88
     */
110
107
    for( p = dek->key, i=0; i < dek->keylen; i++ )
111
108
        csum += *p++;
112
109
 
113
 
    frame = gcry_xmalloc_secure ( nframe );
 
110
    frame = xmalloc_secure( nframe );
114
111
    n = 0;
115
112
    frame[n++] = 0;
116
113
    frame[n++] = 2;
117
114
    i = nframe - 6 - dek->keylen;
118
115
    assert( i > 0 );
119
116
    p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM);
120
 
    /* replace zero bytes by new values */
 
117
    /* Replace zero bytes by new values. */
121
118
    for(;;) {
122
119
        int j, k;
123
120
        byte *pp;
128
125
                k++;
129
126
        if( !k )
130
127
            break; /* okay: no zero bytes */
131
 
        k += k/128; /* better get some more */
132
 
        pp = gcry_random_bytes_secure( k, GCRY_STRONG_RANDOM);
133
 
        for(j=0; j < i && k ; j++ )
 
128
        k += k/128 + 3; /* better get some more */
 
129
        pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM);
 
130
        for(j=0; j < i && k ;) {
134
131
            if( !p[j] )
135
132
                p[j] = pp[--k];
136
 
        xfree (pp);
 
133
            if (p[j])
 
134
              j++;
 
135
        }
 
136
        xfree(pp);
137
137
    }
138
138
    memcpy( frame+n, p, i );
139
 
    xfree (p);
 
139
    xfree(p);
140
140
    n += i;
141
141
    frame[n++] = 0;
142
142
    frame[n++] = dek->algo;
143
143
    memcpy( frame+n, dek->key, dek->keylen ); n += dek->keylen;
144
144
    frame[n++] = csum >>8;
145
145
    frame[n++] = csum;
146
 
    assert (n == nframe);
147
 
 
148
 
    if (DBG_CIPHER)
149
 
      log_printhex ("encoded session key:", frame, nframe );
150
 
 
 
146
    assert( n == nframe );
151
147
    if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, n, &nframe))
152
148
      BUG();
153
 
    xfree (frame);
 
149
    xfree(frame);
154
150
    return a;
155
151
}
156
152
 
157
153
 
158
154
static gcry_mpi_t
159
155
do_encode_md( gcry_md_hd_t md, int algo, size_t len, unsigned nbits,
160
 
              const byte *asn, size_t asnlen, int v3compathack )
 
156
              const byte *asn, size_t asnlen )
161
157
{
162
 
    int nframe = (nbits+7) / 8;
 
158
    size_t nframe = (nbits+7) / 8;
163
159
    byte *frame;
164
160
    int i,n;
165
161
    gcry_mpi_t a;
170
166
 
171
167
    /* We encode the MD in this way:
172
168
     *
173
 
     *     0  A PAD(n bytes)   0  ASN(asnlen bytes)  MD(len bytes)
 
169
     *     0  1 PAD(n bytes)   0  ASN(asnlen bytes)  MD(len bytes)
174
170
     *
175
171
     * PAD consists of FF bytes.
176
172
     */
177
 
    frame = gcry_md_is_secure (md)? xmalloc_secure (nframe): xmalloc (nframe);
 
173
    frame = gcry_md_is_secure (md)? xmalloc_secure (nframe) : xmalloc (nframe);
178
174
    n = 0;
179
175
    frame[n++] = 0;
180
 
    frame[n++] = v3compathack? algo : 1; /* block type */
 
176
    frame[n++] = 1; /* block type */
181
177
    i = nframe - len - asnlen -3 ;
182
178
    assert( i > 1 );
183
179
    memset( frame+n, 0xff, i ); n += i;
185
181
    memcpy( frame+n, asn, asnlen ); n += asnlen;
186
182
    memcpy( frame+n, gcry_md_read (md, algo), len ); n += len;
187
183
    assert( n == nframe );
 
184
 
188
185
    if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, n, &nframe ))
189
186
        BUG();
190
 
    xfree (frame);
 
187
    xfree(frame);
 
188
 
 
189
    /* Note that PGP before version 2.3 encoded the MD as:
 
190
     *
 
191
     *   0   1   MD(16 bytes)   0   PAD(n bytes)   1
 
192
     *
 
193
     * The MD is always 16 bytes here because it's always MD5.  We do
 
194
     * not support pre-v2.3 signatures, but I'm including this comment
 
195
     * so the information is easily found in the future.
 
196
     */
 
197
 
191
198
    return a;
192
199
}
193
200
 
194
201
 
195
202
/****************
196
203
 * Encode a message digest into an MPI.
197
 
 * v3compathack is used to work around a bug in old GnuPG versions
198
 
 * which did put the algo identifier inseatd of the block type 1 into
199
 
 * the encoded value.  Setting this flag forces the old behaviour.
 
204
 * If it's for a DSA signature, make sure that the hash is large
 
205
 * enough to fill up q.  If the hash is too big, take the leftmost
 
206
 * bits.
200
207
 */
201
208
gcry_mpi_t
202
 
encode_md_value (int pubkey_algo, gcry_md_hd_t md, int hash_algo,
203
 
                 unsigned int nbits, int v3compathack )
 
209
encode_md_value (PKT_public_key *pk, PKT_secret_key *sk,
 
210
                 gcry_md_hd_t md, int hash_algo)
204
211
{
205
 
  int algo = hash_algo? hash_algo : gcry_md_get_algo (md);
206
212
  gcry_mpi_t frame;
207
 
  
208
 
  if (pubkey_algo == GCRY_PK_DSA) 
 
213
 
 
214
  assert(hash_algo);
 
215
  assert(pk || sk);
 
216
 
 
217
  if((pk?pk->pubkey_algo:sk->pubkey_algo) == GCRY_PK_DSA)
209
218
    {
210
 
      size_t n = gcry_md_get_algo_dlen(hash_algo);
211
 
      if (n != 20)
212
 
        {
213
 
          log_error (_("DSA requires the use of a 160 bit hash algorithm\n"));
214
 
          return NULL;
215
 
        }
216
 
      if (gcry_mpi_scan( &frame, GCRYMPI_FMT_USG,
217
 
                         gcry_md_read (md, hash_algo), n, &n ) )
 
219
      /* It's a DSA signature, so find out the size of q. */
 
220
 
 
221
      size_t qbytes = gcry_mpi_get_nbits (pk?pk->pkey[1]:sk->skey[1]);
 
222
 
 
223
      /* Make sure it is a multiple of 8 bits. */
 
224
 
 
225
      if(qbytes%8)
 
226
        {
 
227
          log_error(_("DSA requires the hash length to be a"
 
228
                      " multiple of 8 bits\n"));
 
229
          return NULL;
 
230
        }
 
231
 
 
232
      /* Don't allow any q smaller than 160 bits.  This might need a
 
233
         revisit as the DSA2 design firms up, but for now, we don't
 
234
         want someone to issue signatures from a key with a 16-bit q
 
235
         or something like that, which would look correct but allow
 
236
         trivial forgeries.  Yes, I know this rules out using MD5 with
 
237
         DSA. ;) */
 
238
      if (qbytes < 160)
 
239
        {
 
240
          log_error (_("DSA key %s uses an unsafe (%u bit) hash\n"),
 
241
                     pk?keystr_from_pk(pk):keystr_from_sk(sk),
 
242
                     (unsigned int)qbytes);
 
243
          return NULL;
 
244
        }
 
245
 
 
246
      qbytes/=8;
 
247
 
 
248
      /* Check if we're too short.  Too long is safe as we'll
 
249
         automatically left-truncate. */
 
250
      if (gcry_md_get_algo_dlen (hash_algo) < qbytes)
 
251
        {
 
252
          log_error (_("DSA key %s requires a %u bit or larger hash\n"),
 
253
                     pk?keystr_from_pk(pk):keystr_from_sk(sk),
 
254
                     (unsigned int)(qbytes*8));
 
255
          return NULL;
 
256
        }
 
257
 
 
258
      if (gcry_mpi_scan (&frame, GCRYMPI_FMT_USG,
 
259
                         gcry_md_read (md, hash_algo), qbytes, &qbytes))
218
260
        BUG();
219
261
    }
220
262
  else
222
264
      gpg_error_t rc;
223
265
      byte *asn;
224
266
      size_t asnlen;
225
 
      
226
 
      rc = gcry_md_algo_info( algo, GCRYCTL_GET_ASNOID, NULL, &asnlen);
 
267
 
 
268
      rc = gcry_md_test_algo (hash_algo);
 
269
      if (!rc)
 
270
        rc = gcry_md_algo_info (hash_algo, GCRYCTL_GET_ASNOID, NULL, &asnlen);
227
271
      if (rc)
228
 
        log_fatal("can't get OID of algo %d: %s\n",
229
 
                  algo, gpg_strerror (rc));
 
272
        log_fatal ("can't get OID of algo %d: %s\n",
 
273
                   hash_algo, gpg_strerror (rc));
230
274
      asn = xmalloc (asnlen);
231
 
      if( gcry_md_algo_info( algo, GCRYCTL_GET_ASNOID, asn, &asnlen ) )
 
275
      if ( gcry_md_algo_info (hash_algo, GCRYCTL_GET_ASNOID, asn, &asnlen) )
232
276
        BUG();
233
 
      frame = do_encode_md( md, algo, gcry_md_get_algo_dlen( algo ),
234
 
                            nbits, asn, asnlen, v3compathack );
 
277
      frame = do_encode_md (md, hash_algo, gcry_md_get_algo_dlen (hash_algo),
 
278
                            gcry_mpi_get_nbits (pk?pk->pkey[0]:sk->skey[0]),
 
279
                            asn, asnlen);
235
280
      xfree (asn);
236
281
    }
 
282
 
237
283
  return frame;
238
284
}
239
 
 
240
 
 
241
 
 
242
 
 
243
 
 
244