]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/cryptsetup/cryptsetup.c
kernel: keep segment locked for data2txt
[plan9front.git] / sys / src / cmd / cryptsetup / cryptsetup.c
1 // Author Taru Karttunen <taruti@taruti.net>
2 // This file can be used as both Public Domain or Creative Commons CC0.
3 #include                <u.h>
4 #include                <libc.h>
5 #include                "crypt.h"
6
7 void format(char *file[]);
8 void copen(char *file[], int);
9 char*readcons(char *prompt, char *def, int raw, char *buf, int nbuf);
10 int pkcs5_pbkdf2(const unsigned char *pass, int pass_len, const unsigned char *salt, int salt_len, unsigned char *key, int key_len, int rounds);
11
12 void 
13 usage(void)
14 {
15         print("usage: \ncryptsetup -f files \t\t# Format file or device\ncryptsetup -o files \t\t# Print commandline for open\ncryptsetup -i files\t\t# Install (open) files\n");
16         exits("usage");
17 }
18
19 enum
20 {
21         NoMode,
22         Format,
23         Open,
24         Install,
25 };
26
27
28 void
29 main(int argc, char *argv[])
30 {
31         int mode;
32
33         mode = 0;
34
35         ARGBEGIN {
36         default:
37                 usage();
38         case 'f':
39                 mode = Format;
40                 break;
41         case 'o':
42                 mode = Open;
43                 break;
44         case 'i':
45                 mode = Install;
46                 break;
47         } ARGEND;
48
49         if((mode == NoMode) || (argc < 1))
50                 usage();
51
52         switch(mode) {
53         case Format:
54                 format(argv);
55                 break;
56         case Install:
57         case Open:
58                 copen(argv, mode);
59                 break;
60         }
61 }
62
63 void
64 format(char *files[])
65 {
66         char trand[48], pass1[64], pass2[64];
67         unsigned char tkey[16], tivec[16], buf[64*1024];
68         XtsState s;
69         AESstate cbc;
70         int i,j, fd;
71
72         do {
73                 readcons("password", nil, 1, pass1, 64);
74                 readcons("confirm", nil, 1, pass2, 64);
75         } while(strcmp(pass1, pass2) != 0);
76
77         do {
78                 readcons("Are you sure you want to delete all data? (YES to procees)", nil, 0, (char*)buf, 4);
79         } while(strcmp((char*)buf, "YES") != 0);
80
81         srand(truerand());
82
83         for(;*files;files++) {
84
85                 for(i = 0; i < 16*4096; i++)
86                         buf[i] = rand();
87         
88                 for(i = 0; i < 48; i+=4)
89                         *((unsigned*)&trand[i]) = truerand();
90                 memcpy(s.Master, trand, 32);
91                 memcpy(s.Slots[0].Salt, trand+32, 16);
92
93                 pkcs5_pbkdf2((unsigned char*)pass1, strlen(pass1), s.Slots[0].Salt, 16, (unsigned char*)tkey, 16, 9999);
94                 memset(tivec, 0, 16);
95                 setupAESstate(&cbc, tkey, 16, tivec);
96                 memcpy(s.Slots[0].Key, s.Master, 32);
97                 aesCBCencrypt(s.Slots[0].Key, 32, &cbc);
98
99                 for(i=0; i<16; i++)
100                         for(j=0; j<8; j++) {
101                                 buf[(4096*i)]  = 1;
102                                 buf[(4096*i)+(4*j)+1] = s.Slots[j].Salt[i];
103                                 buf[(4096*i)+(4*j)+2] = s.Slots[j].Key[i];
104                                 buf[(4096*i)+(4*j)+3] = s.Slots[j].Key[i+16];
105                         }
106
107                 if((fd = open(*files, OWRITE)) < 0)
108                         exits("Cannot open disk ");
109         
110                 /* make the pad for checking crypto */
111                 for(i=0; i<8; i++) {
112                         buf[(64*1024)-8+i] = ~buf[(64*1024)-16+i];
113                 }
114                 memset(tivec, 0, 16);
115                 setupAESstate(&cbc, s.Master, 16, tivec);
116                 aes_encrypt(cbc.ekey, cbc.rounds, &buf[(64*1024)-16], &buf[(64*1024)-16]);
117
118                 write(fd, buf, 16*4096);
119
120                 print("Disk %s written\n", *files);
121         }
122 }
123
124 void copen(char *files[], int mode) {
125         unsigned char pass[32], buf[1024*64], tkey[16], tivec[16], cbuf[16];
126         XtsState s;
127         int i,j,fd, oldpass;
128         AESstate cbc;
129         char *base, fdpath[1024];
130
131         oldpass = 0;
132         for(;*files; files++) {
133                 if((fd = open(*files, OREAD)) < 0)
134                         exits("Cannot open disk");
135         
136                 if(read(fd, buf, 1024*64) != 1024*64) 
137                         exits("Cannot read disk");
138         
139                 openpass:
140                         for(i=0; i<16; i++) 
141                                 for(j=0; j<8; j++) {
142                                         s.Slots[j].Salt[i] = buf[(4096*i)+(4*j)+1];
143                                         s.Slots[j].Key[i] = buf[(4096*i)+(4*j)+2];
144                                         s.Slots[j].Key[i+16] = buf[(4096*i)+(4*j)+3];
145                                 }
146
147                         if(!oldpass)
148                                 readcons("Password", nil, 1, (char*)pass, 32);
149
150                         memcpy(s.Master, s.Slots[0].Key, 32);
151
152                         pkcs5_pbkdf2(pass, strlen((char*)pass), s.Slots[0].Salt, 16, tkey, 16, 9999);
153                         memset(tivec, 0, 16);
154                         setupAESstate(&cbc, tkey, 16, tivec);
155                         aesCBCdecrypt(s.Master, 32, &cbc);
156                 
157                         memset(tivec, 0, 16);
158                         setupAESstate(&cbc, s.Master, 16, tivec);
159
160                         memcpy(cbuf, &buf[(64*1024)-16], 16);
161                         aes_decrypt(cbc.dkey, cbc.rounds, cbuf, cbuf);
162
163                         /* make the pad for checking crypto */
164                         for(i=0; i<8; i++)
165                                 if((cbuf[i] ^ cbuf[i+8]) != 255) {
166                                         oldpass=0;
167                                         goto openpass;
168                                 }
169
170                 base = utfrrune(*files, '/');
171                 fd2path(fd, fdpath, 1024);
172                 j = sprint((char*)buf, "crypt %s %s ", base ? base+1 : *files, fdpath);
173         
174                 for(i=0; i<32; i++) {
175                         sprint((char*)&buf[j], "%02X", s.Master[i]);
176                         j += 2; 
177                 }
178                 buf[j++] = '\n';
179                 close(fd);
180                 if(mode == Install) {
181                         fd = open("/dev/fs/ctl", OWRITE);
182                         write(fd, buf, j);
183                         close(fd);
184                 } else {
185                         write(1, buf, j);
186                 }
187                 oldpass=1;
188         }
189 }