commit d9d0f1b52c570f0cc91ac5e8d1eb6a5bce4ba146
Author: Dr. Stephen Henson <steve@openssl.org>
Date:   Thu Aug 6 16:32:54 2009 +0000

    Reject leading 0x80 in OID subidentifiers.

commit 7ed485bc9fab7609ad06960bf84118ea4c61da3a
Author: Dr. Stephen Henson <steve@openssl.org>
Date:   Sun Mar 7 16:40:05 2010 +0000

    The OID sanity check was incorrect. It should only disallow *leading* 0x80
    values.

commit b9a73f5481fb8d5aac535622759cb0f632f39914
Author: Emilia Kasper <emilia@openssl.org>
Date:   Wed Jul 2 19:02:33 2014 +0200

    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

Index: openssl-0.9.7g/apps/x509.c
===================================================================
--- openssl-0.9.7g.orig/apps/x509.c	2014-11-27 17:07:44.071983763 +0100
+++ openssl-0.9.7g/apps/x509.c	2014-11-27 17:07:44.204985322 +0100
@@ -857,6 +857,7 @@ bad:
 			else if (text == i)
 				{
 				X509_print_ex(out,x,nmflag, certflag);
+ERR_print_errors_fp(stderr);
 				}
 			else if (startdate == i)
 				{
Index: openssl-0.9.7g/crypto/asn1/a_object.c
===================================================================
--- openssl-0.9.7g.orig/crypto/asn1/a_object.c	2002-11-12 14:21:22.000000000 +0100
+++ openssl-0.9.7g/crypto/asn1/a_object.c	2014-11-27 17:11:44.016807810 +0100
@@ -61,6 +61,7 @@
 #include <openssl/buffer.h>
 #include <openssl/asn1.h>
 #include <openssl/objects.h>
+#include <limits.h>
 
 int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
 	{
@@ -224,7 +225,29 @@ ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT
 	{
 	ASN1_OBJECT *ret=NULL;
 	unsigned char *p;
-	int i;
+	int i, length;
+
+	/* 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
+	 */
+	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)))
+			{
+			ASN1err(ASN1_F_C2I_ASN1_OBJECT,ASN1_R_INVALID_OBJECT_ENCODING);
+			return NULL;
+			}
+		}
 
 	/* only the ASN1_OBJECTs from the 'table' will have values
 	 * for ->sn or ->ln */
@@ -236,20 +259,20 @@ ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT
 	else	ret=(*a);
 
 	p= *pp;
-	if ((ret->data == NULL) || (ret->length < len))
+	if ((ret->data == NULL) || (ret->length < length))
 		{
 		if (ret->data != NULL) OPENSSL_free(ret->data);
-		ret->data=(unsigned char *)OPENSSL_malloc(len ? (int)len : 1);
+		ret->data=(unsigned char *)OPENSSL_malloc(length);
 		ret->flags|=ASN1_OBJECT_FLAG_DYNAMIC_DATA;
 		if (ret->data == NULL)
 			{ i=ERR_R_MALLOC_FAILURE; goto err; }
 		}
