spiped 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/spiped/extconf.rb +3 -0
- data/ext/spiped/spiped-source/BUILDING +46 -0
- data/ext/spiped/spiped-source/CHANGELOG +44 -0
- data/ext/spiped/spiped-source/COPYRIGHT +33 -0
- data/ext/spiped/spiped-source/Makefile +47 -0
- data/ext/spiped/spiped-source/Makefile.POSIX +27 -0
- data/ext/spiped/spiped-source/Makefile.inc +20 -0
- data/ext/spiped/spiped-source/Makefile.prog +23 -0
- data/ext/spiped/spiped-source/POSIX/README +10 -0
- data/ext/spiped/spiped-source/POSIX/posix-cflags.sh +10 -0
- data/ext/spiped/spiped-source/POSIX/posix-clock_realtime.c +3 -0
- data/ext/spiped/spiped-source/POSIX/posix-l.c +1 -0
- data/ext/spiped/spiped-source/POSIX/posix-l.sh +14 -0
- data/ext/spiped/spiped-source/POSIX/posix-msg_nosignal.c +3 -0
- data/ext/spiped/spiped-source/README +198 -0
- data/ext/spiped/spiped-source/STYLE +151 -0
- data/ext/spiped/spiped-source/lib/dnsthread/dnsthread.c +464 -0
- data/ext/spiped/spiped-source/lib/dnsthread/dnsthread.h +45 -0
- data/ext/spiped/spiped-source/libcperciva/alg/sha256.c +442 -0
- data/ext/spiped/spiped-source/libcperciva/alg/sha256.h +95 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport-X86-AESNI.c +13 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport-X86-CPUID.c +8 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport.sh +37 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/cpusupport.h +63 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/cpusupport_x86_aesni.c +30 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes.c +166 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes.h +31 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes_aesni.c +229 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes_aesni.h +31 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aesctr.c +124 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aesctr.h +41 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh.c +293 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh.h +43 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh_group14.c +46 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh_group14.h +9 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_entropy.c +215 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_entropy.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_verify_bytes.c +21 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_verify_bytes.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/elasticarray.c +276 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/elasticarray.h +167 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/mpool.h +85 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/ptrheap.c +334 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/ptrheap.h +89 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/timerqueue.c +241 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/timerqueue.h +60 -0
- data/ext/spiped/spiped-source/libcperciva/events/events.c +203 -0
- data/ext/spiped/spiped-source/libcperciva/events/events.h +106 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_immediate.c +149 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_internal.h +95 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_network.c +347 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_network_selectstats.c +106 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_timer.c +273 -0
- data/ext/spiped/spiped-source/libcperciva/network/network.h +95 -0
- data/ext/spiped/spiped-source/libcperciva/network/network_accept.c +103 -0
- data/ext/spiped/spiped-source/libcperciva/network/network_connect.c +258 -0
- data/ext/spiped/spiped-source/libcperciva/network/network_read.c +155 -0
- data/ext/spiped/spiped-source/libcperciva/network/network_write.c +188 -0
- data/ext/spiped/spiped-source/libcperciva/util/asprintf.c +49 -0
- data/ext/spiped/spiped-source/libcperciva/util/asprintf.h +16 -0
- data/ext/spiped/spiped-source/libcperciva/util/daemonize.c +134 -0
- data/ext/spiped/spiped-source/libcperciva/util/daemonize.h +10 -0
- data/ext/spiped/spiped-source/libcperciva/util/entropy.c +76 -0
- data/ext/spiped/spiped-source/libcperciva/util/entropy.h +13 -0
- data/ext/spiped/spiped-source/libcperciva/util/imalloc.h +33 -0
- data/ext/spiped/spiped-source/libcperciva/util/insecure_memzero.c +19 -0
- data/ext/spiped/spiped-source/libcperciva/util/insecure_memzero.h +33 -0
- data/ext/spiped/spiped-source/libcperciva/util/monoclock.c +52 -0
- data/ext/spiped/spiped-source/libcperciva/util/monoclock.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/util/noeintr.c +54 -0
- data/ext/spiped/spiped-source/libcperciva/util/noeintr.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock.c +472 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock.h +56 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock_internal.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock_util.c +271 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock_util.h +51 -0
- data/ext/spiped/spiped-source/libcperciva/util/sysendian.h +146 -0
- data/ext/spiped/spiped-source/libcperciva/util/warnp.c +76 -0
- data/ext/spiped/spiped-source/libcperciva/util/warnp.h +59 -0
- data/ext/spiped/spiped-source/proto/proto_conn.c +362 -0
- data/ext/spiped/spiped-source/proto/proto_conn.h +25 -0
- data/ext/spiped/spiped-source/proto/proto_crypt.c +396 -0
- data/ext/spiped/spiped-source/proto/proto_crypt.h +102 -0
- data/ext/spiped/spiped-source/proto/proto_handshake.c +330 -0
- data/ext/spiped/spiped-source/proto/proto_handshake.h +30 -0
- data/ext/spiped/spiped-source/proto/proto_pipe.c +202 -0
- data/ext/spiped/spiped-source/proto/proto_pipe.h +23 -0
- data/ext/spiped/spiped-source/spipe/Makefile +90 -0
- data/ext/spiped/spiped-source/spipe/README +24 -0
- data/ext/spiped/spiped-source/spipe/main.c +178 -0
- data/ext/spiped/spiped-source/spipe/pushbits.c +101 -0
- data/ext/spiped/spiped-source/spipe/pushbits.h +10 -0
- data/ext/spiped/spiped-source/spipe/spipe.1 +60 -0
- data/ext/spiped/spiped-source/spiped/Makefile +98 -0
- data/ext/spiped/spiped-source/spiped/README +62 -0
- data/ext/spiped/spiped-source/spiped/dispatch.c +214 -0
- data/ext/spiped/spiped-source/spiped/dispatch.h +27 -0
- data/ext/spiped/spiped-source/spiped/main.c +267 -0
- data/ext/spiped/spiped-source/spiped/spiped.1 +112 -0
- data/lib/spiped.rb +3 -0
- metadata +143 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#ifndef _PROTO_CONN_H_
|
|
2
|
+
#define _PROTO_CONN_H_
|
|
3
|
+
|
|
4
|
+
/* Opaque structures. */
|
|
5
|
+
struct proto_secret;
|
|
6
|
+
struct sock_addr;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* proto_conn_create(s, sas, decr, nofps, requirefps, nokeepalive, K, timeo,
|
|
10
|
+
* callback_dead, cookie):
|
|
11
|
+
* Create a connection with one end at ${s} and the other end connecting to
|
|
12
|
+
* the target addresses ${sas}. If ${decr} is 0, encrypt the outgoing data;
|
|
13
|
+
* if ${decr} is nonzero, decrypt the outgoing data. If ${nofps} is non-zero,
|
|
14
|
+
* don't use perfect forward secrecy. If ${requirefps} is non-zero, drop
|
|
15
|
+
* the connection if the other end tries to disable perfect forward secrecy.
|
|
16
|
+
* Enable transport layer keep-alives (if applicable) on both sockets if and
|
|
17
|
+
* only if ${nokeepalive} is zero. Drop the connection if the handshake or
|
|
18
|
+
* connecting to the target takes more than ${timeo} seconds. When the
|
|
19
|
+
* connection is dropped, invoke ${callback_dead}(${cookie}). Free ${sas}
|
|
20
|
+
* once it is no longer needed.
|
|
21
|
+
*/
|
|
22
|
+
int proto_conn_create(int, struct sock_addr **, int, int, int, int,
|
|
23
|
+
const struct proto_secret *, double, int (*)(void *), void *);
|
|
24
|
+
|
|
25
|
+
#endif /* !_CONN_H_ */
|
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
#include <assert.h>
|
|
2
|
+
#include <stdint.h>
|
|
3
|
+
#include <stdio.h>
|
|
4
|
+
#include <stdlib.h>
|
|
5
|
+
#include <string.h>
|
|
6
|
+
|
|
7
|
+
#include "crypto_aes.h"
|
|
8
|
+
#include "crypto_aesctr.h"
|
|
9
|
+
#include "crypto_verify_bytes.h"
|
|
10
|
+
#include "sha256.h"
|
|
11
|
+
#include "sysendian.h"
|
|
12
|
+
#include "warnp.h"
|
|
13
|
+
|
|
14
|
+
#include "proto_crypt.h"
|
|
15
|
+
|
|
16
|
+
struct proto_secret {
|
|
17
|
+
uint8_t K[32];
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
struct proto_keys {
|
|
21
|
+
struct crypto_aes_key * k_aes;
|
|
22
|
+
uint8_t k_hmac[32];
|
|
23
|
+
uint64_t pnum;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* mkkeypair(kbuf):
|
|
28
|
+
* Convert the 64 bytes of ${kbuf} into a protocol key structure.
|
|
29
|
+
*/
|
|
30
|
+
static struct proto_keys *
|
|
31
|
+
mkkeypair(uint8_t kbuf[64])
|
|
32
|
+
{
|
|
33
|
+
struct proto_keys * k;
|
|
34
|
+
|
|
35
|
+
/* Allocate a structure. */
|
|
36
|
+
if ((k = malloc(sizeof(struct proto_keys))) == NULL)
|
|
37
|
+
goto err0;
|
|
38
|
+
|
|
39
|
+
/* Expand the AES key. */
|
|
40
|
+
if ((k->k_aes = crypto_aes_key_expand(&kbuf[0], 32)) == NULL)
|
|
41
|
+
goto err1;
|
|
42
|
+
|
|
43
|
+
/* Fill in HMAC key. */
|
|
44
|
+
memcpy(k->k_hmac, &kbuf[32], 32);
|
|
45
|
+
|
|
46
|
+
/* The first packet will be packet number zero. */
|
|
47
|
+
k->pnum = 0;
|
|
48
|
+
|
|
49
|
+
/* Success! */
|
|
50
|
+
return (k);
|
|
51
|
+
|
|
52
|
+
err1:
|
|
53
|
+
free(k);
|
|
54
|
+
err0:
|
|
55
|
+
/* Failure! */
|
|
56
|
+
return (NULL);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* proto_crypt_secret(filename):
|
|
61
|
+
* Read the key file ${filename} and return a protocol secret structure.
|
|
62
|
+
*/
|
|
63
|
+
struct proto_secret *
|
|
64
|
+
proto_crypt_secret(const char * filename)
|
|
65
|
+
{
|
|
66
|
+
SHA256_CTX ctx;
|
|
67
|
+
FILE * f;
|
|
68
|
+
struct proto_secret * K;
|
|
69
|
+
uint8_t buf[BUFSIZ];
|
|
70
|
+
size_t lenread;
|
|
71
|
+
|
|
72
|
+
/* Allocate a protocol secret structure. */
|
|
73
|
+
if ((K = malloc(sizeof(struct proto_secret))) == NULL)
|
|
74
|
+
goto err0;
|
|
75
|
+
|
|
76
|
+
/* Open the file. */
|
|
77
|
+
if ((f = fopen(filename, "r")) == NULL) {
|
|
78
|
+
warnp("Cannot open file: %s", filename);
|
|
79
|
+
goto err1;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* Initialize the SHA256 hash context. */
|
|
83
|
+
SHA256_Init(&ctx);
|
|
84
|
+
|
|
85
|
+
/* Read the file until we hit EOF. */
|
|
86
|
+
while ((lenread = fread(buf, 1, BUFSIZ, f)) > 0)
|
|
87
|
+
SHA256_Update(&ctx, buf, lenread);
|
|
88
|
+
|
|
89
|
+
/* Did we hit EOF? */
|
|
90
|
+
if (!feof(f)) {
|
|
91
|
+
warnp("Error reading file: %s", filename);
|
|
92
|
+
goto err2;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/* Close the file. */
|
|
96
|
+
fclose(f);
|
|
97
|
+
|
|
98
|
+
/* Compute the final hash. */
|
|
99
|
+
SHA256_Final(K->K, &ctx);
|
|
100
|
+
|
|
101
|
+
/* Success! */
|
|
102
|
+
return (K);
|
|
103
|
+
|
|
104
|
+
err2:
|
|
105
|
+
fclose(f);
|
|
106
|
+
err1:
|
|
107
|
+
free(K);
|
|
108
|
+
err0:
|
|
109
|
+
/* Failure! */
|
|
110
|
+
return (NULL);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* proto_crypt_dhmac(K, nonce_l, nonce_r, dhmac_l, dhmac_r, decr):
|
|
115
|
+
* Using the key file hash ${K}, and the local and remote nonces ${nonce_l}
|
|
116
|
+
* and ${nonce_r}, compute the local and remote diffie-hellman parameter MAC
|
|
117
|
+
* keys ${dhmac_l} and ${dhmac_r}. If ${decr} is non-zero, "local" == "S"
|
|
118
|
+
* and "remote" == "C"; otherwise the assignments are opposite.
|
|
119
|
+
*/
|
|
120
|
+
void
|
|
121
|
+
proto_crypt_dhmac(const struct proto_secret * K,
|
|
122
|
+
const uint8_t nonce_l[PCRYPT_NONCE_LEN],
|
|
123
|
+
const uint8_t nonce_r[PCRYPT_NONCE_LEN],
|
|
124
|
+
uint8_t dhmac_l[PCRYPT_DHMAC_LEN], uint8_t dhmac_r[PCRYPT_DHMAC_LEN],
|
|
125
|
+
int decr)
|
|
126
|
+
{
|
|
127
|
+
uint8_t nonce_CS[PCRYPT_NONCE_LEN * 2];
|
|
128
|
+
uint8_t dk_1[PCRYPT_DHMAC_LEN * 2];
|
|
129
|
+
const uint8_t * nonce_c, * nonce_s;
|
|
130
|
+
uint8_t * dhmac_c, * dhmac_s;
|
|
131
|
+
|
|
132
|
+
/* Figure out how {c, s} maps to {l, r}. */
|
|
133
|
+
nonce_c = decr ? nonce_r : nonce_l;
|
|
134
|
+
dhmac_c = decr ? dhmac_r : dhmac_l;
|
|
135
|
+
nonce_s = decr ? nonce_l : nonce_r;
|
|
136
|
+
dhmac_s = decr ? dhmac_l : dhmac_r;
|
|
137
|
+
|
|
138
|
+
/* Copy in nonces (in the right order). */
|
|
139
|
+
memcpy(&nonce_CS[0], nonce_c, PCRYPT_NONCE_LEN);
|
|
140
|
+
memcpy(&nonce_CS[PCRYPT_NONCE_LEN], nonce_s, PCRYPT_NONCE_LEN);
|
|
141
|
+
|
|
142
|
+
/* Compute dk_1. */
|
|
143
|
+
PBKDF2_SHA256(K->K, 32, nonce_CS, PCRYPT_NONCE_LEN * 2, 1,
|
|
144
|
+
dk_1, PCRYPT_DHMAC_LEN * 2);
|
|
145
|
+
|
|
146
|
+
/* Copy out diffie-hellman parameter MAC keys (in the right order). */
|
|
147
|
+
memcpy(dhmac_c, &dk_1[0], PCRYPT_DHMAC_LEN);
|
|
148
|
+
memcpy(dhmac_s, &dk_1[PCRYPT_DHMAC_LEN], PCRYPT_DHMAC_LEN);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* is_not_one(x, len):
|
|
153
|
+
* Returns non-zero if the big-endian value stored at (${x}, ${len}) is not
|
|
154
|
+
* equal to 1.
|
|
155
|
+
*/
|
|
156
|
+
static int
|
|
157
|
+
is_not_one(const uint8_t * x, size_t len)
|
|
158
|
+
{
|
|
159
|
+
size_t i;
|
|
160
|
+
char y;
|
|
161
|
+
|
|
162
|
+
for (i = 0, y = 0; i < len - 1; i++) {
|
|
163
|
+
y |= x[i];
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return (y | (x[len - 1] - 1));
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* proto_crypt_dh_validate(yh_r, dhmac_r, requirefps):
|
|
171
|
+
* Return non-zero if the value ${yh_r} received from the remote party is not
|
|
172
|
+
* correctly MACed using the diffie-hellman parameter MAC key ${dhmac_r}, or
|
|
173
|
+
* if the included y value is >= the diffie-hellman group modulus, or if
|
|
174
|
+
* ${requirefps} is non-zero and the included y value is 1.
|
|
175
|
+
*/
|
|
176
|
+
int
|
|
177
|
+
proto_crypt_dh_validate(const uint8_t yh_r[PCRYPT_YH_LEN],
|
|
178
|
+
const uint8_t dhmac_r[PCRYPT_DHMAC_LEN], int requirefps)
|
|
179
|
+
{
|
|
180
|
+
uint8_t hbuf[32];
|
|
181
|
+
|
|
182
|
+
/* Compute HMAC. */
|
|
183
|
+
HMAC_SHA256_Buf(dhmac_r, PCRYPT_DHMAC_LEN, yh_r, CRYPTO_DH_PUBLEN,
|
|
184
|
+
hbuf);
|
|
185
|
+
|
|
186
|
+
/* Check that the MAC matches. */
|
|
187
|
+
if (crypto_verify_bytes(&yh_r[CRYPTO_DH_PUBLEN], hbuf, 32))
|
|
188
|
+
return (1);
|
|
189
|
+
|
|
190
|
+
/* Sanity-check the diffie-hellman value. */
|
|
191
|
+
if (crypto_dh_sanitycheck(&yh_r[0]))
|
|
192
|
+
return (1);
|
|
193
|
+
|
|
194
|
+
/* If necessary, enforce that the diffie-hellman value is != 1. */
|
|
195
|
+
if (requirefps) {
|
|
196
|
+
if (! is_not_one(&yh_r[0], CRYPTO_DH_PUBLEN))
|
|
197
|
+
return (1);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/* Everything is good. */
|
|
201
|
+
return (0);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* proto_crypt_dh_generate(yh_l, x, dhmac_l, nofps):
|
|
206
|
+
* Using the MAC key ${dhmac_l}, generate the MACed diffie-hellman handshake
|
|
207
|
+
* parameter ${yh_l}. Store the diffie-hellman private value in ${x}. If
|
|
208
|
+
* ${nofps} is non-zero, skip diffie-hellman generation and use y = 1.
|
|
209
|
+
*/
|
|
210
|
+
int
|
|
211
|
+
proto_crypt_dh_generate(uint8_t yh_l[PCRYPT_YH_LEN], uint8_t x[PCRYPT_X_LEN],
|
|
212
|
+
const uint8_t dhmac_l[PCRYPT_DHMAC_LEN], int nofps)
|
|
213
|
+
{
|
|
214
|
+
|
|
215
|
+
/* Are we skipping the diffie-hellman generation? */
|
|
216
|
+
if (nofps) {
|
|
217
|
+
/* Set y_l to a big-endian 1. */
|
|
218
|
+
memset(yh_l, 0, CRYPTO_DH_PUBLEN - 1);
|
|
219
|
+
yh_l[CRYPTO_DH_PUBLEN - 1] = 1;
|
|
220
|
+
} else {
|
|
221
|
+
/* Generate diffie-hellman parameters x and y. */
|
|
222
|
+
if (crypto_dh_generate(yh_l, x))
|
|
223
|
+
goto err0;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/* Append an HMAC. */
|
|
227
|
+
HMAC_SHA256_Buf(dhmac_l, PCRYPT_DHMAC_LEN, yh_l, CRYPTO_DH_PUBLEN,
|
|
228
|
+
&yh_l[CRYPTO_DH_PUBLEN]);
|
|
229
|
+
|
|
230
|
+
/* Success! */
|
|
231
|
+
return (0);
|
|
232
|
+
|
|
233
|
+
err0:
|
|
234
|
+
/* Failure! */
|
|
235
|
+
return (-1);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* proto_crypt_mkkeys(K, nonce_l, nonce_r, yh_r, x, nofps, decr, eh_c, eh_s):
|
|
240
|
+
* Using the protocol secret ${K}, the local and remote nonces ${nonce_l} and
|
|
241
|
+
* ${nonce_r}, the remote MACed diffie-hellman handshake parameter ${yh_r},
|
|
242
|
+
* and the local diffie-hellman secret ${x}, generate the keys ${eh_c} and
|
|
243
|
+
* ${eh_s}. If ${nofps} is non-zero, we are performing weak handshaking and
|
|
244
|
+
* y_SC is set to 1 rather than being computed. If ${decr} is non-zero,
|
|
245
|
+
* "local" == "S" and "remote" == "C"; otherwise the assignments are opposite.
|
|
246
|
+
*/
|
|
247
|
+
int
|
|
248
|
+
proto_crypt_mkkeys(const struct proto_secret * K,
|
|
249
|
+
const uint8_t nonce_l[PCRYPT_NONCE_LEN],
|
|
250
|
+
const uint8_t nonce_r[PCRYPT_NONCE_LEN],
|
|
251
|
+
const uint8_t yh_r[PCRYPT_YH_LEN], const uint8_t x[PCRYPT_X_LEN],
|
|
252
|
+
int nofps, int decr,
|
|
253
|
+
struct proto_keys ** eh_c, struct proto_keys ** eh_s)
|
|
254
|
+
{
|
|
255
|
+
uint8_t nonce_y[PCRYPT_NONCE_LEN * 2 + CRYPTO_DH_KEYLEN];
|
|
256
|
+
uint8_t dk_2[128];
|
|
257
|
+
const uint8_t * nonce_c, * nonce_s;
|
|
258
|
+
|
|
259
|
+
/* Copy in nonces (in the right order). */
|
|
260
|
+
nonce_c = decr ? nonce_r : nonce_l;
|
|
261
|
+
nonce_s = decr ? nonce_l : nonce_r;
|
|
262
|
+
memcpy(&nonce_y[0], nonce_c, PCRYPT_NONCE_LEN);
|
|
263
|
+
memcpy(&nonce_y[PCRYPT_NONCE_LEN], nonce_s, PCRYPT_NONCE_LEN);
|
|
264
|
+
|
|
265
|
+
/* Are we bypassing the diffie-hellman computation? */
|
|
266
|
+
if (nofps) {
|
|
267
|
+
/* We sent y_l = 1, so y_SC is also 1. */
|
|
268
|
+
memset(&nonce_y[PCRYPT_NONCE_LEN * 2], 0,
|
|
269
|
+
CRYPTO_DH_KEYLEN - 1);
|
|
270
|
+
nonce_y[PCRYPT_NONCE_LEN * 2 + CRYPTO_DH_KEYLEN - 1] = 1;
|
|
271
|
+
} else {
|
|
272
|
+
/* Perform the diffie-hellman computation. */
|
|
273
|
+
if (crypto_dh_compute(yh_r, x,
|
|
274
|
+
&nonce_y[PCRYPT_NONCE_LEN * 2]))
|
|
275
|
+
goto err0;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/* Compute dk_2. */
|
|
279
|
+
PBKDF2_SHA256(K->K, 32, nonce_y,
|
|
280
|
+
PCRYPT_NONCE_LEN * 2 + CRYPTO_DH_KEYLEN, 1, dk_2, 128);
|
|
281
|
+
|
|
282
|
+
/* Create key structures. */
|
|
283
|
+
if ((*eh_c = mkkeypair(&dk_2[0])) == NULL)
|
|
284
|
+
goto err0;
|
|
285
|
+
if ((*eh_s = mkkeypair(&dk_2[64])) == NULL)
|
|
286
|
+
goto err1;
|
|
287
|
+
|
|
288
|
+
/* Success! */
|
|
289
|
+
return (0);
|
|
290
|
+
|
|
291
|
+
err1:
|
|
292
|
+
proto_crypt_free(*eh_c);
|
|
293
|
+
err0:
|
|
294
|
+
/* Failure! */
|
|
295
|
+
return (-1);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* proto_crypt_enc(ibuf, len, obuf, k):
|
|
300
|
+
* Encrypt ${len} bytes from ${ibuf} into PCRYPT_ESZ bytes using the keys in
|
|
301
|
+
* ${k}, and write the result into ${obuf}.
|
|
302
|
+
*/
|
|
303
|
+
void
|
|
304
|
+
proto_crypt_enc(uint8_t * ibuf, size_t len, uint8_t obuf[PCRYPT_ESZ],
|
|
305
|
+
struct proto_keys * k)
|
|
306
|
+
{
|
|
307
|
+
HMAC_SHA256_CTX ctx;
|
|
308
|
+
uint8_t pnum_exp[8];
|
|
309
|
+
|
|
310
|
+
/* Sanity-check the length. */
|
|
311
|
+
assert(len <= PCRYPT_MAXDSZ);
|
|
312
|
+
|
|
313
|
+
/* Copy the decrypted data into the encrypted buffer. */
|
|
314
|
+
memcpy(obuf, ibuf, len);
|
|
315
|
+
|
|
316
|
+
/* Pad up to PCRYPT_MAXDSZ with zeroes. */
|
|
317
|
+
memset(&obuf[len], 0, PCRYPT_MAXDSZ - len);
|
|
318
|
+
|
|
319
|
+
/* Add the length. */
|
|
320
|
+
be32enc(&obuf[PCRYPT_MAXDSZ], len);
|
|
321
|
+
|
|
322
|
+
/* Encrypt the buffer in-place. */
|
|
323
|
+
crypto_aesctr_buf(k->k_aes, k->pnum, obuf, obuf, PCRYPT_MAXDSZ + 4);
|
|
324
|
+
|
|
325
|
+
/* Append an HMAC. */
|
|
326
|
+
be64enc(pnum_exp, k->pnum);
|
|
327
|
+
HMAC_SHA256_Init(&ctx, k->k_hmac, 32);
|
|
328
|
+
HMAC_SHA256_Update(&ctx, obuf, PCRYPT_MAXDSZ + 4);
|
|
329
|
+
HMAC_SHA256_Update(&ctx, pnum_exp, 8);
|
|
330
|
+
HMAC_SHA256_Final(&obuf[PCRYPT_MAXDSZ + 4], &ctx);
|
|
331
|
+
|
|
332
|
+
/* Increment packet number. */
|
|
333
|
+
k->pnum += 1;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* proto_crypt_dec(ibuf, obuf, k):
|
|
338
|
+
* Decrypt PCRYPT_ESZ bytes from ${ibuf} using the keys in ${k}. If the data
|
|
339
|
+
* is valid, write it into ${obuf} and return the length; otherwise, return
|
|
340
|
+
* -1.
|
|
341
|
+
*/
|
|
342
|
+
ssize_t proto_crypt_dec(uint8_t ibuf[PCRYPT_ESZ], uint8_t * obuf,
|
|
343
|
+
struct proto_keys * k)
|
|
344
|
+
{
|
|
345
|
+
HMAC_SHA256_CTX ctx;
|
|
346
|
+
uint8_t hbuf[32];
|
|
347
|
+
uint8_t pnum_exp[8];
|
|
348
|
+
size_t len;
|
|
349
|
+
|
|
350
|
+
/* Verify HMAC. */
|
|
351
|
+
be64enc(pnum_exp, k->pnum);
|
|
352
|
+
HMAC_SHA256_Init(&ctx, k->k_hmac, 32);
|
|
353
|
+
HMAC_SHA256_Update(&ctx, ibuf, PCRYPT_MAXDSZ + 4);
|
|
354
|
+
HMAC_SHA256_Update(&ctx, pnum_exp, 8);
|
|
355
|
+
HMAC_SHA256_Final(hbuf, &ctx);
|
|
356
|
+
if (crypto_verify_bytes(hbuf, &ibuf[PCRYPT_MAXDSZ + 4], 32))
|
|
357
|
+
return (-1);
|
|
358
|
+
|
|
359
|
+
/* Decrypt the buffer in-place. */
|
|
360
|
+
crypto_aesctr_buf(k->k_aes, k->pnum, ibuf, ibuf, PCRYPT_MAXDSZ + 4);
|
|
361
|
+
|
|
362
|
+
/* Increment packet number. */
|
|
363
|
+
k->pnum += 1;
|
|
364
|
+
|
|
365
|
+
/* Parse length. */
|
|
366
|
+
len = be32dec(&ibuf[PCRYPT_MAXDSZ]);
|
|
367
|
+
|
|
368
|
+
/* Make sure nobody is being evil here... */
|
|
369
|
+
if ((len == 0) || (len > PCRYPT_MAXDSZ))
|
|
370
|
+
return (-1);
|
|
371
|
+
|
|
372
|
+
/* Copy the bytes into the output buffer. */
|
|
373
|
+
memcpy(obuf, ibuf, len);
|
|
374
|
+
|
|
375
|
+
/* Return the decrypted length. */
|
|
376
|
+
return (len);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* proto_crypt_free(k):
|
|
381
|
+
* Free the protocol key structure ${k}.
|
|
382
|
+
*/
|
|
383
|
+
void
|
|
384
|
+
proto_crypt_free(struct proto_keys * k)
|
|
385
|
+
{
|
|
386
|
+
|
|
387
|
+
/* Be compatible with free(NULL). */
|
|
388
|
+
if (k == NULL)
|
|
389
|
+
return;
|
|
390
|
+
|
|
391
|
+
/* Free the AES key. */
|
|
392
|
+
crypto_aes_key_free(k->k_aes);
|
|
393
|
+
|
|
394
|
+
/* Free the key structure. */
|
|
395
|
+
free(k);
|
|
396
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#ifndef _PCRYPT_H_
|
|
2
|
+
#define _PCRYPT_H_
|
|
3
|
+
|
|
4
|
+
#include <stdint.h>
|
|
5
|
+
#include <unistd.h>
|
|
6
|
+
|
|
7
|
+
#include "crypto_dh.h"
|
|
8
|
+
|
|
9
|
+
struct proto_keys;
|
|
10
|
+
struct proto_secret;
|
|
11
|
+
|
|
12
|
+
/* Size of nonce. */
|
|
13
|
+
#define PCRYPT_NONCE_LEN 32
|
|
14
|
+
|
|
15
|
+
/* Size of temporary MAC keys used for Diffie-Hellman parameters. */
|
|
16
|
+
#define PCRYPT_DHMAC_LEN 32
|
|
17
|
+
|
|
18
|
+
/* Size of private Diffie-Hellman value. */
|
|
19
|
+
#define PCRYPT_X_LEN CRYPTO_DH_PRIVLEN
|
|
20
|
+
|
|
21
|
+
/* Size of MACed Diffie-Hellman parameter. */
|
|
22
|
+
#define PCRYPT_YH_LEN (CRYPTO_DH_PUBLEN + 32)
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* proto_crypt_secret(filename):
|
|
26
|
+
* Read the key file ${filename} and return a protocol secret structure.
|
|
27
|
+
*/
|
|
28
|
+
struct proto_secret * proto_crypt_secret(const char *);
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* proto_crypt_dhmac(K, nonce_l, nonce_r, dhmac_l, dhmac_r, decr):
|
|
32
|
+
* Using the protocol secret ${K}, and the local and remote nonces ${nonce_l}
|
|
33
|
+
* and ${nonce_r}, compute the local and remote diffie-hellman parameter MAC
|
|
34
|
+
* keys ${dhmac_l} and ${dhmac_r}. If ${decr} is non-zero, "local" == "S"
|
|
35
|
+
* and "remote" == "C"; otherwise the assignments are opposite.
|
|
36
|
+
*/
|
|
37
|
+
void proto_crypt_dhmac(const struct proto_secret *,
|
|
38
|
+
const uint8_t[PCRYPT_NONCE_LEN], const uint8_t[PCRYPT_NONCE_LEN],
|
|
39
|
+
uint8_t[PCRYPT_DHMAC_LEN], uint8_t[PCRYPT_DHMAC_LEN], int);
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* proto_crypt_dh_validate(yh_r, dhmac_r, requirefps):
|
|
43
|
+
* Return non-zero if the value ${yh_r} received from the remote party is not
|
|
44
|
+
* correctly MACed using the diffie-hellman parameter MAC key ${dhmac_r}, or
|
|
45
|
+
* if the included y value is >= the diffie-hellman group modulus, or if
|
|
46
|
+
* ${requirefps} is non-zero and the included y value is 1.
|
|
47
|
+
*/
|
|
48
|
+
int proto_crypt_dh_validate(const uint8_t[PCRYPT_YH_LEN],
|
|
49
|
+
const uint8_t[PCRYPT_DHMAC_LEN], int);
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* proto_crypt_dh_generate(yh_l, x, dhmac_l, nofps):
|
|
53
|
+
* Using the MAC key ${dhmac_l}, generate the MACed diffie-hellman handshake
|
|
54
|
+
* parameter ${yh_l}. Store the diffie-hellman private value in ${x}. If
|
|
55
|
+
* ${nofps} is non-zero, skip diffie-hellman generation and use y = 1.
|
|
56
|
+
*/
|
|
57
|
+
int proto_crypt_dh_generate(uint8_t[PCRYPT_YH_LEN], uint8_t[PCRYPT_X_LEN],
|
|
58
|
+
const uint8_t[PCRYPT_DHMAC_LEN], int);
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* proto_crypt_mkkeys(K, nonce_l, nonce_r, yh_r, x, nofps, decr, eh_c, eh_s):
|
|
62
|
+
* Using the protocol secret ${K}, the local and remote nonces ${nonce_l} and
|
|
63
|
+
* ${nonce_r}, the remote MACed diffie-hellman handshake parameter ${yh_r},
|
|
64
|
+
* and the local diffie-hellman secret ${x}, generate the keys ${eh_c} and
|
|
65
|
+
* ${eh_s}. If ${nofps} is non-zero, we are performing weak handshaking and
|
|
66
|
+
* y_SC is set to 1 rather than being computed. If ${decr} is non-zero,
|
|
67
|
+
* "local" == "S" and "remote" == "C"; otherwise the assignments are opposite.
|
|
68
|
+
*/
|
|
69
|
+
int proto_crypt_mkkeys(const struct proto_secret *,
|
|
70
|
+
const uint8_t[PCRYPT_NONCE_LEN], const uint8_t[PCRYPT_NONCE_LEN],
|
|
71
|
+
const uint8_t[PCRYPT_YH_LEN], const uint8_t[PCRYPT_X_LEN], int, int,
|
|
72
|
+
struct proto_keys **, struct proto_keys **);
|
|
73
|
+
|
|
74
|
+
/* Maximum size of an unencrypted packet. */
|
|
75
|
+
#define PCRYPT_MAXDSZ 1024
|
|
76
|
+
|
|
77
|
+
/* Size of an encrypted packet. */
|
|
78
|
+
#define PCRYPT_ESZ (PCRYPT_MAXDSZ + 4 /* len */ + 32 /* hmac */)
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* proto_crypt_enc(ibuf, len, obuf, k):
|
|
82
|
+
* Encrypt ${len} bytes from ${ibuf} into PCRYPT_ESZ bytes using the keys in
|
|
83
|
+
* ${k}, and write the result into ${obuf}.
|
|
84
|
+
*/
|
|
85
|
+
void proto_crypt_enc(uint8_t *, size_t, uint8_t[PCRYPT_ESZ],
|
|
86
|
+
struct proto_keys *);
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* proto_crypt_dec(ibuf, obuf, k):
|
|
90
|
+
* Decrypt PCRYPT_ESZ bytes from ${ibuf} using the keys in ${k}. If the data
|
|
91
|
+
* is valid, write it into ${obuf} and return the length; otherwise, return
|
|
92
|
+
* -1.
|
|
93
|
+
*/
|
|
94
|
+
ssize_t proto_crypt_dec(uint8_t[PCRYPT_ESZ], uint8_t *, struct proto_keys *);
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* proto_crypt_free(k):
|
|
98
|
+
* Free the protocol key structure ${k}.
|
|
99
|
+
*/
|
|
100
|
+
void proto_crypt_free(struct proto_keys *);
|
|
101
|
+
|
|
102
|
+
#endif /* !_PCRYPT_H_ */
|