msg.c (4692B)
1 #include <stddef.h> 2 #include <time.h> 3 #include <libtasn1.h> 4 5 #include "lq/msg.h" 6 #include "lq/mem.h" 7 #include "lq/err.h" 8 #include "lq/crypto.h" 9 #include "lq/wire.h" 10 #include "lq/store.h" 11 #include "endian.h" 12 13 static char zeros[LQ_PUBKEY_LEN]; 14 static LQPubKey nokey = { 15 .pk = NULL, 16 .impl = zeros, 17 }; 18 19 LQMsg* lq_msg_new(const char *msg_data, size_t msg_len) { 20 LQMsg *msg; 21 22 msg = lq_alloc(sizeof(LQMsg)); 23 lq_zero(msg, sizeof(LQMsg)); 24 clock_gettime(CLOCK_REALTIME, &msg->time); 25 26 msg->data = lq_alloc(msg_len); 27 lq_cpy(msg->data, msg_data, msg_len); 28 msg->len = msg_len; 29 30 return msg; 31 } 32 33 LQSig* lq_msg_sign(LQMsg *msg, LQPrivKey *pk, const char *salt) { 34 return lq_msg_sign_extra(msg, pk, salt, NULL, 0); 35 } 36 37 LQSig* lq_msg_sign_extra(LQMsg *msg, LQPrivKey *pk, const char *salt, const char *extra, size_t extra_len) { 38 int l; 39 int r; 40 char *data; 41 char digest[LQ_DIGEST_LEN]; 42 43 if (extra == NULL) { 44 extra_len = 0; 45 } 46 l = msg->len + extra_len; 47 data = lq_alloc(l); 48 if (extra_len > 0) { 49 lq_cpy(data, extra, extra_len); 50 } 51 lq_cpy(data + extra_len, msg->data, msg->len); 52 msg->pubkey = lq_publickey_from_privatekey(pk); 53 54 r = lq_digest(data, l, (char*)digest); 55 if (r != ERR_OK) { 56 return NULL; 57 } 58 return lq_privatekey_sign(pk, digest, LQ_DIGEST_LEN, salt); 59 } 60 61 void lq_msg_free(LQMsg *msg) { 62 if (msg->pubkey->pk = NULL) { 63 lq_free(msg->pubkey); 64 } 65 lq_free(msg->data); 66 lq_free(msg); 67 } 68 69 int lq_msg_serialize(LQMsg *msg, char *out, size_t *out_len, LQResolve *resolve) { 70 size_t c; 71 int r; 72 size_t mx; 73 char tmp[LQ_DIGEST_LEN]; 74 char timedata[8]; 75 char err[1024]; 76 LQPubKey *pubkey; 77 LQResolve *resolve_active; 78 asn1_node node; 79 char *keydata; 80 81 mx = *out_len; 82 *out_len = 0; 83 lq_set(&node, 0, sizeof(node)); 84 r = asn1_array2tree(defs_asn1_tab, &node, err); 85 if (r != ASN1_SUCCESS) { 86 return ERR_INIT; 87 } 88 89 c = LQ_DIGEST_LEN; 90 *out_len += c; 91 if (*out_len > mx) { 92 return ERR_OVERFLOW; 93 } 94 r = lq_digest(msg->data, msg->len, tmp); 95 if (r != ERR_OK) { 96 return r; 97 } 98 99 resolve_active = resolve; 100 while (resolve_active != NULL) { 101 r = resolve_active->store->put(LQ_CONTENT_MSG, resolve_active->store, tmp, &c, msg->data, msg->len); 102 if (r != ERR_OK) { 103 return r; 104 } 105 resolve_active = resolve_active->next; 106 } 107 108 r = asn1_write_value(node, "Qaeda.Msg.data", tmp, c); 109 if (r != ASN1_SUCCESS) { 110 return ERR_WRITE; 111 } 112 113 lq_cpy(timedata, &msg->time.tv_sec, 4); 114 lq_cpy(((char*)timedata)+4, &msg->time.tv_nsec, 4); 115 r = to_endian(TO_ENDIAN_BIG, 4, timedata); 116 if (r) { 117 return ERR_BYTEORDER; 118 } 119 r = to_endian(TO_ENDIAN_BIG, 4, ((char*)timedata)+4); 120 if (r) { 121 return ERR_BYTEORDER; 122 } 123 124 c = sizeof(int); 125 *out_len += c; 126 if (*out_len > mx) { 127 return ERR_OVERFLOW; 128 } 129 r = asn1_write_value(node, "Qaeda.Msg.timestamp", &timedata, c); 130 if (r != ASN1_SUCCESS) { 131 return ERR_WRITE; 132 } 133 134 pubkey = msg->pubkey; 135 if (pubkey == NULL) { 136 pubkey = &nokey; 137 } 138 c = lq_publickey_bytes(pubkey, &keydata); 139 *out_len += c; 140 if (*out_len > mx) { 141 return ERR_OVERFLOW; 142 } 143 r = asn1_write_value(node, "Qaeda.Msg.pubkey", keydata, c); 144 if (r != ASN1_SUCCESS) { 145 return ERR_WRITE; 146 } 147 148 *out_len = mx; 149 r = asn1_der_coding(node, "Qaeda.Msg", out, (int*)out_len, err); 150 if (r != ASN1_SUCCESS) { 151 return ERR_ENCODING; 152 } 153 154 return ERR_OK; 155 } 156 157 int lq_msg_deserialize(LQMsg **msg, const char *in, size_t in_len, LQResolve *resolve) { 158 int r; 159 size_t c; 160 char err[1024]; 161 char z[LQ_DIGEST_LEN]; 162 char tmp[1024]; 163 asn1_node node; 164 asn1_node item; 165 LQResolve *resolve_active; 166 167 lq_zero(&node, sizeof(node)); 168 lq_zero(&item, sizeof(item)); 169 r = asn1_array2tree(defs_asn1_tab, &node, err); 170 if (r != ASN1_SUCCESS) { 171 return ERR_INIT; 172 } 173 174 r = asn1_create_element(node, "Qaeda.Msg", &item); 175 if (r != ASN1_SUCCESS) { 176 return ERR_READ; 177 } 178 179 r = asn1_der_decoding(&item, in, in_len, err); 180 if (r != ASN1_SUCCESS) { 181 return ERR_ENCODING; 182 } 183 184 c = LQ_DIGEST_LEN; 185 r = asn1_read_value(item, "data", z, (int*)&c); 186 if (r != ASN1_SUCCESS) { 187 return ERR_READ; 188 } 189 c = 1024; 190 resolve_active = resolve; 191 while (resolve_active != NULL) { 192 r = resolve_active->store->get(LQ_CONTENT_MSG, resolve_active->store, z, LQ_DIGEST_LEN, tmp, &c); 193 if (r != ERR_OK) { 194 return r; 195 } 196 resolve_active = resolve_active->next; 197 } 198 199 *msg = lq_msg_new((const char*)tmp, c); 200 201 /// \todo document timestamp size 202 c = 8; 203 r = asn1_read_value(item, "timestamp", tmp, (int*)&c); 204 if (r != ASN1_SUCCESS) { 205 return ERR_READ; 206 } 207 if (is_le()) { 208 flip_endian(4, (char*)tmp); 209 flip_endian(4, ((char*)tmp)+4); 210 } 211 lq_cpy(&((*msg)->time.tv_sec), tmp, 4); 212 lq_cpy(&((*msg)->time.tv_nsec), ((char*)tmp)+4, 4); 213 214 c = 65; 215 r = asn1_read_value(item, "pubkey", tmp, (int*)&c); 216 if (r != ASN1_SUCCESS) { 217 return ERR_READ; 218 } 219 220 return ERR_OK; 221 }