1 /* seskey.c - make sesssion keys etc.
2 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
3 * 2006 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
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 3 of the License, or
10 * (at your option) any later version.
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.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
35 * Make a session key and put it into DEK
38 make_session_key( DEK
*dek
)
43 dek
->keylen
= gcry_cipher_get_algo_keylen (dek
->algo
);
45 if (gcry_cipher_open (&chd
, dek
->algo
, GCRY_CIPHER_MODE_CFB
,
48 0 : GCRY_CIPHER_ENABLE_SYNC
))) )
50 gcry_randomize (dek
->key
, dek
->keylen
, GCRY_STRONG_RANDOM
);
51 for (i
=0; i
< 16; i
++ )
53 rc
= gcry_cipher_setkey (chd
, dek
->key
, dek
->keylen
);
56 gcry_cipher_close (chd
);
59 if (gpg_err_code (rc
) != GPG_ERR_WEAK_KEY
)
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
);
65 log_fatal (_("cannot avoid weak key for symmetric cipher; "
66 "tried %d times!\n"), i
);
71 * Encode the session key. NBITS is the number of bits which should be used
72 * for packing the session key.
73 * returns: A mpi with the session key (caller must free)
76 encode_session_key (DEK
*dek
, unsigned int nbits
)
78 size_t nframe
= (nbits
+7) / 8;
85 /* The current limitation is that we can only use a session key
86 * whose length is a multiple of BITS_PER_MPI_LIMB
87 * I think we can live with that.
89 if( dek
->keylen
+ 7 > nframe
|| !nframe
)
90 log_bug("can't encode a %d bit key in a %d bits frame\n",
91 dek
->keylen
*8, nbits
);
93 /* We encode the session key in this way:
95 * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes)
97 * (But how can we store the leading 0 - the external representaion
98 * of MPIs doesn't allow leading zeroes =:-)
100 * RND are non-zero random bytes.
101 * A is the cipher algorithm
102 * DEK is the encryption key (session key) length k depends on the
103 * cipher algorithm (20 is used with blowfish160).
104 * CSUM is the 16 bit checksum over the DEK
107 for( p
= dek
->key
, i
=0; i
< dek
->keylen
; i
++ )
110 frame
= xmalloc_secure( nframe
);
114 i
= nframe
- 6 - dek
->keylen
;
116 p
= gcry_random_bytes_secure (i
, GCRY_STRONG_RANDOM
);
117 /* Replace zero bytes by new values. */
122 /* count the zero bytes */
123 for(j
=k
=0; j
< i
; j
++ )
127 break; /* okay: no zero bytes */
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
;) {
138 memcpy( frame
+n
, p
, i
);
142 frame
[n
++] = dek
->algo
;
143 memcpy( frame
+n
, dek
->key
, dek
->keylen
); n
+= dek
->keylen
;
144 frame
[n
++] = csum
>>8;
146 assert( n
== nframe
);
147 if (gcry_mpi_scan( &a
, GCRYMPI_FMT_USG
, frame
, n
, &nframe
))
155 do_encode_md( gcry_md_hd_t md
, int algo
, size_t len
, unsigned nbits
,
156 const byte
*asn
, size_t asnlen
)
158 size_t nframe
= (nbits
+7) / 8;
163 if( len
+ asnlen
+ 4 > nframe
)
164 log_bug("can't encode a %d bit MD into a %d bits frame\n",
165 (int)(len
*8), (int)nbits
);
167 /* We encode the MD in this way:
169 * 0 1 PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes)
171 * PAD consists of FF bytes.
173 frame
= gcry_md_is_secure (md
)? xmalloc_secure (nframe
) : xmalloc (nframe
);
176 frame
[n
++] = 1; /* block type */
177 i
= nframe
- len
- asnlen
-3 ;
179 memset( frame
+n
, 0xff, i
); n
+= i
;
181 memcpy( frame
+n
, asn
, asnlen
); n
+= asnlen
;
182 memcpy( frame
+n
, gcry_md_read (md
, algo
), len
); n
+= len
;
183 assert( n
== nframe
);
185 if (gcry_mpi_scan( &a
, GCRYMPI_FMT_USG
, frame
, n
, &nframe
))
189 /* Note that PGP before version 2.3 encoded the MD as:
191 * 0 1 MD(16 bytes) 0 PAD(n bytes) 1
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.
203 * Encode a message digest into an MPI.
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
209 encode_md_value (PKT_public_key
*pk
, PKT_secret_key
*sk
,
210 gcry_md_hd_t md
, int hash_algo
)
217 if((pk
?pk
->pubkey_algo
:sk
->pubkey_algo
) == GCRY_PK_DSA
)
219 /* It's a DSA signature, so find out the size of q. */
221 size_t qbytes
= gcry_mpi_get_nbits (pk
?pk
->pkey
[1]:sk
->skey
[1]);
223 /* Make sure it is a multiple of 8 bits. */
227 log_error(_("DSA requires the hash length to be a"
228 " multiple of 8 bits\n"));
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
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
);
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
)
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));
258 if (gcry_mpi_scan (&frame
, GCRYMPI_FMT_USG
,
259 gcry_md_read (md
, hash_algo
), qbytes
, &qbytes
))
268 rc
= gcry_md_test_algo (hash_algo
);
270 rc
= gcry_md_algo_info (hash_algo
, GCRYCTL_GET_ASNOID
, NULL
, &asnlen
);
272 log_fatal ("can't get OID of algo %d: %s\n",
273 hash_algo
, gpg_strerror (rc
));
274 asn
= xmalloc (asnlen
);
275 if ( gcry_md_algo_info (hash_algo
, GCRYCTL_GET_ASNOID
, asn
, &asnlen
) )
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]),