#ifndef HEADER_ASN1_MAC_H #define HEADER_ASN1_MAC_H #include "asn1.h" #ifdef __cplusplus extern "C" { #endif #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), __FILE__, (line)) #define M_ASN1_D2I_vars(a, type, func) \ ASN1_const_CTX c; \ type ret = NULL; \ \ c.pp = (const unsigned char **)pp; \ c.q = *(const unsigned char **)pp; \ c.error = ERR_R_NESTED_ASN1_ERROR; \ if ((a == NULL) || ((*a) == NULL)) { \ if ((ret = (type)func()) == NULL) { \ c.line = __LINE__; \ goto err; \ } \ } else \ ret = (*a); #define M_ASN1_D2I_Init() \ c.p = *(const unsigned char **)pp; \ c.max = (length == 0) ? 0 : (c.p + length); #define M_ASN1_D2I_Finish_2(a) \ if (!asn1_const_Finish(&c)) { \ c.line = __LINE__; \ goto err; \ } \ *(const unsigned char **)pp = c.p; \ if (a != NULL) \ (*a) = ret; \ return (ret); #define M_ASN1_D2I_Finish(a, func, e) \ M_ASN1_D2I_Finish_2(a); \ err: \ ASN1_MAC_H_err((e), c.error, c.line); \ asn1_add_error(*(const unsigned char **)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)) { \ c.line = __LINE__; \ goto err; \ } /* Begin reading ASN1 without a surrounding sequence */ #define M_ASN1_D2I_begin() c.slen = length; /* End reading ASN1 with no check on length */ #define M_ASN1_D2I_Finish_nolen(a, func, e) \ *pp = c.p; \ if (a != NULL) \ (*a) = ret; \ return (ret); \ err: \ 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_end_sequence() \ (((c.inf & 1) == 0) ? \ (c.slen <= 0) : \ (c.eos = ASN1_const_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) { \ c.line = __LINE__; \ goto err; \ } \ c.slen -= (c.p - c.q); /* Don't use this with d2i_ASN1_BOOLEAN() */ #define M_ASN1_D2I_get_x(type, b, func) \ c.q = c.p; \ if (((D2I_OF(type))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) \ if ((c.slen != 0) && ((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) == \ (V_ASN1_UNIVERSAL | (type)))) { \ 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 = M_ASN1_next; \ M_ASN1_D2I_get_imp(b, func, type); \ } #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_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_type(type, b, func, free_func, tag, \ V_ASN1_CONTEXT_SPECIFIC); \ } #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, 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, free_func); \ } #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_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, \ (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) { \ c.line = __LINE__; \ goto err; \ } \ c.slen -= (c.p - c.q); #define M_ASN1_D2I_get_EXP_opt(r, func, tag) \ if ((c.slen != 0L) && \ (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 (func(&(r), &c.p, Tlen) == NULL) { \ c.line = __LINE__; \ goto err; \ } \ if (Tinf == (V_ASN1_CONSTRUCTED + 1)) { \ Tlen = c.slen - (c.p - c.q); \ if (!ASN1_const_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, 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(&(r), &c.p, Tlen, (char *(*)())func, \ (void (*)())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); \ } #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 *)OPENSSL_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: ASN1_MAC_H_err((a),ERR_R_NESTED_ASN1_ERROR,c.line); \ return(NULL);*/ \ err2: \ ASN1_MAC_H_err((a), ERR_R_MALLOC_FAILURE, c.line); \ return (NULL) /* BIG UGLY WARNING! This is so damn ugly I wanna puke. Unfortunately, some macros that use ASN1_const_CTX still insist on writing in the input stream. ARGH! ARGH! ARGH! Let's get rid of this macro package. Please? -- Richard Levitte */ #define M_ASN1_next (*((unsigned char *)(c.p))) #define M_ASN1_next_prev (*((unsigned char *)(c.q))) /*************************************************/ #define M_ASN1_I2D_vars(a) \ int r = 0, ret = 0; \ unsigned char *p; \ if (a == NULL) \ return (0) /* Length Macros */ #define M_ASN1_I2D_len(a, f) ret += f(a, NULL) #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, IS_SET); #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_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_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, IS_SET); #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, \ 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) { \ v = f(a, NULL); \ ret += ASN1_object_size(1, v, mtag); \ } #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, \ 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); \ } /* Put Macros */ #define M_ASN1_I2D_put(a, f) f(a, &p) #define M_ASN1_I2D_put_IMP_opt(a, f, t) \ if (a != NULL) { \ unsigned char *q = p; \ f(a, &p); \ *q = (V_ASN1_CONTEXT_SPECIFIC | t | \ (*q & V_ASN1_CONSTRUCTED)); \ } #define M_ASN1_I2D_put_SET(a, f) \ i2d_ASN1_SET(a, &p, f, V_ASN1_SET, 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_IMP_SET_opt(a, f, x) \ if ((a != NULL) && (sk_num(a) != 0)) { \ 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_SEQUENCE_opt(a, f, x) \ if ((a != NULL) && (sk_num(a) != 0)) { \ 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) { \ ASN1_put_object(&p, 1, v, tag, V_ASN1_CONTEXT_SPECIFIC); \ f(a, &p); \ } #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, 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() \ r = ASN1_object_size(1, ret, V_ASN1_SEQUENCE); \ if (pp == NULL) \ return (r); \ p = *pp; \ ASN1_put_object(&p, 1, ret, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL) #define M_ASN1_I2D_INF_seq_start(tag, ctx) \ *(p++) = (V_ASN1_CONSTRUCTED | (tag) | (ctx)); \ *(p++) = 0x80 #define M_ASN1_I2D_INF_seq_end() \ *(p++) = 0x00; \ *(p++) = 0x00 #define M_ASN1_I2D_finish() \ *pp = p; \ return (r); int asn1_GetSequence(ASN1_const_CTX *c, long *length); void asn1_add_error(const unsigned char *address, int offset); #ifdef __cplusplus } #endif #endif