libqaeda

Unnamed repository; edit this file 'description' to name the repository.
Info | Log | Files | Refs | README | LICENSE

envelope.c (5107B)


      1 #include <stddef.h>
      2 
      3 #include <libtasn1.h>
      4 #include <llog.h>
      5 #include <lq/envelope.h>
      6 #include <lq/cert.h>
      7 #include <lq/mem.h>
      8 #include <lq/err.h>
      9 #include <debug.h>
     10 
     11 
     12 extern asn1_node asn;
     13 
     14 static struct lq_attach *lq_attach_new() {
     15 	struct lq_attach *o;
     16        
     17 	o = lq_alloc(sizeof(struct lq_attach));
     18 	if (o == NULL) {
     19 		return o;
     20 	}
     21 	lq_zero(o, sizeof(struct lq_attach));
     22 	return o;
     23 }
     24 
     25 static struct lq_attach *lq_attach_add(struct lq_attach *attach, const char *data, size_t data_len) {
     26 	attach->len = data_len;
     27 	attach->data = lq_alloc(data_len);
     28 	lq_cpy(attach->data, data, data_len);
     29 	attach->next = lq_alloc(sizeof(struct lq_attach));
     30 	lq_zero(attach->next, sizeof(struct lq_attach));
     31 	return attach->next;
     32 }
     33 
     34 static int lq_envelope_get(struct lq_envelope *env, char *out, size_t *out_len) {
     35 	struct lq_attach *attach;
     36 
     37 	attach = env->attach_start;
     38 	if (attach == NULL) {
     39 		return ERR_NOENT;
     40 	}
     41 	lq_cpy(out, attach->data, attach->len);
     42 	*out_len = attach->len;
     43 	lq_free(attach->data);
     44 	if (attach->next == NULL) {
     45 		return ERR_NOENT;
     46 	}
     47 	env->attach_start = attach->next;
     48 	lq_free(attach);
     49 	return ERR_OK;
     50 }
     51 
     52 static void lq_attach_free(struct lq_attach *attach) {
     53 	if (attach->next != NULL) {
     54 		lq_attach_free(attach->next);
     55 	}
     56 	lq_free(attach->data);
     57 	lq_free(attach);
     58 }
     59 
     60 LQEnvelope *lq_envelope_new(LQCert *cert, int hint) {
     61 	LQEnvelope *env;
     62 
     63 	env = lq_alloc(sizeof(LQEnvelope));
     64 	env->hint = hint;
     65 	env->cert = cert;
     66 	env->attach_start = lq_attach_new();
     67 	env->attach_cur = env->attach_start;
     68 
     69 	return env;
     70 }
     71 
     72 int lq_envelope_attach(LQEnvelope *env, const char *data, size_t data_len) {
     73 	struct lq_attach *attach;
     74 
     75 	attach = lq_attach_add(env->attach_cur, data, data_len);
     76 	if (attach == NULL) {
     77 		return ERR_FAIL;
     78 	}
     79 	env->attach_cur = attach;
     80 
     81 	return ERR_OK;
     82 }
     83 
     84 // TODO: DRY
     85 static int asn_except(asn1_node *node, int err) {
     86 	int r;
     87 
     88 	r = asn1_delete_structure(node);
     89 	if (r != ASN1_SUCCESS) {
     90 		debug_logerr(LLOG_ERROR, ERR_FAIL, (char*)asn1_strerror(err));
     91 	}
     92 
     93 	return err;
     94 }
     95 
     96 int lq_envelope_serialize(LQEnvelope *env, LQResolve *resolve, char *out, size_t *out_len) {
     97 	size_t c;
     98 	int mx;
     99 	int r;
    100 	int hint;
    101 	char err[LQ_ERRSIZE];
    102 	char buf[LQ_BLOCKSIZE];
    103 	asn1_node item;
    104 
    105 	mx = *out_len;
    106 	*out_len = 0;
    107 	lq_zero(&item, sizeof(item));
    108 
    109 	r = asn1_create_element(asn, "Qaeda", &item);
    110 	if (r != ASN1_SUCCESS) {
    111 		return ERR_READ;
    112 	}
    113 
    114 	hint = env->hint;
    115 	r = to_endian(TO_ENDIAN_BIG, sizeof(int), &hint);
    116 	if (r) {
    117 		return asn_except(&item, ERR_BYTEORDER);
    118 	}
    119 	c = sizeof(int);
    120 	r = asn1_write_value(item, "Envelope.hint", &hint, c);
    121 	if (r != ASN1_SUCCESS) {
    122 		return asn_except(&item, ERR_WRITE);
    123 	}
    124 
    125 	c = mx - sizeof(int);
    126 	r = lq_certificate_serialize(env->cert, resolve, buf, &c);
    127 	if (r != ERR_OK) {
    128 		return asn_except(&item, r);
    129 	}
    130 	*out_len += c;
    131 	if (*out_len > mx) {
    132 		return asn_except(&item, ERR_OVERFLOW);
    133 	}
    134 	r = asn1_write_value(item, "Envelope.cert", buf, c);
    135 	if (r != ASN1_SUCCESS) {
    136 		return asn_except(&item, ERR_WRITE);
    137 	}
    138 
    139 	while(1) {
    140 		c = LQ_BLOCKSIZE;
    141 		r = lq_envelope_get(env, buf, &c);
    142 		if (r) {
    143 			break;
    144 		}
    145 		r = asn1_write_value(item, "Envelope.attach", "NEW", 1);
    146 		if (r != ASN1_SUCCESS) {
    147 			return asn_except(&item, ERR_WRITE);
    148 		}
    149 		r = asn1_write_value(item, "Envelope.attach.?LAST", buf, c);
    150 		if (r != ASN1_SUCCESS) {
    151 			return asn_except(&item, ERR_WRITE);
    152 		}
    153 	}	
    154 
    155 	*out_len = mx;
    156 	r = asn1_der_coding(item, "Envelope", out, (int*)out_len, err);
    157 	if (r != ASN1_SUCCESS) {
    158 		return asn_except(&item, ERR_ENCODING);
    159 	}
    160 
    161 	r = asn1_delete_structure(&item);
    162 	if (r != ASN1_SUCCESS) {
    163 		return ERR_FAIL;
    164 	}
    165 
    166 	return ERR_OK;
    167 }
    168 
    169 int lq_envelope_deserialize(LQEnvelope **env, LQResolve *resolve, const char *in, size_t in_len) {
    170 	int c;
    171 	int r;
    172 	int i;
    173 	char err[LQ_ERRSIZE];
    174 	char tmp[LQ_BLOCKSIZE];
    175 	char node_seq_name[32];
    176 	int hint;
    177 	char *p;
    178 	LQCert *cert;
    179 	asn1_node item;
    180 
    181 	r = asn1_create_element(asn, "Qaeda.Envelope", &item);
    182 	if (r != ASN1_SUCCESS) {
    183 		return ERR_READ;
    184 	}
    185 
    186 	r = asn1_der_decoding(&item, in, in_len, err);
    187 	if (r != ASN1_SUCCESS) {
    188 		return asn_except(&item, ERR_ENCODING);
    189 	}
    190 
    191 	hint = 0;
    192 	c = sizeof(int);
    193 	r = asn1_read_value(item, "hint", &hint, &c);
    194 	if (r != ASN1_SUCCESS) {
    195 		return asn_except(&item, ERR_READ);
    196 	}
    197 	hint <<= ((sizeof(int) - c) * 8);
    198 	if (is_le()) {
    199 		flip_endian(sizeof(int), (char*)(&hint));
    200 	}
    201 
    202 	c = LQ_BLOCKSIZE;
    203 	r = asn1_read_value(item, "cert", tmp, &c);
    204 	if (r != ASN1_SUCCESS) {
    205 		return asn_except(&item, ERR_READ);
    206 	}
    207 	r = lq_certificate_deserialize(&cert, resolve, tmp, c);
    208 	if (r != ERR_OK) {
    209 		return asn_except(&item, r);
    210 	}
    211 
    212 	*env = lq_envelope_new(cert, hint);
    213 
    214 	i = 0;
    215 	while(++i) {
    216 		c = LQ_BLOCKSIZE;
    217 		sprintf(node_seq_name, "attach.?%i", i);
    218 		r = asn1_read_value(item, node_seq_name, tmp, &c);
    219 		if (r != ASN1_SUCCESS) {
    220 			break;
    221 		}
    222 		r = lq_envelope_attach(*env, tmp, c);
    223 		if (r != ERR_OK) {
    224 			lq_envelope_free(*env);
    225 			return ERR_FAIL;
    226 		}
    227 	}
    228 
    229 	r = asn1_delete_structure(&item);
    230 	if (r != ASN1_SUCCESS) {
    231 		return ERR_FAIL;
    232 	}
    233 
    234 	return ERR_OK;
    235 }
    236 
    237 void lq_envelope_free(LQEnvelope *env) {
    238 	lq_attach_free(env->attach_start);
    239 	lq_certificate_free(env->cert);
    240 	lq_free(env);
    241 }