deprecate the buffer_init() sshbuf entrypoint.

Allows making struct sshbuf opaque
This commit is contained in:
Damien Miller
2012-10-04 15:25:36 +10:00
committed by Markus Friedl
parent 25ba47881f
commit b305993cea
4 changed files with 56 additions and 54 deletions

View File

@@ -79,6 +79,20 @@ sshbuf_get_bignum1(struct sshbuf *buf, BIGNUM *v)
return 0;
}
static int
get_ec(const u_char *d, size_t len, EC_POINT *v, const EC_GROUP *g)
{
/* Refuse overlong bignums */
if (len == 0 || len > SSHBUF_MAX_ECPOINT)
return SSH_ERR_ECPOINT_TOO_LARGE;
/* Only handle uncompressed points */
if (*d != POINT_CONVERSION_UNCOMPRESSED)
return SSH_ERR_INVALID_FORMAT;
if (v != NULL && EC_POINT_oct2point(g, v, d, len, NULL) != 1)
return SSH_ERR_INVALID_FORMAT; /* XXX assumption */
return 0;
}
int
sshbuf_get_ec(struct sshbuf *buf, EC_POINT *v, const EC_GROUP *g)
{
@@ -88,14 +102,8 @@ sshbuf_get_ec(struct sshbuf *buf, EC_POINT *v, const EC_GROUP *g)
if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0)
return r;
/* Refuse overlong bignums */
if (len == 0 || len > SSHBUF_MAX_ECPOINT)
return SSH_ERR_ECPOINT_TOO_LARGE;
/* Only handle uncompressed points */
if (*d != POINT_CONVERSION_UNCOMPRESSED)
return SSH_ERR_INVALID_FORMAT;
if (v != NULL && EC_POINT_oct2point(g, v, d, len, NULL) != 1)
return SSH_ERR_INVALID_FORMAT; /* XXX assumption */
if ((r = get_ec(d, len, v, g)) != 0)
return r;
/* Skip string */
if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) {
/* Shouldn't happen */
@@ -111,20 +119,29 @@ sshbuf_get_eckey(struct sshbuf *buf, EC_KEY *v)
{
EC_POINT *pt = EC_POINT_new(EC_KEY_get0_group(v));
int r;
size_t ooff = buf->off; /* NB. uses buffer internals to rewind on err */
const u_char *d;
size_t len;
if (pt == NULL) {
SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL"));
return SSH_ERR_ALLOC_FAIL;
}
if ((r = sshbuf_get_ec(buf, pt, EC_KEY_get0_group(v))) < 0)
if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0)
return r;
if ((r = get_ec(d, len, pt, EC_KEY_get0_group(v))) != 0)
return r;
if (EC_KEY_set_public_key(v, pt) != 1) {
buf->off = ooff;
EC_POINT_free(pt);
return SSH_ERR_ALLOC_FAIL; /* XXX assumption */
}
EC_POINT_free(pt);
/* Skip string */
if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) {
/* Shouldn't happen */
SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
SSHBUF_ABORT();
return SSH_ERR_INTERNAL_ERROR;
}
return 0;
}

View File

