Some constification and stacks that slipped through the cracks (how?).
[openssl.git] / crypto / asn1 / asn1_mac.h
index 4fba70e..42825f5 100644 (file)
 extern "C" {
 #endif
 
-#include "asn1.h"
-#include "x509.h"
-#include "pkcs7.h"
+#include <openssl/asn1.h>
+#include <openssl/x509.h>
+#include <openssl/pkcs7.h>
+
+#ifndef ASN1_MAC_ERR_LIB
+#define ASN1_MAC_ERR_LIB       ERR_LIB_ASN1
+#endif 
+
+#define ASN1_MAC_H_err(f,r,line) \
+       ERR_PUT_error(ASN1_MAC_ERR_LIB,(f),(r),ERR_file_name,(line))
 
 #define M_ASN1_D2I_vars(a,type,func) \
        ASN1_CTX c; \
        type ret=NULL; \
        \
        c.pp=pp; \
-       c.error=ASN1_R_ERROR_STACK; \
+       c.q= *pp; \
+       c.error=ERR_R_NESTED_ASN1_ERROR; \
        if ((a == NULL) || ((*a) == NULL)) \
-               { if ((ret=(type)func()) == NULL) goto err; } \
+               { if ((ret=(type)func()) == NULL) \
+                       { c.line=__LINE__; goto err; } } \
        else    ret=(*a);
 
 #define M_ASN1_D2I_Init() \
@@ -82,7 +91,8 @@ extern "C" {
        c.max=(length == 0)?0:(c.p+length);
 
 #define M_ASN1_D2I_Finish_2(a) \
-       if (!asn1_Finish(&c)) goto err; \
+       if (!asn1_Finish(&c)) \
+               { c.line=__LINE__; goto err; } \
        *pp=c.p; \
        if (a != NULL) (*a)=ret; \
        return(ret);
@@ -90,21 +100,31 @@ extern "C" {
 #define M_ASN1_D2I_Finish(a,func,e) \
        M_ASN1_D2I_Finish_2(a); \
 err:\
-       ASN1err((e),c.error); \
+       ASN1_MAC_H_err((e),c.error,c.line); \
        asn1_add_error(*pp,(int)(c.q- *pp)); \
        if ((ret != NULL) && ((a == NULL) || (*a != ret))) func(ret); \
        return(NULL)
 
 #define M_ASN1_D2I_start_sequence() \
-       if (!asn1_GetSequence(&c,&length)) goto err;
+       if (!asn1_GetSequence(&c,&length)) \
+               { c.line=__LINE__; goto err; }
 
 #define M_ASN1_D2I_end_sequence() \
        (((c.inf&1) == 0)?(c.slen <= 0): \
                (c.eos=ASN1_check_infinite_end(&c.p,c.slen)))
 
+/* Don't use this with d2i_ASN1_BOOLEAN() */
 #define M_ASN1_D2I_get(b,func) \
        c.q=c.p; \
-       if (func(&(b),&c.p,c.slen) == NULL) goto err; \
+       if (func(&(b),&c.p,c.slen) == NULL) \
+               {c.line=__LINE__; goto err; } \
+       c.slen-=(c.p-c.q);
+
+/* use this instead () */
+#define M_ASN1_D2I_get_int(b,func) \
+       c.q=c.p; \
+       if (func(&(b),&c.p,c.slen) < 0) \
+               {c.line=__LINE__; goto err; } \
        c.slen-=(c.p-c.q);
 
 #define M_ASN1_D2I_get_opt(b,func,type) \
@@ -114,49 +134,118 @@ err:\
                M_ASN1_D2I_get(b,func); \
                }
 
+#define M_ASN1_D2I_get_imp(b,func, type) \
+       M_ASN1_next=(_tmp& V_ASN1_CONSTRUCTED)|type; \
+       c.q=c.p; \
+       if (func(&(b),&c.p,c.slen) == NULL) \
+               {c.line=__LINE__; M_ASN1_next_prev = _tmp; goto err; } \
+       c.slen-=(c.p-c.q);\
+       M_ASN1_next_prev=_tmp;
+
 #define M_ASN1_D2I_get_IMP_opt(b,func,tag,type) \
        if ((c.slen != 0) && ((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) == \
                (V_ASN1_CONTEXT_SPECIFIC|(tag)))) \
                { \
-               unsigned char tmp; \
-               tmp=M_ASN1_next; \
-               M_ASN1_next=(tmp& ~V_ASN1_PRIMATIVE_TAG)|type; \
-               M_ASN1_D2I_get(b,func); \
-               M_ASN1_next_prev=tmp; \
+               unsigned char _tmp = M_ASN1_next; \
+               M_ASN1_D2I_get_imp(b,func, type);\
                }
 
-#define M_ASN1_D2I_get_set(r,func) \
-               M_ASN1_D2I_get_imp_set(r,func,V_ASN1_SET,V_ASN1_UNIVERSAL);
+#define M_ASN1_D2I_get_set(r,func,free_func) \
+               M_ASN1_D2I_get_imp_set(r,func,free_func, \
+                       V_ASN1_SET,V_ASN1_UNIVERSAL);
+
+#define M_ASN1_D2I_get_set_type(type,r,func,free_func) \
+               M_ASN1_D2I_get_imp_set_type(type,r,func,free_func, \
+                       V_ASN1_SET,V_ASN1_UNIVERSAL);
+
+#define M_ASN1_D2I_get_set_opt(r,func,free_func) \
+       if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+               V_ASN1_CONSTRUCTED|V_ASN1_SET)))\
+               { M_ASN1_D2I_get_set(r,func,free_func); }
+
+#define M_ASN1_D2I_get_set_opt_type(type,r,func,free_func) \
+       if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+               V_ASN1_CONSTRUCTED|V_ASN1_SET)))\
+               { M_ASN1_D2I_get_set_type(type,r,func,free_func); }
+
+#define M_ASN1_I2D_len_SET_opt(a,f) \
+       if ((a != NULL) && (sk_num(a) != 0)) \
+               M_ASN1_I2D_len_SET(a,f);
+
+#define M_ASN1_I2D_put_SET_opt(a,f) \
+       if ((a != NULL) && (sk_num(a) != 0)) \
+               M_ASN1_I2D_put_SET(a,f);
+
+#define M_ASN1_I2D_put_SEQUENCE_opt(a,f) \
+       if ((a != NULL) && (sk_num(a) != 0)) \
+               M_ASN1_I2D_put_SEQUENCE(a,f);
+
+#define M_ASN1_I2D_put_SEQUENCE_opt_type(type,a,f) \
+       if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+               M_ASN1_I2D_put_SEQUENCE_type(type,a,f);
+
+#define M_ASN1_D2I_get_IMP_set_opt(b,func,free_func,tag) \
+       if ((c.slen != 0) && \
+               (M_ASN1_next == \
+               (V_ASN1_CONTEXT_SPECIFIC|V_ASN1_CONSTRUCTED|(tag))))\
+               { \
+               M_ASN1_D2I_get_imp_set(b,func,free_func,\
+                       tag,V_ASN1_CONTEXT_SPECIFIC); \
+               }
 
