constify *_dup() and *i2d_*() and related functions as far as possible, introducing...
[openssl.git] / crypto / asn1 / tasn_enc.c
index 411b53e0625bcbfaec17b3e4fb891d1f24988d84..8ab9c370fdef4e4242d98459a3fd7f231fe09273 100644 (file)
 #include "internal/asn1_int.h"
 #include "asn1_locl.h"
 
-static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
+static int asn1_i2d_ex_primitive(const ASN1_VALUE **pval, unsigned char **out,
                                  const ASN1_ITEM *it, int tag, int aclass);
-static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
+static int asn1_set_seq_out(STACK_OF(const_ASN1_VALUE) *sk,
+                            unsigned char **out,
                             int skcontlen, const ASN1_ITEM *item,
                             int do_sort, int iclass);
-static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
+static int asn1_template_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
                                 const ASN1_TEMPLATE *tt, int tag, int aclass);
-static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
+static int asn1_item_flags_i2d(const ASN1_VALUE *val, unsigned char **out,
                                const ASN1_ITEM *it, int flags);
-static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
+static int asn1_ex_i2c(const ASN1_VALUE **pval, unsigned char *cout, int *putype,
                        const ASN1_ITEM *it);
 
 /*
@@ -33,13 +34,13 @@ static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
  * indefinite length constructed encoding, where appropriate
  */
 
-int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out,
+int ASN1_item_ndef_i2d(const ASN1_VALUE *val, unsigned char **out,
                        const ASN1_ITEM *it)
 {
     return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
 }
 
-int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
+int ASN1_item_i2d(const ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
 {
     return asn1_item_flags_i2d(val, out, it, 0);
 }
@@ -51,7 +52,7 @@ int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
  * allocated and populated with the encoding.
  */
 
-static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
+static int asn1_item_flags_i2d(const ASN1_VALUE *val, unsigned char **out,
                                const ASN1_ITEM *it, int flags)
 {
     if (out && !*out) {
@@ -79,20 +80,22 @@ static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
  * performs the normal item handling: it can be used in external types.
  */
 
-int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
+int ASN1_item_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
                      const ASN1_ITEM *it, int tag, int aclass)
 {
     const ASN1_TEMPLATE *tt = NULL;
     int i, seqcontlen, seqlen, ndef = 1;
     const ASN1_EXTERN_FUNCS *ef;
     const ASN1_AUX *aux = it->funcs;
-    ASN1_aux_cb *asn1_cb = 0;
+    ASN1_aux_const_cb *asn1_cb = NULL;
 
     if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
         return 0;
 
-    if (aux && aux->asn1_cb)
-        asn1_cb = aux->asn1_cb;
+    if (aux != NULL) {
+        asn1_cb = ((aux->flags & ASN1_AFLG_CONST_CB) != 0) ? aux->asn1_const_cb
+            : (ASN1_aux_const_cb *)aux->asn1_cb; /* backward compatibility */
+    }
 
     switch (it->itype) {
 
@@ -108,12 +111,12 @@ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
     case ASN1_ITYPE_CHOICE:
         if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
             return 0;
-        i = asn1_get_choice_selector(pval, it);
+        i = asn1_get_choice_selector_const(pval, it);
         if ((i >= 0) && (i < it->tcount)) {
-            ASN1_VALUE **pchval;
+            const ASN1_VALUE **pchval;
             const ASN1_TEMPLATE *chtt;
             chtt = it->templates + i;
-            pchval = asn1_get_field_ptr(pval, chtt);
+            pchval = asn1_get_const_field_ptr(pval, chtt);
             return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass);
         }
         /* Fixme: error condition if selector out of range */
@@ -154,12 +157,12 @@ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
         /* First work out sequence content length */
         for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
             const ASN1_TEMPLATE *seqtt;
-            ASN1_VALUE **pseqval;
+            const ASN1_VALUE **pseqval;
             int tmplen;
-            seqtt = asn1_do_adb(pval, tt, 1);
+            seqtt = asn1_do_adb(*pval, tt, 1);
             if (!seqtt)
                 return 0;
-            pseqval = asn1_get_field_ptr(pval, seqtt);
+            pseqval = asn1_get_const_field_ptr(pval, seqtt);
             tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, aclass);
             if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen))
                 return -1;
@@ -173,11 +176,11 @@ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
         ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
         for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
             const ASN1_TEMPLATE *seqtt;
-            ASN1_VALUE **pseqval;
-            seqtt = asn1_do_adb(pval, tt, 1);
+            const ASN1_VALUE **pseqval;
+            seqtt = asn1_do_adb(*pval, tt, 1);
             if (!seqtt)
                 return 0;
-            pseqval = asn1_get_field_ptr(pval, seqtt);
+            pseqval = asn1_get_const_field_ptr(pval, seqtt);
             /* FIXME: check for errors in enhanced version */
             asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
         }
@@ -194,11 +197,11 @@ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
     return 0;
 }
 