@@ -25,6 +25,20 @@
#define SSHBUF_INTERNAL
#include "sshbuf.h"
/*
* NB. do not depend on the internals of this. It will be made opaque
* one day.
*/
struct sshbuf {
u_char *d; /* Data */
const u_char *cd; /* Const data */
size_t off; /* First available byte is buf->d + buf->off */
size_t size; /* Last byte is buf->d + buf->size - 1 */
size_t max_size; /* Maximum size of buffer */
size_t alloc; /* Total bytes allocated to buf->d */
int readonly; /* Refers to external, const data */
};
static inline int
sshbuf_check_sanity(const struct sshbuf *buf)
{
@@ -32,7 +46,6 @@ sshbuf_check_sanity(const struct sshbuf *buf)
if (__predict_false(buf == NULL ||
(!buf->readonly && buf->d != buf->cd) ||
buf->cd == NULL ||
(!buf->freeme && buf->readonly) ||
buf->max_size > SSHBUF_SIZE_MAX ||
buf->alloc > buf->max_size ||
buf->size > buf->alloc ||
@@ -69,7 +82,6 @@ sshbuf_new(void)
return NULL;
ret->alloc = SSHBUF_SIZE_INIT;
ret->max_size = SSHBUF_SIZE_MAX;
ret->freeme = 1;
ret->readonly = 0;
if ((ret->cd = ret->d = calloc(1, ret->alloc)) == NULL) {
free(ret);
@@ -87,7 +99,6 @@ sshbuf_from(const void *blob, size_t len)
(ret = calloc(sizeof(*ret), 1)) == NULL)
return NULL;
ret->alloc = ret->size = ret->max_size = len;
ret->freeme = 1;
ret->readonly = 1;
ret->cd = blob;
ret->d = NULL;
@@ -106,22 +117,9 @@ sshbuf_fromb(const struct sshbuf *buf)
return sshbuf_from(sshbuf_ptr(buf), sshbuf_len(buf));
}
void
sshbuf_init(struct sshbuf *ret)
{
bzero(ret, sizeof(*ret));
ret->alloc = SSHBUF_SIZE_INIT;
ret->max_size = SSHBUF_SIZE_MAX;
ret->readonly = 0;
if ((ret->cd = ret->d = calloc(1, ret->alloc)) == NULL)
ret->alloc = 0;
}
void
sshbuf_free(struct sshbuf *buf)
{
int freeme;
if (buf == NULL)
return;
/*
@@ -136,10 +134,8 @@ sshbuf_free(struct sshbuf *buf)
bzero(buf->d, buf->alloc);
free(buf->d);
}
freeme = buf->freeme;
bzero(buf, sizeof(buf));
if (freeme)
free(buf);
free(buf);
}
void
@@ -169,6 +165,12 @@ sshbuf_max_size(const struct sshbuf *buf)
return buf->max_size;
}
size_t
sshbuf_alloc(const struct sshbuf *buf)
{
return buf->alloc;
}
int
sshbuf_set_max_size(struct sshbuf *buf, size_t max_size)
{

View File

@@ -32,29 +32,7 @@
#define SSHBUF_MAX_BIGNUM (8192 / 8) /* Max bignum *bytes* */
#define SSHBUF_MAX_ECPOINT ((528 * 2 / 8) + 1) /* Max EC point *bytes* */
/*
* NB. do not depend on the internals of this. It will be made opaque
* one day.
*/
struct sshbuf {
u_char *d; /* Data */
const u_char *cd; /* Const data */
size_t off; /* First available byte is buf->d + buf->off */
size_t size; /* Last byte is buf->d + buf->size - 1 */
size_t max_size; /* Maximum size of buffer */
size_t alloc; /* Total bytes allocated to buf->d */
int freeme; /* Kludge to support sshbuf_init */
int readonly; /* Refers to external, const data */
};
#ifndef SSHBUF_NO_DEPREACTED
/*
* NB. Please do not use sshbuf_init() in new code. Please use sshbuf_new()
* instead. sshbuf_init() is deprectated and will go away soon (it is
* only included to allow compat with buffer_* in OpenSSH)
*/
void sshbuf_init(struct sshbuf *buf);
#endif
struct sshbuf;
/*
* Create a new sshbuf buffer.
@@ -272,6 +250,11 @@ int sshbuf_b64tod(struct sshbuf *buf, const char *b64);
/* Internal definitions follow. Exposed for regress tests */
#ifdef SSHBUF_INTERNAL
/*
* Return the allocation size of buf
*/
size_t sshbuf_alloc(const struct sshbuf *buf);
# define SSHBUF_SIZE_INIT 256 /* Initial allocation */
# define SSHBUF_SIZE_INC 256 /* Preferred increment length */
# define SSHBUF_PACK_MIN 8192 /* Minimim packable offset */

View File

@@ -213,7 +213,7 @@ sshbuf_tests(void)
ASSERT_MEM_FILLED_EQ(cdp, 0xd7, 1000);
ASSERT_MEM_FILLED_EQ(cdp + 1000, 0x7d, 223);
ASSERT_MEM_FILLED_EQ(cdp + 1223, 0xff, 1);
ASSERT_SIZE_T_EQ(p1->alloc % SSHBUF_SIZE_INC, 0);
ASSERT_SIZE_T_EQ(sshbuf_alloc(p1) % SSHBUF_SIZE_INC, 0);
sshbuf_free(p1);
TEST_DONE();