-#define M_ASN1_D2I_get_IMP_set_opt(b,func,tag) \
+#define M_ASN1_D2I_get_IMP_set_opt_type(type,b,func,free_func,tag) \
        if ((c.slen != 0) && \
                (M_ASN1_next == \
                (V_ASN1_CONTEXT_SPECIFIC|V_ASN1_CONSTRUCTED|(tag))))\
                { \
-               M_ASN1_D2I_get_imp_set(b,func,tag,V_ASN1_CONTEXT_SPECIFIC); \
+               M_ASN1_D2I_get_imp_set_type(type,b,func,free_func,\
+                       tag,V_ASN1_CONTEXT_SPECIFIC); \
                }
 
-#define M_ASN1_D2I_get_seq(r,func) \
-               M_ASN1_D2I_get_imp_set(r,func,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL);
+#define M_ASN1_D2I_get_seq(r,func,free_func) \
+               M_ASN1_D2I_get_imp_set(r,func,free_func,\
+                       V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL);
+
+#define M_ASN1_D2I_get_seq_type(type,r,func,free_func) \
+               M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,\
+                                           V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL)
 
-#define M_ASN1_D2I_get_seq_opt(r,func) \
+#define M_ASN1_D2I_get_seq_opt(r,func,free_func) \
        if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
                V_ASN1_CONSTRUCTED|V_ASN1_SEQUENCE)))\
