Add support for shared libraries with OS/2.
[oweals/openssl.git] / crypto / asn1 / tasn_enc.c
index f6d33e177672de624ccb450b78bc6d7e34700a06..f6c8ddef0aada2a0fe61a68ce2f0baec062b12c7 100644 (file)
@@ -58,6 +58,7 @@
 
 
 #include <stddef.h>
+#include <string.h>
 #include <openssl/asn1.h>
 #include <openssl/asn1t.h>
 #include <openssl/objects.h>
@@ -221,7 +222,11 @@ int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLAT
                int skcontlen, sklen;
                ASN1_VALUE *skitem;
                if(!*pval) return 0;
-               isset = flags & ASN1_TFLG_SET_OF;
+               if(flags & ASN1_TFLG_SET_OF) {
+                       isset = 1;
+                       /* 2 means we reorder */
+                       if(flags & ASN1_TFLG_SEQUENCE_OF) isset = 2;
+               } else isset = 0;
                /* First work out inner tag value */
                if(flags & ASN1_TFLG_IMPTAG) {
                        sktag = tt->tag;
@@ -235,7 +240,7 @@ int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLAT
                skcontlen = 0;
                for(i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
                        skitem = sk_ASN1_VALUE_value(sk, i);
-                       skcontlen += ASN1_item_ex_i2d(&skitem, NULL, tt->item, -1, 0);
+                       skcontlen += ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item), -1, 0);
                }
                sklen = ASN1_object_size(1, skcontlen, sktag);
                /* If EXPLICIT need length of surrounding tag */
@@ -252,7 +257,7 @@ int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLAT
                /* SET or SEQUENCE and IMPLICIT tag */
                ASN1_put_object(out, 1, skcontlen, sktag, skaclass);
                /* And finally the stuff itself */
-               asn1_set_seq_out(sk, out, skcontlen, tt->item, isset);
+               asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item), isset);
 
                return ret;
        }
@@ -260,23 +265,23 @@ int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLAT
        if(flags & ASN1_TFLG_EXPTAG) {
                /* EXPLICIT tagging */
                /* Find length of tagged item */
-               i = ASN1_item_ex_i2d(pval, NULL, tt->item, -1, 0);
+               i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, 0);
                if(!i) return 0;
                /* Find length of EXPLICIT tag */
                ret = ASN1_object_size(1, i, tt->tag);
                if(out) {
                        /* Output tag and item */
                        ASN1_put_object(out, 1, i, tt->tag, aclass);
-                       ASN1_item_ex_i2d(pval, out, tt->item, -1, 0);
+                       ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, 0);
                }
                return ret;
        }
        if(flags & ASN1_TFLG_IMPTAG) {
                /* IMPLICIT tagging */
-               return ASN1_item_ex_i2d(pval, out, tt->item, tt->tag, aclass);
+               return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), tt->tag, aclass);
        }
        /* Nothing special: treat as normal */
-       return ASN1_item_ex_i2d(pval, out, tt->item, -1, 0);
+       return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, 0);
 }
 
 /* Temporary structure used to hold DER encoding of items for SET OF */
@@ -284,6 +289,7 @@ int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLAT
 typedef        struct {
        unsigned char *data;
        int length;
+       ASN1_VALUE *field;
 } DER_ENC;
 
 static int der_cmp(const void *a, const void *b)
@@ -302,8 +308,8 @@ static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, int s
 {
        int i;
        ASN1_VALUE *skitem;
-       unsigned char *tmpdat, *p;
-       DER_ENC *derlst, *tder;
+       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) do_sort = 0;
@@ -327,6 +333,7 @@ static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, int s
                skitem = sk_ASN1_VALUE_value(sk, i);
                tder->data = p;
                tder->length = ASN1_item_i2d(skitem, &p, item);
+               tder->field = skitem;
        }
        /* Now sort them */
        qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
@@ -337,6 +344,11 @@ static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, int s
                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++)
+                       sk_ASN1_VALUE_set(sk, i, tder->field);
+       }
        OPENSSL_free(derlst);
        OPENSSL_free(tmpdat);
        return 1;