summaryrefslogtreecommitdiff
path: root/src/encryption.c
blob: 052b9aa2994f77310a1c8acb043103f8be1a7337 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#define _GNU_SOURCE

#include "encryption.h"
#include "shared.h"

#include <sodium.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <stdarg.h>
#include <unistd.h>
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <stdio.h>

#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.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) {
    return open(dest, (O_TMPFILE | O_WRONLY | O_CLOEXEC | O_SYNC), (S_IRUSR | S_IWUSR));
}

int encrypttotmp(const char *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)]);
        free(lstr);
        if(ret < 0)
            return -1;

        lstr = tmp;
    }

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


#define TESTING
#ifdef TESTING

#include <string.h>

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);
    //*///

    return 0;
}

#endif