-               { M_ASN1_D2I_get_seq(r,func); }
+               { M_ASN1_D2I_get_seq(r,func,free_func); }
 
-#define M_ASN1_D2I_get_IMP_set(r,func,x) \
-               M_ASN1_D2I_get_imp_set(r,func,x,V_ASN1_CONTEXT_SPECIFIC);
+#define M_ASN1_D2I_get_seq_opt_type(type,r,func,free_func) \
+       if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \
+               V_ASN1_CONSTRUCTED|V_ASN1_SEQUENCE)))\
+               { M_ASN1_D2I_get_seq_type(type,r,func,free_func); }
+
+#define M_ASN1_D2I_get_IMP_set(r,func,free_func,x) \
+               M_ASN1_D2I_get_imp_set(r,func,free_func,\
+                       x,V_ASN1_CONTEXT_SPECIFIC);
 
-#define M_ASN1_D2I_get_imp_set(r,func,a,b) \
+#define M_ASN1_D2I_get_IMP_set_type(type,r,func,free_func,x) \
+               M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,\
+                       x,V_ASN1_CONTEXT_SPECIFIC);
+
+#define M_ASN1_D2I_get_imp_set(r,func,free_func,a,b) \
        c.q=c.p; \
-       if (d2i_ASN1_SET(&(r),&c.p,c.slen,(char *(*)())func,a,b) == NULL) \
-               goto err; \
+       if (d2i_ASN1_SET(&(r),&c.p,c.slen,(char *(*)())func,\
+               (void (*)())free_func,a,b) == NULL) \
+               { c.line=__LINE__; goto err; } \
+       c.slen-=(c.p-c.q);
+
+#define M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,a,b) \
+       c.q=c.p; \
+       if (d2i_ASN1_SET_OF_##type(&(r),&c.p,c.slen,func,\
+                                  free_func,a,b) == NULL) \
+               { c.line=__LINE__; goto err; } \
        c.slen-=(c.p-c.q);
 
 #define M_ASN1_D2I_get_set_strings(r,func,a,b) \
        c.q=c.p; \
        if (d2i_ASN1_STRING_SET(&(r),&c.p,c.slen,a,b) == NULL) \
-               goto err; \
+               { c.line=__LINE__; goto err; } \
        c.slen-=(c.p-c.q);
 
 #define M_ASN1_D2I_get_EXP_opt(r,func,tag) \
@@ -169,13 +258,22 @@ err:\
                c.q=c.p; \
                Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
                if (Tinf & 0x80) \
-                       { c.error=ASN1_R_BAD_OBJECT_HEADER; goto err; } \
+                       { c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
+                       c.line=__LINE__; goto err; } \
+               if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
+                                       Tlen = c.slen - (c.p - c.q) - 2; \
                if (func(&(r),&c.p,Tlen) == NULL) \
-                       goto err; \
+                       { c.line=__LINE__; goto err; } \
+               if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
+                       Tlen = c.slen - (c.p - c.q); \
+                       if(!ASN1_check_infinite_end(&c.p, Tlen)) \
+                               { c.error=ERR_R_MISSING_ASN1_EOS; \
+                               c.line=__LINE__; goto err; } \
+               }\
                c.slen-=(c.p-c.q); \
                }
 
