Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/tilkinsc/COTP
Browse files Browse the repository at this point in the history
  • Loading branch information
tilkinsc committed Aug 22, 2024
2 parents c86d7ad + f7eca66 commit 4922822
Show file tree
Hide file tree
Showing 11 changed files with 1,213 additions and 1,067 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# How to contribute

1. PRs should target a development branch to be merged into master
2. Its best if you create your PR with the following text,
2. It's best if you create your PR with the following text,
```
Problem: So and so
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2023 Cody Tilkins
Copyright (c) 2024 Cody Tilkins

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,5 @@ This product includes software developed by the OpenSSL Project for use in the O

## TODO

* SHA256 needs to be verified if its working fully
* SHA512 needs to be verified if its working fully
* SHA256 needs to be verified if it's working fully
* SHA512 needs to be verified if it's working fully
34 changes: 17 additions & 17 deletions build.bat
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
@echo off

echo Compiling
gcc -O2 -Wall -shared -c cotp.c otpuri.c

echo Building DLL
gcc -O2 -Wall -shared -o libcotp.dll cotp.o otpuri.o -lcrypto

echo Building static library
ar rcs -o libcotp.a cotp.o otpuri.o

echo Building test C application
gcc -O2 -Wall -L . -I . -o test_c.exe test/main.c libcotp.a -lcrypto

echo Building test C++ application
g++ -O2 -Wall -L . -I . -o test_cpp.exe test/main.cpp libcotp.a -lcrypto

@echo off

echo Compiling
gcc -O2 -Wall -shared -c cotp.c otpuri.c

echo Building DLL
gcc -O2 -Wall -shared -o libcotp.dll cotp.o otpuri.o -lcrypto

echo Building static library
ar rcs -o libcotp.a cotp.o otpuri.o

echo Building test C application
gcc -O2 -Wall -L . -I . -o test_c.exe test/main.c libcotp.a -lcrypto

echo Building test C++ application
g++ -O2 -Wall -L . -I . -o test_cpp.exe test/main.cpp libcotp.a -lcrypto

12 changes: 7 additions & 5 deletions cotp.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,10 @@ COTPRESULT otp_byte_secret(OTPData* data, char* out_str)
for (int j = 0; j < 8; j++)
{
char c = data->base32_secret[i * 8 + j];
if (c == '=')
break;

int found = 0;

for (int k = 0; k < 32; k++)
{
if (c == OTP_DEFAULT_BASE32_CHARS[k])
Expand Down Expand Up @@ -453,9 +455,9 @@ 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 + 1;
char byte_secret[bs_len];
memset(byte_secret, 0, bs_len);
size_t bs_len = (strlen(data->base32_secret)/8)*5;
char byte_secret[bs_len + 1];
memset(byte_secret, 0, bs_len + 1);

char hmac[64+1];
memset(hmac, 0, 64+1);
Expand All @@ -464,7 +466,7 @@ COTPRESULT otp_generate(OTPData* data, uint64_t input, char* out_str)
|| otp_byte_secret(data, byte_secret) == 0)
return OTP_ERROR;

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

Expand Down
231 changes: 115 additions & 116 deletions cotp.h
Original file line number Diff line number Diff line change
@@ -1,116 +1,115 @@
#pragma once

#include <stdlib.h>
#include <stdint.h>


// OTPRESULT can either be 1 (success) or 0 (error)
typedef int COTPRESULT;

#define OTP_OK ((COTPRESULT) 1)
#define OTP_ERROR ((COTPRESULT) 0)


/*
Default characters used in BASE32 digests.
For use with otp_random_base32()
*/
static const char OTP_DEFAULT_BASE32_CHARS[32] =
{
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5',
'6', '7'
};


/*
Used for differentiation on which
method you are using. Necessary
when you go to generate a URI.
*/
typedef enum OTPType
{
OTP, TOTP, HOTP
} OTPType;

const char* OTPType_asString(OTPType type);


/*
Must compute HMAC using passed arguments,
output as char array through output.
key is base32 secret key.
input is input number as string.
output is an output char buffer of the resulting HMAC operation.
Must return 0 if error, or the length in bytes of the HMAC operation.
*/
typedef int (*COTP_ALGO)(const char* key, const char* input, char* output);

/*
Must return the current time in seconds.
*/
typedef uint64_t (*COTP_TIME)();


/*
Holds data for use by the cotp module.
If you know what you are doing,
feel free to initialize this yourself.
*/
typedef struct OTPData
{
uint32_t digits;
uint32_t interval; // TOTP exclusive
uint64_t count;

OTPType method;
COTP_ALGO algo;
COTP_TIME time;

const char* base32_secret;
} OTPData;


/*
Struct initialization functions
*/
OTPData* otp_new(OTPData* data, const char* base32_secret, COTP_ALGO algo, uint32_t digits);
OTPData* totp_new(OTPData* data, const char* base32_secret, COTP_ALGO algo, COTP_TIME time, uint32_t digits, uint32_t interval);
OTPData* hotp_new(OTPData* data, const char* base32_secret, COTP_ALGO algo, uint32_t digits, uint64_t count);

/*
OTP free function
*/
void otp_free(OTPData* data);

/*
OTP functions
*/
COTPRESULT otp_generate(OTPData* data, uint64_t input, char* out_str);
COTPRESULT otp_byte_secret(OTPData* data, char* out_str);
COTPRESULT otp_num_to_bytestring(uint64_t integer, char* out_str);
COTPRESULT otp_random_base32(size_t len, char* out_str);


/*
TOTP functions
*/
COTPRESULT totp_compare(OTPData* data, const char* key, int64_t offset, uint64_t for_time);
COTPRESULT totp_at(OTPData* data, uint64_t for_time, int64_t offset, char* out_str);
COTPRESULT totp_now(OTPData* data, char* out_str);
COTPRESULT totp_verify(OTPData* data, const char* key, uint64_t for_time, int64_t valid_window);
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);


/*
HOTP functions
*/
COTPRESULT hotp_compare(OTPData* data, const char* key, uint64_t counter);
COTPRESULT hotp_at(OTPData* data, uint64_t counter, char* out_str);
COTPRESULT hotp_next(OTPData* data, char* out_str);

#pragma once

#include <stdlib.h>
#include <stdint.h>


// OTPRESULT can either be 1 (success) or 0 (error)
typedef int COTPRESULT;

#define OTP_OK ((COTPRESULT) 1)
#define OTP_ERROR ((COTPRESULT) 0)


/*
Default characters used in BASE32 digests.
For use with otp_random_base32()
*/
static const char OTP_DEFAULT_BASE32_CHARS[32] =
{
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5',
'6', '7'
};


/*
Used for differentiation on which
method you are using. Necessary
when you go to generate a URI.
*/
typedef enum OTPType
{
OTP, TOTP, HOTP
} OTPType;

const char* OTPType_asString(OTPType type);


/*
Must compute HMAC using passed arguments,
output as char array through output.
key is base32 secret key.
input is input number as string.
output is an output char buffer of the resulting HMAC operation.
Must return 0 if error, or the length in bytes of the HMAC operation.
*/
typedef int (*COTP_ALGO)(const char* key, int key_length, const char* input, char* output);

/*
Must return the current time in seconds.
*/
typedef uint64_t (*COTP_TIME)();


/*
Holds data for use by the cotp module.
If you know what you are doing,
feel free to initialize this yourself.
*/
typedef struct OTPData
{
uint32_t digits;
uint32_t interval; // TOTP exclusive
uint64_t count;

OTPType method;
COTP_ALGO algo;
COTP_TIME time;

const char* base32_secret;
} OTPData;


/*
Struct initialization functions
*/
OTPData* otp_new(OTPData* data, const char* base32_secret, COTP_ALGO algo, uint32_t digits);
OTPData* totp_new(OTPData* data, const char* base32_secret, COTP_ALGO algo, COTP_TIME time, uint32_t digits, uint32_t interval);
OTPData* hotp_new(OTPData* data, const char* base32_secret, COTP_ALGO algo, uint32_t digits, uint64_t count);

/*
OTP free function
*/
void otp_free(OTPData* data);

/*
OTP functions
*/
COTPRESULT otp_generate(OTPData* data, uint64_t input, char* out_str);
COTPRESULT otp_byte_secret(OTPData* data, char* out_str);
COTPRESULT otp_num_to_bytestring(uint64_t integer, char* out_str);
COTPRESULT otp_random_base32(size_t len, char* out_str);


/*
TOTP functions
*/
COTPRESULT totp_compare(OTPData* data, const char* key, int64_t offset, uint64_t for_time);
COTPRESULT totp_at(OTPData* data, uint64_t for_time, int64_t offset, char* out_str);
COTPRESULT totp_now(OTPData* data, char* out_str);
COTPRESULT totp_verify(OTPData* data, const char* key, uint64_t for_time, int64_t valid_window);
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);


/*
HOTP functions
*/
COTPRESULT hotp_compare(OTPData* data, const char* key, uint64_t counter);
COTPRESULT hotp_at(OTPData* data, uint64_t counter, char* out_str);
COTPRESULT hotp_next(OTPData* data, char* out_str);
Loading

0 comments on commit 4922822

Please sign in to comment.