forked from lolo859/vystem
Vystem 0.2
This commit is contained in:
@@ -7,79 +7,22 @@ extern "C" {
|
||||
#include "sha3.h"
|
||||
}
|
||||
#undef str
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
using namespace std;
|
||||
namespace fs=filesystem;
|
||||
const map<string,string> azerty_to_qwerty={
|
||||
{"a","q"},
|
||||
{"A","Q"},
|
||||
{"z","w"},
|
||||
{"Z","W"},
|
||||
{"q","a"},
|
||||
{"Q","A"},
|
||||
{"m",";"},
|
||||
{"M",":"},
|
||||
{"w","z"},
|
||||
{"W","Z"},
|
||||
{",","m"},
|
||||
{"?","M"},
|
||||
{"²","`"},
|
||||
{"&","1"},
|
||||
{"é","2"},
|
||||
{"\"","3"},
|
||||
{"'","4"},
|
||||
{"(","5"},
|
||||
{"-","6"},
|
||||
{"è","7"},
|
||||
{"_","8"},
|
||||
{"ç","9"},
|
||||
{"à","0"},
|
||||
{"~","2"},
|
||||
{"#","3"},
|
||||
{"{","4"},
|
||||
{"[","5"},
|
||||
{"|","6"},
|
||||
{"`","7"},
|
||||
{"\\","8"},
|
||||
{"^","9"},
|
||||
{"@","0"},
|
||||
{"1","!"},
|
||||
{"2","@"},
|
||||
{"3","#"},
|
||||
{"4","$"},
|
||||
{"5","%"},
|
||||
{"6","^"},
|
||||
{"7","&"},
|
||||
{"8","*"},
|
||||
{"9","("},
|
||||
{"0",")"},
|
||||
{";",","},
|
||||
{".","<"},
|
||||
{":","."},
|
||||
{"/",">"},
|
||||
{"!","/"},
|
||||
{"§","?"},
|
||||
{"<","\\"},
|
||||
{">","|"},
|
||||
{"ù","'"},
|
||||
{"%","\""},
|
||||
{"^","["},
|
||||
{"¨","{"},
|
||||
{"$","]"},
|
||||
{"£","}"},
|
||||
{"µ","|"}
|
||||
};
|
||||
void secure_erase(void *address,size_t size) {
|
||||
explicit_bzero(address,size);
|
||||
}
|
||||
@@ -118,6 +61,115 @@ int main(int argc,char **argv) {
|
||||
cout<<"[Keygen] Error: can't setup security."<<endl;
|
||||
return -1;
|
||||
}
|
||||
// VFTM stuff
|
||||
unsigned char pk_root[CRYPTO_PUBLICKEYBYTES];
|
||||
unsigned char sk_root[CRYPTO_SECRETKEYBYTES];
|
||||
mlock(pk_root,sizeof(pk_root));
|
||||
mlock(sk_root,sizeof(sk_root));
|
||||
madvise(pk_root,sizeof(pk_root),MADV_DONTDUMP);
|
||||
madvise(sk_root,sizeof(sk_root),MADV_DONTDUMP);
|
||||
if (crypto_sign_keypair(pk_root,sk_root)) {
|
||||
cout<<"[Keygen] Error: can't generate root keypair."<<endl;
|
||||
return -1;
|
||||
}
|
||||
unsigned char pk_manifest[CRYPTO_PUBLICKEYBYTES];
|
||||
unsigned char sk_manifest[CRYPTO_SECRETKEYBYTES];
|
||||
mlock(pk_manifest,sizeof(pk_manifest));
|
||||
mlock(sk_manifest,sizeof(sk_manifest));
|
||||
madvise(pk_manifest,sizeof(pk_manifest),MADV_DONTDUMP);
|
||||
madvise(sk_manifest,sizeof(sk_manifest),MADV_DONTDUMP);
|
||||
if (crypto_sign_keypair(pk_manifest,sk_manifest)) {
|
||||
cout<<"[Keygen] Error: can't generate manifest keypair."<<endl;
|
||||
return -1;
|
||||
}
|
||||
unsigned char sig_root[CRYPTO_BYTES];
|
||||
mlock(sig_root,sizeof(sig_root));
|
||||
madvise(sig_root,sizeof(sig_root),MADV_DONTDUMP);
|
||||
size_t siglen;
|
||||
if (crypto_sign_signature(sig_root,&siglen,pk_manifest,sizeof(pk_manifest),sk_root)) {
|
||||
cout<<"[Keygen] Error: can't generate signature for manifest public key."<<endl;
|
||||
secure_erase(pk_root,sizeof(pk_root));
|
||||
secure_erase(sk_root,sizeof(sk_root));
|
||||
secure_erase(pk_manifest,sizeof(pk_manifest));
|
||||
secure_erase(sk_manifest,sizeof(sk_manifest));
|
||||
secure_erase(sig_root,siglen);
|
||||
return -1;
|
||||
}
|
||||
if (siglen!=CRYPTO_BYTES) {
|
||||
cout<<"[Keygen] Error: signature isn't the expected size for manifest public key."<<endl;
|
||||
secure_erase(pk_root,sizeof(pk_root));
|
||||
secure_erase(sk_root,sizeof(sk_root));
|
||||
secure_erase(pk_manifest,sizeof(pk_manifest));
|
||||
secure_erase(sk_manifest,sizeof(sk_manifest));
|
||||
secure_erase(sig_root,siglen);
|
||||
return -1;
|
||||
}
|
||||
secure_erase(sk_root,sizeof(sk_root));
|
||||
uint8_t payload[CRYPTO_PUBLICKEYBYTES+CRYPTO_SECRETKEYBYTES];
|
||||
mlock(payload,sizeof(payload));
|
||||
madvise(payload,sizeof(payload),MADV_DONTDUMP);
|
||||
memcpy(payload,pk_manifest,CRYPTO_PUBLICKEYBYTES);
|
||||
memcpy(payload+CRYPTO_PUBLICKEYBYTES,sk_manifest,CRYPTO_SECRETKEYBYTES);
|
||||
int fd=socket(AF_UNIX,SOCK_SEQPACKET,0);
|
||||
if (fd<0) {
|
||||
cout<<"[Keygen] Error: couldn't create client socket."<<endl;
|
||||
secure_erase(pk_root,sizeof(pk_root));
|
||||
secure_erase(pk_manifest,sizeof(pk_manifest));
|
||||
secure_erase(sk_manifest,sizeof(sk_manifest));
|
||||
secure_erase(sig_root,siglen);
|
||||
return -1;
|
||||
}
|
||||
sockaddr_un addr{};
|
||||
addr.sun_family=AF_UNIX;
|
||||
strcpy(addr.sun_path,"./vftm.sock");
|
||||
int r=connect(fd,(sockaddr*)&addr,sizeof(sockaddr_un));
|
||||
if (r<0) {
|
||||
cout<<"[Keygen] Error: couldn't connect to server socket."<<endl;
|
||||
secure_erase(pk_root,sizeof(pk_root));
|
||||
secure_erase(pk_manifest,sizeof(pk_manifest));
|
||||
secure_erase(sk_manifest,sizeof(sk_manifest));
|
||||
secure_erase(sig_root,siglen);
|
||||
return -1;
|
||||
}
|
||||
size_t s=send(fd,payload,sizeof(payload),0);
|
||||
if (s<0 || s!=sizeof(payload)) {
|
||||
perror("send");
|
||||
cout<<"[Keygen] Error: couldn't send keys to caller."<<endl;
|
||||
secure_erase(pk_root,sizeof(pk_root));
|
||||
secure_erase(pk_manifest,sizeof(pk_manifest));
|
||||
secure_erase(sk_manifest,sizeof(sk_manifest));
|
||||
secure_erase(sig_root,siglen);
|
||||
return -1;
|
||||
}
|
||||
secure_erase(pk_manifest,sizeof(pk_manifest));
|
||||
secure_erase(sk_manifest,sizeof(sk_manifest));
|
||||
secure_erase(payload,sizeof(payload));
|
||||
// SBFIE stuff
|
||||
bool set_files_to_user=true;
|
||||
const char* original_user=getenv("SUDO_USER");
|
||||
const char* original_uid=getenv("SUDO_UID");
|
||||
const char* original_gid=getenv("SUDO_GID");
|
||||
if (!(original_gid && original_uid && original_user)) {
|
||||
cout<<"[Keygen] Warning: it look like keygen is running without sudo or as root. It won't be able to make the file it produces accessible to original user."<<endl;
|
||||
set_files_to_user=false;
|
||||
}
|
||||
struct passwd* user_info=nullptr;
|
||||
if (set_files_to_user) {
|
||||
user_info=getpwnam(original_user);
|
||||
if (user_info==nullptr) {
|
||||
cout<<"[Keygen] Warning: couldn't found user named \""<<string(original_user)<<"\"."<<endl;
|
||||
set_files_to_user=false;
|
||||
}
|
||||
}
|
||||
const char* password_env=getenv("VYSTEM_KEYGEN_PASSWORD");
|
||||
string password="";
|
||||
if (password_env) {
|
||||
password=string(password_env);
|
||||
if (password=="") {
|
||||
cout<<"[Keygen] Warning: VYSTEM_KEYGEN_PASSWORD defined but empty, defaulting to manual password setup."<<endl;
|
||||
password_env=nullptr;
|
||||
}
|
||||
}
|
||||
vector<string> files;
|
||||
if (argc>1) {
|
||||
for (int i=1;i<argc;++i) {
|
||||
@@ -212,112 +264,99 @@ int main(int argc,char **argv) {
|
||||
filesystem::create_directory("./sign");
|
||||
}
|
||||
for (int i=0;i<files.size();i++) {
|
||||
ofstream sigfile("./sign/"+fs::path(files[i]).filename().string()+".sig",ios::binary);
|
||||
fs::path sigpath="./sign/"+fs::path(files[i]).filename().string();
|
||||
sigpath.replace_extension(".sig");
|
||||
ofstream sigfile(sigpath,ios::binary);
|
||||
if (!sigfile) {
|
||||
cout<<"[Keygen] Error: can't open signature file for file: "<<files[i]<<endl;
|
||||
return -1;
|
||||
}
|
||||
sigfile.write(reinterpret_cast<const char*>(sigsbuf.data()+i*CRYPTO_BYTES),CRYPTO_BYTES);
|
||||
sigfile.close();
|
||||
if (set_files_to_user && user_info) {
|
||||
if (chown(sigpath.c_str(),user_info->pw_uid,user_info->pw_gid)!=0) {
|
||||
cout<<"[Keygen] Warning: couldn't change file "<<sigpath<<" to owner "<<string(original_user)<<"."<<endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
secure_erase(sigsbuf.data(),sigsbuf.size());
|
||||
cout<<"[Keygen] You are about to define a boot password. This password will be asked everytime you boot this instance of Vystem."<<endl;
|
||||
cout<<"[Keygen] It will be used to sign every public key on this instance of Vystem. Make sure it's secure. Here are the requirements:\n - It should be at least 12 characters.\n - Password can only include ASCII characters.\n - Password shouldn't be longer than 512 characters.\n - DO NOT use the numerical pad at all. It's not supported in the EFI environment."<<endl;
|
||||
cout<<"[Keygen] Leave empty for us to generate entropy as a password."<<endl;
|
||||
char* pwd=getpass("[Keygen] Enter boot password: ");
|
||||
string password;
|
||||
if (strlen(pwd)==0) {
|
||||
cout<<"[Keygen] You asked for entropy. It will be provided as hexadecimal characters. Please enter the amount of hexadecimal characters you want."<<endl;
|
||||
cout<<"[Keygen] The amount of hex characters shouldn't be bigger than 512."<<endl;
|
||||
cout<<"[Keygen] Amount of hex characters (should be a multiple of 2 and at least 16 characters to be a minimum secure): ";
|
||||
string amount;
|
||||
getline(cin,amount);
|
||||
uint64_t num;
|
||||
try {
|
||||
num=stoi(amount);
|
||||
} catch (const exception e) {
|
||||
cout<<"[Keygen] Value entered isn't a number. Using default amount of 16 characters."<<endl;
|
||||
num=8;
|
||||
}
|
||||
if (num%2!=0) {
|
||||
cout<<"[Keygen] Number entered isn't a multiple of 2. Using default amount of 16 characters."<<endl;
|
||||
num=8;
|
||||
} else if (num<513) {
|
||||
num=num/2;
|
||||
if (!password_env) {
|
||||
cout<<"[Keygen] You are about to define a boot password. This password will be asked everytime you boot this instance of Vystem."<<endl;
|
||||
cout<<"[Keygen] It will be used to sign every public key on this instance of Vystem. Make sure it's secure. Here are the requirements:\n - It should be at least 12 characters.\n - Password can only include ASCII characters.\n - Password shouldn't be longer than 512 characters.\n - DO NOT use the numerical pad at all. It's not supported in the EFI environment."<<endl;
|
||||
cout<<"[Keygen] Leave empty for us to generate entropy as a password."<<endl;
|
||||
char* pwd=getpass("[Keygen] Enter boot password: ");
|
||||
if (strlen(pwd)==0) {
|
||||
cout<<"[Keygen] You asked for entropy. It will be provided as hexadecimal characters. Please enter the amount of hexadecimal characters you want."<<endl;
|
||||
cout<<"[Keygen] The amount of hex characters shouldn't be bigger than 512."<<endl;
|
||||
cout<<"[Keygen] Amount of hex characters (should be a multiple of 2 and at least 16 characters to be a minimum secure): ";
|
||||
string amount;
|
||||
getline(cin,amount);
|
||||
uint64_t num;
|
||||
try {
|
||||
num=stoi(amount);
|
||||
} catch (const exception e) {
|
||||
cout<<"[Keygen] Value entered isn't a number. Using default amount of 16 characters."<<endl;
|
||||
num=8;
|
||||
}
|
||||
if (num%2!=0) {
|
||||
cout<<"[Keygen] Number entered isn't a multiple of 2. Using default amount of 16 characters."<<endl;
|
||||
num=8;
|
||||
} else if (num<513) {
|
||||
num=num/2;
|
||||
} else {
|
||||
cout<<"[Keygen] Error: password is too long."<<endl;
|
||||
return -1;
|
||||
}
|
||||
vector<uint8_t> passhex;
|
||||
passhex.resize(num);
|
||||
try {
|
||||
passhex=get_urandom(num);
|
||||
} catch (const exception e) {
|
||||
if (string(e.what())=="open") {
|
||||
cout<<"[Keygen] Error: can't open secure source of randomness."<<endl;
|
||||
return -1;
|
||||
} else if (string(e.what())=="error") {
|
||||
cout<<"[Keygen] Error: can't read enought secure entropy."<<endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ostringstream oss;
|
||||
oss<<hex<<setfill('0');
|
||||
for (uint8_t byte:passhex) {
|
||||
oss<<setw(2)<<std::uppercase<<static_cast<int>(byte);
|
||||
}
|
||||
password=oss.str();
|
||||
secure_erase(passhex.data(),passhex.size());
|
||||
} else if (strlen(pwd)<=512){
|
||||
password=string(pwd);
|
||||
char* confirm_pwd=getpass("[Keygen] Confirm password: ");
|
||||
string confirm_password(confirm_pwd);
|
||||
if (confirm_password!=password) {
|
||||
cout<<"[Keygen] Error: password don't correspond. Please try again."<<endl;
|
||||
return -1;
|
||||
}
|
||||
secure_erase(confirm_pwd,strlen(confirm_pwd));
|
||||
} else {
|
||||
cout<<"[Keygen] Error: password is too long."<<endl;
|
||||
return -1;
|
||||
}
|
||||
vector<uint8_t> passhex;
|
||||
passhex.resize(num);
|
||||
try {
|
||||
passhex=get_urandom(num);
|
||||
} catch (const exception e) {
|
||||
if (string(e.what())=="open") {
|
||||
cout<<"[Keygen] Error: can't open secure source of randomness."<<endl;
|
||||
return -1;
|
||||
} else if (string(e.what())=="error") {
|
||||
cout<<"[Keygen] Error: can't read enought secure entropy."<<endl;
|
||||
string pass=password;
|
||||
cout<<"[Keygen] Your password is set to be: "<<pass<<endl;
|
||||
cout<<endl;
|
||||
secure_erase(pwd,strlen(pwd));
|
||||
for (unsigned char c:password) {
|
||||
if (c>=0x80) {
|
||||
cout<<"[Keygen] Error: one character isn't ASCII."<<endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ostringstream oss;
|
||||
oss<<hex<<setfill('0');
|
||||
for (uint8_t byte:passhex) {
|
||||
oss<<setw(2)<<std::uppercase<<static_cast<int>(byte);
|
||||
}
|
||||
password=oss.str();
|
||||
secure_erase(passhex.data(),passhex.size());
|
||||
} else if (strlen(pwd)<=512){
|
||||
password=string(pwd);
|
||||
char* confirm_pwd=getpass("[Keygen] Confirm password: ");
|
||||
string confirm_password(confirm_pwd);
|
||||
if (confirm_password!=password) {
|
||||
cout<<"[Keygen] Error: password don't correspond. Please try again."<<endl;
|
||||
return -1;
|
||||
}
|
||||
secure_erase(confirm_pwd,strlen(confirm_pwd));
|
||||
} else {
|
||||
cout<<"[Keygen] Error: password is too long."<<endl;
|
||||
return -1;
|
||||
}
|
||||
string pass=password;
|
||||
string rep;
|
||||
cout<<"[Keygen] Do you use a keyboard with another layout than QWERTY (y/N) ? : ";
|
||||
getline(cin,rep);
|
||||
if (rep=="y") {
|
||||
cout<<"[Keygen] Do you want to automatically translate your password into what it should look like into a QWERTY layout (y/N) ?"<<endl;
|
||||
cout<<"[Keygen] Please note that for the moment, only AZERTY to QWERTY is supported."<<endl;
|
||||
cout<<"[Keygen] Your answer : ";
|
||||
getline(cin,rep);
|
||||
if (rep=="y") {
|
||||
for (int i=0;i<password.size();i++) {
|
||||
try {
|
||||
password[i]=azerty_to_qwerty.at(string(1,password.at(i)))[0];
|
||||
} catch (const exception e) {
|
||||
continue;
|
||||
}
|
||||
cout<<"[Keygen] Password provided from VYSTEM_KEYGEN_PASSWORD: "+password<<endl;
|
||||
for (unsigned char c:password) {
|
||||
if (c>=0x80) {
|
||||
cout<<"[Keygen] Error: one character isn't ASCII."<<endl;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
cout<<"[Keygen] Skipping password translation."<<endl;
|
||||
}
|
||||
} else {
|
||||
cout<<"[Keygen] No password translation needed."<<endl;
|
||||
}
|
||||
cout<<"[Keygen] Your password is set to be: "<<pass<<endl;
|
||||
cout<<"[Keygen] The password that will be hashed is: "<<password<<endl;
|
||||
cout<<"[Keygen] If you have a keyboard layout other than QWERTY and didn't selected to translate it, you will have to type the second provided password."<<endl;
|
||||
cout<<"[Keygen] If you have a keyboard layout other than QWERTY and selected to translate it, just type it like you would do in your keyboard layout."<<endl;
|
||||
cout<<"[Keygen] If you don't remember it or write it down somewhere else, you will not be able to boot into your system."<<endl;
|
||||
cout<<"[Keygen] Press enter to continue.";
|
||||
string dummy;
|
||||
getline(cin,dummy);
|
||||
cout<<endl;
|
||||
secure_erase(pwd,strlen(pwd));
|
||||
for (unsigned char c:password) {
|
||||
if (c>=0x80) {
|
||||
cout<<"[Keygen] Error: one character isn't ASCII."<<endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
vector<unsigned char> passutf16(password.size()*2);
|
||||
@@ -339,7 +378,6 @@ int main(int argc,char **argv) {
|
||||
}
|
||||
secure_erase(pk,sizeof(pk));
|
||||
secure_erase(seed.data(),seed.size());
|
||||
size_t siglen;
|
||||
if (crypto_sign_signature(sig,&siglen,pksbuf.data(),pksbuf.size(),sk)!=0) {
|
||||
cout<<"[Keygen] Error: can't generate signature from all publics keys."<<endl;
|
||||
return -1;
|
||||
@@ -361,12 +399,47 @@ int main(int argc,char **argv) {
|
||||
keyfile<<"0x"<<hex<<setw(2)<<setfill('0')<<(int)salt[i];
|
||||
if (i+1!=salt.size()) keyfile<<",";
|
||||
}
|
||||
keyfile<<"};\nUINT8 bp_key_pk_root["<<to_string(sizeof(pk_root))<<"]={";
|
||||
for (int i=0;i<sizeof(pk_root);++i) {
|
||||
keyfile<<"0x"<<hex<<setw(2)<<setfill('0')<<(int)pk_root[i];
|
||||
if (i+1!=sizeof(pk_root)) keyfile<<",";
|
||||
}
|
||||
keyfile<<"};\nUINT8 bp_key_sig_root["<<to_string(sizeof(sig_root))<<"]={";
|
||||
for (int i=0;i<sizeof(sig_root);++i) {
|
||||
keyfile<<"0x"<<hex<<setw(2)<<setfill('0')<<(int)sig_root[i];
|
||||
if (i+1!=sizeof(sig_root)) keyfile<<",";
|
||||
}
|
||||
keyfile<<"};\nSTATIC const CHAR16 * const bp_key_files["<<files.size()<<"]={";
|
||||
for (int i=0;i<files.size();++i) {
|
||||
keyfile<<"L\""<<fs::path(files[i]).filename().string()+"\"";
|
||||
string filename=fs::path(files[i]).filename().string();
|
||||
std::transform(filename.begin(),filename.end(),filename.begin(),
|
||||
[](unsigned char c) {
|
||||
return toupper(c);
|
||||
}
|
||||
);
|
||||
keyfile<<"L\""<<filename+"\"";
|
||||
if (i+1!=files.size()) keyfile<<",";
|
||||
}
|
||||
keyfile<<"};\nSTATIC const CHAR16 * const bp_key_files_sign["<<files.size()<<"]={";
|
||||
for (int i=0;i<files.size();++i) {
|
||||
string filename=fs::path(files[i]).filename().replace_extension(".sig").string();
|
||||
std::transform(filename.begin(),filename.end(),filename.begin(),
|
||||
[](unsigned char c) {
|
||||
return toupper(c);
|
||||
}
|
||||
);
|
||||
keyfile<<"L\""<<filename+"\"";
|
||||
if (i+1!=files.size()) keyfile<<",";
|
||||
}
|
||||
keyfile<<"};\n#endif";
|
||||
keyfile.close();
|
||||
if (set_files_to_user && user_info) {
|
||||
if (chown(fs::absolute("key.h").c_str(),user_info->pw_uid,user_info->pw_gid)!=0) {
|
||||
cout<<"[Keygen] Warning: couldn't change file \""<<fs::absolute("key.h")<<"\" to owner "<<string(original_user)<<"."<<endl;
|
||||
}
|
||||
if (chown(fs::absolute("sign").c_str(),user_info->pw_uid,user_info->pw_gid)!=0) {
|
||||
cout<<"[Keygen] Warning: couldn't change file \""<<fs::absolute("sign")<<"\" to owner "<<string(original_user)<<"."<<endl;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user