-#define M_ASN1_D2I_get_EXP_set_opt(r,func,tag,b) \
+#define M_ASN1_D2I_get_EXP_set_opt(r,func,free_func,tag,b) \
        if ((c.slen != 0) && (M_ASN1_next == \
                (V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \
                { \
@@ -185,24 +283,61 @@ err:\
                c.q=c.p; \
                Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
                if (Tinf & 0x80) \
-                       { c.error=ASN1_R_BAD_OBJECT_HEADER; goto err; } \
+                       { c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
+                       c.line=__LINE__; goto err; } \
+               if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
+                                       Tlen = c.slen - (c.p - c.q) - 2; \
                if (d2i_ASN1_SET(&(r),&c.p,Tlen,(char *(*)())func, \
+                       (void (*)())free_func, \
                        b,V_ASN1_UNIVERSAL) == NULL) \
-                       goto err; \
+                       { c.line=__LINE__; goto err; } \
+               if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
+                       Tlen = c.slen - (c.p - c.q); \
+                       if(!ASN1_check_infinite_end(&c.p, Tlen)) \
+                               { c.error=ERR_R_MISSING_ASN1_EOS; \
+                               c.line=__LINE__; goto err; } \
+               }\
+               c.slen-=(c.p-c.q); \
+               }
+
+#define M_ASN1_D2I_get_EXP_set_opt_type(type,r,func,free_func,tag,b) \
+       if ((c.slen != 0) && (M_ASN1_next == \
+               (V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \
+               { \
+               int Tinf,Ttag,Tclass; \
+               long Tlen; \
+               \
+               c.q=c.p; \
+               Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \
+               if (Tinf & 0x80) \
+                       { c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \
+                       c.line=__LINE__; goto err; } \
+               if (Tinf == (V_ASN1_CONSTRUCTED+1)) \
+                                       Tlen = c.slen - (c.p - c.q) - 2; \
+               if (d2i_ASN1_SET_OF_##type(&(r),&c.p,Tlen,func, \
+                       free_func,b,V_ASN1_UNIVERSAL) == NULL) \
+                       { c.line=__LINE__; goto err; } \
+               if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \
+                       Tlen = c.slen - (c.p - c.q); \
+                       if(!ASN1_check_infinite_end(&c.p, Tlen)) \
+                               { c.error=ERR_R_MISSING_ASN1_EOS; \
+                               c.line=__LINE__; goto err; } \
+               }\
                c.slen-=(c.p-c.q); \
                }
 
 /* New macros */
 #define M_ASN1_New_Malloc(ret,type) \
-       if ((ret=(type *)Malloc(sizeof(type))) == NULL) goto err2;
+       if ((ret=(type *)Malloc(sizeof(type))) == NULL) \
+               { c.line=__LINE__; goto err2; }
 
 #define M_ASN1_New(arg,func) \
        if (((arg)=func()) == NULL) return(NULL)
 
 #define M_ASN1_New_Error(a) \
-/*     err:    ASN1err((a),ASN1_R_ERROR_STACK); \
+/*     err:    ASN1_MAC_H_err((a),ERR_R_NESTED_ASN1_ERROR,c.line); \
                return(NULL);*/ \
-       err2:   ASN1err((a),ERR_R_MALLOC_FAILURE); \
+       err2:   ASN1_MAC_H_err((a),ERR_R_MALLOC_FAILURE,c.line); \
                return(NULL)
 
 
@@ -220,21 +355,59 @@ err:\
 #define M_ASN1_I2D_len_IMP_opt(a,f)    if (a != NULL) M_ASN1_I2D_len(a,f)
 
 #define M_ASN1_I2D_len_SET(a,f) \
-               ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SET,V_ASN1_UNIVERSAL);
+               ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET);
 
-#define M_ASN1_I2D_len_SEQ(a,f) \
-               ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL);
+#define M_ASN1_I2D_len_SET_type(type,a,f) \
+               ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,V_ASN1_SET, \
+                                           V_ASN1_UNIVERSAL,IS_SET);
 
-#define M_ASN1_I2D_len_SEQ_opt(a,f) \
+#define M_ASN1_I2D_len_SEQUENCE(a,f) \
+               ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL, \
+                                 IS_SEQUENCE);
+
+#define M_ASN1_I2D_len_SEQUENCE_type(type,a,f) \
+               ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,V_ASN1_SEQUENCE, \
+                                           V_ASN1_UNIVERSAL,IS_SEQUENCE)
+
+#define M_ASN1_I2D_len_SEQUENCE_opt(a,f) \
                if ((a != NULL) && (sk_num(a) != 0)) \
