Fix OID handling:

- Upon parsing, reject OIDs with invalid base-128 encoding.
- Always NUL-terminate the destination buffer in OBJ_obj2txt printing function.

CVE-2014-3508

Reviewed-by: Dr. Stephen Henson <steve@openssl.org>
Reviewed-by: Kurt Roeckx <kurt@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
This commit is contained in:
Emilia Kasper 2014-07-02 19:02:33 +02:00 committed by Matt Caswell
parent 9fd3555305
commit 57b0c4697a
2 changed files with 30 additions and 16 deletions

View File

@ -283,17 +283,29 @@ err:
ASN1err(ASN1_F_D2I_ASN1_OBJECT,i); ASN1err(ASN1_F_D2I_ASN1_OBJECT,i);
return(NULL); return(NULL);
} }
ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
long len) long len)
{ {
ASN1_OBJECT *ret=NULL; ASN1_OBJECT *ret=NULL;
const unsigned char *p; const unsigned char *p;
unsigned char *data; unsigned char *data;
int i; int i, length;
/* Sanity check OID encoding: can't have leading 0x80 in
* subidentifiers, see: X.690 8.19.2 /* Sanity check OID encoding.
* Need at least one content octet.
* MSB must be clear in the last octet.
* can't have leading 0x80 in subidentifiers, see: X.690 8.19.2
*/ */
for (i = 0, p = *pp; i < len; i++, p++) if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
p[len - 1] & 0x80)
{
ASN1err(ASN1_F_C2I_ASN1_OBJECT,ASN1_R_INVALID_OBJECT_ENCODING);
return NULL;
}
/* Now 0 < len <= INT_MAX, so the cast is safe. */
length = (int)len;
for (i = 0; i < length; i++, p++)
{ {
if (*p == 0x80 && (!i || !(p[-1] & 0x80))) if (*p == 0x80 && (!i || !(p[-1] & 0x80)))
{ {
@ -316,23 +328,23 @@ ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
data = (unsigned char *)ret->data; data = (unsigned char *)ret->data;
ret->data = NULL; ret->data = NULL;
/* once detached we can change it */ /* once detached we can change it */
if ((data == NULL) || (ret->length < len)) if ((data == NULL) || (ret->length < length))
{ {
ret->length=0; ret->length=0;
if (data != NULL) OPENSSL_free(data); if (data != NULL) OPENSSL_free(data);
data=(unsigned char *)OPENSSL_malloc(len ? (int)len : 1); data=(unsigned char *)OPENSSL_malloc(length);
if (data == NULL) if (data == NULL)
{ i=ERR_R_MALLOC_FAILURE; goto err; } { i=ERR_R_MALLOC_FAILURE; goto err; }
ret->flags|=ASN1_OBJECT_FLAG_DYNAMIC_DATA; ret->flags|=ASN1_OBJECT_FLAG_DYNAMIC_DATA;
} }
memcpy(data,p,(int)len); memcpy(data,p,length);
/* reattach data to object, after which it remains const */ /* reattach data to object, after which it remains const */
ret->data =data; ret->data =data;
ret->length=(int)len; ret->length=length;
ret->sn=NULL; ret->sn=NULL;
ret->ln=NULL; ret->ln=NULL;
/* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */ /* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
p+=len; p+=length;
if (a != NULL) (*a)=ret; if (a != NULL) (*a)=ret;
*pp=p; *pp=p;

View File

@ -471,11 +471,12 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name)
const unsigned char *p; const unsigned char *p;
char tbuf[DECIMAL_SIZE(i)+DECIMAL_SIZE(l)+2]; char tbuf[DECIMAL_SIZE(i)+DECIMAL_SIZE(l)+2];
if ((a == NULL) || (a->data == NULL)) { /* Ensure that, at every state, |buf| is NUL-terminated. */
buf[0]='\0'; if (buf && buf_len > 0)
return(0); buf[0] = '\0';
}
if ((a == NULL) || (a->data == NULL))
return(0);
if (!no_name && (nid=OBJ_obj2nid(a)) != NID_undef) if (!no_name && (nid=OBJ_obj2nid(a)) != NID_undef)
{ {
@ -554,9 +555,10 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name)
i=(int)(l/40); i=(int)(l/40);
l-=(long)(i*40); l-=(long)(i*40);
} }
if (buf && (buf_len > 0)) if (buf && (buf_len > 1))
{ {
*buf++ = i + '0'; *buf++ = i + '0';
*buf = '\0';
buf_len--; buf_len--;
} }
n++; n++;
@ -571,9 +573,10 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name)
i = strlen(bndec); i = strlen(bndec);
if (buf) if (buf)
{ {
if (buf_len > 0) if (buf_len > 1)
{ {
*buf++ = '.'; *buf++ = '.';
*buf = '\0';
buf_len--; buf_len--;
} }
BUF_strlcpy(buf,bndec,buf_len); BUF_strlcpy(buf,bndec,buf_len);
@ -807,4 +810,3 @@ err:
OPENSSL_free(buf); OPENSSL_free(buf);
return(ok); return(ok);
} }