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
|
#pragma once
/* WARNING: none of these functions is reentrant because all use the
same scratch buffer */
#include <fcntl.h>
#include <strings.h>
#include "nacl/crypto_box.h"
#include "common.h"
/* scratchpad for crypto operations */
byte crypto_buf[MAXBUFLEN];
char *key_path(char *task, char *type) {
char *base = getenv("HBBP_KEYDIR"),
*res = (char*) crypto_buf;
if (!base) base = "/etc/hbbp/keys";
if ((unsigned) snprintf(res, MAXBUFLEN, "%s/%s/%s", base, task, type)
> MAXBUFLEN)
return NULL;
return res;
}
int key_load(char *task, char *type, byte *key, int key_len) {
int fd = open(key_path(task, type), O_RDONLY);
if (fd == -1) /* no specific key? -> try default */
fd = open(key_path("default", type), O_RDONLY);
if (fd == -1) return 0;
if (read(fd, key, key_len) != key_len) {
fprintf(stderr, "invalid key %s\n", crypto_buf);
return 0;
}
ENP(close(fd), "close");
return 1;
}
/* return error msg or null on sucess */
char* encipher(char *task, byte *data, int *len) {
byte key_priv[crypto_box_SECRETKEYBYTES],
key_pub [crypto_box_PUBLICKEYBYTES];
switch(key_load(task, "send.priv", key_priv, crypto_box_SECRETKEYBYTES)
+ key_load(task, "recv.pub", key_pub, crypto_box_PUBLICKEYBYTES)) {
case 0: return NULL; /* no keys -> no encryption required */
case 1: return "missing key";
}
/* copy data to scratch buffer */
if ((*len + crypto_box_ZEROBYTES > MAXBUFLEN)
|| (*len + crypto_box_ZEROBYTES + crypto_box_NONCEBYTES + strlen(task) + 1 > MAXBUFLEN))
return "payload to large (no space left for crypto)";
bzero (crypto_buf, crypto_box_ZEROBYTES);
memcpy(crypto_buf + crypto_box_ZEROBYTES, data, *len);
/* encrypt */
byte *nonce = data,
*cdata = data + crypto_box_NONCEBYTES;
memset(nonce, 42, crypto_box_NONCEBYTES); /* URGENT TODO: random nonce */
if (crypto_box(cdata, crypto_buf, *len + crypto_box_ZEROBYTES, nonce, key_pub, key_priv) != 0) return "oooh";
memmove(data + crypto_box_NONCEBYTES,
data + crypto_box_NONCEBYTES + crypto_box_BOXZEROBYTES,
*len + crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES);
*len += crypto_box_NONCEBYTES + crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES;
return NULL;
}
int decipher(char *task, byte **data, int *len) {
byte key_priv[crypto_box_SECRETKEYBYTES],
key_pub [crypto_box_PUBLICKEYBYTES];
switch(key_load(task, "recv.priv", key_priv, crypto_box_SECRETKEYBYTES)
+ key_load(task, "send.pub", key_pub, crypto_box_PUBLICKEYBYTES)) {
case 0: return 1; /* no keys -> no decryption required */
case 1: return 0; /* one missing key -> error */
}
byte nonce[crypto_box_NONCEBYTES];
memcpy(nonce, *data, crypto_box_NONCEBYTES);
byte *cdata = *data + (crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES);
int cdata_len = *len - (crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES);
if (cdata_len < crypto_box_BOXZEROBYTES) return 0;
bzero(cdata, crypto_box_BOXZEROBYTES);
if (crypto_box_open(crypto_buf, cdata, cdata_len, nonce,
key_pub, key_priv) == -1) return 0;
*data = crypto_buf + crypto_box_ZEROBYTES;
*len = cdata_len - crypto_box_ZEROBYTES;
return 1;
}
|