-                       M_ASN1_I2D_len_SEQ(a,f);
+                       M_ASN1_I2D_len_SEQUENCE(a,f);
+
+#define M_ASN1_I2D_len_SEQUENCE_opt_type(type,a,f) \
+               if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+                       M_ASN1_I2D_len_SEQUENCE_type(type,a,f);
 
-#define M_ASN1_I2D_len_IMP_set(a,f,x) \
-               ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC);
+#define M_ASN1_I2D_len_IMP_SET(a,f,x) \
+               ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC,IS_SET);
 
-#define M_ASN1_I2D_len_IMP_set_opt(a,f,x) \
+#define M_ASN1_I2D_len_IMP_SET_type(type,a,f,x) \
+               ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \
+                                           V_ASN1_CONTEXT_SPECIFIC,IS_SET);
+
+#define M_ASN1_I2D_len_IMP_SET_opt(a,f,x) \
                if ((a != NULL) && (sk_num(a) != 0)) \
-                       ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC);
+                       ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+                                         IS_SET);
+
+#define M_ASN1_I2D_len_IMP_SET_opt_type(type,a,f,x) \
+               if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+                       ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \
+                                              V_ASN1_CONTEXT_SPECIFIC,IS_SET);
+
+#define M_ASN1_I2D_len_IMP_SEQUENCE(a,f,x) \
+               ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+                                 IS_SEQUENCE);
+
+#define M_ASN1_I2D_len_IMP_SEQUENCE_opt(a,f,x) \
+               if ((a != NULL) && (sk_num(a) != 0)) \
+                       ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+                                         IS_SEQUENCE);
+
+#define M_ASN1_I2D_len_IMP_SEQUENCE_opt_type(type,a,f,x) \
+               if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+                       ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \
+                                                   V_ASN1_CONTEXT_SPECIFIC, \
+                                                   IS_SEQUENCE);
 
 #define M_ASN1_I2D_len_EXP_opt(a,f,mtag,v) \
                if (a != NULL)\
@@ -243,10 +416,27 @@ err:\
                        ret+=ASN1_object_size(1,v,mtag); \
                        }
 
-#define M_ASN1_I2D_len_EXP_set_opt(a,f,mtag,tag,v) \
+#define M_ASN1_I2D_len_EXP_SET_opt(a,f,mtag,tag,v) \
+               if ((a != NULL) && (sk_num(a) != 0))\
+                       { \
+                       v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL,IS_SET); \
+                       ret+=ASN1_object_size(1,v,mtag); \
+                       }
+
+#define M_ASN1_I2D_len_EXP_SEQUENCE_opt(a,f,mtag,tag,v) \
                if ((a != NULL) && (sk_num(a) != 0))\
                        { \
-                       v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL); \
+                       v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL, \
+                                      IS_SEQUENCE); \
+                       ret+=ASN1_object_size(1,v,mtag); \
+                       }
+
+#define M_ASN1_I2D_len_EXP_SEQUENCE_opt_type(type,a,f,mtag,tag,v) \
+               if ((a != NULL) && (sk_##type##_num(a) != 0))\
+                       { \
+                       v=i2d_ASN1_SET_OF_##type(a,NULL,f,tag, \
+                                                V_ASN1_UNIVERSAL, \
+                                                IS_SEQUENCE); \
                        ret+=ASN1_object_size(1,v,mtag); \
                        }
 
@@ -262,20 +452,48 @@ err:\
                        }
 
 #define M_ASN1_I2D_put_SET(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SET,\
