aboutsummaryrefslogtreecommitdiff
path: root/service_provider.c
blob: 4faf43f28ac2b29c16b46dde9d4e43a86a0654a5 (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
/* implementation of a basic service provider for use with the trusted
 * module */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include "crypto.h"
#include "helper.h"
#include "service_provider.h"
#include "trusted_module.h"

struct file_version {
    hash_t kf; /* h(key, file_idx) */
    hash_t l; /* h(h(file contents), kf) */
    hash_t enc_key; /* XOR'd with h(kf, module secret) */

    struct tm_cert cert; /* VR certificate */
    hash_t cert_hmac;

    void *contents;
    size_t len;
};

struct file_record {
    int version;
    int counter;

    struct iomt_node *acl;
    int acl_nodes;

    struct tm_cert fr_cert; /* issued by module */
    hash_t fr_hmac;

    struct file_version *versions;
    int n_versions;
};

struct service_provider {
    struct trusted_module *tm;

    struct file_record *records;
    int n_records;

    struct iomt_node *mt; /* leaves of CDI-IOMT, value is counter */
    int mt_nodes;
};

struct service_provider *sp_new(const void *key, size_t keylen)
{
    struct service_provider *sp = calloc(1, sizeof(*sp));

    sp->tm = tm_new(key, keylen);

    /* everything else is already zeroed by calloc */
    return sp;
}

struct tm_cert sp_request(struct service_provider *sp,
                          const struct user_request *req, hash_t req_hmac,
                          hash_t *hmac_out,
                          struct tm_cert *vr_out, hash_t *vr_hmac,
                          hash_t *ack_hmac)
{
    /* see if module succeeds; if so, update the databases */
    return tm_request(sp->tm, req, req_hmac, hmac_out, vr_out, vr_hmac, ack_hmac);
}

void check(int condition);

void sp_test(void)
{
    struct service_provider *sp = sp_new("a", 1);
    /* construct a request to create a file */
    struct user_request req;
    req.idx = 1;
    req.user_id = 1;
    req.type = ACL_UPDATE;
    req.counter = 0;

    struct iomt_node acl_node;
    acl_node.idx = 1;
    memset(&acl_node.val, 0, sizeof(acl_node.val));
    acl_node.val.hash[0] = 3; /* full access */
    acl_node.next_idx = 1;
    req.val = merkle_compute(hash_node(&acl_node), NULL, NULL, 0);
    
    struct iomt_node node;
    node.idx = 1;
    memset(node.val.hash, 0, 32);
    node.next_idx = 1;

    hash_t one;
    memset(one.hash, 0, 32);
    one.hash[0] = 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(sp->tm, &node, one,
                                NULL, NULL, 0,
                                &ru_hmac,
                                0, NULL, NULL);
    printf("RU generation: ");
    check(ru.type == RU &&
          ru.ru.idx == 1 &&
          hash_equals(ru.ru.orig_val, node.val) &&
          hash_equals(ru.ru.new_val, one));

    /* now create a request */
    req.create.ru_cert = ru;
    req.create.ru_hmac = ru_hmac;
    hash_t req_hmac = hmac_sha256(&req, sizeof(req), "a", 1);
    hash_t fr_hmac;
    hash_t ack_hmac;
    
    struct tm_cert fr_cert = sp_request(sp, &req, req_hmac, &fr_hmac, NULL, NULL, &ack_hmac);

    printf("File creation: ");
    check(fr_cert.type == FR &&
          fr_cert.fr.counter == 1 &&
          fr_cert.fr.version == 0);
}