-static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
+static int asn1_template_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
                                 const ASN1_TEMPLATE *tt, int tag, int iclass)
 {
     int i, ret, flags, ttag, tclass, ndef;
-    ASN1_VALUE *tval;
+    const ASN1_VALUE *tval;
     flags = tt->flags;
 
     /*
@@ -250,10 +253,10 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
 
     if (flags & ASN1_TFLG_SK_MASK) {
         /* SET OF, SEQUENCE OF */
-        STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
+        STACK_OF(const_ASN1_VALUE) *sk = (STACK_OF(const_ASN1_VALUE) *)*pval;
         int isset, sktag, skaclass;
         int skcontlen, sklen;
-        ASN1_VALUE *skitem;
+        const ASN1_VALUE *skitem;
 
         if (!*pval)
             return 0;
@@ -283,9 +286,9 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
 
         /* Determine total length of items */
         skcontlen = 0;
-        for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
+        for (i = 0; i < sk_const_ASN1_VALUE_num(sk); i++) {
             int tmplen;
-            skitem = sk_ASN1_VALUE_value(sk, i);
+            skitem = sk_const_ASN1_VALUE_value(sk, i);
             tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item),
                                       -1, iclass);
             if (tmplen == -1 || (skcontlen > INT_MAX - tmplen))
@@ -351,7 +354,7 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
 typedef struct {
     unsigned char *data;
     int length;
-    ASN1_VALUE *field;
+    const ASN1_VALUE *field;
 } DER_ENC;
 
 static int der_cmp(const void *a, const void *b)
@@ -367,20 +370,21 @@ static int der_cmp(const void *a, const void *b)
 
 /* Output the content octets of SET OF or SEQUENCE OF */
 
-static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
+static int asn1_set_seq_out(STACK_OF(const_ASN1_VALUE) *sk,
+                            unsigned char **out,
                             int skcontlen, const ASN1_ITEM *item,
                             int do_sort, int iclass)
 {
     int i;
-    ASN1_VALUE *skitem;
+    const ASN1_VALUE *skitem;
     unsigned char *tmpdat = NULL, *p = NULL;
     DER_ENC *derlst = NULL, *tder;
     if (do_sort) {
         /* Don't need to sort less than 2 items */
-        if (sk_ASN1_VALUE_num(sk) < 2)
+        if (sk_const_ASN1_VALUE_num(sk) < 2)
             do_sort = 0;
         else {
-            derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk)
+            derlst = OPENSSL_malloc(sk_const_ASN1_VALUE_num(sk)
                                     * sizeof(*derlst));
             if (derlst == NULL)
                 return 0;
@@ -393,8 +397,8 @@ static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
     }
     /* If not sorting just output each item */
     if (!do_sort) {
-        for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
-            skitem = sk_ASN1_VALUE_value(sk, i);
+        for (i = 0; i < sk_const_ASN1_VALUE_num(sk); i++) {
+            skitem = sk_const_ASN1_VALUE_value(sk, i);
             ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
         }
         return 1;
@@ -402,33 +406,33 @@ static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
     p = tmpdat;
 
     /* Doing sort: build up a list of each member's DER encoding */
-    for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
-        skitem = sk_ASN1_VALUE_value(sk, i);
+    for (i = 0, tder = derlst; i < sk_const_ASN1_VALUE_num(sk); i++, tder++) {
+        skitem = sk_const_ASN1_VALUE_value(sk, i);
         tder->data = p;
         tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
         tder->field = skitem;
     }
 
     /* Now sort them */
-    qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
+    qsort(derlst, sk_const_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
     /* Output sorted DER encoding */
     p = *out;
-    for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
+    for (i = 0, tder = derlst; i < sk_const_ASN1_VALUE_num(sk); i++, tder++) {
         memcpy(p, tder->data, tder->length);
         p += tder->length;
     }
     *out = p;
     /* If do_sort is 2 then reorder the STACK */
     if (do_sort == 2) {
-        for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
-            (void)sk_ASN1_VALUE_set(sk, i, tder->field);
+        for (i = 0, tder = derlst; i < sk_const_ASN1_VALUE_num(sk); i++, tder++)
+            (void)sk_const_ASN1_VALUE_set(sk, i, tder->field);
     }
     OPENSSL_free(derlst);
     OPENSSL_free(tmpdat);
     return 1;
 }
 
-static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
+static int asn1_i2d_ex_primitive(const ASN1_VALUE **pval, unsigned char **out,
                                  const ASN1_ITEM *it, int tag, int aclass)
 {
     int len;
@@ -488,7 +492,7 @@ static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
 
 /* Produce content octets from a structure */
 
-static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
+static int asn1_ex_i2c(const ASN1_VALUE **pval, unsigned char *cout, int *putype,
                        const ASN1_ITEM *it)
 {
     ASN1_BOOLEAN *tbool = NULL;
@@ -521,7 +525,7 @@ static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
         typ = (ASN1_TYPE *)*pval;
         utype = typ->type;
         *putype = utype;
-        pval = &typ->value.asn1_value;
+        pval = (const ASN1_VALUE **)&typ->value.asn1_value; /* actually is const */
     } else
         utype = *putype;