-                       V_ASN1_UNIVERSAL)
-#define M_ASN1_I2D_put_IMP_set(a,f,x) i2d_ASN1_SET(a,&p,f,x,\
-                       V_ASN1_CONTEXT_SPECIFIC)
-
-#define M_ASN1_I2D_put_SEQ(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SEQUENCE,\
-                       V_ASN1_UNIVERSAL)
+                       V_ASN1_UNIVERSAL,IS_SET)
+#define M_ASN1_I2D_put_SET_type(type,a,f) \
+     i2d_ASN1_SET_OF_##type(a,&p,f,V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET)
+#define M_ASN1_I2D_put_IMP_SET(a,f,x) i2d_ASN1_SET(a,&p,f,x,\
+                       V_ASN1_CONTEXT_SPECIFIC,IS_SET)
+#define M_ASN1_I2D_put_IMP_SET_type(type,a,f,x) \
+     i2d_ASN1_SET_OF_##type(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC,IS_SET)
+#define M_ASN1_I2D_put_IMP_SEQUENCE(a,f,x) i2d_ASN1_SET(a,&p,f,x,\
+                       V_ASN1_CONTEXT_SPECIFIC,IS_SEQUENCE)
+
+#define M_ASN1_I2D_put_SEQUENCE(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SEQUENCE,\
+                                            V_ASN1_UNIVERSAL,IS_SEQUENCE)
+
+#define M_ASN1_I2D_put_SEQUENCE_type(type,a,f) \
+     i2d_ASN1_SET_OF_##type(a,&p,f,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL, \
+                           IS_SEQUENCE)
+
+#define M_ASN1_I2D_put_SEQUENCE_opt(a,f) \
+               if ((a != NULL) && (sk_num(a) != 0)) \
+                       M_ASN1_I2D_put_SEQUENCE(a,f);
 
-#define M_ASN1_I2D_put_SEQ_opt(a,f) \
+#define M_ASN1_I2D_put_IMP_SET_opt(a,f,x) \
                if ((a != NULL) && (sk_num(a) != 0)) \
-                       M_ASN1_I2D_put_SEQ(a,f);
+                       { i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+                                      IS_SET); }
+
+#define M_ASN1_I2D_put_IMP_SET_opt_type(type,a,f,x) \
+               if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+                       { i2d_ASN1_SET_OF_##type(a,&p,f,x, \
+                                                V_ASN1_CONTEXT_SPECIFIC, \
+                                                IS_SET); }
 
-#define M_ASN1_I2D_put_IMP_set_opt(a,f,x) \
+#define M_ASN1_I2D_put_IMP_SEQUENCE_opt(a,f,x) \
                if ((a != NULL) && (sk_num(a) != 0)) \
-                       { i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC); }
+                       { i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC, \
+                                      IS_SEQUENCE); }
+
+#define M_ASN1_I2D_put_IMP_SEQUENCE_opt_type(type,a,f,x) \
+               if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+                       { i2d_ASN1_SET_OF_##type(a,&p,f,x, \
+                                                V_ASN1_CONTEXT_SPECIFIC, \
+                                                IS_SEQUENCE); }
 
 #define M_ASN1_I2D_put_EXP_opt(a,f,tag,v) \
                if (a != NULL) \
@@ -284,11 +502,26 @@ err:\
                        f(a,&p); \
                        }
 
-#define M_ASN1_I2D_put_EXP_set_opt(a,f,mtag,tag,v) \
+#define M_ASN1_I2D_put_EXP_SET_opt(a,f,mtag,tag,v) \
                if ((a != NULL) && (sk_num(a) != 0)) \
                        { \
                        ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
-                       i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL); \
+                       i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL,IS_SET); \
+                       }
+
+#define M_ASN1_I2D_put_EXP_SEQUENCE_opt(a,f,mtag,tag,v) \
+               if ((a != NULL) && (sk_num(a) != 0)) \
+                       { \
+                       ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
+                       i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL,IS_SEQUENCE); \
+                       }
+
+#define M_ASN1_I2D_put_EXP_SEQUENCE_opt_type(type,a,f,mtag,tag,v) \
+               if ((a != NULL) && (sk_##type##_num(a) != 0)) \
+                       { \
+                       ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
+                       i2d_ASN1_SET_OF_##type(a,&p,f,tag,V_ASN1_UNIVERSAL, \
+                                              IS_SEQUENCE); \
                        }
 
 #define M_ASN1_I2D_seq_total() \
@@ -306,14 +539,8 @@ err:\
 #define M_ASN1_I2D_finish()    *pp=p; \
                                return(r);
 
-#ifndef NOPROTO
 int asn1_GetSequence(ASN1_CTX *c, long *length);
 void asn1_add_error(unsigned char *address,int offset);
-#else 
-int asn1_GetSequence();
-void asn1_add_error();
-#endif
-
 #ifdef  __cplusplus
 }
 #endif