1 // Author Taru Karttunen <taruti@taruti.net>
2 // This file can be used as both Public Domain or Creative Commons CC0.
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);
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");
29 main(int argc, char *argv[])
49 if((mode == NoMode) || (argc < 1))
66 char trand[48], pass1[64], pass2[64];
67 unsigned char tkey[16], tivec[16], buf[64*1024];
73 readcons("password", nil, 1, pass1, 64);
74 readcons("confirm", nil, 1, pass2, 64);
75 } while(strcmp(pass1, pass2) != 0);
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);
83 for(;*files;files++) {
85 for(i = 0; i < 16*4096; i++)
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);
93 pkcs5_pbkdf2((unsigned char*)pass1, strlen(pass1), s.Slots[0].Salt, 16, (unsigned char*)tkey, 16, 9999);
95 setupAESstate(&cbc, tkey, 16, tivec);
96 memcpy(s.Slots[0].Key, s.Master, 32);
97 aesCBCencrypt(s.Slots[0].Key, 32, &cbc);
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];
107 if((fd = open(*files, OWRITE)) < 0)
108 exits("Cannot open disk ");
110 /* make the pad for checking crypto */
112 buf[(64*1024)-8+i] = ~buf[(64*1024)-16+i];
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]);
118 write(fd, buf, 16*4096);
120 print("Disk %s written\n", *files);
124 void copen(char *files[], int mode) {
125 unsigned char pass[32], buf[1024*64], tkey[16], tivec[16], cbuf[16];
129 char *base, fdpath[1024];
132 for(;*files; files++) {
133 if((fd = open(*files, OREAD)) < 0)
134 exits("Cannot open disk");
136 if(read(fd, buf, 1024*64) != 1024*64)
137 exits("Cannot read disk");
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];
148 readcons("Password", nil, 1, (char*)pass, 32);
150 memcpy(s.Master, s.Slots[0].Key, 32);
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);
157 memset(tivec, 0, 16);
158 setupAESstate(&cbc, s.Master, 16, tivec);
160 memcpy(cbuf, &buf[(64*1024)-16], 16);
161 aes_decrypt(cbc.dkey, cbc.rounds, cbuf, cbuf);
163 /* make the pad for checking crypto */
165 if((cbuf[i] ^ cbuf[i+8]) != 255) {
170 base = utfrrune(*files, '/');
171 fd2path(fd, fdpath, 1024);
172 j = sprint((char*)buf, "crypt %s %s ", base ? base+1 : *files, fdpath);
174 for(i=0; i<32; i++) {
175 sprint((char*)&buf[j], "%02X", s.Master[i]);
180 if(mode == Install) {
181 fd = open("/dev/fs/ctl", OWRITE);