Skip to content

Commit ed4b592

Browse files
committedJan 6, 2020
This commit fixes the timestamp issues in public key tests.
In order to do this, the ability to disable timestamp verification is enabled. Furthermore, pubkey mode can be modified to decrypt topic messages IF the client does not hold a public key for that identifier. This option should be avoided where possible.
1 parent bf6c791 commit ed4b592

File tree

6 files changed

+92
-59
lines changed

6 files changed

+92
-59
lines changed
 

‎README.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ key management framework for MQTT and other publish-subscribe protocols.
3131
const uint8_t *message,
3232
size_t message_len,
3333
const char *topic_name,
34-
e4storage *storage);` - this function takes a message
34+
e4storage *storage,
35+
const uint32_t proto_opts);` - this function takes a message
3536
to be protected and a "topic" for which it should be protected and returns
3637
ciphertext that can be sent using your messaging layer.
3738
* `int e4c_unprotect_message(uint8_t *message,
@@ -40,7 +41,8 @@ key management framework for MQTT and other publish-subscribe protocols.
4041
const uint8_t *ciphertext,
4142
size_t ciphertext_len,
4243
const char *topic_name,
43-
e4storage *storage);`
44+
e4storage *storage,
45+
const uint32_t proto_opts);`
4446
This function performs the reverse of the protect function.
4547

4648
We talk of message *protection* instead of just *encryption* because the

‎include/e4/e4.h

+17-3
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,19 @@ struct _e4storage;
9595
defines. */
9696
typedef struct _e4storage e4storage;
9797

98+
/* Options bits for e4c crypto functions: */
99+
100+
/* Disable checks on message timestamp within acceptable window
101+
* Packet timestamps are still covered by authenticated encryption,
102+
* but older messages are allowed */
103+
#define E4_OPTION_IGNORE_TIMESTAMP 0x01
104+
/* Disable failure if we do not have a client public key to validate
105+
* signatures. Corrupt signatures will ALWAYS fail, this is only
106+
* for the case where too many clients exist for us to store all of
107+
* their keys. */
108+
#define E4_OPTION_IGNORE_MISSING_PUBKEY 0x02
109+
110+
98111
/* e4c_protect_message produces a protected message for onwards
99112
transmission.
100113
@@ -126,7 +139,8 @@ int e4c_protect_message(uint8_t *ciphertext,
126139
const uint8_t *message,
127140
size_t message_len,
128141
const char *topic_name,
129-
e4storage *storage);
142+
e4storage *storage,
143+
const uint32_t proto_opts);
130144

131145
/* e4c_unprotect_message retrieves and authenticates a message that was
132146
encrypted by E4.
@@ -158,8 +172,8 @@ int e4c_unprotect_message(uint8_t *message,
158172
const uint8_t *ciphertext,
159173
size_t ciphertext_len,
160174
const char *topic_name,
161-
e4storage *storage
162-
);
175+
e4storage *storage,
176+
const uint32_t proto_opts);
163177

164178

165179
/* the e4storage type pre-defined above implements these API calls */

‎src/e4pkcclient.c

+42-34
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ int e4c_protect_message(uint8_t *cptr,
4747
const uint8_t *mptr,
4848
size_t mlen,
4949
const char *topic,
50-
e4storage *storage)
50+
e4storage *storage,
51+
const uint32_t proto_opts)
5152
{
5253
int i = 0;
5354
size_t clen_siv = 0;
@@ -140,7 +141,8 @@ int e4c_unprotect_message(uint8_t *mptr,
140141
const uint8_t *cptr,
141142
size_t clen,
142143
const char *topic,
143-
e4storage *storage)
144+
e4storage *storage,
145+
const uint32_t proto_opts)
144146
{
145147
uint8_t control = 0;
146148
int j = 0, r = 0;
@@ -152,9 +154,9 @@ int e4c_unprotect_message(uint8_t *mptr,
152154
size_t sivpayloadlen = 0;
153155

154156
#ifndef __AVR__
155-
/*uint64_t secs1970;
157+
uint64_t secs1970;
156158

157-
secs1970 = (uint64_t)time(NULL); / this system has a RTC */
159+
secs1970 = (uint64_t)time(NULL); /* this system has a RTC */
158160
#endif
159161

160162
if (cptr == NULL ||
@@ -225,27 +227,31 @@ int e4c_unprotect_message(uint8_t *mptr,
225227
if (i >= 0)
226228
{
227229
e4c_getdevicekey(sender_pk, storage, i);
228-
}
229-
else
230-
{
231-
/* TODO: policies to not validate sigs if key not found
232-
due to storage constraints.
233-
234-
NOTE: this MUST NOT be conflated with signature verif
235-
failure. If signatures fail to verify we will _always_
236-
reject the message.
237-
*/
238-
239-
return E4_ERROR_DEVICEPK_MISSING;
240-
}
241-
242-
/* check signature attached to end */
243-
signverifresult = ed25519_verify(&cptr[clen-E4_PK_EDDSA_SIG_LEN],
230+
231+
/* check signature attached to end */
232+
signverifresult = ed25519_verify(&cptr[clen-E4_PK_EDDSA_SIG_LEN],
244233
cptr, clen-E4_PK_EDDSA_SIG_LEN, sender_pk);
245234

246-
if (signverifresult != 1)
235+
if (signverifresult != 1)
236+
{
237+
return E4_ERROR_PK_SIGVERIF_FAILED;
238+
}
239+
}
240+
else
247241
{
248-
return E4_ERROR_PK_SIGVERIF_FAILED;
242+
/* NOTE: given the limited storage capacity of
243+
* client devices, it might be acceptable to decrypt topic messages
244+
* even when we do not have the public key of the sending client.
245+
* If E4_OPTION_IGNORE_MISSING_PUBKEY is set, the client has
246+
* asked for this behaviour. If not, we should return an error.
247+
*
248+
* THIS IS NOT THE SAME as disabling signature validation. IF we
249+
* have a key at all for a client, signature verification
250+
* must succeed. This option is a get-out for when we cannot
251+
* store keys due to storage constraints */
252+
if ( !(proto_opts & E4_OPTION_IGNORE_MISSING_PUBKEY) ) {
253+
return E4_ERROR_DEVICEPK_MISSING;
254+
}
249255
}
250256

251257
/* find the topic key and set it */
@@ -299,31 +305,33 @@ int e4c_unprotect_message(uint8_t *mptr,
299305

300306

301307
/* Since AVR has no real time clock, time is initially unknown. */
302-
/*if (secs1970 < 946684800)
308+
if (secs1970 < 946684800)
303309
{
304-
/.* calibrate message if this is a control message
310+
/* calibrate message if this is a control message */
305311
if (control) {
306312
secs1970 = tstamp;
307313
}
308314
}
309315
else
310316
{
311317

312-
if (tstamp >= secs1970)
313-
{
314-
if (tstamp - secs1970 > E4C_TIME_FUTURE)
318+
if (!(proto_opts & E4_OPTION_IGNORE_TIMESTAMP )) {
319+
if (tstamp >= secs1970)
315320
{
316-
return E4_ERROR_TIMESTAMP_IN_FUTURE;
321+
if (tstamp - secs1970 > E4C_TIME_FUTURE)
322+
{
323+
return E4_ERROR_TIMESTAMP_IN_FUTURE;
324+
}
317325
}
318-
}
319-
else
320-
{
321-
if (secs1970 - tstamp > E4C_TIME_TOO_OLD)
326+
else
322327
{
323-
return E4_ERROR_TIMESTAMP_TOO_OLD;
328+
if (secs1970 - tstamp > E4C_TIME_TOO_OLD)
329+
{
330+
return E4_ERROR_TIMESTAMP_TOO_OLD;
331+
}
324332
}
325333
}
326-
}*/
334+
}
327335

328336
/* if not control channel, we can exit now; no command to process. */
329337
if (!(control)) return E4_RESULT_OK;

‎src/e4symclient.c

+15-12
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ int e4c_protect_message(uint8_t *cptr,
4343
const uint8_t *mptr,
4444
size_t mlen,
4545
const char *topic,
46-
e4storage *storage)
46+
e4storage *storage,
47+
const uint32_t proto_opts)
4748
{
4849
int i = 0;
4950
uint8_t key[E4_KEY_LEN];
@@ -112,7 +113,8 @@ int e4c_unprotect_message(uint8_t *mptr,
112113
const uint8_t *cptr,
113114
size_t clen,
114115
const char *topic,
115-
e4storage *storage)
116+
e4storage *storage,
117+
const uint32_t proto_opts)
116118
{
117119
uint8_t control = 0;
118120
int i = 0, j = 0, r = 0;
@@ -190,19 +192,20 @@ int e4c_unprotect_message(uint8_t *mptr,
190192
}
191193
else
192194
{
193-
194-
if (tstamp >= secs1970)
195-
{
196-
if (tstamp - secs1970 > E4C_TIME_FUTURE)
195+
if (!(proto_opts & E4_OPTION_IGNORE_TIMESTAMP )) {
196+
if (tstamp >= secs1970)
197197
{
198-
return E4_ERROR_TIMESTAMP_IN_FUTURE;
198+
if (tstamp - secs1970 > E4C_TIME_FUTURE)
199+
{
200+
return E4_ERROR_TIMESTAMP_IN_FUTURE;
201+
}
199202
}
200-
}
201-
else
202-
{
203-
if (secs1970 - tstamp > E4C_TIME_TOO_OLD)
203+
else
204204
{
205-
return E4_ERROR_TIMESTAMP_TOO_OLD;
205+
if (secs1970 - tstamp > E4C_TIME_TOO_OLD)
206+
{
207+
return E4_ERROR_TIMESTAMP_TOO_OLD;
208+
}
206209
}
207210
}
208211
}

‎test/pubkey/pubkey_e4cmd_test.c

+12-6
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ int main(int argc, char** argv, char** envp) {
102102
pkkat[i].cmd_resettopics,
103103
pkkat[i].cmd_resettopics_len,
104104
ctrltopic,
105-
&store);
105+
&store,
106+
E4_OPTION_IGNORE_TIMESTAMP);
106107

107108
if ( e4retcode != E4_RESULT_OK_CONTROL ) {
108109
printf("Failed: e4c_unprotect_message returned error code other than 'this is a command'\n");
@@ -120,7 +121,8 @@ int main(int argc, char** argv, char** envp) {
120121
pkkat[i].cmd_settopickey,
121122
pkkat[i].cmd_settopickey_len,
122123
ctrltopic,
123-
&store);
124+
&store,
125+
E4_OPTION_IGNORE_TIMESTAMP);
124126

125127
if ( e4retcode != E4_RESULT_OK_CONTROL ) {
126128
printf("Failed: e4c_unprotect_message returned error code other than 'this is a command'\n");
@@ -138,7 +140,8 @@ int main(int argc, char** argv, char** envp) {
138140
pkkat[i].cmd_removetopic,
139141
pkkat[i].cmd_removetopic_len,
140142
ctrltopic,
141-
&store);
143+
&store,
144+
E4_OPTION_IGNORE_TIMESTAMP);
142145

143146
if ( e4retcode != E4_RESULT_OK_CONTROL ) {
144147
printf("Failed: e4c_unprotect_message returned error code other than 'this is a command'\n");
@@ -156,7 +159,8 @@ int main(int argc, char** argv, char** envp) {
156159
pkkat[i].cmd_resetpubkeys,
157160
pkkat[i].cmd_resetpubkeys_len,
158161
ctrltopic,
159-
&store);
162+
&store,
163+
E4_OPTION_IGNORE_TIMESTAMP);
160164

161165
if ( e4retcode != E4_RESULT_OK_CONTROL ) {
162166
printf("Failed: e4c_unprotect_message returned error code other than 'this is a command'\n");
@@ -174,7 +178,8 @@ int main(int argc, char** argv, char** envp) {
174178
pkkat[i].cmd_setpubkey,
175179
pkkat[i].cmd_setpubkey_len,
176180
ctrltopic,
177-
&store);
181+
&store,
182+
E4_OPTION_IGNORE_TIMESTAMP);
178183

179184
if ( e4retcode != E4_RESULT_OK_CONTROL ) {
180185
printf("Failed: e4c_unprotect_message returned error code other than 'this is a command'\n");
@@ -192,7 +197,8 @@ int main(int argc, char** argv, char** envp) {
192197
pkkat[i].cmd_removepubkey,
193198
pkkat[i].cmd_removepubkey_len,
194199
ctrltopic,
195-
&store);
200+
&store,
201+
E4_OPTION_IGNORE_TIMESTAMP);
196202

197203
if ( e4retcode != E4_RESULT_OK_CONTROL ) {
198204
printf("Failed: e4c_unprotect_message returned error code other than 'this is a command'\n");

‎test/symkey/symkey_file.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ int main(int argc, char** argv, char** envp) {
146146
}
147147

148148
e4retcode = e4c_protect_message(ciphertext_buffer, PT_MAX+E4_MSGHDR_LEN, &ciphertext_len,
149-
plaintext_buffer, PT_MAX, topicname, &store);
149+
plaintext_buffer, PT_MAX, topicname, &store, 0);
150150

151151
if (e4retcode != E4_RESULT_OK) {
152152
returncode = 12;
@@ -164,7 +164,7 @@ int main(int argc, char** argv, char** envp) {
164164
get rid of this functionality and leave it to the user. For now,
165165
we fix it by passing the correct length of the recovered buffer. */
166166
e4retcode = e4c_unprotect_message(recovered_buffer, PT_MAX+1, &recovered_len,
167-
ciphertext_buffer, PT_MAX+E4_MSGHDR_LEN, topicname, &store);
167+
ciphertext_buffer, PT_MAX+E4_MSGHDR_LEN, topicname, &store, 0);
168168

169169
if (e4retcode != E4_RESULT_OK) {
170170
returncode = 13;

0 commit comments

Comments
 (0)
Please sign in to comment.