Skip to content

Commit ff4eb95

Browse files
committed
Fix time sensitive exploit as referenced in https://gruss.cc/files/counterseveillance.pdf (thank you)
1 parent d96c79c commit ff4eb95

File tree

3 files changed

+40
-32
lines changed

3 files changed

+40
-32
lines changed

cotp.c

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -124,43 +124,29 @@ void otp_free(OTPData* data)
124124
1 success
125125
error, 0
126126
*/
127-
COTPRESULT otp_byte_secret(OTPData* data, char* out_str)
128-
{
129-
if (out_str == NULL || strlen(data->base32_secret) % 8 != 0)
127+
COTPRESULT otp_byte_secret(OTPData* data, char* out_str) {
128+
if (out_str == NULL || strlen(data->base32_secret) % 8 != 0) {
130129
return OTP_ERROR;
130+
}
131131

132132
size_t base32_length = strlen(data->base32_secret);
133133
size_t num_blocks = base32_length / 8;
134134
size_t output_length = num_blocks * 5;
135135

136-
if (output_length == 0)
136+
if (output_length == 0) {
137137
return OTP_OK;
138+
}
138139

139-
for (size_t i = 0; i < num_blocks; i++)
140-
{
140+
int valid = 1;
141+
142+
for (size_t i = 0; i < num_blocks; i++) {
141143
unsigned int block_values[8] = { 0 };
142144

143-
for (int j = 0; j < 8; j++)
144-
{
145+
for (int j = 0; j < 8; j++) {
145146
char c = data->base32_secret[i * 8 + j];
146-
if (c == '=')
147-
break;
148-
149-
int found = 0;
150-
for (int k = 0; k < 32; k++)
151-
{
152-
if (c == OTP_DEFAULT_BASE32_CHARS[k])
153-
{
154-
block_values[j] = k;
155-
found = 1;
156-
break;
157-
}
158-
}
159-
160-
if (!found)
161-
{
162-
return OTP_ERROR;
163-
}
147+
unsigned int value = (unsigned char) c < 256 ? OTP_DEFAULT_BASE32_OFFSETS[(unsigned char) c] : -1;
148+
block_values[j] = value & 31;
149+
valid &= (value >= 0);
164150
}
165151

166152
out_str[i * 5] = (block_values[0] << 3) | (block_values[1] >> 2);
@@ -169,8 +155,8 @@ COTPRESULT otp_byte_secret(OTPData* data, char* out_str)
169155
out_str[i * 5 + 3] = (block_values[4] << 7) | (block_values[5] << 2) | (block_values[6] >> 3);
170156
out_str[i * 5 + 4] = (block_values[6] << 5) | block_values[7];
171157
}
172-
173-
return OTP_OK;
158+
159+
return valid ? OTP_OK : OTP_ERROR;
174160
}
175161

176162
/*

cotp.h

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,30 @@ typedef int COTPRESULT;
1212

1313

1414
/*
15-
Default characters used in BASE32 digests.
15+
Default characters used in BASE32 digests for security concious linear lookup.
16+
For use with otp_byte_secret()
17+
*/
18+
static const int OTP_DEFAULT_BASE32_OFFSETS[256] = {
19+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15
20+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31
21+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32-47
22+
0, 0, 26, 27, 28, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, // 48-63 ('2'-'7')
23+
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79 ('A'-'O')
24+
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, // 80-95 ('P'-'Z')
25+
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 96-111 ('a'-'o')
26+
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, // 112-127 ('p'-'z')
27+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128-143
28+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144-159
29+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160-175
30+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176-191
31+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192-207
32+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208-223
33+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224-239
34+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 240-255
35+
};
36+
37+
/*
38+
1639
For use with otp_random_base32()
1740
*/
1841
static const char OTP_DEFAULT_BASE32_CHARS[32] =
@@ -23,7 +46,6 @@ static const char OTP_DEFAULT_BASE32_CHARS[32] =
2346
'6', '7'
2447
};
2548

26-
2749
/*
2850
Used for differentiation on which
2951
method you are using. Necessary

test/main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,8 @@ int main(int argc, char** argv)
226226
char base32_new_secret[base32_len + 1];
227227
memset(&base32_new_secret, 0, base32_len + 1);
228228

229-
otp_random_base32(base32_len, base32_new_secret);
230-
printf("Random Generated BASE32 Secret: `%s`\n", base32_new_secret);
229+
int random_otp_err = otp_random_base32(base32_len, base32_new_secret);
230+
printf("Random Generated BASE32 Secret pass=1: `%s` `%d`\n", base32_new_secret, random_otp_err);
231231

232232
puts(""); // line break for readability
233233

0 commit comments

Comments
 (0)