1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00
gnupg/common/t-openpgp-oid.c
Werner Koch 8445ef24fc Fix buffer overflow in openpgp_oid_to_str.
* common/openpgp-oid.c (openpgp_oid_to_str): Fix unsigned underflow.

* common/t-openpgp-oid.c (BADOID): New.
(test_openpgp_oid_to_str): Add test cases.
--

The code has an obvious error by not considering invalid encoding for
arc-2.  A first byte of 0x80 can be used to make a value of less then
80 and we then subtract 80 from that value as required by the OID
encoding rules.  Due to the unsigned integer this results in a pretty
long value which won't fit anymore into the allocated buffer.

The fix is obvious.  Also added a few simple test cases.  Note that we
keep on using sprintf instead of snprintf because managing the
remaining length of the buffer would probably be more error prone than
assuring that the buffer is large enough.  Getting rid of sprintf
altogether by using direct conversion along with membuf_t like code
might be possible.

Reported-by: Hanno Böck
Signed-off-by: Werner Koch <wk@gnupg.org>

Ported from libksba commit f715b9e156dfa99ae829fc694e5a0abd23ef97d7
2014-11-25 11:58:56 +01:00

199 lines
4.6 KiB
C

/* t-openpgp-oid.c - Module test for openpgp-oid.c
* Copyright (C) 2011 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "util.h"
#define pass() do { ; } while(0)
#define fail(a,e) \
do { fprintf (stderr, "%s:%d: test %d failed (%s)\n", \
__FILE__,__LINE__, (a), gpg_strerror (e)); \
exit (1); \
} while(0)
#define BADOID "1.3.6.1.4.1.11591.2.12242973"
static void
test_openpgp_oid_from_str (void)
{
static char *sample_oids[] =
{
"0.0",
"1.0",
"1.2.3",
"1.2.840.10045.3.1.7",
"1.3.132.0.34",
"1.3.132.0.35",
NULL
};
gpg_error_t err;
gcry_mpi_t a;
int idx;
char *string;
unsigned char *p;
unsigned int nbits;
size_t length;
err = openpgp_oid_from_str ("", &a);
if (gpg_err_code (err) != GPG_ERR_INV_VALUE)
fail (0, err);
gcry_mpi_release (a);
err = openpgp_oid_from_str (".", &a);
if (gpg_err_code (err) != GPG_ERR_INV_OID_STRING)
fail (0, err);
gcry_mpi_release (a);
err = openpgp_oid_from_str ("0", &a);
if (gpg_err_code (err) != GPG_ERR_INV_OID_STRING)
fail (0, err);
gcry_mpi_release (a);
for (idx=0; sample_oids[idx]; idx++)
{
err = openpgp_oid_from_str (sample_oids[idx], &a);
if (err)
fail (idx, err);
string = openpgp_oid_to_str (a);
if (!string)
fail (idx, gpg_error_from_syserror ());
if (strcmp (string, sample_oids[idx]))
fail (idx, 0);
xfree (string);
p = gcry_mpi_get_opaque (a, &nbits);
length = (nbits+7)/8;
if (!p || !length || p[0] != length - 1)
fail (idx, 0);
gcry_mpi_release (a);
}
}
static void
test_openpgp_oid_to_str (void)
{
static struct {
const char *string;
unsigned char der[10];
} samples[] = {
{ "1.2.840.10045.3.1.7",
{8, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07 }},
{ "1.3.132.0.34",
{5, 0x2B, 0x81, 0x04, 0x00, 0x22 }},
{ "1.3.132.0.35",
{ 5, 0x2B, 0x81, 0x04, 0x00, 0x23 }},
{ BADOID,
{ 9, 0x80, 0x02, 0x70, 0x50, 0x25, 0x46, 0xfd, 0x0c, 0xc0 }},
{ BADOID,
{ 1, 0x80 }},
{ NULL }};
gcry_mpi_t a;
int idx;
char *string;
unsigned char *p;
for (idx=0; samples[idx].string; idx++)
{
p = xmalloc (samples[idx].der[0]+1);
memcpy (p, samples[idx].der, samples[idx].der[0]+1);
a = gcry_mpi_set_opaque (NULL, p, (samples[idx].der[0]+1)*8);
if (!a)
fail (idx, gpg_error_from_syserror ());
string = openpgp_oid_to_str (a);
if (!string)
fail (idx, gpg_error_from_syserror ());
if (strcmp (string, samples[idx].string))
fail (idx, 0);
xfree (string);
gcry_mpi_release (a);
}
}
static void
test_openpgp_oid_is_ed25519 (void)
{
static struct
{
int yes;
const char *oidstr;
} samples[] = {
{ 0, "0.0" },
{ 0, "1.3.132.0.35" },
{ 0, "1.3.6.1.4.1.3029.1.5.0" },
{ 0, "1.3.6.1.4.1.3029.1.5.1" }, /* Used during Libgcrypt development. */
{ 0, "1.3.6.1.4.1.3029.1.5.2" },
{ 0, "1.3.6.1.4.1.3029.1.5.1.0" },
{ 0, "1.3.6.1.4.1.3029.1.5" },
{ 0, "1.3.6.1.4.1.11591.15.0" },
{ 1, "1.3.6.1.4.1.11591.15.1" }, /* Your the one we want. */
{ 0, "1.3.6.1.4.1.11591.15.2" },
{ 0, "1.3.6.1.4.1.11591.15.1.0" },
{ 0, "1.3.6.1.4.1.11591.15" },
{ 0, NULL },
};
gpg_error_t err;
gcry_mpi_t a;
int idx;
for (idx=0; samples[idx].oidstr; idx++)
{
err = openpgp_oid_from_str (samples[idx].oidstr, &a);
if (err)
fail (idx, err);
if (openpgp_oid_is_ed25519 (a) != samples[idx].yes)
fail (idx, 0);
gcry_mpi_release (a);
}
}
int
main (int argc, char **argv)
{
(void)argc;
(void)argv;
test_openpgp_oid_from_str ();
test_openpgp_oid_to_str ();
test_openpgp_oid_is_ed25519 ();
return 0;
}