From 2f66e8678971ba0340a96d811ced405d75dbb114 Mon Sep 17 00:00:00 2001 From: "@syxhe" Date: Sun, 19 Jan 2025 17:58:45 -0600 Subject: Write example code for generating, storing, and verifying a password --- src/encryption.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++------- src/encryption.h | 2 +- src/shared.c | 57 +++++++++++++++++++++++++++++++++++++++++-- src/shared.h | 3 +++ 4 files changed, 124 insertions(+), 12 deletions(-) diff --git a/src/encryption.c b/src/encryption.c index 052b9aa..692b46a 100644 --- a/src/encryption.c +++ b/src/encryption.c @@ -8,12 +8,14 @@ #include #include #include +#include #include #include #include #include #include + #if defined ___VXGG___ALWAYS_CHECK_LIBSODIUM___ && ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 void naclfaildefault(void *none) { none = none; // Makes gcc happy @@ -60,17 +62,20 @@ void checksodium(void) { // 2- Encrypt the file's contents to the temp file -- // 2.1- Open the file -- // 2.2- Stream the file's contents into some encryption algo -- + // 2.2.1- Pick which encryption algo to use -- + // 2.2.2- Generate a key -- + // 2.2.2.1- Create a password to derrive a key from -- DONE // 2.3- Pipe the output of the encryption into the temp file -- // 3- Once the file has been encrypted, hard link it back to the original location, with the right name -- // 4- Delete the original file -- // 5- Delete the temp file -- -int maketmp(const char *dest) { +int maketmp(const char * const dest) { return open(dest, (O_TMPFILE | O_WRONLY | O_CLOEXEC | O_SYNC), (S_IRUSR | S_IWUSR)); } -int encrypttotmp(const char *toencrypt) { +int encrypttotmp(const char * const toencrypt) { #if defined ___VXGG___ALWAYS_CHECK_LIBSODIUM___ && ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 checksodium(); #endif @@ -110,6 +115,7 @@ int genpassword(char **str, unsigned int words) { int ret; for(unsigned int i = 1; i < words; i++) { ret = asprintf(&tmp, "%s %s", lstr, PASSWORD_WORDS[randombytes_uniform(PASSWORD_WORDS_LEN)]); + sodium_memzero(lstr, strlen(lstr) + 1); free(lstr); if(ret < 0) return -1; @@ -119,18 +125,29 @@ int genpassword(char **str, unsigned int words) { *str = lstr; return words; - - // This function was exploding because of some weird conflict with using my buggy implementation of asprintf instead of the - // _GNU_SOURCE version. Don't know why it wasn't using the _GNU_SOURCE version, as I had a define macro put in place to - // prevent it from being compiled if _GNU_SOURCE was defined, but whatever } +// sodium_malloc wrapper. Calls `error()` or `abort()` depnding on the value of `___VXGG___XALLOC_EXIT_ON_ERROR___`. Will make sure libsodium is initialized if `___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0` +void* xsodium_malloc(size_t size) { + #if defined ___VXGG___ALWAYS_CHECK_LIBSODIUM___ && ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 + checksodium(); + #endif + + void *mem = sodium_malloc(size); + if(mem == NULL) { + #if defined ___VXGG___XALLOC_EXIT_ON_ERROR___ && ___VXGG___XALLOC_EXIT_ON_ERROR___ > 0 + error(1, errno, "xsodium_malloc: could not allocate memory... Quitting"); + #endif + + abort(); + } + + return mem; +} #define TESTING #ifdef TESTING -#include - int main(void) { /*// Example code for creating a temp file, writing to it, then linking it back into the fs const char *dir = ".", *testmsg = "we do a little testing\n"; @@ -153,7 +170,7 @@ int main(void) { error(1, errno, "close broke"); //*/// - //*// Example code for getting a password using genpassword + /*// Example code for getting a password using genpassword checksodium(); char *password = NULL; @@ -162,6 +179,45 @@ int main(void) { free(password); //*/// + //*// Example code for generating a password, derriving a secret key from it, and storing things properly + + // Initialization + checksodium(); + char *pass = NULL, hpass[crypto_pwhash_STRBYTES]; + + if(genpassword(&pass, 20) < 0) { + error(1, 0, "Could not generate password, quitting..."); + abort(); // Makes gcc happy. Not sure why gcc randomly decides that error() isn't a proper exit, but hey whatever + } + sodium_mlock(pass, strlen(pass) + 1); + printf("Password:%s\n", pass); + + // Store the password + if(crypto_pwhash_str(hpass, pass, strlen(pass) + 1, crypto_pwhash_OPSLIMIT_MODERATE, crypto_pwhash_MEMLIMIT_MODERATE) != 0) + error(1, errno, "Couldn't generate password, quitting..."); + /* Don't know if I want to use MODERATE or SENSITIVE for this. SENSITIVE takes a little bit on my laptop, which honestly + // shouldn't be a problem, but it annoys me. MODERATE is quick and snappy, or at least quick enough that the slowdown is + // barely noticable. I might do MODERATE for testing and SENSITIVE for release */ + + sodium_munlock(pass, strlen(pass) + 1); + free(pass); + + printf("Hashed password: %s\n", hpass); + + // Check if the password from the user is correct + char *uin = NULL; int size = -1; + if((size = readwholebuffer(&uin, 20, STDIN_FILENO)) < 0) + error(1, errno, "Could not read from stdin"); + sodium_mlock(uin, size); + + printf("Valid password? %s\n", (crypto_pwhash_str_verify(hpass, uin, size) == 0) ? "True" : "False"); + + + sodium_munlock(uin, strlen(uin) + 1); + free(uin); + + //*/// + return 0; } diff --git a/src/encryption.h b/src/encryption.h index 01aa704..c780e2b 100644 --- a/src/encryption.h +++ b/src/encryption.h @@ -77,6 +77,6 @@ void vxgg_setsodiumfailcb(const vxgg_naclfailcb cb, void *data); void checksodium(void); // open() with the flags O_TMPFILE, O_WRONLY, O_CLOEXEC, and O_SYNC. Opened with mode S_IRUSR, S_IWUSR -int maketmp(const char *dest); +int maketmp(const char * const dest); #endif \ No newline at end of file diff --git a/src/shared.c b/src/shared.c index b154391..e5f0f13 100644 --- a/src/shared.c +++ b/src/shared.c @@ -2,6 +2,8 @@ #include #include +#include +#include #include #include #include @@ -9,7 +11,7 @@ void* xcalloc(size_t nmemb, size_t size) { void *mem = calloc(nmemb, size); - if(mem == NULL) { + if(!mem) { #if defined ___VXGG___XALLOC_EXIT_ON_ERROR___ && ___VXGG___XALLOC_EXIT_ON_ERROR___ > 0 error(1, errno, " Could not allocate memory"); #endif @@ -33,4 +35,55 @@ void* xreallocarray(void *ptr, size_t nmemb, size_t size) { } return mem; -} \ No newline at end of file +} + +int readwholebuffer(char **str, unsigned long int initsize, int fd) { + // Try to read bytes from fd into str + // Bytes read == 0, return 0 + // Bytes read < 0, free string, return -1; + // When string hits capacity, double the capacity, and reallocate the string + + char *lstr = NULL, *tmp = NULL; + ssize_t bytesread = -1; + int csize = initsize, ccap = initsize; + + lstr = xcalloc(initsize, sizeof(char)); + while((bytesread = read(fd, lstr + (csize - ccap), ccap)) > 0) { + ccap -= bytesread; + if(ccap <= 0) { + csize *= 2; + ccap = csize / 2; + + tmp = realloc(lstr, csize * sizeof(char)); + if(!tmp) { + error(0, errno, "Could not reallocate enough space for lstr"); + free(lstr); + bytesread = -100; + break; + } + lstr = tmp; + } + } + if(bytesread < 0 && bytesread != -100) { + error(0, errno, "Ran into a read() error"); + free(lstr); + lstr = NULL; + } + + if(lstr) { + tmp = realloc(lstr, csize - ccap + 1); + if(!tmp) { + error(0, errno, "Could not shrink lstr after reading buffer"); + free(lstr); + bytesread = -100; + } + lstr = tmp; + } + + if(lstr) { + lstr[csize - ccap - 1] = '\0'; // Don't include the newline + } + + *str = lstr; + return ((bytesread == 0) ? (csize - ccap) : -1); +} diff --git a/src/shared.h b/src/shared.h index 620ec82..dce02fc 100644 --- a/src/shared.h +++ b/src/shared.h @@ -17,4 +17,7 @@ void* xcalloc(size_t nmemb, size_t size); // `reallocarray()` with error checking. Calls `error()` or `abort()` on error, depending on the value of `___VXGG___XALLOC_EXIT_ON_ERROR___` void* xreallocarray(void *ptr, size_t nmemb, size_t size); +// Read the entire contents of a file descriptor into a malloc()'ed buffer +int readwholebuffer(char **str, unsigned long int initsize, int fd); + #endif \ No newline at end of file -- cgit v1.2.3