Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 56 additions & 32 deletions cotp.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,32 @@

#include <openssl/rand.h>

// Not valid
enum { NV = 64 };

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

/*
Converts an OTPType enum to string.

Expand Down Expand Up @@ -115,6 +141,14 @@ void otp_free(OTPData* data)
free(data);
}

static size_t base32_len(const char *s)
{
size_t len = s ? strlen(s) : 0;
while (len > 0 && s[len-1] == '=')
--len;
return len;
}

/*
Un-base32's a base32 string stored inside an OTPData.

Expand All @@ -125,39 +159,29 @@ void otp_free(OTPData* data)
error, 0
*/
COTPRESULT otp_byte_secret(OTPData* data, char* out_str) {
if (out_str == NULL || strlen(data->base32_secret) % 8 != 0) {
const size_t base32_length = base32_len(data->base32_secret);

if (base32_length == 0)
return OTP_ERROR;
}

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;
}

int valid = 1;
unsigned char invalid = 0;
unsigned bits = 0, block_value = 0;

for (size_t i = 0; i < num_blocks; i++) {
uint64_t block_value = 0;

for (int j = 0; j < 8; j++) {
block_value <<= 5;
char c = data->base32_secret[i * 8 + j];
unsigned int value = (unsigned char) c < 256 ? OTP_DEFAULT_BASE32_OFFSETS[(unsigned char) c] : -1;
block_value |= value & 31;
valid &= (value >= 0);
for (size_t i = 0; i < base32_length ; i++) {
block_value <<= 5;
bits += 5;
unsigned char c = (unsigned char) data->base32_secret[i];
unsigned char value = c < 256 ? OTP_DEFAULT_BASE32_OFFSETS[c] : NV;
block_value |= value & 31;
invalid |= value;

if (bits >= 8) {
bits -= 8;
*out_str++ = (block_value >> bits) & 255;
}

out_str[i * 5 + 0] = block_value >> 32;
out_str[i * 5 + 1] = block_value >> 24;
out_str[i * 5 + 2] = block_value >> 16;
out_str[i * 5 + 3] = block_value >> 8;
out_str[i * 5 + 4] = block_value >> 0;
}

return valid ? OTP_OK : OTP_ERROR;
return invalid < NV ? OTP_OK : OTP_ERROR;
}

/*
Expand All @@ -174,13 +198,13 @@ COTPRESULT otp_num_to_bytestring(uint64_t integer, char* out_str)
if (out_str == NULL)
return OTP_ERROR;

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

return OTP_OK;
}
Expand Down Expand Up @@ -448,7 +472,7 @@ COTPRESULT otp_generate(OTPData* data, uint64_t input, char* out_str)
char byte_string[8+1];
memset(byte_string, 0, 8+1);

size_t bs_len = (strlen(data->base32_secret)/8)*5;
size_t bs_len = (base32_len(data->base32_secret)*5)/8;
char byte_secret[bs_len + 1];
memset(byte_secret, 0, bs_len + 1);

Expand Down
23 changes: 0 additions & 23 deletions cotp.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,6 @@ typedef int COTPRESULT;
#define OTP_ERROR ((COTPRESULT) 0)


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

/*

For use with otp_random_base32()
Expand Down
10 changes: 5 additions & 5 deletions test/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ int main(int argc, char** argv)
int totp_err_1 = totp_now(tdata, tcode);
if(totp_err_1 == OTP_ERROR)
{
fputs("TOTP Error totp_now", stderr);
fputs("TOTP Error totp_now\n", stderr);
return EXIT_FAILURE;
}
printf("totp_now() pass=1: `%s` `%d`\n", tcode, totp_err_1);
Expand All @@ -251,7 +251,7 @@ int main(int argc, char** argv)
int totp_err_2 = totp_at(tdata, 0, 0, tcode2);
if(totp_err_2 == OTP_ERROR)
{
fputs("TOTP Error totp_at", stderr);
fputs("TOTP Error totp_at\n", stderr);
return EXIT_FAILURE;
}
printf("totp_at(0, 0) pass=1: `%s` `%d`\n", tcode2, totp_err_2);
Expand Down Expand Up @@ -288,7 +288,7 @@ int main(int argc, char** argv)
int totp_err_3 = totp_now(tdata_padding, tcode3);
if(totp_err_3 == OTP_ERROR)
{
fputs("TOTP Error totp_now (padding)", stderr);
fputs("TOTP Error totp_now (padding)\n", stderr);
return EXIT_FAILURE;
}
printf("totp_now() (padding) pass=1: `%s` `%d`\n", tcode3, totp_err_3);
Expand All @@ -301,7 +301,7 @@ int main(int argc, char** argv)
int totp_err_4 = totp_at(tdata_padding, 0, 0, tcode4);
if(totp_err_4 == OTP_ERROR)
{
fputs("TOTP Error totp_at (padding)", stderr);
fputs("TOTP Error totp_at (padding)\n", stderr);
return EXIT_FAILURE;
}
printf("totp_at(0, 0) (padding) pass=1: `%s` `%d`\n", tcode4, totp_err_4);
Expand Down Expand Up @@ -337,7 +337,7 @@ int main(int argc, char** argv)
int hotp_err_1 = hotp_at(hdata, 1, hcode);
if(hotp_err_1 == OTP_ERROR)
{
puts("HOTP Error hotp_at");
fputs("HOTP Error hotp_at\n", stderr);
return EXIT_FAILURE;
}
printf("hotp_at(1) pass=1: `%s` `%d`\n", hcode, hotp_err_1);
Expand Down
10 changes: 5 additions & 5 deletions test/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ int main(int argc, char** argv)
int totp_err_1 = tdata.now(tcode);
if(totp_err_1 == OTP_ERROR)
{
cout << "TOTP Error totp_now (padding)" << endl;
cerr << "TOTP Error totp_now (padding)" << endl;
return EXIT_FAILURE;
}
cout << "totp_now() (padding) pass=1: `" << tcode << "` `" << totp_err_1 << "`" << endl;
Expand All @@ -259,7 +259,7 @@ int main(int argc, char** argv)
int totp_err_2 = tdata.at(0, 0, tcode2);
if(totp_err_2 == 0)
{
cout << "TOTP Error totp_at (padding)" << endl;
cerr << "TOTP Error totp_at (padding)" << endl;
return EXIT_FAILURE;
}
cout << "totp_at(0, 0) (padding) pass=1: `" << tcode2 << "` `" << totp_err_2 << "`" << endl;
Expand Down Expand Up @@ -296,7 +296,7 @@ int main(int argc, char** argv)
int totp_err_3 = tdata_padding.now(tcode3);
if(totp_err_3 == OTP_ERROR)
{
cout << "TOTP Error totp_now" << endl;
cerr << "TOTP Error totp_now" << endl;
return EXIT_FAILURE;
}
cout << "totp_now() pass=1: `" << tcode3 << "` `" << totp_err_3 << "`" << endl;
Expand All @@ -309,7 +309,7 @@ int main(int argc, char** argv)
int totp_err_4 = tdata_padding.at(0, 0, tcode4);
if(totp_err_4 == 0)
{
cout << "TOTP Error totp_at" << endl;
cerr << "TOTP Error totp_at" << endl;
return EXIT_FAILURE;
}
cout << "totp_at(0, 0) pass=1: `" << tcode4 << "` `" << totp_err_4 << "`" << endl;
Expand Down Expand Up @@ -344,7 +344,7 @@ int main(int argc, char** argv)

int hotp_err_1 = hdata.at(1, hcode);
if(hotp_err_1 == 0) {
cout << "HOTP Error hotp_at" << endl;
cerr << "HOTP Error hotp_at" << endl;
return EXIT_FAILURE;
}
cout << "hotp_at(1) pass=1: `" << hcode << "`" << " `" << hotp_err_1 << "`" << endl;
Expand Down
Loading