RTE RBC 2oo2 Reference Application
0.1.0 build 0006685
SIL 4 2oo2 Dual-Site Fault-Tolerant ERTMS Radio Block Centre Reference Architecture
Toggle main menu visibility
Loading...
Searching...
No Matches
ab_gp_takeover_key.c
Go to the documentation of this file.
1
5
#include "
ab_gp_takeover_key.h
"
6
7
#include <stdio.h>
8
#include <string.h>
9
10
#include "safecomm/mac/mac.h"
11
12
static
uint8_t
s_key
[SAFECOMM_MAC_KEY_LEN];
13
static
bool
s_key_loaded
=
false
;
14
15
static
int
hex_nibble
(
char
c)
16
{
17
if
((c >=
'0'
) && (c <=
'9'
))
18
{
19
return
c -
'0'
;
20
}
21
if
((c >=
'a'
) && (c <=
'f'
))
22
{
23
return
(c -
'a'
) + 10;
24
}
25
if
((c >=
'A'
) && (c <=
'F'
))
26
{
27
return
(c -
'A'
) + 10;
28
}
29
return
-1;
30
}
31
32
/* Exactly 2 * len hex characters from hex into out; false on any non-hex character. */
33
static
bool
decode_hex
(
const
char
*hex, uint8_t *out,
size_t
len)
34
{
35
size_t
i;
36
37
for
(i = 0U; i < len; i++)
38
{
39
int
hi =
hex_nibble
(hex[2U * i]);
40
int
lo =
hex_nibble
(hex[(2U * i) + 1U]);
41
42
if
((hi < 0) || (lo < 0))
43
{
44
return
false
;
45
}
46
out[i] = (uint8_t)((hi << 4) | lo);
47
}
48
return
true
;
49
}
50
51
/* Strips a `#` comment and surrounding whitespace in place; returns the remaining text (may be empty). */
52
static
char
*
trim_line
(
char
*line)
53
{
54
char
*hash = strchr(line,
'#'
);
55
char
*p = line;
56
size_t
n;
57
58
if
(hash != NULL)
59
{
60
*hash =
'\0'
;
61
}
62
while
((*p ==
' '
) || (*p ==
'\t'
))
63
{
64
p++;
65
}
66
n = strlen(p);
67
while
((n > 0U) && ((p[n - 1U] ==
' '
) || (p[n - 1U] ==
'\t'
) || (p[n - 1U] ==
'\r'
) || (p[n - 1U] ==
'\n'
)))
68
{
69
p[n - 1U] =
'\0'
;
70
n--;
71
}
72
return
p;
73
}
74
75
bool
ab_gp_takeover_key_load_file
(
const
char
*path)
76
{
77
FILE *fp;
78
char
line[160];
79
uint8_t key[SAFECOMM_MAC_KEY_LEN];
80
uint32_t keys = 0U;
81
bool
ok =
true
;
82
83
s_key_loaded
=
false
;
84
(void)memset(
s_key
, 0,
sizeof
(
s_key
));
85
if
(path == NULL)
86
{
87
return
false
;
88
}
89
fp = fopen(path,
"r"
);
90
if
(fp == NULL)
91
{
92
return
false
;
93
}
94
while
(ok && (fgets(line, (
int
)
sizeof
(line), fp) != NULL))
95
{
96
char
*p =
trim_line
(line);
97
98
if
(*p ==
'\0'
)
99
{
100
continue
;
101
}
102
keys++;
103
ok = (keys == 1U) && (strlen(p) == (2U * SAFECOMM_MAC_KEY_LEN)) &&
decode_hex
(p, key,
sizeof
(key));
104
}
105
(void)fclose(fp);
106
(void)memset(line, 0,
sizeof
(line));
107
if
(ok && (keys == 1U))
108
{
109
(void)memcpy(
s_key
, key,
sizeof
(
s_key
));
110
s_key_loaded
=
true
;
111
}
112
(void)memset(key, 0,
sizeof
(key));
113
return
s_key_loaded
;
114
}
115
116
bool
ab_gp_takeover_key_loaded
(
void
)
117
{
118
return
s_key_loaded
;
119
}
120
121
bool
ab_gp_takeover_verify_mac
(
void
*user,
const
uint8_t *msg,
size_t
msg_len,
122
const
uint8_t mac[RTE_SITE_ROLE_TOKEN_MAC_LEN])
123
{
124
safecomm_mac_ctx_t mac_ctx;
125
bool
match;
126
127
(void)user;
128
if
((!
s_key_loaded
) || (msg == NULL) || (mac == NULL))
129
{
130
return
false
;
131
}
132
(void)memcpy(mac_ctx.ksmac,
s_key
,
sizeof
(mac_ctx.ksmac));
133
mac_ctx.alg = SAFECOMM_MAC_ALG_3DES_SS037;
134
match = (safecomm_mac_verify(&mac_ctx, msg, msg_len, mac) == SAFECOMM_STATUS_OK);
135
(void)memset(&mac_ctx, 0,
sizeof
(mac_ctx));
136
return
match;
137
}
138
139
bool
ab_gp_takeover_token_from_payload
(
const
char
*payload, uint8_t out[RTE_SITE_ROLE_TOKEN_LEN])
140
{
141
const
size_t
prefix_len =
sizeof
(
AB_GP_TAKEOVER_TOKEN_PREFIX
) - 1U;
142
143
if
((payload == NULL) || (out == NULL) || (strncmp(payload,
AB_GP_TAKEOVER_TOKEN_PREFIX
, prefix_len) != 0) ||
144
(strlen(&payload[prefix_len]) != (2U * (
size_t
)RTE_SITE_ROLE_TOKEN_LEN)))
145
{
146
return
false
;
147
}
148
return
decode_hex
(&payload[prefix_len], out, (
size_t
)RTE_SITE_ROLE_TOKEN_LEN);
149
}
150
151
bool
ab_gp_takeover_token_build
(uint8_t site_id, uint8_t channel_id, uint32_t challenge, uint32_t seq,
152
uint8_t out[RTE_SITE_ROLE_TOKEN_LEN])
153
{
154
safecomm_mac_ctx_t mac_ctx;
155
bool
ok;
156
157
if
((!
s_key_loaded
) || (out == NULL))
158
{
159
return
false
;
160
}
161
(void)memset(out, 0, RTE_SITE_ROLE_TOKEN_LEN);
162
out[0] = (uint8_t)RTE_SITE_ROLE_TOKEN_VERSION;
163
out[1] = site_id;
164
out[2] = channel_id;
165
out[4] = (uint8_t)(challenge & 0xFFU);
166
out[5] = (uint8_t)((challenge >> 8U) & 0xFFU);
167
out[6] = (uint8_t)((challenge >> 16U) & 0xFFU);
168
out[7] = (uint8_t)((challenge >> 24U) & 0xFFU);
169
out[8] = (uint8_t)(seq & 0xFFU);
170
out[9] = (uint8_t)((seq >> 8U) & 0xFFU);
171
out[10] = (uint8_t)((seq >> 16U) & 0xFFU);
172
out[11] = (uint8_t)((seq >> 24U) & 0xFFU);
173
(void)memcpy(mac_ctx.ksmac,
s_key
,
sizeof
(mac_ctx.ksmac));
174
mac_ctx.alg = SAFECOMM_MAC_ALG_3DES_SS037;
175
ok = (safecomm_mac_compute(&mac_ctx, out, (
size_t
)RTE_SITE_ROLE_TOKEN_MSG_LEN, &out[RTE_SITE_ROLE_TOKEN_MSG_LEN]) ==
176
SAFECOMM_STATUS_OK);
177
(void)memset(&mac_ctx, 0,
sizeof
(mac_ctx));
178
return
ok;
179
}
180
181
bool
ab_gp_takeover_token_to_payload
(
const
uint8_t token[RTE_SITE_ROLE_TOKEN_LEN],
char
*out,
size_t
out_size)
182
{
183
static
const
char
digits[] =
"0123456789abcdef"
;
184
const
size_t
prefix_len =
sizeof
(
AB_GP_TAKEOVER_TOKEN_PREFIX
) - 1U;
185
size_t
i;
186
187
if
((token == NULL) || (out == NULL) || (out_size < (prefix_len + (2U * (
size_t
)RTE_SITE_ROLE_TOKEN_LEN) + 1U)))
188
{
189
return
false
;
190
}
191
(void)memcpy(out,
AB_GP_TAKEOVER_TOKEN_PREFIX
, prefix_len);
192
for
(i = 0U; i < (size_t)RTE_SITE_ROLE_TOKEN_LEN; i++)
193
{
194
out[prefix_len + (2U * i)] = digits[(token[i] >> 4U) & 0x0FU];
195
out[prefix_len + (2U * i) + 1U] = digits[token[i] & 0x0FU];
196
}
197
out[prefix_len + (2U * (size_t)RTE_SITE_ROLE_TOKEN_LEN)] =
'\0'
;
198
return
true
;
199
}
hex_nibble
static int hex_nibble(char c)
Definition
ab_gp_saf_train.c:160
ab_gp_takeover_token_from_payload
bool ab_gp_takeover_token_from_payload(const char *payload, uint8_t out[RTE_SITE_ROLE_TOKEN_LEN])
Decodes a util payload token=<48 hex> into a token.
Definition
ab_gp_takeover_key.c:139
s_key
static uint8_t s_key[SAFECOMM_MAC_KEY_LEN]
Definition
ab_gp_takeover_key.c:12
ab_gp_takeover_token_to_payload
bool ab_gp_takeover_token_to_payload(const uint8_t token[RTE_SITE_ROLE_TOKEN_LEN], char *out, size_t out_size)
Encodes a token as the util payload token=<48 hex> (NUL-terminated).
Definition
ab_gp_takeover_key.c:181
trim_line
static char * trim_line(char *line)
Definition
ab_gp_takeover_key.c:52
s_key_loaded
static bool s_key_loaded
Definition
ab_gp_takeover_key.c:13
ab_gp_takeover_key_loaded
bool ab_gp_takeover_key_loaded(void)
Definition
ab_gp_takeover_key.c:116
ab_gp_takeover_verify_mac
bool ab_gp_takeover_verify_mac(void *user, const uint8_t *msg, size_t msg_len, const uint8_t mac[RTE_SITE_ROLE_TOKEN_MAC_LEN])
rte_site_role verify_mac callback: true only when a key is loaded and the Subset-037 MAC over msg mat...
Definition
ab_gp_takeover_key.c:121
ab_gp_takeover_token_build
bool ab_gp_takeover_token_build(uint8_t site_id, uint8_t channel_id, uint32_t challenge, uint32_t seq, uint8_t out[RTE_SITE_ROLE_TOKEN_LEN])
Builds a token for one channel: the message (version, site id, channel id, challenge,...
Definition
ab_gp_takeover_key.c:151
decode_hex
static bool decode_hex(const char *hex, uint8_t *out, size_t len)
Definition
ab_gp_takeover_key.c:33
ab_gp_takeover_key_load_file
bool ab_gp_takeover_key_load_file(const char *path)
Loads the key file (one key, 48 hex characters) into this process's key slot.
Definition
ab_gp_takeover_key.c:75
ab_gp_takeover_key.h
The site's takeover key and the token codec for the dispatcher takeover confirmation (ADR-040 step 4b...
AB_GP_TAKEOVER_TOKEN_PREFIX
#define AB_GP_TAKEOVER_TOKEN_PREFIX
Definition
ab_gp_takeover_key.h:30
src
application
AB
GP
com
ab_gp_takeover_key.c
Generated by
1.18.0