Skip to content

Commit

Permalink
Did the following:
Browse files Browse the repository at this point in the history
- Milliseconds are not valid for TOTP
- Rolling a new Base32 decoder
- Code formatting
  • Loading branch information
tilkinsc committed Jun 13, 2023
1 parent 56c6b53 commit 1a6ad6e
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 53 deletions.
106 changes: 60 additions & 46 deletions cotp.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,37 +126,48 @@ void otp_free(OTPData* data)
*/
COTPRESULT otp_byte_secret(OTPData* data, char* out_str)
{
if(out_str == NULL || strlen(data->base32_secret) % 8 != 0)
if (out_str == NULL || strlen(data->base32_secret) % 8 != 0)
return OTP_ERROR;

int n = 5;
for (size_t i=0; ; i++)
size_t base32_length = strlen(data->base32_secret);
size_t num_blocks = base32_length / 8;
size_t output_length = num_blocks * 5;

if (output_length == 0)
return OTP_OK;

static const char* base32_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";

for (size_t i = 0; i < num_blocks; i++)
{
n = -1;
out_str[i*5] = 0;
for (int block=0; block<8; block++)
unsigned int block_values[8] = { 0 };

for (int j = 0; j < 8; j++)
{
int offset = (3 - (5*block) % 8);
int octet = (block*5)/8;
char c = data->base32_secret[i * 8 + j];
int found = 0;

unsigned int c = data->base32_secret[i*8 + block];
if (c >= 'A' && c <= 'Z')
n = c - 'A';
if (c >= '2' && c <= '7')
n = 26 + c - '2';
if (n < 0)
for (int k = 0; k < 32; k++)
{
n = octet;
break;
if (c == base32_chars[k])
{
block_values[j] = k;
found = 1;
break;
}
}
out_str[i*5 + octet] |= -offset > 0 ? n >> -offset : n << offset;
if (offset < 0)

if (!found)
{
out_str[i*5 + octet + 1] = -(8 + offset) > 0 ? n >> -(8 + offset) : n << (8 + offset);
return OTP_ERROR;
}
}
if(n < 5)
break;

out_str[i * 5] = (block_values[0] << 3) | (block_values[1] >> 2);
out_str[i * 5 + 1] = (block_values[1] << 6) | (block_values[2] << 1) | (block_values[3] >> 4);
out_str[i * 5 + 2] = (block_values[3] << 4) | (block_values[4] >> 1);
out_str[i * 5 + 3] = (block_values[4] << 7) | (block_values[5] << 2) | (block_values[6] >> 3);
out_str[i * 5 + 4] = (block_values[6] << 5) | block_values[7];
}

return OTP_OK;
Expand All @@ -173,13 +184,14 @@ COTPRESULT otp_byte_secret(OTPData* data, char* out_str)
*/
COTPRESULT otp_num_to_bytestring(uint64_t integer, char* out_str)
{
if(out_str == NULL)
if (out_str == NULL)
return OTP_ERROR;

size_t i = 7;
while (integer != 0)
{
out_str[i--] = integer & 0xFF;
out_str[i] = integer & 0xFF;
i--;
integer >>= 8;
}

Expand All @@ -202,7 +214,7 @@ COTPRESULT otp_num_to_bytestring(uint64_t integer, char* out_str)
*/
COTPRESULT otp_random_base32(size_t len, const char* chars, char* out_str)
{
if(chars == NULL || out_str == NULL)
if (chars == NULL || out_str == NULL)
return OTP_ERROR;

len = len > 0 ? len : 16;
Expand Down Expand Up @@ -238,12 +250,12 @@ COTPRESULT totp_compare(OTPData* data, const char* key, int64_t offset, uint64_t
char time_str[data->digits+1];
memset(time_str, 0, data->digits+1);

if(totp_at(data, for_time, offset, time_str) == 0)
if (totp_at(data, for_time, offset, time_str) == 0)
return OTP_ERROR;

for (size_t i=0; i<data->digits; i++)
{
if(key[i] != time_str[i])
if (key[i] != time_str[i])
return OTP_ERROR;
}

Expand Down Expand Up @@ -295,15 +307,15 @@ COTPRESULT totp_now(OTPData* data, char* out_str)
*/
COTPRESULT totp_verify(OTPData* data, const char* key, uint64_t for_time, int64_t valid_window)
{
if(valid_window < 0)
if (key == NULL || valid_window < 0)
return OTP_ERROR;

if(valid_window > 0)
if (valid_window > 0)
{
for (int64_t i=-valid_window; i<valid_window+1; i++)
{
int cmp = totp_compare(data, key, i, for_time);
if(cmp == 1)
if (cmp == 1)
return cmp;
}
return OTP_ERROR;
Expand Down Expand Up @@ -342,7 +354,7 @@ uint64_t totp_valid_until(OTPData* data, uint64_t for_time, int64_t valid_window
*/
uint64_t totp_timecode(OTPData* data, uint64_t for_time)
{
if(data->interval <= 0)
if (data->interval <= 0)
return OTP_ERROR;

return for_time/data->interval;
Expand All @@ -363,15 +375,18 @@ uint64_t totp_timecode(OTPData* data, uint64_t for_time)
*/
int hotp_compare(OTPData* data, const char* key, uint64_t counter)
{
if (key == NULL)
return OTP_ERROR;

char cnt_str[data->digits+1];
memset(cnt_str, 0, data->digits+1);

if(hotp_at(data, counter, cnt_str) == 0)
if (hotp_at(data, counter, cnt_str) == 0)
return OTP_ERROR;

for (size_t i=0; i<data->digits; i++)
{
if(key[i] != cnt_str[i])
if (key[i] != cnt_str[i])
return OTP_ERROR;
}

Expand Down Expand Up @@ -419,9 +434,9 @@ int hotp_next(OTPData* data, char* out_str)
*/
COTPRESULT otp_generate(OTPData* data, uint64_t input, char* out_str)
{
// char* byte_string = calloc(8+1, sizeof(char));
// char* byte_secret = calloc((strlen(data->base32_secret)/8)*5 + 1, sizeof(char));
// char* hmac = calloc(64+1, sizeof(char));
if (out_str == NULL)
return OTP_ERROR;

char byte_string[8+1];
memset(byte_string, 0, 8+1);

Expand All @@ -432,26 +447,25 @@ COTPRESULT otp_generate(OTPData* data, uint64_t input, char* out_str)
char hmac[64+1];
memset(hmac, 0, 64+1);

if(otp_num_to_bytestring(input, byte_string) == 0
if (otp_num_to_bytestring(input, byte_string) == 0
|| otp_byte_secret(data, byte_secret) == 0)
return OTP_ERROR;

int hmac_len = (*(data->algo))(byte_secret, byte_string, hmac);
if (hmac_len == 0)
return OTP_ERROR;

uint64_t offset = (hmac[hmac_len-1] & 0xF);
uint64_t offset = (hmac[hmac_len - 1] & 0xF);
uint64_t code =
((hmac[offset] & 0x7F) << 24 |
(hmac[offset+1] & 0xFF) << 16 |
(hmac[offset+2] & 0xFF) << 8 |
(hmac[offset+3] & 0xFF));
code %= (uint64_t) pow(10, data->digits);
(((hmac[offset] & 0x7F) << 24)
| ((hmac[offset+1] & 0xFF) << 16)
| ((hmac[offset+2] & 0xFF) << 8)
| ((hmac[offset+3] & 0xFF)));

if(out_str != NULL)
{
sprintf(out_str, "%0*zu", data->digits, code);
}
static const uint64_t POWERS[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
code %= (uint64_t) POWERS[data->digits];

sprintf(out_str, "%0*zu", data->digits, code);

return OTP_OK;
}
Expand Down
4 changes: 2 additions & 2 deletions otpuri.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
*/
COTPRESULT otpuri_encode_url(const char* data, size_t length, char* output)
{
if (data == 0 || output == 0)
if (data == NULL || output == NULL)
return OTP_ERROR;

static const char to_test[] = "\"<>#%@{}|\\^~[]` ?&";
Expand Down Expand Up @@ -82,7 +82,7 @@ size_t otpuri_strlen(OTPData* data, const char* issuer, const char* name, const
*/
COTPRESULT otpuri_build_uri(OTPData* data, const char* issuer, const char* name, const char* digest, char* output)
{
if (issuer == 0 || name == 0 || digest == 0 || output == 0)
if (issuer == NULL || name == NULL || digest == NULL || output == NULL)
return OTP_ERROR;

strcat(output, "otpuri://");
Expand Down
7 changes: 3 additions & 4 deletions test/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ int hmac_algo_sha512(const char* byte_secret, const char* byte_string, char* out
return result == 0 ? 0 : len;
}

// TODO: use a secure random generator
uint64_t get_current_time()
{
uint64_t milliseconds = 0;
Expand All @@ -90,12 +89,12 @@ uint64_t get_current_time()
largeInteger.LowPart = fileTime.dwLowDateTime;
largeInteger.HighPart = fileTime.dwHighDateTime;

milliseconds = (largeInteger.QuadPart - 116444736000000000ULL) / 10000;
milliseconds = (largeInteger.QuadPart - 116444736000000000ULL) / 10000000ULL;
#elif defined(__linux__)
struct timeval sys_time;
gettimeofday(&sys_time, NULL);

milliseconds = sys_time.tv_sec * 1000 + sys_time.tv_usec / 1000;
milliseconds = sys_time.tv_sec;
#endif

return milliseconds;
Expand All @@ -114,7 +113,7 @@ int main(int argc, char** argv)


// Base32 secret to utilize
const char BASE32_SECRET[] = "JBSWY3DPEHPK3PXP";
const char BASE32_SECRET[] = "JBSWY3DPEHPK3PXP"; // JBSWY3DPEHPK3PXP 3E56263A4A655ED7

OTPData odata1;
memset(&odata1, 0, sizeof(OTPData));
Expand Down
2 changes: 1 addition & 1 deletion test/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ uint64_t get_current_time()
auto now = system_clock::now();
auto dur = now.time_since_epoch();

return duration_cast<chrono::milliseconds>(dur).count();
return duration_cast<chrono::seconds>(dur).count();
}


Expand Down

0 comments on commit 1a6ad6e

Please sign in to comment.