1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-01-05 12:31:50 +01:00

gpg: Refactor function encrypt_seskey.

* g10/encrypt.c (encrypt_seskey): Allocate the buffer for the
encrypted key and returns that buffer and its length.
(encrypt_simple): Adjust for above change.
(write_symkey_enc): Ditto.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2018-01-22 15:50:24 +01:00
parent 7356d6ec50
commit 0131d4369a
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
3 changed files with 112 additions and 53 deletions

View File

@ -67,45 +67,75 @@ encrypt_store (const char *filename)
} }
/* *SESKEY contains the unencrypted session key ((*SESKEY)->KEY) and /* Encrypt a session key using DEK and store a pointer to the result
the algorithm that will be used to encrypt the contents of the SED * at R_ENCKEY and its length at R_ENCKEYLEN.
packet ((*SESKEY)->ALGO). If *SESKEY is NULL, then a random *
session key that is appropriate for DEK->ALGO is generated and * R_SESKEY points to the unencrypted session key (.KEY, >KEYLEN) and
stored there. * the algorithm that will be used to encrypt the contents of the
* SKESK packet (.ALGO). If R_SESKEY points to NULL, then a random
Encrypt that session key using DEK and store the result in ENCKEY, * session key that is appropriate for DEK->ALGO is generated and
which must be large enough to hold (*SESKEY)->KEYLEN + 1 bytes. */ * stored at R_SESKEY.
void */
encrypt_seskey (DEK *dek, DEK **seskey, byte *enckey) gpg_error_t
encrypt_seskey (DEK *dek, DEK **r_seskey, void **r_enckey, size_t *r_enckeylen)
{ {
gcry_cipher_hd_t hd; gpg_error_t err;
byte buf[33]; gcry_cipher_hd_t hd = NULL;
byte *buf = NULL;
DEK *seskey;
log_assert ( dek->keylen <= 32 ); *r_enckey = NULL;
if (!*seskey) *r_enckeylen = 0;
if (*r_seskey)
seskey = *r_seskey;
else
{ {
*seskey=xmalloc_clear(sizeof(DEK)); seskey = xtrycalloc (1, sizeof(DEK));
(*seskey)->algo=dek->algo; if (!seskey)
make_session_key(*seskey); {
err = gpg_error_from_syserror ();
goto leave;
}
seskey->algo = dek->algo;
make_session_key (seskey);
/*log_hexdump( "thekey", c->key, c->keylen );*/ /*log_hexdump( "thekey", c->key, c->keylen );*/
} }
buf = xtrymalloc_secure (1 + seskey->keylen);
if (!buf)
{
err = gpg_error_from_syserror ();
goto leave;
}
/* The encrypted session key is prefixed with a one-octet algorithm id. */ /* The encrypted session key is prefixed with a one-octet algorithm id. */
buf[0] = (*seskey)->algo; buf[0] = seskey->algo;
memcpy( buf + 1, (*seskey)->key, (*seskey)->keylen ); memcpy (buf + 1, seskey->key, seskey->keylen);
/* We only pass already checked values to the following function, err = openpgp_cipher_open (&hd, dek->algo, GCRY_CIPHER_MODE_CFB, 1);
thus we consider any failure as fatal. */ if (!err)
if (openpgp_cipher_open (&hd, dek->algo, GCRY_CIPHER_MODE_CFB, 1)) err = gcry_cipher_setkey (hd, dek->key, dek->keylen);
BUG (); if (!err)
if (gcry_cipher_setkey (hd, dek->key, dek->keylen)) err = gcry_cipher_setiv (hd, NULL, 0);
BUG (); if (!err)
gcry_cipher_setiv (hd, NULL, 0); err = gcry_cipher_encrypt (hd, buf, seskey->keylen + 1, NULL, 0);
gcry_cipher_encrypt (hd, buf, (*seskey)->keylen + 1, NULL, 0); if (err)
goto leave;
*r_enckey = buf;
buf = NULL;
*r_enckeylen = seskey->keylen + 1;
/* Return the session key in case we allocated it. */
*r_seskey = seskey;
seskey = NULL;
leave:
gcry_cipher_close (hd); gcry_cipher_close (hd);
if (seskey != *r_seskey)
memcpy( enckey, buf, (*seskey)->keylen + 1 ); xfree (seskey);
wipememory( buf, sizeof buf ); /* burn key */ xfree (buf);
return err;
} }
@ -218,9 +248,9 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
PACKET pkt; PACKET pkt;
PKT_plaintext *pt = NULL; PKT_plaintext *pt = NULL;
STRING2KEY *s2k = NULL; STRING2KEY *s2k = NULL;
byte enckey[33]; void *enckey = NULL;
size_t enckeylen = 0;
int rc = 0; int rc = 0;
int seskeylen = 0;
u32 filesize; u32 filesize;
cipher_filter_context_t cfx; cipher_filter_context_t cfx;
armor_filter_context_t *afx = NULL; armor_filter_context_t *afx = NULL;
@ -273,6 +303,7 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
if ( mode ) if ( mode )
{ {
int canceled; int canceled;
aead_algo_t aead_algo;
s2k = xmalloc_clear( sizeof *s2k ); s2k = xmalloc_clear( sizeof *s2k );
s2k->mode = opt.s2k_mode; s2k->mode = opt.s2k_mode;
@ -296,21 +327,33 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
"due to the S2K mode\n")); "due to the S2K mode\n"));
} }
/* See whether we want to use AEAD. */
aead_algo = use_aead (NULL, cfx.dek->algo)? default_aead_algo () : 0;
if ( use_seskey ) if ( use_seskey )
{ {
DEK *dek = NULL; DEK *dek = NULL;
seskeylen = openpgp_cipher_get_algo_keylen (default_cipher_algo ()); rc = encrypt_seskey (cfx.dek, &dek, &enckey, &enckeylen);
encrypt_seskey( cfx.dek, &dek, enckey ); if (rc)
xfree( cfx.dek ); cfx.dek = dek; {
xfree (cfx.dek);
xfree (s2k);
iobuf_close (inp);
release_progress_context (pfx);
return rc;
}
/* Replace key in DEK. */
xfree (cfx.dek);
cfx.dek = dek;
} }
if (opt.verbose) if (opt.verbose)
log_info(_("using cipher %s\n"), log_info(_("using cipher %s\n"),
openpgp_cipher_algo_name (cfx.dek->algo)); openpgp_cipher_algo_name (cfx.dek->algo));
if (use_aead (NULL, cfx.dek->algo)) if (aead_algo)
cfx.dek->use_aead = default_aead_algo (); cfx.dek->use_aead = aead_algo;
else else
cfx.dek->use_mdc = !!use_mdc (NULL, cfx.dek->algo); cfx.dek->use_mdc = !!use_mdc (NULL, cfx.dek->algo);
} }
@ -342,20 +385,23 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
if ( s2k ) if ( s2k )
{ {
PKT_symkey_enc *enc = xmalloc_clear( sizeof *enc + seskeylen + 1 ); /* Fixme: This is quite similar to write_symkey_enc. */
PKT_symkey_enc *enc = xmalloc_clear (sizeof *enc + enckeylen);
enc->version = 4; enc->version = 4;
enc->cipher_algo = cfx.dek->algo; enc->cipher_algo = cfx.dek->algo;
enc->s2k = *s2k; enc->s2k = *s2k;
if ( use_seskey && seskeylen ) if (enckeylen)
{ {
enc->seskeylen = seskeylen + 1; /* algo id */ enc->seskeylen = enckeylen;
memcpy (enc->seskey, enckey, seskeylen + 1 ); memcpy (enc->seskey, enckey, enckeylen);
} }
pkt.pkttype = PKT_SYMKEY_ENC; pkt.pkttype = PKT_SYMKEY_ENC;
pkt.pkt.symkey_enc = enc; pkt.pkt.symkey_enc = enc;
if ((rc = build_packet( out, &pkt ))) if ((rc = build_packet( out, &pkt )))
log_error("build symkey packet failed: %s\n", gpg_strerror (rc) ); log_error("build symkey packet failed: %s\n", gpg_strerror (rc) );
xfree (enc); xfree (enc);
xfree (enckey);
enckey = NULL;
} }
if (!opt.no_literal) if (!opt.no_literal)
@ -459,6 +505,7 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
if (pt) if (pt)
pt->buf = NULL; pt->buf = NULL;
free_packet (&pkt, NULL); free_packet (&pkt, NULL);
xfree (enckey);
xfree (cfx.dek); xfree (cfx.dek);
xfree (s2k); xfree (s2k);
release_armor_context (afx); release_armor_context (afx);
@ -493,20 +540,29 @@ static int
write_symkey_enc (STRING2KEY *symkey_s2k, DEK *symkey_dek, DEK *dek, write_symkey_enc (STRING2KEY *symkey_s2k, DEK *symkey_dek, DEK *dek,
iobuf_t out) iobuf_t out)
{ {
int rc, seskeylen = openpgp_cipher_get_algo_keylen (dek->algo); int rc;
void *enckey;
size_t enckeylen;
PKT_symkey_enc *enc; PKT_symkey_enc *enc;
byte enckey[33];
PACKET pkt; PACKET pkt;
enc=xmalloc_clear(sizeof(PKT_symkey_enc)+seskeylen+1); rc = encrypt_seskey (symkey_dek, &dek, &enckey, &enckeylen);
encrypt_seskey(symkey_dek,&dek,enckey); if (rc)
return rc;
enc = xtrycalloc (1, sizeof (PKT_symkey_enc) + enckeylen);
if (!enc)
{
rc = gpg_error_from_syserror ();
xfree (enckey);
return rc;
}
enc->version = 4; enc->version = 4;
enc->cipher_algo = opt.s2k_cipher_algo; enc->cipher_algo = opt.s2k_cipher_algo;
enc->s2k = *symkey_s2k; enc->s2k = *symkey_s2k;
enc->seskeylen = seskeylen + 1; /* algo id */ enc->seskeylen = enckeylen;
memcpy( enc->seskey, enckey, seskeylen + 1 ); memcpy (enc->seskey, enckey, enckeylen);
xfree (enckey);
pkt.pkttype = PKT_SYMKEY_ENC; pkt.pkttype = PKT_SYMKEY_ENC;
pkt.pkt.symkey_enc = enc; pkt.pkt.symkey_enc = enc;
@ -514,7 +570,7 @@ write_symkey_enc (STRING2KEY *symkey_s2k, DEK *symkey_dek, DEK *dek,
if ((rc=build_packet(out,&pkt))) if ((rc=build_packet(out,&pkt)))
log_error("build symkey_enc packet failed: %s\n",gpg_strerror (rc)); log_error("build symkey_enc packet failed: %s\n",gpg_strerror (rc));
xfree(enc); xfree (enc);
return rc; return rc;
} }

View File

@ -2283,9 +2283,11 @@ sk_esk (const char *option, int argc, char *argv[], void *cookie)
DEK *sesdekp = &sesdek; DEK *sesdekp = &sesdek;
/* Now encrypt the session key (or rather, the algorithm used to /* Now encrypt the session key (or rather, the algorithm used to
encrypt the SED plus the session key) using ENCKEY. */ encrypt the SKESK plus the session key) using ENCKEY. */
ske->seskeylen = 1 + sesdek.keylen; err = encrypt_seskey (&s2kdek, &sesdekp,
encrypt_seskey (&s2kdek, &sesdekp, ske->seskey); (void**)&ske->seskey, (size_t *)&ske->seskeylen);
if (err)
log_fatal ("encrypt_seskey failed: %s\n", gpg_strerror (err));
/* Save the session key for later. */ /* Save the session key for later. */
session_key = sesdek; session_key = sesdek;

View File

@ -232,7 +232,8 @@ void display_online_help( const char *keyword );
/*-- encode.c --*/ /*-- encode.c --*/
int setup_symkey (STRING2KEY **symkey_s2k,DEK **symkey_dek); int setup_symkey (STRING2KEY **symkey_s2k,DEK **symkey_dek);
void encrypt_seskey (DEK *dek, DEK **seskey, byte *enckey); gpg_error_t encrypt_seskey (DEK *dek, DEK **r_seskey,
void **r_enckey, size_t *r_enckeylen);
int use_aead (pk_list_t pk_list, int algo); int use_aead (pk_list_t pk_list, int algo);
int use_mdc (pk_list_t pk_list,int algo); int use_mdc (pk_list_t pk_list,int algo);
int encrypt_symmetric (const char *filename ); int encrypt_symmetric (const char *filename );