aboutsummaryrefslogtreecommitdiff
path: root/crypto.h
blob: 23b380916b9f2e4dd0a75682c697f85975d0c91f (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
#ifndef CSAA_CRYPTO_H
#define CSAA_CRYPTO_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <time.h>

struct tm_request;
struct version_info;

/* Various useful cryptographic functions; shared between TM and SP.
 * This has also grown to include some decidely non-cryptographic
 * functions, namely profiling code and file I/O helpers, which are
 * shared with the client code as well. */

/* we use SHA256 for h() */
typedef struct hash_t {
    /* a hash of all zeros is given a special meaning */
    unsigned char hash[32];
} hash_t;

/* guaranteed to be zero */
static const struct hash_t hash_null = { { 0 } };

bool encloses(uint64_t b, uint64_t bprime, uint64_t a);
bool hash_equals(hash_t a, hash_t b);
bool is_zero(hash_t u);

hash_t hash_xor(hash_t a, hash_t b);

hash_t sha256(const void *data, size_t datalen);
hash_t hmac_sha256(const void *data, size_t datalen, const void *key, size_t keylen);

hash_t merkle_compute(hash_t node, const hash_t *comp, const int *orders, size_t n);
hash_t merkle_parent(hash_t u, hash_t v, int order);

/* Calculate the indicies of the complementary nodes to a
 * leaf. `leafidx' is 0 for the rightmost leaf node. This function
 * will return an array with a length equal to the number of levels in
 * the tree minus one (the root is not a complentary node). The 0th
 * element of the returned array will be the index of the immediate
 * sibling, while the 1st element will be the index of the
 * complementary node one level above the leaf node, and so on. Note
 * that logleaves = log2(nleaves). If `orders' is not NULL, the
 * function will additionally allocate an array of `logleaves' *
 * sizeof(int) with each element representing whether each
 * complementary node is a left or right child. */
uint64_t *bintree_complement(uint64_t leafidx, int logleaves, int **orders);
int *bintree_complement_ordersonly(uint64_t leafidx, int logleaves);

/* Return an array of indices of tree nodes that are dependent on a
 * given leaf node. Will be ordered from nearest relative to root. */
uint64_t *bintree_ancestors(uint64_t leafidx, int logleaves);

/* Given a node's index, return the index of the parent in an array
 * representation of a binary tree. */
static inline uint64_t bintree_parent(uint64_t idx)
{
    return (idx - 1) / 2;
}

static inline uint64_t bintree_sibling(uint64_t idx)
{
    return idx + ((idx & 1) ? 1 : -1);
}

uint64_t bintree_parent(uint64_t idx);
uint64_t bintree_sibling(uint64_t idx);

uint64_t hash_to_u64(hash_t h);
hash_t u64_to_hash(uint64_t n);
void dump_hash(hash_t u);

struct hashstring {
    char str[32 * 2 + 1];
};

struct hashstring hash_format(hash_t h, int n);

hash_t crypt_secret(hash_t encrypted_secret,
                    uint64_t file_idx, uint64_t file_version,
                    const void *key, size_t keylen);

struct iomt;

hash_t calc_lambda(hash_t gamma, hash_t h_bc, hash_t h_cf, hash_t kf);

/* Generate a signed acknowledgement for successful completion of a
 * request. We append a zero byte to the user request and take the
 * HMAC. */
hash_t sign_ack(const struct tm_request *req, int nzeros, const void *key, size_t keylen);
bool verify_ack(const struct tm_request *req,
                const void *secret, size_t secret_len,
                hash_t hmac);

hash_t sign_verinfo(const struct version_info *verinfo, const void *key, size_t len);
bool verify_verinfo(const struct version_info *verinfo, const void *key, size_t len, hash_t nonce, hash_t hmac);

void dump_versioninfo(const struct version_info *verinfo);

void write_to_fd(void *userdata, const void *data, size_t len);
int read_from_fd(void *userdata, void *buf, size_t len);

void crypt_bytes(unsigned char *data, size_t len, hash_t key);
hash_t generate_nonce(void);
hash_t derive_key(const char *passphrase, hash_t nonce);
hash_t calc_kf(hash_t encryption_key, uint64_t file_idx);

void begin_transaction(void *db);
void commit_transaction(void *db);

void *deserialize_file(int cl, size_t *len);
void serialize_file(int cl, const void *buf, size_t len);

void *load_file(const char *path, size_t *len);
void write_file(const char *path, const void *contents, size_t len);

void warn(const char *fmt, ...) __attribute__((format(printf, 1, 2)));

/* profiling */

#define MAX_TIMES 30
#define MAX_LABEL 40

/* this struct records a series of clock() times, and labels for them */
struct server_profile {
    clock_t times[MAX_TIMES];
    char labels[MAX_TIMES][MAX_LABEL];

    int n_times;
};

void prof_reset(struct server_profile *prof);
void prof_add(struct server_profile *prof, const char *label);
void prof_dump(struct server_profile *profile, bool labels, bool labels_only);
void prof_read(int fd, struct server_profile *profile_out);

void prof_concat(struct server_profile *out, const struct server_profile *in);

/* self-test */
void crypto_test(void);
#endif