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 }