mirror of
git://git.gnupg.org/gnupg.git
synced 2025-04-17 15:44:34 +02:00
Update OpenPGP parser to support ECC
This commit is contained in:
parent
25f292ed89
commit
740629de00
@ -1,3 +1,12 @@
|
|||||||
|
2011-04-28 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* keybox-openpgp.c: Include ../common/openpgpdefs.h.
|
||||||
|
(enum packet_types): Remove.
|
||||||
|
(_keybox_parse_openpgp): Update NPARSED also on errors.
|
||||||
|
(parse_key): Take care of ecc algorithms.
|
||||||
|
* kbxutil.c (import_openpgp): Do not print an error for non-RSA v3
|
||||||
|
packets.
|
||||||
|
|
||||||
2010-07-23 Werner Koch <wk@g10code.com>
|
2010-07-23 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* keybox-blob.c (_keybox_create_x509_blob): Fix reallocation bug.
|
* keybox-blob.c (_keybox_create_x509_blob): Fix reallocation bug.
|
||||||
@ -365,7 +374,7 @@
|
|||||||
|
|
||||||
|
|
||||||
Copyright 2001, 2002, 2003, 2004, 2005, 2006,
|
Copyright 2001, 2002, 2003, 2004, 2005, 2006,
|
||||||
2007, 2008 Free Software Foundation, Inc.
|
2007, 2008, 2011 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is free software; as a special exception the author gives
|
This file is free software; as a special exception the author gives
|
||||||
unlimited permission to copy and/or distribute it, with or without
|
unlimited permission to copy and/or distribute it, with or without
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* kbxutil.c - The Keybox utility
|
/* kbxutil.c - The Keybox utility
|
||||||
* Copyright (C) 2000, 2001, 2004, 2007 Free Software Foundation, Inc.
|
* Copyright (C) 2000, 2001, 2004, 2007, 2011 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -389,8 +389,18 @@ import_openpgp (const char *filename)
|
|||||||
{
|
{
|
||||||
if (gpg_err_code (err) == GPG_ERR_NO_DATA)
|
if (gpg_err_code (err) == GPG_ERR_NO_DATA)
|
||||||
break;
|
break;
|
||||||
log_info ("%s: failed to parse OpenPGP keyblock: %s\n",
|
if (gpg_err_code (err) == GPG_ERR_UNSUPPORTED_ALGORITHM)
|
||||||
filename, gpg_strerror (err));
|
{
|
||||||
|
/* This is likely a v3 key packet with a non-RSA
|
||||||
|
algorithm. These are keys from very early versions
|
||||||
|
of GnuPG (pre-OpenPGP). */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fflush (stdout);
|
||||||
|
log_info ("%s: failed to parse OpenPGP keyblock: %s\n",
|
||||||
|
filename, gpg_strerror (err));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* keybox-openpgp.c - OpenPGP key parsing
|
/* keybox-openpgp.c - OpenPGP key parsing
|
||||||
* Copyright (C) 2001, 2003 Free Software Foundation, Inc.
|
* Copyright (C) 2001, 2003, 2011 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -35,41 +35,16 @@
|
|||||||
|
|
||||||
#include <gcrypt.h>
|
#include <gcrypt.h>
|
||||||
|
|
||||||
|
#include "../common/openpgpdefs.h"
|
||||||
enum packet_types
|
|
||||||
{
|
|
||||||
PKT_NONE =0,
|
|
||||||
PKT_PUBKEY_ENC =1, /* public key encrypted packet */
|
|
||||||
PKT_SIGNATURE =2, /* secret key encrypted packet */
|
|
||||||
PKT_SYMKEY_ENC =3, /* session key packet (OpenPGP)*/
|
|
||||||
PKT_ONEPASS_SIG =4, /* one pass sig packet (OpenPGP)*/
|
|
||||||
PKT_SECRET_KEY =5, /* secret key */
|
|
||||||
PKT_PUBLIC_KEY =6, /* public key */
|
|
||||||
PKT_SECRET_SUBKEY =7, /* secret subkey (OpenPGP) */
|
|
||||||
PKT_COMPRESSED =8, /* compressed data packet */
|
|
||||||
PKT_ENCRYPTED =9, /* conventional encrypted data */
|
|
||||||
PKT_MARKER =10, /* marker packet (OpenPGP) */
|
|
||||||
PKT_PLAINTEXT =11, /* plaintext data with filename and mode */
|
|
||||||
PKT_RING_TRUST =12, /* keyring trust packet */
|
|
||||||
PKT_USER_ID =13, /* user id packet */
|
|
||||||
PKT_PUBLIC_SUBKEY =14, /* public subkey (OpenPGP) */
|
|
||||||
PKT_OLD_COMMENT =16, /* comment packet from an OpenPGP draft */
|
|
||||||
PKT_ATTRIBUTE =17, /* PGP's attribute packet */
|
|
||||||
PKT_ENCRYPTED_MDC =18, /* integrity protected encrypted data */
|
|
||||||
PKT_MDC =19, /* manipulation detection code packet */
|
|
||||||
PKT_COMMENT =61, /* new comment packet (private) */
|
|
||||||
PKT_GPG_CONTROL =63 /* internal control packet */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Assume a valid OpenPGP packet at the address pointed to by BUFBTR
|
/* Assume a valid OpenPGP packet at the address pointed to by BUFBTR
|
||||||
which is of amaximum length as stored at BUFLEN. Return the header
|
which has a maximum length as stored at BUFLEN. Return the header
|
||||||
information of that packet and advance the pointer stored at BUFPTR
|
information of that packet and advance the pointer stored at BUFPTR
|
||||||
to the next packet; also adjust the length stored at BUFLEN to
|
to the next packet; also adjust the length stored at BUFLEN to
|
||||||
match the remaining bytes. If there are no more packets, store NULL
|
match the remaining bytes. If there are no more packets, store NULL
|
||||||
at BUFPTR. Return an non-zero error code on failure or the
|
at BUFPTR. Return an non-zero error code on failure or the
|
||||||
follwing data on success:
|
following data on success:
|
||||||
|
|
||||||
R_DATAPKT = Pointer to the begin of the packet data.
|
R_DATAPKT = Pointer to the begin of the packet data.
|
||||||
R_DATALEN = Length of this data. This has already been checked to fit
|
R_DATALEN = Length of this data. This has already been checked to fit
|
||||||
@ -166,8 +141,8 @@ next_packet (unsigned char const **bufptr, size_t *buflen,
|
|||||||
return gpg_error (GPG_ERR_UNEXPECTED);
|
return gpg_error (GPG_ERR_UNEXPECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pktlen == 0xffffffff)
|
if (pktlen == (unsigned long)(-1))
|
||||||
return gpg_error (GPG_ERR_INV_PACKET);
|
return gpg_error (GPG_ERR_INV_PACKET);
|
||||||
|
|
||||||
if (pktlen > len)
|
if (pktlen > len)
|
||||||
return gpg_error (GPG_ERR_INV_PACKET); /* Packet length header too long. */
|
return gpg_error (GPG_ERR_INV_PACKET); /* Packet length header too long. */
|
||||||
@ -201,6 +176,7 @@ parse_key (const unsigned char *data, size_t datalen,
|
|||||||
const unsigned char *mpi_n = NULL;
|
const unsigned char *mpi_n = NULL;
|
||||||
size_t mpi_n_len = 0, mpi_e_len = 0;
|
size_t mpi_n_len = 0, mpi_e_len = 0;
|
||||||
gcry_md_hd_t md;
|
gcry_md_hd_t md;
|
||||||
|
int is_ecc = 0;
|
||||||
|
|
||||||
if (datalen < 5)
|
if (datalen < 5)
|
||||||
return gpg_error (GPG_ERR_INV_PACKET);
|
return gpg_error (GPG_ERR_INV_PACKET);
|
||||||
@ -219,7 +195,6 @@ parse_key (const unsigned char *data, size_t datalen,
|
|||||||
return gpg_error (GPG_ERR_INV_PACKET);
|
return gpg_error (GPG_ERR_INV_PACKET);
|
||||||
ndays = ((data[0]<<8)|(data[1]));
|
ndays = ((data[0]<<8)|(data[1]));
|
||||||
data +=2; datalen -= 2;
|
data +=2; datalen -= 2;
|
||||||
if (ndays)
|
|
||||||
expiredate = ndays? (timestamp + ndays * 86400L) : 0;
|
expiredate = ndays? (timestamp + ndays * 86400L) : 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -245,9 +220,11 @@ parse_key (const unsigned char *data, size_t datalen,
|
|||||||
break;
|
break;
|
||||||
case 18: /* ECDH */
|
case 18: /* ECDH */
|
||||||
npkey = 3;
|
npkey = 3;
|
||||||
|
is_ecc = 1;
|
||||||
break;
|
break;
|
||||||
case 19: /* ECDSA */
|
case 19: /* ECDSA */
|
||||||
npkey = 2;
|
npkey = 2;
|
||||||
|
is_ecc = 1;
|
||||||
break;
|
break;
|
||||||
default: /* Unknown algorithm. */
|
default: /* Unknown algorithm. */
|
||||||
return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
|
return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
|
||||||
@ -259,20 +236,34 @@ parse_key (const unsigned char *data, size_t datalen,
|
|||||||
|
|
||||||
if (datalen < 2)
|
if (datalen < 2)
|
||||||
return gpg_error (GPG_ERR_INV_PACKET);
|
return gpg_error (GPG_ERR_INV_PACKET);
|
||||||
nbits = ((data[0]<<8)|(data[1]));
|
|
||||||
data += 2; datalen -=2;
|
if (is_ecc && (i == 0 || i == 2))
|
||||||
nbytes = (nbits+7) / 8;
|
|
||||||
if (datalen < nbytes)
|
|
||||||
return gpg_error (GPG_ERR_INV_PACKET);
|
|
||||||
/* For use by v3 fingerprint calculation we need to know the RSA
|
|
||||||
modulus and exponent. */
|
|
||||||
if (i==0)
|
|
||||||
{
|
{
|
||||||
mpi_n = data;
|
nbytes = data[0];
|
||||||
mpi_n_len = nbytes;
|
if (nbytes < 2 || nbytes > 254)
|
||||||
|
return gpg_error (GPG_ERR_INV_PACKET);
|
||||||
|
nbytes++; /* The size byte itself. */
|
||||||
|
if (datalen < nbytes)
|
||||||
|
return gpg_error (GPG_ERR_INV_PACKET);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nbits = ((data[0]<<8)|(data[1]));
|
||||||
|
data += 2;
|
||||||
|
datalen -= 2;
|
||||||
|
nbytes = (nbits+7) / 8;
|
||||||
|
if (datalen < nbytes)
|
||||||
|
return gpg_error (GPG_ERR_INV_PACKET);
|
||||||
|
/* For use by v3 fingerprint calculation we need to know the RSA
|
||||||
|
modulus and exponent. */
|
||||||
|
if (i==0)
|
||||||
|
{
|
||||||
|
mpi_n = data;
|
||||||
|
mpi_n_len = nbytes;
|
||||||
|
}
|
||||||
|
else if (i==1)
|
||||||
|
mpi_e_len = nbytes;
|
||||||
}
|
}
|
||||||
else if (i==1)
|
|
||||||
mpi_e_len = nbytes;
|
|
||||||
|
|
||||||
data += nbytes; datalen -= nbytes;
|
data += nbytes; datalen -= nbytes;
|
||||||
}
|
}
|
||||||
@ -297,7 +288,7 @@ parse_key (const unsigned char *data, size_t datalen,
|
|||||||
if (mpi_n_len < 8)
|
if (mpi_n_len < 8)
|
||||||
{
|
{
|
||||||
/* Moduli less than 64 bit are out of the specs scope. Zero
|
/* Moduli less than 64 bit are out of the specs scope. Zero
|
||||||
them out becuase this is what gpg does too. */
|
them out because this is what gpg does too. */
|
||||||
memset (ki->keyid, 0, 8);
|
memset (ki->keyid, 0, 8);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -307,10 +298,10 @@ parse_key (const unsigned char *data, size_t datalen,
|
|||||||
{
|
{
|
||||||
/* Its a pitty that we need to prefix the buffer with the tag
|
/* Its a pitty that we need to prefix the buffer with the tag
|
||||||
and a length header: We can't simply pass it to the fast
|
and a length header: We can't simply pass it to the fast
|
||||||
hashing fucntion for that reason. It might be a good idea to
|
hashing function for that reason. It might be a good idea to
|
||||||
have a scatter-gather enabled hash function. What we do here
|
have a scatter-gather enabled hash function. What we do here
|
||||||
is to use a static buffer if this one is large enough and
|
is to use a static buffer if this one is large enough and
|
||||||
only use the regular hash fucntions if this buffer is not
|
only use the regular hash functions if this buffer is not
|
||||||
large enough. */
|
large enough. */
|
||||||
if ( 3 + n < sizeof hashbuffer )
|
if ( 3 + n < sizeof hashbuffer )
|
||||||
{
|
{
|
||||||
@ -344,19 +335,19 @@ parse_key (const unsigned char *data, size_t datalen,
|
|||||||
/* The caller must pass the address of an INFO structure which will
|
/* The caller must pass the address of an INFO structure which will
|
||||||
get filled on success with information pertaining to the OpenPGP
|
get filled on success with information pertaining to the OpenPGP
|
||||||
keyblock IMAGE of length IMAGELEN. Note that a caller does only
|
keyblock IMAGE of length IMAGELEN. Note that a caller does only
|
||||||
need to release this INFO structure when the function returns
|
need to release this INFO structure if the function returns
|
||||||
success. If NPARSED is not NULL the actual number of bytes parsed
|
success. If NPARSED is not NULL the actual number of bytes parsed
|
||||||
will be stored at this address. */
|
will be stored at this address. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
_keybox_parse_openpgp (const unsigned char *image, size_t imagelen,
|
_keybox_parse_openpgp (const unsigned char *image, size_t imagelen,
|
||||||
size_t *nparsed,
|
size_t *nparsed, keybox_openpgp_info_t info)
|
||||||
keybox_openpgp_info_t info)
|
|
||||||
{
|
{
|
||||||
gpg_error_t err = 0;
|
gpg_error_t err = 0;
|
||||||
const unsigned char *image_start, *data;
|
const unsigned char *image_start, *data;
|
||||||
size_t n, datalen;
|
size_t n, datalen;
|
||||||
int pkttype;
|
int pkttype;
|
||||||
int first = 1;
|
int first = 1;
|
||||||
|
int read_error = 0;
|
||||||
struct _keybox_openpgp_key_info *k, **ktail = NULL;
|
struct _keybox_openpgp_key_info *k, **ktail = NULL;
|
||||||
struct _keybox_openpgp_uid_info *u, **utail = NULL;
|
struct _keybox_openpgp_uid_info *u, **utail = NULL;
|
||||||
|
|
||||||
@ -369,7 +360,10 @@ _keybox_parse_openpgp (const unsigned char *image, size_t imagelen,
|
|||||||
{
|
{
|
||||||
err = next_packet (&image, &imagelen, &data, &datalen, &pkttype, &n);
|
err = next_packet (&image, &imagelen, &data, &datalen, &pkttype, &n);
|
||||||
if (err)
|
if (err)
|
||||||
break;
|
{
|
||||||
|
read_error = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
@ -380,6 +374,8 @@ _keybox_parse_openpgp (const unsigned char *image, size_t imagelen,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
err = gpg_error (GPG_ERR_UNEXPECTED);
|
err = gpg_error (GPG_ERR_UNEXPECTED);
|
||||||
|
if (nparsed)
|
||||||
|
*nparsed += n;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
first = 0;
|
first = 0;
|
||||||
@ -439,9 +435,12 @@ _keybox_parse_openpgp (const unsigned char *image, size_t imagelen,
|
|||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
info->nsubkeys--;
|
info->nsubkeys--;
|
||||||
if (gpg_err_code (err) != GPG_ERR_UNKNOWN_ALGORITHM)
|
|
||||||
break;
|
|
||||||
/* We ignore subkeys with unknown algorithms. */
|
/* We ignore subkeys with unknown algorithms. */
|
||||||
|
if (gpg_err_code (err) == GPG_ERR_UNKNOWN_ALGORITHM
|
||||||
|
|| gpg_err_code (err) == GPG_ERR_UNSUPPORTED_ALGORITHM)
|
||||||
|
err = 0;
|
||||||
|
if (err)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ktail = &info->subkeys.next;
|
ktail = &info->subkeys.next;
|
||||||
@ -459,9 +458,12 @@ _keybox_parse_openpgp (const unsigned char *image, size_t imagelen,
|
|||||||
{
|
{
|
||||||
xfree (k);
|
xfree (k);
|
||||||
info->nsubkeys--;
|
info->nsubkeys--;
|
||||||
if (gpg_err_code (err) != GPG_ERR_UNKNOWN_ALGORITHM)
|
|
||||||
break;
|
|
||||||
/* We ignore subkeys with unknown algorithms. */
|
/* We ignore subkeys with unknown algorithms. */
|
||||||
|
if (gpg_err_code (err) == GPG_ERR_UNKNOWN_ALGORITHM
|
||||||
|
|| gpg_err_code (err) == GPG_ERR_UNSUPPORTED_ALGORITHM)
|
||||||
|
err = 0;
|
||||||
|
if (err)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -475,11 +477,10 @@ _keybox_parse_openpgp (const unsigned char *image, size_t imagelen,
|
|||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
_keybox_destroy_openpgp_info (info);
|
_keybox_destroy_openpgp_info (info);
|
||||||
if (!first
|
if (!read_error)
|
||||||
&& (gpg_err_code (err) == GPG_ERR_UNSUPPORTED_ALGORITHM
|
|
||||||
|| gpg_err_code (err) == GPG_ERR_UNKNOWN_ALGORITHM))
|
|
||||||
{
|
{
|
||||||
/* We are able to skip to the end of this keyblock. */
|
/* Packet parsing worked, thus we should be able to skip the
|
||||||
|
rest of the keyblock. */
|
||||||
while (image)
|
while (image)
|
||||||
{
|
{
|
||||||
if (next_packet (&image, &imagelen,
|
if (next_packet (&image, &imagelen,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user