Reject BMPStrings and UniversalStrings of invalid length. This prevents
authorDr. Stephen Henson <steve@openssl.org>
Wed, 25 Mar 2009 10:35:57 +0000 (10:35 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Wed, 25 Mar 2009 10:35:57 +0000 (10:35 +0000)
a crash in ASN1_STRING_print_ex() which assumes they are valid.

CHANGES
crypto/asn1/asn1.h
crypto/asn1/asn1_err.c
crypto/asn1/tasn_dec.c

diff --git a/CHANGES b/CHANGES
index fe35aa6ed789833e05fb8cba20db6aef076f08e2..37f8ee52099f9ba96ec197e28a37892607e9c118 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,11 @@
 
  Changes between 0.9.8j and 0.9.8k  [xx XXX xxxx]
 
+  *) Reject UniversalString and BMPString types with invalid lengths. This
+     prevents a crash in ASN1_STRING_print_ex() which assumes the strings have
+     a legal length. (CVE-2009-0590)
+     [Steve Henson]
+
   *) Set S/MIME signing as the default purpose rather than setting it 
      unconditionally. This allows applications to override it at the store
      level.
index f06d942503ad25a20e055c59d819665ac5ed4a88..e3385226d4a5b0aa540305ae1931351145773b37 100644 (file)
@@ -1218,6 +1218,7 @@ void ERR_load_ASN1_strings(void);
 #define ASN1_R_BAD_OBJECT_HEADER                        102
 #define ASN1_R_BAD_PASSWORD_READ                        103
 #define ASN1_R_BAD_TAG                                  104
+#define ASN1_R_BMPSTRING_IS_WRONG_LENGTH                210
 #define ASN1_R_BN_LIB                                   105
 #define ASN1_R_BOOLEAN_IS_WRONG_LENGTH                  106
 #define ASN1_R_BUFFER_TOO_SMALL                                 107
@@ -1307,6 +1308,7 @@ void ERR_load_ASN1_strings(void);
 #define ASN1_R_UNABLE_TO_DECODE_RSA_KEY                         157
 #define ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY                 158
 #define ASN1_R_UNEXPECTED_EOC                           159
+#define ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH          211
 #define ASN1_R_UNKNOWN_FORMAT                           160
 #define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM                 161
 #define ASN1_R_UNKNOWN_OBJECT_TYPE                      162
index f8a3e2e6cd015ebd2b56b215cbcb5d7d6a181313..5f5de98eed530a199aca422cd09ee8d89cc59ab6 100644 (file)
@@ -195,6 +195,7 @@ static ERR_STRING_DATA ASN1_str_reasons[]=
 {ERR_REASON(ASN1_R_BAD_OBJECT_HEADER)    ,"bad object header"},
 {ERR_REASON(ASN1_R_BAD_PASSWORD_READ)    ,"bad password read"},
 {ERR_REASON(ASN1_R_BAD_TAG)              ,"bad tag"},
+{ERR_REASON(ASN1_R_BMPSTRING_IS_WRONG_LENGTH),"bmpstring is wrong length"},
 {ERR_REASON(ASN1_R_BN_LIB)               ,"bn lib"},
 {ERR_REASON(ASN1_R_BOOLEAN_IS_WRONG_LENGTH),"boolean is wrong length"},
 {ERR_REASON(ASN1_R_BUFFER_TOO_SMALL)     ,"buffer too small"},
@@ -284,6 +285,7 @@ static ERR_STRING_DATA ASN1_str_reasons[]=
 {ERR_REASON(ASN1_R_UNABLE_TO_DECODE_RSA_KEY),"unable to decode rsa key"},
 {ERR_REASON(ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY),"unable to decode rsa private key"},
 {ERR_REASON(ASN1_R_UNEXPECTED_EOC)       ,"unexpected eoc"},
+{ERR_REASON(ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH),"universalstring is wrong length"},
 {ERR_REASON(ASN1_R_UNKNOWN_FORMAT)       ,"unknown format"},
 {ERR_REASON(ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM),"unknown message digest algorithm"},
 {ERR_REASON(ASN1_R_UNKNOWN_OBJECT_TYPE)  ,"unknown object type"},
index 05129f229c738d59f76216eaa1e517881955ee67..36626da421c6cc037adf821d10ea08fc00ef802c 100644 (file)
@@ -1012,6 +1012,18 @@ int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
                case V_ASN1_SET:
                case V_ASN1_SEQUENCE:
                default:
+               if (utype == V_ASN1_BMPSTRING && (len & 1))
+                       {
+                       ASN1err(ASN1_F_ASN1_EX_C2I,
+                                       ASN1_R_BMPSTRING_IS_WRONG_LENGTH);
+                       goto err;
+                       }
+               if (utype == V_ASN1_UNIVERSALSTRING && (len & 3))
+                       {
+                       ASN1err(ASN1_F_ASN1_EX_C2I,
+                                       ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH);
+                       goto err;
+                       }
                /* All based on ASN1_STRING and handled the same */
                if (!*pval)
                        {