/*
* pgp - pubdec . c
* Decrypt public - key encrypted session key .
*
* Copyright ( c ) 2005 Marko Kreen
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1 . Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2 . Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ` ` AS IS ' ' AND
* ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED . IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL
* DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION )
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT
* LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE .
*
* contrib / pgcrypto / pgp - pubdec . c
*/
#include "postgres.h"
#include "pgp.h"
#include "px.h"
/*
* padded msg = 02 | | PS | | 00 | | M
* PS - pad bytes
* M - msg
*/
static uint8 *
check_eme_pkcs1_v15(uint8 *data, int len)
{
uint8 *data_end = data + len;
uint8 *p = data;
int rnd = 0 ;
if (len < 1 + 8 + 1 )
return NULL;
if (*p++ != 2 )
return NULL;
while (p < data_end && *p)
{
p++;
rnd++;
}
if (p == data_end)
return NULL;
if (*p != 0 )
return NULL;
if (rnd < 8 )
return NULL;
return p + 1 ;
}
/*
* secret message : 1 byte algo , sesskey , 2 byte cksum
* ignore algo in cksum
*/
static int
control_cksum(uint8 *msg, int msglen)
{
int i;
unsigned my_cksum,
got_cksum;
if (msglen < 3 )
return PXE_PGP_WRONG_KEY;
my_cksum = 0 ;
for (i = 1 ; i < msglen - 2 ; i++)
my_cksum += msg[i];
my_cksum &= 0 xFFFF;
got_cksum = ((unsigned ) (msg[msglen - 2 ]) << 8 ) + msg[msglen - 1 ];
if (my_cksum != got_cksum)
{
px_debug("pubenc cksum failed" );
return PXE_PGP_WRONG_KEY;
}
return 0 ;
}
static int
decrypt_elgamal(PGP_PubKey *pk, PullFilter *pkt, PGP_MPI **m_p)
{
int res;
PGP_MPI *c1 = NULL;
PGP_MPI *c2 = NULL;
if (pk->algo != PGP_PUB_ELG_ENCRYPT)
return PXE_PGP_WRONG_KEY;
/* read elgamal encrypted data */
res = pgp_mpi_read(pkt, &c1);
if (res < 0 )
goto out;
res = pgp_mpi_read(pkt, &c2);
if (res < 0 )
goto out;
/* decrypt */
res = pgp_elgamal_decrypt(pk, c1, c2, m_p);
out:
pgp_mpi_free(c1);
pgp_mpi_free(c2);
return res;
}
static int
decrypt_rsa(PGP_PubKey *pk, PullFilter *pkt, PGP_MPI **m_p)
{
int res;
PGP_MPI *c;
if (pk->algo != PGP_PUB_RSA_ENCRYPT
&& pk->algo != PGP_PUB_RSA_ENCRYPT_SIGN)
return PXE_PGP_WRONG_KEY;
/* read rsa encrypted data */
res = pgp_mpi_read(pkt, &c);
if (res < 0 )
return res;
/* decrypt */
res = pgp_rsa_decrypt(pk, c, m_p);
pgp_mpi_free(c);
return res;
}
/* key id is missing - user is expected to try all keys */
static const uint8
any_key[] = {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 };
int
pgp_parse_pubenc_sesskey(PGP_Context *ctx, PullFilter *pkt)
{
int ver;
int algo;
int res;
uint8 key_id[8 ];
PGP_PubKey *pk;
uint8 *msg;
int msglen;
PGP_MPI *m;
unsigned sess_key_len;
pk = ctx->pub_key;
if (pk == NULL)
{
px_debug("no pubkey?" );
return PXE_BUG;
}
GETBYTE(pkt, ver);
if (ver != 3 )
{
px_debug("unknown pubenc_sesskey pkt ver=%d" , ver);
return PXE_PGP_CORRUPT_DATA;
}
/*
* check if keyid ' s match - user - friendly msg
*/
res = pullf_read_fixed(pkt, 8 , key_id);
if (res < 0 )
return res;
if (memcmp(key_id, any_key, 8 ) != 0
&& memcmp(key_id, pk->key_id, 8 ) != 0 )
{
px_debug("key_id's does not match" );
return PXE_PGP_WRONG_KEY;
}
/*
* Decrypt
*/
GETBYTE(pkt, algo);
switch (algo)
{
case PGP_PUB_ELG_ENCRYPT:
res = decrypt_elgamal(pk, pkt, &m);
break ;
case PGP_PUB_RSA_ENCRYPT:
case PGP_PUB_RSA_ENCRYPT_SIGN:
res = decrypt_rsa(pk, pkt, &m);
break ;
default :
res = PXE_PGP_UNKNOWN_PUBALGO;
}
if (res < 0 )
return res;
/*
* extract message
*/
msg = check_eme_pkcs1_v15(m->data, m->bytes);
if (msg == NULL)
{
px_debug("check_eme_pkcs1_v15 failed" );
res = PXE_PGP_WRONG_KEY;
goto out;
}
msglen = m->bytes - (msg - m->data);
res = control_cksum(msg, msglen);
if (res < 0 )
goto out;
sess_key_len = msglen - 3 ;
if (sess_key_len > PGP_MAX_KEY)
{
px_debug("incorrect session key length=%u" , sess_key_len);
res = PXE_PGP_KEY_TOO_BIG;
goto out;
}
/*
* got sesskey
*/
ctx->cipher_algo = *msg;
ctx->sess_key_len = sess_key_len;
memcpy(ctx->sess_key, msg + 1 , ctx->sess_key_len);
out:
pgp_mpi_free(m);
if (res < 0 )
return res;
return pgp_expect_packet_end(pkt);
}
Messung V0.5 in Prozent C=91 H=86 G=88
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-08-08)
¤
*© Formatika GbR, Deutschland