-	memcpy(ret->data,p,(int)len);
-	ret->length=(int)len;
+	memcpy(ret->data,p,length);
+	ret->length=length;
 	ret->sn=NULL;
 	ret->ln=NULL;
 	/* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
-	p+=len;
+	p+=length;
 
 	if (a != NULL) (*a)=ret;
 	*pp=p;
Index: openssl-0.9.7g/crypto/asn1/asn1.h
===================================================================
--- openssl-0.9.7g.orig/crypto/asn1/asn1.h	2014-11-27 17:07:44.079983857 +0100
+++ openssl-0.9.7g/crypto/asn1/asn1.h	2014-11-27 17:16:49.114411318 +0100
@@ -993,6 +993,7 @@ void ERR_load_ASN1_strings(void);
 #define ASN1_F_ASN1_VERIFY				 137
 #define ASN1_F_BN_TO_ASN1_ENUMERATED			 138
 #define ASN1_F_BN_TO_ASN1_INTEGER			 139
+#define ASN1_F_C2I_ASN1_OBJECT				 196
 #define ASN1_F_COLLECT_DATA				 140
 #define ASN1_F_D2I_ASN1_BIT_STRING			 141
 #define ASN1_F_D2I_ASN1_BOOLEAN				 142
@@ -1067,6 +1068,7 @@ void ERR_load_ASN1_strings(void);
 #define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG		 128
 #define ASN1_R_INVALID_BMPSTRING_LENGTH			 129
 #define ASN1_R_INVALID_DIGIT				 130
+#define ASN1_R_INVALID_OBJECT_ENCODING			 216
 #define ASN1_R_INVALID_SEPARATOR			 131
 #define ASN1_R_INVALID_TIME_FORMAT			 132
 #define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH		 133
Index: openssl-0.9.7g/crypto/asn1/asn1_err.c
===================================================================
--- openssl-0.9.7g.orig/crypto/asn1/asn1_err.c	2014-11-27 17:07:44.098984079 +0100
+++ openssl-0.9.7g/crypto/asn1/asn1_err.c	2014-11-27 17:25:34.469614131 +0100
@@ -113,6 +113,7 @@ static ERR_STRING_DATA ASN1_str_functs[]
 {ERR_PACK(0,ASN1_F_ASN1_VERIFY,0),	"ASN1_verify"},
 {ERR_PACK(0,ASN1_F_BN_TO_ASN1_ENUMERATED,0),	"BN_to_ASN1_ENUMERATED"},
 {ERR_PACK(0,ASN1_F_BN_TO_ASN1_INTEGER,0),	"BN_to_ASN1_INTEGER"},
+{ERR_PACK(0,ASN1_F_C2I_ASN1_OBJECT,0),	"c2i_ASN1_OBJECT"},
 {ERR_PACK(0,ASN1_F_COLLECT_DATA,0),	"COLLECT_DATA"},
 {ERR_PACK(0,ASN1_F_D2I_ASN1_BIT_STRING,0),	"D2I_ASN1_BIT_STRING"},
 {ERR_PACK(0,ASN1_F_D2I_ASN1_BOOLEAN,0),	"d2i_ASN1_BOOLEAN"},
@@ -190,6 +191,7 @@ static ERR_STRING_DATA ASN1_str_reasons[
 {ASN1_R_INTEGER_TOO_LARGE_FOR_LONG       ,"integer too large for long"},
 {ASN1_R_INVALID_BMPSTRING_LENGTH         ,"invalid bmpstring length"},
 {ASN1_R_INVALID_DIGIT                    ,"invalid digit"},
+{ASN1_R_INVALID_OBJECT_ENCODING          ,"invalid object encoding"},
 {ASN1_R_INVALID_SEPARATOR                ,"invalid separator"},
 {ASN1_R_INVALID_TIME_FORMAT              ,"invalid time format"},
 {ASN1_R_INVALID_UNIVERSALSTRING_LENGTH   ,"invalid universalstring length"},
Index: openssl-0.9.7g/crypto/objects/obj_dat.c
===================================================================
--- openssl-0.9.7g.orig/crypto/objects/obj_dat.c	2004-12-05 02:04:38.000000000 +0100
+++ openssl-0.9.7g/crypto/objects/obj_dat.c	2014-11-27 17:07:44.205985334 +0100
@@ -440,12 +440,12 @@ int OBJ_obj2txt(char *buf, int buf_len,
 	const char *s;
 	char tbuf[DECIMAL_SIZE(i)+DECIMAL_SIZE(l)+2];
 
-	if (buf_len <= 0) return(0);
+	/* Ensure that, at every state, |buf| is NUL-terminated. */
+	if (buf && buf_len > 0)
+		buf[0] = '\0';
 
-	if ((a == NULL) || (a->data == NULL)) {
-		buf[0]='\0';
+	if ((a == NULL) || (a->data == NULL))
 		return(0);
-	}
 
 	if (no_name || (nid=OBJ_obj2nid(a)) == NID_undef) {
 		len=a->length;
@@ -665,4 +665,3 @@ err:
 	OPENSSL_free(buf);
 	return(ok);
 	}
-
