#define _GNU_SOURCE #include "encryption.h" #include "shared.h" #include #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 error(1, ENOTSUP, "Couldn't initialize sodium for some reason. Quitting..."); } int checksodiumcb(const vxgg_naclfailcb callback, void *data) { static vxgg_naclfailcb cb = naclfaildefault; static void *usr = NULL; if(callback != NULL) { cb = callback; usr = data; return 2; // libsodium normally returns 1 if the library is already initialized, so this is to signal that the callback has been updated } int ret = sodium_init(); if(ret < 0) cb(usr); return ret; } void vxgg_setsodiumfailcb(vxgg_naclfailcb cb, void *data) { checksodiumcb(cb, data); } #endif void checksodium(void) { #if defined ___VXGG___ALWAYS_CHECK_LIBSODIUM___ && ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 checksodiumcb(NULL, NULL); #else if(sodium_init() < 0) error(1, ENOTSUP, "Couldn't initialize sodium for some reason. Quitting..."); #endif return; } // To encrypt: // 1- Create a temp file with the correct name in the root folder of the partition being encrypted -- // 1.1- Detect the partition and find the root folder -- DONE || NOT NECESSARY // 1.2- Create the temp file -- DONE // 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 * const dest) { return open(dest, (O_TMPFILE | O_WRONLY | O_CLOEXEC | O_SYNC), (S_IRUSR | S_IWUSR)); } int encrypttotmp(const char * const toencrypt) { #if defined ___VXGG___ALWAYS_CHECK_LIBSODIUM___ && ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 checksodium(); #endif struct stat esb; int efd = -1; // Make sure the file is real and an actual file that can be encrypted if(stat(toencrypt, &esb) < 0) return -1; if(!S_ISREG(esb.st_mode)) return -2; // Open the file as read-only if((efd = open(toencrypt, O_RDONLY)) < 0) return -3; // Need to get a secret key from a password and then set up cryptostream from libsodium return 0; } int genpassword(char **str, unsigned int words) { // Early returns if(words < 1) return 0; #if defined ___VXGG___ALWAYS_CHECK_LIBSODIUM___ && ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 checksodium(); #endif // Bootstrap the first word char *lstr = NULL, *tmp = NULL; if(asprintf(&lstr, "%s", PASSWORD_WORDS[randombytes_uniform(PASSWORD_WORDS_LEN)]) < 0) return -1; // Concat the rest of the words into the password (without leaking memory) 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; lstr = tmp; } *str = lstr; return words; } // 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 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"; char *path = NULL; int fd = maketmp(dir); if(fd < 0) error(1, errno, "Couldn't make temp file at %s", dir); if(write(fd, testmsg, strlen(testmsg)) < 0) error(1, errno, "write broke"); asprintf(&path, "/proc/self/fd/%d", fd); linkat(AT_FDCWD, path, AT_FDCWD, "./test", AT_SYMLINK_FOLLOW); free(path); // Apparently, I don't have the CAP_DAC_READ_SEARCH capibility. Thanks for the solution, linux man pages if(close(fd) < 0) error(1, errno, "close broke"); //*/// /*// Example code for getting a password using genpassword checksodium(); char *password = NULL; genpassword(&password, 20); printf("%s\n", (password != NULL) ? password : "Couldn't get a password"); 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; } #endif