1 /* pubkey-enc.c - public key encoded packet handling
2 * Copyright (C) 1998, 1999, 2000, 2001, 2002,
3 * 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
41 #include "call-agent.h"
43 static int get_it( PKT_pubkey_enc
*k
,
44 DEK
*dek
, PKT_secret_key
*sk
, u32
*keyid
);
47 /* check that the given algo is mentioned in one of the valid user IDs */
49 is_algo_in_prefs ( KBNODE keyblock
, preftype_t type
, int algo
)
53 for (k
=keyblock
; k
; k
=k
->next
) {
54 if (k
->pkt
->pkttype
== PKT_USER_ID
) {
55 PKT_user_id
*uid
= k
->pkt
->pkt
.user_id
;
56 prefitem_t
*prefs
= uid
->prefs
;
58 if (uid
->created
&& prefs
&&
59 !uid
->is_revoked
&& !uid
->is_expired
) {
60 for (; prefs
->type
; prefs
++ )
61 if (prefs
->type
== type
&& prefs
->value
== algo
)
71 * Get the session key from a pubkey enc packet and return
72 * it in DEK, which should have been allocated in secure memory.
75 get_session_key( PKT_pubkey_enc
*k
, DEK
*dek
)
77 PKT_secret_key
*sk
= NULL
;
80 rc
= openpgp_pk_test_algo (k
->pubkey_algo
, PUBKEY_USAGE_ENC
);
84 if( (k
->keyid
[0] || k
->keyid
[1]) && !opt
.try_all_secrets
) {
85 sk
= xcalloc (1, sizeof *sk
);
86 sk
->pubkey_algo
= k
->pubkey_algo
; /* we want a pubkey with this algo*/
87 if( !(rc
= get_seckey( sk
, k
->keyid
)) )
88 rc
= get_it( k
, dek
, sk
, k
->keyid
);
90 else { /* anonymous receiver: Try all available secret keys */
91 void *enum_context
= NULL
;
97 free_secret_key( sk
);
98 sk
= xcalloc (1, sizeof *sk
);
99 rc
=enum_secret_keys( &enum_context
, sk
, 1, 0);
101 rc
= GPG_ERR_NO_SECKEY
;
104 if( sk
->pubkey_algo
!= k
->pubkey_algo
)
106 keyid_from_sk( sk
, keyid
);
107 log_info(_("anonymous recipient; trying secret key %08lX ...\n"),
110 if(!opt
.try_all_secrets
&& !is_status_enabled())
112 p
=get_last_passphrase();
113 set_next_passphrase(p
);
117 rc
= check_secret_key( sk
, opt
.try_all_secrets
?1:-1 ); /* ask
121 rc
= get_it( k
, dek
, sk
, keyid
);
123 log_info(_("okay, we are the anonymous recipient.\n") );
127 enum_secret_keys( &enum_context
, NULL
, 0, 0 ); /* free context */
132 free_secret_key( sk
);
138 get_it( PKT_pubkey_enc
*enc
, DEK
*dek
, PKT_secret_key
*sk
, u32
*keyid
)
141 gcry_mpi_t plain_dek
= NULL
;
147 if (sk
->is_protected
&& sk
->protect
.s2k
.mode
== 1002)
148 { /* FIXME: Note that we do only support RSA for now. */
152 unsigned char *indata
= NULL
;
153 unsigned int indatalen
;
155 snbuf
= serialno_and_fpr_from_sk (sk
->protect
.iv
, sk
->protect
.ivlen
, sk
);
157 if (gcry_mpi_aprint (GCRYMPI_FMT_USG
, &indata
, &indatalen
,
161 rc
= agent_scd_pkdecrypt (snbuf
, indata
, indatalen
, &rbuf
, &rbuflen
);
173 rc
= pk_decrypt (sk
->pubkey_algo
, &plain_dek
, enc
->data
, sk
->skey
);
176 if (gcry_mpi_aprint (GCRYMPI_FMT_USG
, &frame
, &nframe
, plain_dek
))
178 gcry_mpi_release (plain_dek
); plain_dek
= NULL
;
182 /* Now get the DEK (data encryption key) from the frame
184 * Old versions encode the DEK in in this format (msb is left):
186 * 0 1 DEK(16 bytes) CSUM(2 bytes) 0 RND(n bytes) 2
188 * Later versions encode the DEK like this:
190 * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes)
192 * (mpi_get_buffer already removed the leading zero).
194 * RND are non-zero randow bytes.
195 * A is the cipher algorithm
196 * DEK is the encryption key (session key) with length k
200 log_printhex ("DEK frame:", frame
, nframe
);
205 { rc
= GPG_ERR_WRONG_SECKEY
; goto leave
; }
206 if( frame
[n
] == 1 && frame
[nframe
-1] == 2 ) {
207 log_info(_("old encoding of the DEK is not supported\n"));
208 rc
= GPG_ERR_CIPHER_ALGO
;
211 if( frame
[n
] != 2 ) /* somethink is wrong */
212 { rc
= GPG_ERR_WRONG_SECKEY
; goto leave
; }
213 for(n
++; n
< nframe
&& frame
[n
]; n
++ ) /* skip the random bytes */
215 n
++; /* and the zero byte */
219 { rc
= GPG_ERR_WRONG_SECKEY
; goto leave
; }
220 dek
->keylen
= nframe
- (n
+1) - 2;
221 dek
->algo
= frame
[n
++];
222 if( dek
->algo
== CIPHER_ALGO_IDEA
)
223 write_status(STATUS_RSA_OR_IDEA
);
224 rc
= openpgp_cipher_test_algo (dek
->algo
);
226 if( !opt
.quiet
&& gpg_err_code (rc
) == GPG_ERR_CIPHER_ALGO
) {
227 log_info(_("cipher algorithm %d%s is unknown or disabled\n"),
228 dek
->algo
, dek
->algo
== CIPHER_ALGO_IDEA
? " (IDEA)":"");
229 if(dek
->algo
==CIPHER_ALGO_IDEA
)
235 if( dek
->keylen
!= gcry_cipher_get_algo_keylen (dek
->algo
) ) {
236 rc
= GPG_ERR_WRONG_SECKEY
;
240 /* copy the key to DEK and compare the checksum */
241 csum
= frame
[nframe
-2] << 8;
242 csum
|= frame
[nframe
-1];
243 memcpy( dek
->key
, frame
+n
, dek
->keylen
);
244 for( csum2
=0, n
=0; n
< dek
->keylen
; n
++ )
245 csum2
+= dek
->key
[n
];
246 if( csum
!= csum2
) {
247 rc
= GPG_ERR_WRONG_SECKEY
;
251 log_printhex ("DEK is:", dek
->key
, dek
->keylen
);
252 /* check that the algo is in the preferences and whether it has expired */
254 PKT_public_key
*pk
= NULL
;
255 KBNODE pkb
= get_pubkeyblock (keyid
);
259 log_error("oops: public key not found for preference check\n");
261 else if( pkb
->pkt
->pkt
.public_key
->selfsigversion
> 3
262 && dek
->algo
!= CIPHER_ALGO_3DES
263 && !is_algo_in_prefs( pkb
, PREFTYPE_SYM
, dek
->algo
) ) {
264 /* Don't print a note while we are not on verbose mode,
265 * the cipher is blowfish and the preferences have twofish
267 if( opt
.verbose
|| dek
->algo
!= CIPHER_ALGO_BLOWFISH
268 || !is_algo_in_prefs( pkb
, PREFTYPE_SYM
, CIPHER_ALGO_TWOFISH
))
270 "NOTE: cipher algorithm %d not found in preferences\n"),
277 for (k
=pkb
; k
; k
= k
->next
) {
278 if (k
->pkt
->pkttype
== PKT_PUBLIC_KEY
279 || k
->pkt
->pkttype
== PKT_PUBLIC_SUBKEY
){
281 keyid_from_pk(k
->pkt
->pkt
.public_key
, aki
);
283 if (aki
[0]==keyid
[0] && aki
[1]==keyid
[1]) {
284 pk
= k
->pkt
->pkt
.public_key
;
291 if ( pk
->expiredate
&& pk
->expiredate
<= make_timestamp() ) {
292 log_info(_("NOTE: secret key %08lX expired at %s\n"),
293 (ulong
)keyid
[1], asctimestamp( pk
->expiredate
) );
297 if ( pk
&& pk
->is_revoked
) {
298 log_info( _("NOTE: key has been revoked") );
299 putc( '\n', log_get_stream() );
300 show_revocation_reason( pk
, 1 );
303 release_kbnode (pkb
);
309 gcry_mpi_release (plain_dek
);
316 * Get the session key from the given string.
317 * String is supposed to be formatted as this:
318 * <algo-id>:<even-number-of-hex-digits>
321 get_override_session_key( DEK
*dek
, const char *string
)
327 return GPG_ERR_BAD_KEY
;
328 dek
->algo
= atoi(string
);
330 return GPG_ERR_BAD_KEY
;
331 if ( !(s
= strchr ( string
, ':' )) )
332 return GPG_ERR_BAD_KEY
;
334 for(i
=0; i
< DIM(dek
->key
) && *s
; i
++, s
+=2 ) {
335 int c
= hextobyte ( s
);
337 return GPG_ERR_BAD_KEY
;
341 return GPG_ERR_BAD_KEY
;