i2d_ASN1_OBJECT(): allocate memory if the user didn't provide a buffer
authorRichard Levitte <levitte@openssl.org>
Sat, 11 Aug 2018 07:59:20 +0000 (09:59 +0200)
committerRichard Levitte <levitte@openssl.org>
Sat, 11 Aug 2018 10:27:02 +0000 (12:27 +0200)
Since 0.9.7, all i2d_ functions were documented to allocate an output
buffer if the user didn't provide one, under these conditions (from
the 1.0.2 documentation):

    For OpenSSL 0.9.7 and later if B<*out> is B<NULL> memory will be
    allocated for a buffer and the encoded data written to it. In this
    case B<*out> is not incremented and it points to the start of the
    data just written.

i2d_ASN1_OBJECT was found not to do this, and would crash if a NULL
output buffer was provided.

Fixes #6914

Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
(Merged from https://github.com/openssl/openssl/pull/6918)

crypto/asn1/a_object.c
crypto/asn1/asn1_err.c
crypto/err/openssl.txt
include/openssl/asn1err.h

index 42c138c2cdf52060195f7b2cec873377cf9fb91a..5e1424a806fbd98089b66e151f009169892c21bc 100644 (file)
@@ -20,7 +20,7 @@
 
 int i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp)
 {
-    unsigned char *p;
+    unsigned char *p, *allocated = NULL;
     int objsize;
 
     if ((a == NULL) || (a->data == NULL))
@@ -30,12 +30,23 @@ int i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp)
     if (pp == NULL || objsize == -1)
         return objsize;
 
-    p = *pp;
+    if (*pp == NULL) {
+        if ((p = allocated = OPENSSL_malloc(objsize)) == NULL) {
+            ASN1err(ASN1_F_I2D_ASN1_OBJECT, ERR_R_MALLOC_FAILURE);
+            return 0;
+        }
+    } else {
+        p = *pp;
+    }
+
     ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
     memcpy(p, a->data, a->length);
-    p += a->length;
 
-    *pp = p;
+    /*
+     * If a new buffer was allocated, just return it back.
+     * If not, return the incremented buffer pointer.
+     */
+    *pp = allocated != NULL ? allocated : p + a->length;
     return objsize;
 }
 
index 5907c94bc98dff12587854d6c0f182628ad340c8..613f9ae71333a5b0248bbf444232ca6a43c62e35 100644 (file)
@@ -116,6 +116,7 @@ static const ERR_STRING_DATA ASN1_str_functs[] = {
     {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2A_ASN1_OBJECT, 0), "i2a_ASN1_OBJECT"},
     {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_ASN1_BIO_STREAM, 0),
      "i2d_ASN1_bio_stream"},
+    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_ASN1_OBJECT, 0), "i2d_ASN1_OBJECT"},
     {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_DSA_PUBKEY, 0), "i2d_DSA_PUBKEY"},
     {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_EC_PUBKEY, 0), "i2d_EC_PUBKEY"},
     {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_PRIVATEKEY, 0), "i2d_PrivateKey"},
index 90b5c4e046b3a9d6ad83f4e338395af4aebaabb3..3ecd44b5e83a8c5144612a89e2648b52097441d3 100644 (file)
@@ -88,6 +88,7 @@ ASN1_F_DO_DUMP:125:do_dump
 ASN1_F_DO_TCREATE:222:do_tcreate
 ASN1_F_I2A_ASN1_OBJECT:126:i2a_ASN1_OBJECT
 ASN1_F_I2D_ASN1_BIO_STREAM:211:i2d_ASN1_bio_stream
+ASN1_F_I2D_ASN1_OBJECT:143:i2d_ASN1_OBJECT
 ASN1_F_I2D_DSA_PUBKEY:161:i2d_DSA_PUBKEY
 ASN1_F_I2D_EC_PUBKEY:181:i2d_EC_PUBKEY
 ASN1_F_I2D_PRIVATEKEY:163:i2d_PrivateKey
index 8001120bdfd12710d6d8a9dae49afdf87cc6aed8..5a91126db954d044d581cc844513c18cd87f89d1 100644 (file)
@@ -101,6 +101,7 @@ int ERR_load_ASN1_strings(void);
 # define ASN1_F_DO_TCREATE                                222
 # define ASN1_F_I2A_ASN1_OBJECT                           126
 # define ASN1_F_I2D_ASN1_BIO_STREAM                       211
+# define ASN1_F_I2D_ASN1_OBJECT                           143
 # define ASN1_F_I2D_DSA_PUBKEY                            161
 # define ASN1_F_I2D_EC_PUBKEY                             181
 # define ASN1_F_I2D_PRIVATEKEY                            163