2006-06-09 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / g10 / pubkey-enc.c
blobdc0124bd482cafc409f49ac681d43b97cf03f1c1
1 /* pubkey-enc.c - public key encoded packet handling
2 * Copyright (C) 1998, 1999, 2000, 2001, 2002,
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 2 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, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20 * USA.
23 #include <config.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
29 #include "gpg.h"
30 #include "util.h"
31 #include "packet.h"
32 #include "keydb.h"
33 #include "trustdb.h"
34 #include "cipher.h"
35 #include "status.h"
36 #include "options.h"
37 #include "main.h"
38 #include "i18n.h"
39 #include "pkglue.h"
42 static int get_it( PKT_pubkey_enc *k,
43 DEK *dek, PKT_secret_key *sk, u32 *keyid );
46 /* check that the given algo is mentioned in one of the valid user IDs */
47 static int
48 is_algo_in_prefs ( KBNODE keyblock, preftype_t type, int algo )
50 KBNODE k;
52 for (k=keyblock; k; k=k->next) {
53 if (k->pkt->pkttype == PKT_USER_ID) {
54 PKT_user_id *uid = k->pkt->pkt.user_id;
55 prefitem_t *prefs = uid->prefs;
57 if (uid->created && prefs &&
58 !uid->is_revoked && !uid->is_expired ) {
59 for (; prefs->type; prefs++ )
60 if (prefs->type == type && prefs->value == algo)
61 return 1;
65 return 0;
69 /****************
70 * Get the session key from a pubkey enc packet and return
71 * it in DEK, which should have been allocated in secure memory.
73 int
74 get_session_key( PKT_pubkey_enc *k, DEK *dek )
76 PKT_secret_key *sk = NULL;
77 int rc;
79 rc = openpgp_pk_test_algo2 (k->pubkey_algo, PUBKEY_USAGE_ENC);
80 if( rc )
81 goto leave;
83 if( (k->keyid[0] || k->keyid[1]) && !opt.try_all_secrets ) {
84 sk = xmalloc_clear( sizeof *sk );
85 sk->pubkey_algo = k->pubkey_algo; /* we want a pubkey with this algo*/
86 if( !(rc = get_seckey( sk, k->keyid )) )
87 rc = get_it( k, dek, sk, k->keyid );
89 else { /* anonymous receiver: Try all available secret keys */
90 void *enum_context = NULL;
91 u32 keyid[2];
92 char *p;
94 for(;;) {
95 if( sk )
96 free_secret_key( sk );
97 sk = xmalloc_clear( sizeof *sk );
98 rc=enum_secret_keys( &enum_context, sk, 1, 0);
99 if( rc ) {
100 rc = G10ERR_NO_SECKEY;
101 break;
103 if( sk->pubkey_algo != k->pubkey_algo )
104 continue;
105 keyid_from_sk( sk, keyid );
106 log_info(_("anonymous recipient; trying secret key %s ...\n"),
107 keystr(keyid));
109 if(!opt.try_all_secrets && !is_status_enabled())
111 p=get_last_passphrase();
112 set_next_passphrase(p);
113 xfree(p);
116 rc = check_secret_key( sk, opt.try_all_secrets?1:-1 ); /* ask
117 only
118 once */
119 if( !rc )
121 rc = get_it( k, dek, sk, keyid );
122 /* Successfully checked the secret key (either it was
123 a card, had no passphrase, or had the right
124 passphrase) but couldn't decrypt the session key,
125 so thus that key is not the anonymous recipient.
126 Move the next passphrase into last for the next
127 round. We only do this if the secret key was
128 successfully checked as in the normal case,
129 check_secret_key handles this for us via
130 passphrase_to_dek */
131 if(rc)
132 next_to_last_passphrase();
135 if( !rc )
137 log_info(_("okay, we are the anonymous recipient.\n") );
138 break;
141 enum_secret_keys( &enum_context, NULL, 0, 0 ); /* free context */
144 leave:
145 if( sk )
146 free_secret_key( sk );
147 return rc;
151 static int
152 get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid )
154 int rc;
155 gcry_mpi_t plain_dek = NULL;
156 byte *frame = NULL;
157 unsigned n, nframe;
158 u16 csum, csum2;
160 int card = 0;
162 if (sk->is_protected && sk->protect.s2k.mode == 1002)
163 { /* Note, that we only support RSA for now. */
164 #ifdef ENABLE_CARD_SUPPORT
165 unsigned char *rbuf;
166 size_t rbuflen;
167 char *snbuf;
168 unsigned char *indata = NULL;
169 unsigned int indatalen;
171 snbuf = serialno_and_fpr_from_sk (sk->protect.iv, sk->protect.ivlen, sk);
173 if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &indata, &indatalen, enc->data[0]))
174 BUG ();
176 rc = agent_scd_pkdecrypt (snbuf, indata, indatalen, &rbuf, &rbuflen);
177 xfree (snbuf);
178 xfree (indata);
179 if (rc)
180 goto leave;
182 frame = rbuf;
183 nframe = rbuflen;
184 card = 1;
185 #else
186 rc = gpg_error (GPG_ERR_NOT_SUPPORTED);
187 goto leave;
188 #endif /*!ENABLE_CARD_SUPPORT*/
190 else
192 rc = pk_decrypt (sk->pubkey_algo, &plain_dek, enc->data, sk->skey );
193 if( rc )
194 goto leave;
195 if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &frame, &nframe, plain_dek))
196 BUG();
197 gcry_mpi_release (plain_dek); plain_dek = NULL;
200 /* Now get the DEK (data encryption key) from the frame
202 * Old versions encode the DEK in in this format (msb is left):
204 * 0 1 DEK(16 bytes) CSUM(2 bytes) 0 RND(n bytes) 2
206 * Later versions encode the DEK like this:
208 * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes)
210 * (mpi_get_buffer already removed the leading zero).
212 * RND are non-zero randow bytes.
213 * A is the cipher algorithm
214 * DEK is the encryption key (session key) with length k
215 * CSUM
217 if (DBG_CIPHER)
218 log_printhex ("DEK frame:", frame, nframe );
219 n=0;
220 if (!card)
222 if( n + 7 > nframe )
223 { rc = G10ERR_WRONG_SECKEY; goto leave; }
224 if( frame[n] == 1 && frame[nframe-1] == 2 ) {
225 log_info(_("old encoding of the DEK is not supported\n"));
226 rc = G10ERR_CIPHER_ALGO;
227 goto leave;
229 if( frame[n] != 2 ) /* somethink is wrong */
230 { rc = G10ERR_WRONG_SECKEY; goto leave; }
231 for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */
233 n++; /* and the zero byte */
236 if( n + 4 > nframe )
237 { rc = G10ERR_WRONG_SECKEY; goto leave; }
239 dek->keylen = nframe - (n+1) - 2;
240 dek->algo = frame[n++];
241 if( dek->algo == CIPHER_ALGO_IDEA )
242 write_status(STATUS_RSA_OR_IDEA);
243 rc = openpgp_cipher_test_algo (dek->algo);
244 if( rc ) {
245 if( !opt.quiet && gpg_err_code (rc) == GPG_ERR_CIPHER_ALGO ) {
246 log_info(_("cipher algorithm %d%s is unknown or disabled\n"),
247 dek->algo, dek->algo == CIPHER_ALGO_IDEA? " (IDEA)":"");
248 if(dek->algo==CIPHER_ALGO_IDEA)
249 idea_cipher_warn(0);
251 dek->algo = 0;
252 goto leave;
254 if ( dek->keylen != gcry_cipher_get_algo_keylen (dek->algo) ) {
255 rc = GPG_ERR_WRONG_SECKEY;
256 goto leave;
259 /* copy the key to DEK and compare the checksum */
260 csum = frame[nframe-2] << 8;
261 csum |= frame[nframe-1];
262 memcpy( dek->key, frame+n, dek->keylen );
263 for( csum2=0, n=0; n < dek->keylen; n++ )
264 csum2 += dek->key[n];
265 if( csum != csum2 ) {
266 rc = G10ERR_WRONG_SECKEY;
267 goto leave;
269 if( DBG_CIPHER )
270 log_printhex ("DEK is:", dek->key, dek->keylen );
271 /* check that the algo is in the preferences and whether it has expired */
273 PKT_public_key *pk = NULL;
274 KBNODE pkb = get_pubkeyblock (keyid);
276 if( !pkb ) {
277 rc = -1;
278 log_error("oops: public key not found for preference check\n");
280 else if(pkb->pkt->pkt.public_key->selfsigversion > 3
281 && dek->algo != CIPHER_ALGO_3DES
282 && !opt.quiet
283 && !is_algo_in_prefs( pkb, PREFTYPE_SYM, dek->algo ))
284 log_info (_("WARNING: cipher algorithm %s not found in recipient"
285 " preferences\n"), gcry_cipher_algo_name (dek->algo));
286 if (!rc) {
287 KBNODE k;
289 for (k=pkb; k; k = k->next) {
290 if (k->pkt->pkttype == PKT_PUBLIC_KEY
291 || k->pkt->pkttype == PKT_PUBLIC_SUBKEY){
292 u32 aki[2];
293 keyid_from_pk(k->pkt->pkt.public_key, aki);
295 if (aki[0]==keyid[0] && aki[1]==keyid[1]) {
296 pk = k->pkt->pkt.public_key;
297 break;
301 if (!pk)
302 BUG ();
303 if ( pk->expiredate && pk->expiredate <= make_timestamp() ) {
304 log_info(_("NOTE: secret key %s expired at %s\n"),
305 keystr(keyid), asctimestamp( pk->expiredate) );
309 if ( pk && pk->is_revoked ) {
310 log_info( _("NOTE: key has been revoked") );
311 putc( '\n', log_get_stream() );
312 show_revocation_reason( pk, 1 );
315 release_kbnode (pkb);
316 rc = 0;
320 leave:
321 gcry_mpi_release (plain_dek);
322 xfree (frame);
323 return rc;
327 /****************
328 * Get the session key from the given string.
329 * String is supposed to be formatted as this:
330 * <algo-id>:<even-number-of-hex-digits>
333 get_override_session_key( DEK *dek, const char *string )
335 const char *s;
336 int i;
338 if ( !string )
339 return G10ERR_BAD_KEY;
340 dek->algo = atoi(string);
341 if ( dek->algo < 1 )
342 return G10ERR_BAD_KEY;
343 if ( !(s = strchr ( string, ':' )) )
344 return G10ERR_BAD_KEY;
345 s++;
346 for(i=0; i < DIM(dek->key) && *s; i++, s +=2 ) {
347 int c = hextobyte ( s );
348 if (c == -1)
349 return G10ERR_BAD_KEY;
350 dek->key[i] = c;
352 if ( *s )
353 return G10ERR_BAD_KEY;
354 dek->keylen = i;
355 return 0;