aboutsummaryrefslogtreecommitdiff
path: root/helper.c
blob: b909707f5cb87a0b63a928475181796bde20939c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/* Functions to help with certificate generation (untrusted). */

/* Some of the certificate generation routines require multiple other
 * certificates to function. This file provides various helper
 * functions to handle the generation of these needed certificates. */

#include <assert.h>
#include <stdlib.h>

#include "crypto.h"
#include "trusted_module.h"

struct tm_cert cert_ru(const struct trusted_module *tm,
                       struct iomt_node node, hash_t new_val,
                       const hash_t *comp, const int *orders, size_t n,
                       hash_t *hmac_out)
{
    struct iomt_node new_node = node;
    new_node.val = new_val;
    hash_t nu_hmac;
    struct tm_cert nu = tm_cert_node_update(tm,
                                            hash_node(node),
                                            hash_node(new_node),
                                            comp, orders, n,
                                            &nu_hmac);

    return tm_cert_record_update(tm, &nu, nu_hmac, node, new_val, hmac_out);
}

struct tm_cert cert_rv(const struct trusted_module *tm,
                       struct iomt_node node,
                       const hash_t *comp, const int *orders, size_t n,
                       hash_t *hmac_out,
                       uint64_t b,
                       struct tm_cert *nonexist, hash_t *hmac_nonexist)
{
    hash_t nu_hmac;
    struct tm_cert nu = tm_cert_node_update(tm,
                                            hash_node(node),
                                            hash_node(node),
                                            comp, orders, n,
                                            &nu_hmac);

    return tm_cert_record_verify(tm,
                                 &nu, nu_hmac,
                                 node,
                                 hmac_out,
                                 b, nonexist, hmac_nonexist);
}

struct tm_cert cert_rv_by_idx(const struct trusted_module *tm,
                              const struct iomt *tree,
                              uint64_t idx,
                              hash_t *hmac_out)
{
    uint64_t leafidx;
    struct iomt_node node = iomt_find_leaf_or_encloser(tree, idx, &leafidx);

    if(!node.idx)
        return cert_null;

    /* find the complement */
    int *orders;
    hash_t *comp = merkle_complement(tree, leafidx, &orders);

    struct tm_cert cert;

    if(idx == node.idx)
    {
        /* node exists */
        cert = cert_rv(tm,
                       node,
                       comp, orders, tree->mt_logleaves,
                       hmac_out,
                       0, NULL, NULL);
    }
    else
    {
        /* We have an encloser node, indicating that the requested
         * node does not exist. */
        cert_rv(tm,
                node,
                comp, orders, tree->mt_logleaves,
                NULL,
                idx,
                &cert, hmac_out);
    }

    free(comp);
    free(orders);

    return cert;
}

/* Fill out a tm_request struct to create a file with the index
 * given in file_node->idx with the user added with level 3 access in
 * the ACL. */
struct tm_request req_filecreate(const struct trusted_module *tm,
                                 uint64_t user_id,
                                 struct iomt_node file_node,
                                 const hash_t *file_comp, const int *file_orders, size_t file_n)
{
    /* construct a request to create a file */
    struct tm_request req = req_null;
    req.idx = file_node.idx;
    req.user_id = user_id;
    req.type = ACL_UPDATE;
    req.counter = 0;

    /* construct ACL with a single element (the user, with full access) */
    struct iomt_node acl_node = (struct iomt_node) { user_id, user_id, u64_to_hash(3) };
    req.val = merkle_compute(hash_node(acl_node), NULL, NULL, 0);

    hash_t one = u64_to_hash(1);

    hash_t ru_hmac;

    /* we need a RU certificate of the form [f, 0, root, 1, new root],
     * which requires a NU certificate of the form [v, root, v', new
     * root], where v=h(original IOMT node) and v'=h(new IOMT node) */
    struct tm_cert ru = cert_ru(tm,
                                file_node, one,
                                file_comp, file_orders, file_n,
                                &ru_hmac);

    req.create.ru_cert = ru;
    req.create.ru_hmac = ru_hmac;

    return req;
}

/* Fill out a tm_request struct to modify an existing file's
 * contents, given the previously generated FR certificate, and the
 * ACL node giving the user's access rights. */
struct tm_request req_filemodify(const struct trusted_module *tm,
                                 const struct tm_cert *fr_cert, hash_t fr_hmac,
                                 struct iomt_node file_node,
                                 const hash_t *file_comp, const int *file_orders, size_t file_n,
                                 struct iomt_node acl_node,
                                 const hash_t *acl_comp, const int *acl_orders, size_t acl_n,
                                 hash_t fileval)
{
    /* modification */
    struct tm_request req = req_null;
    req.type = FILE_UPDATE;

    req.idx = file_node.idx;
    req.counter = hash_to_u64(file_node.val);

    req.user_id = acl_node.idx;

    req.modify.fr_cert = *fr_cert;
    req.modify.fr_hmac = fr_hmac;

    req.modify.rv_cert = cert_rv(tm,
                                 acl_node,
                                 acl_comp, acl_orders, acl_n,
                                 &req.modify.rv_hmac,
                                 0, NULL, NULL);

    hash_t next_counter = u64_to_hash(req.counter + 1);

    req.modify.ru_cert = cert_ru(tm, file_node, next_counter,
                                 file_comp, file_orders, file_n,
                                 &req.modify.ru_hmac);
    req.val = fileval;

    return req;
}

/* Fill out a tm_request struct to modify a file's ACL. Same
 * parameters as req_filemodify(), except the hash is the root of the
 * new ACL. */
struct tm_request req_aclmodify(const struct trusted_module *tm,
                                const struct tm_cert *fr_cert, hash_t fr_hmac,
                                struct iomt_node file_node,
                                const hash_t *file_comp, const int *file_orders, size_t file_n,
                                struct iomt_node oldacl_node,
                                const hash_t *oldacl_comp, const int *oldacl_orders, size_t oldacl_n,
                                hash_t newacl_root)
{
    struct tm_request req = req_null;
    req.type = ACL_UPDATE;

    req.idx = file_node.idx;
    req.counter = hash_to_u64(file_node.val);

    req.user_id = oldacl_node.idx;

    req.modify.fr_cert = *fr_cert;
    req.modify.fr_hmac = fr_hmac;

    req.modify.rv_cert = cert_rv(tm,
                                 oldacl_node,
                                 oldacl_comp, oldacl_orders, oldacl_n,
                                 &req.modify.rv_hmac,
                                 0, NULL, NULL);

    hash_t next_counter = u64_to_hash(req.counter + 1);

    req.modify.ru_cert = cert_ru(tm, file_node, next_counter,
                                 file_comp, file_orders, file_n,
                                 &req.modify.ru_hmac);
    req.val = newacl_root;

    return req;
}