+void dipe_encrypt(dipe_param_t param, dipe_master_publickey_t mpk, element_t* x, size_t ptxt_len, char* ptxt, size_t ctxt_len, char* ctxt) {
+ element_t key;
+ uint8_t aes[32];
+ dipe_ctxt_t cap;
+ size_t cap_len;
+
+ element_init_GT(key, param->pairing);
+ element_random(key);
+ dipe_generate_aeskey(key, aes);
+ dipe_encap(param, mpk, x, key, &cap);
+ cap_len = dipe_serialize_ctxt(param, cap, (uint8_t*)ctxt);
+ ctxt += cap_len; ctxt_len -= cap_len;
+
+ dipe_aes_encrypt(aes, ptxt_len, (uint8_t*)ptxt, ctxt_len, (uint8_t*)ctxt);
+
+ dipe_free_ctxt(cap);
+ element_clear(key);
+}
+
+size_t dipe_decrypt(dipe_param_t param, dipe_secretkey_t sk, char* cid, element_t* y, size_t ctxt_len, char* ctxt, char* ptxt) {
+ dipe_ctxt_t cap;
+ uint8_t aes[32];
+ element_t key;
+ size_t cap_len;
+
+ element_init_GT(key, param->pairing);
+ cap_len = dipe_deserialize_ctxt(param, sk->dimension, &cap, (uint8_t*)ctxt);
+ ctxt += cap_len;
+ ctxt_len -= cap_len;
+ dipe_decap(param, sk, cid, y, cap, key);
+ dipe_generate_aeskey(key, aes);
+
+ dipe_free_ctxt(cap);
+ element_clear(key);
+
+ return dipe_aes_decrypt(aes, ctxt_len, (uint8_t*)ctxt, (uint8_t*)ptxt);
+}
+
+/* Note: we're generating random-looking bytes here. Therefore we
+ * can't encode the dimension of the predicate vector (supposed to be
+ * set as system parameter) or information about the secret sharing
+ * (needs to be retrieved by some sort of trial decryption).
+ */
+size_t dipe_serialize_ctxt(__attribute__((unused)) dipe_param_t param, dipe_ctxt_t ctxt, uint8_t* buffer) {
+ size_t bytes_written = 0;
+ element_to_bytes_compressed(buffer, ctxt->s);
+ buffer += element_length_in_bytes_compressed(ctxt->s);
+ bytes_written += element_length_in_bytes_compressed(ctxt->s);
+
+ for (size_t i = 0; i < ctxt->dimension; ++i) {
+ element_to_bytes_compressed(buffer, ctxt->cx[i]);
+ buffer += element_length_in_bytes_compressed(ctxt->cx[i]);
+ bytes_written += element_length_in_bytes_compressed(ctxt->cx[i]);
+ }
+
+ element_to_bytes(buffer, ctxt->c);
+ buffer += element_length_in_bytes(ctxt->c);
+ bytes_written += element_length_in_bytes(ctxt->c);
+
+ return bytes_written;
+}
+
+size_t dipe_deserialize_ctxt(dipe_param_t param, size_t dimension, dipe_ctxt_t* ctxt, uint8_t* buffer) {
+ size_t bytes_read = 0;
+ *ctxt = (dipe_ctxt_t)malloc(sizeof(dipe_ctxt));
+ (*ctxt)->dimension = dimension;
+
+ element_init_G1((*ctxt)->s, param->pairing);
+ element_from_bytes_compressed((*ctxt)->s, buffer);
+ buffer += element_length_in_bytes_compressed((*ctxt)->s);
+ bytes_read += element_length_in_bytes_compressed((*ctxt)->s);
+
+ (*ctxt)->cx = (element_t*)calloc(dimension, sizeof(element_t));
+ for (size_t i = 0; i < dimension; ++i) {
+ element_init_G1((*ctxt)->cx[i], param->pairing);
+ element_from_bytes_compressed((*ctxt)->cx[i], buffer);
+ buffer += element_length_in_bytes_compressed((*ctxt)->cx[i]);
+ bytes_read += element_length_in_bytes_compressed((*ctxt)->cx[i]);
+ }
+
+ element_init_GT((*ctxt)->c, param->pairing);
+ element_from_bytes((*ctxt)->c, buffer);
+ buffer += element_length_in_bytes((*ctxt)->c);
+ bytes_read += element_length_in_bytes((*ctxt)->c);
+
+ return bytes_read;
+}
+
+size_t dipe_ciphertext_overhead(dipe_param_t param, size_t dimension) {
+ size_t overhead = 12 + 16 + 4 /* IV + Tag + Size */;
+ element_t t;
+
+ element_init_G1(t, param->pairing);
+ overhead += element_length_in_bytes_compressed(t);
+ overhead += dimension * element_length_in_bytes_compressed(t);
+ element_clear(t);
+ element_init_GT(t, param->pairing);
+ overhead += element_length_in_bytes(t);
+ element_clear(t);
+
+ return overhead;
+}