int main(int argc, char *argv[]) { if (argc != 5) error(2, "Usage: tweetnacl-encrypt send-key.sec recv-key.pub text.txt text.enc"); // This will also erroneously fail if the file "-" exists if (file_exists(argv[4])) errorf(1, "File <%s> exists", argv[4]); // Alice is sending to Bob, not surprisingly unsigned char a_secret_key[crypto_box_SECRETKEYBYTES]; unsigned char b_public_key[crypto_box_PUBLICKEYBYTES]; read_key(argv[1], a_secret_key, crypto_box_SECRETKEYBYTES); read_key(argv[2], b_public_key, crypto_box_PUBLICKEYBYTES); unsigned char nonce[crypto_box_NONCEBYTES]; randombytes(nonce, sizeof(nonce)); FILE *out; if (strcmp(argv[4], "-") != 0) { out = create_file(argv[4]); fwrite(nonce, sizeof(nonce), 1, out); } else { out = stdout; fwrite(bytes_to_hex(nonce, sizeof(nonce)), sizeof(nonce) * 2, 1, out); fputs("\n", out); } // Input // unsigned char *message = read_file(argv[3]); Content c = read_file(argv[3]); long psize = crypto_box_ZEROBYTES + c.size; unsigned char *padded = malloc(psize); if (padded == NULL) error(1, "Malloc failed!"); memset(padded, 0, crypto_box_ZEROBYTES); memcpy(padded + crypto_box_ZEROBYTES, c.bytes, c.size); free(c.bytes); // Output unsigned char *encrypted = calloc(psize, sizeof(unsigned char)); if (encrypted == NULL) error(1, "Calloc failed!"); // Encrypt crypto_box(encrypted, padded, psize, nonce, b_public_key, a_secret_key); free(padded); if (out != stdout) { fwrite(encrypted + crypto_box_BOXZEROBYTES, psize - crypto_box_BOXZEROBYTES, 1, out); } else { fwrite(bytes_to_hex(encrypted + crypto_box_BOXZEROBYTES, psize - crypto_box_BOXZEROBYTES), (psize - crypto_box_BOXZEROBYTES) * 2, 1, out); fputs("\n", out); } free(encrypted); return 0; }
interval_db* node_mgr::init_interval_db(const string endid, const string my_vid, const string startid) { string filename(filebase + bytes_to_hex(endid)); // truncate filename to 255 characters if (filename.size() > 255) filename.resize(255); interval_db* i = new interval_db; if (startid != "") { cout << "[init_interval_db] Interval is [" << bytes_to_hex(startid) << " , " << bytes_to_hex(endid) << " ] " << endl; cout << "Creating file (init): " << filename << endl; i->h = fawn::FawnDS<FawnDS_Flash>::Create_FawnDS(filename.c_str(), NUM_RECORD_INIT, .9, .8, TEXT_KEYS); DBID d_endid(endid); DBID d_startid(startid); i->h->setStartID(d_startid); i->h->setEndID(d_endid); cout << "Creating db from xml file: " << xmlfile << endl; silt::Configuration* config = new silt::Configuration(xmlfile); i->siltds = silt::FawnDS_Factory::New(config); i->siltds->Create(); } else { cout << "[init_interval_db] startid isnt set" << endl; cout << "Opening file: " << filename << endl; i->h = fawn::FawnDS<FawnDS_Flash>::Open_FawnDS(filename.c_str(), TEXT_KEYS); cout << "Opening db from xml file: " << xmlfile << endl; silt::Configuration* config = new silt::Configuration(xmlfile); i->siltds = silt::FawnDS_Factory::New(config); i->siltds->Open(); } i->valid = true; i->tempDS = NULL; i->name = filename; i->splitPoint = ""; i->largest_seq = 0; i->last_ack = 0; i->sequence = 1; // If vid specified, set, otherwise endid = owner vid if (my_vid == "") i->vid = endid; else i->vid = my_vid; pthread_rwlock_init(&(i->dbLock), NULL); return i; }
std::string Authentication2Command::toString() { std::stringstream builder; builder << "Authentication 2:" << std::endl; builder << "\tIDm: " << bytes_to_hex(idm, 8) << std::endl; builder << "\tChallenge 2 Response: " << bytes_to_hex(challenge_2_response, 8) << std::endl; return builder.str(); }
std::string Authentication2ResponseCommand::toString() { std::stringstream builder; builder << "Authentication 2 Response:" << std::endl; builder << "\tIDm: " << bytes_to_hex(idm, 8) << std::endl; builder << "\tIDi: " << bytes_to_hex(idi, 8) << std::endl; builder << "\tPMi: " << bytes_to_hex(pmi, 8) << std::endl; return builder.str(); }
void node_mgr::create_interval_file(const string ps_endid, const string ps_startid, const string my_vid) { string filename(filebase + bytes_to_hex(ps_endid)); cout << "Creating file: " << filename << endl; cout << "[create_interval_file] Interval is [" << bytes_to_hex(ps_startid) << " , " << bytes_to_hex(ps_endid) << " ] " << endl; struct stat fileInfo; // truncate filename to 255 characters if (filename.size() > 255) filename.resize(255); int statRet = stat(filename.c_str(), &fileInfo); if (statRet == 0) { // File exists cout << "File exists already" << endl; if (overwrite) cout << "Overwriting..." << endl; else { cout << "Opening existing file " << endl; interval_db* i = init_interval_db(ps_endid, my_vid); insertIntervalFile(i); return; } } bool b_create_done = false; // lock intervaldb (read mode) pthread_rwlock_rdlock(&interval_lock); // Don't create if name already exists in existing db. for (uint dbi = 0; dbi < dbs.size(); dbi++) { if (dbs[dbi] != NULL) { if (dbs[dbi]->name == filename) { b_create_done = true; break; } } } // Don't hold interval lock while creating fawnds file. Assumes no // one else will be creating a similarly named file during this short // period of filename collision vulnerability pthread_rwlock_unlock(&interval_lock); if (b_create_done) return; interval_db* i = init_interval_db(ps_endid, my_vid, ps_startid); insertIntervalFile(i); }
void lastpass_update_account(enum blobsync sync, unsigned const char key[KDF_HASH_LEN], const struct session *session, const struct account *account, struct blob *blob) { _cleanup_free_ char *url = NULL; _cleanup_free_ char *fields = NULL; bytes_to_hex(account->url, &url, strlen(account->url)); fields = stringify_fields(account->field_head); ++blob->version; if (account->share) upload_queue_enqueue(sync, key, session, "show_website.php", "extjs", "1", "token", session->token, "aid", account->id, "name", account->name_encrypted, "grouping", account->group_encrypted, "url", url, "username", account->username_encrypted, "password", account->password_encrypted, /* "data", fields, Removing until server-side catches up. */ "pwprotect", account->pwprotect ? "on" : "off", "extra", account->note_encrypted, "sharedfolderid", account->share->id, NULL); else upload_queue_enqueue(sync, key, session, "show_website.php", "extjs", "1", "token", session->token, "aid", account->id, "name", account->name_encrypted, "grouping", account->group_encrypted, "url", url, "username", account->username_encrypted, "password", account->password_encrypted, /* "data", fields, Removing until server-side catches up. */ "pwprotect", account->pwprotect ? "on" : "off", "extra", account->note_encrypted, NULL); }
std::string ReadWithoutEncryptionCommand::toString() { std::stringstream builder; builder << "Read without Encryption:" << std::endl; builder << "\tIDm: " << bytes_to_hex(idm, 8) << std::endl; builder << "\tNumber of Services to read: " << (unsigned int)number_of_services << std::endl; if(number_of_services > 0) { builder << "\tServices to read:" << std::endl; for(int i = 0; i < number_of_services; i++) { builder << "\t\t"<< std::setw(2) << std::setfill('0') << i <<": "; builder << format_node_code(service_code_list[i]) << std::dec << std::setw(0) << std::setfill(' ') << std::endl; } } builder << "\tNumber of Blocks to read: " << (unsigned int)number_of_blocks << std::endl; if(number_of_blocks > 0) { builder << "\tBlocks to read: " << std::endl; for(int i = 0; i < number_of_blocks; i++) { unsigned int service_code_list_order = block_headers_list[i] & 0x0f; unsigned int access_mode = (block_headers_list[i] & 0x70) >> 4; builder << "\t\t" << std::setw(2) << std::setfill('0') << i <<": "; builder << "Service #" << service_code_list_order << ", Block #" << (unsigned int)block_list[i] << " (" << (access_mode == 1 ? "purse cashback access" : "r/w operation") << ")" << std::endl; } }
int gs_start_app(PSERVER_DATA server, STREAM_CONFIGURATION *config, int appId, bool sops, bool localaudio) { uuid_t uuid; char uuid_str[37]; RAND_bytes(config->remoteInputAesKey, 16); memset(config->remoteInputAesIv, 0, 16); srand(time(NULL)); char url[4096]; u_int32_t rikeyid = 1; char rikey_hex[33]; bytes_to_hex(config->remoteInputAesKey, rikey_hex, 16); PHTTP_DATA data = http_create_data(); if (data == NULL) return GS_OUT_OF_MEMORY; uuid_generate_random(uuid); uuid_unparse(uuid, uuid_str); if (server->currentGame == 0) { int channelCounnt = config->audioConfiguration == AUDIO_CONFIGURATION_STEREO ? CHANNEL_COUNT_STEREO : CHANNEL_COUNT_51_SURROUND; int mask = config->audioConfiguration == AUDIO_CONFIGURATION_STEREO ? CHANNEL_MASK_STEREO : CHANNEL_MASK_51_SURROUND; sprintf(url, "https://%s:47984/launch?uniqueid=%s&uuid=%s&appid=%d&mode=%dx%dx%d&additionalStates=1&sops=%d&rikey=%s&rikeyid=%d&localAudioPlayMode=%d&surroundAudioInfo=%d", server->address, unique_id, uuid_str, appId, config->width, config->height, config->fps, sops, rikey_hex, rikeyid, localaudio, (mask << 16) + channelCounnt); } else sprintf(url, "https://%s:47984/resume?uniqueid=%s&uuid=%s&rikey=%s&rikeyid=%d", server->address, unique_id, uuid_str, rikey_hex, rikeyid); int ret = http_request(url, data); if (ret == GS_OK) server->currentGame = appId; http_free_data(data); return ret; }
std::string SearchServiceCodeResponseCommand::toString() { std::stringstream builder; builder << "Search Service Code Response:" << std::endl; builder << "\tIDm: " << bytes_to_hex(idm, 8) << std::endl; builder << "\tService Code: " << format_node_code(service_code); if(is_area) { uint8_t area_end_code_bytes[] = { (area_end_code & 0xff00) >> 8, (area_end_code & 0x00ff) }; builder << "\tArea End: "<< bytes_to_hex(area_end_code_bytes, 2) << std::endl; } return builder.str(); }
void output_key(char filename[], unsigned char key[], int key_size) { // http://stackoverflow.com/a/8004250 if (strcmp(filename, "-") != 0) { FILE *out = create_file(filename); fwrite(key, key_size, 1, out); fclose(out); } else { fwrite(bytes_to_hex(key, key_size), key_size * 2, 1, stdout); fputs("\n", stdout); } }
static int check_resource(struct resource_list *list, const char *file_resource_name, struct archive *a, struct archive_entry *ae) { struct resource_list *item = rlist_find_by_name(list, file_resource_name); if (!item) ERR_RETURN("Can't find file-resource for %s", file_resource_name); if (item->processed) ERR_RETURN("Processing %s twice. Archive is corrupt.", file_resource_name); item->processed = true; struct sparse_file_map sfm; sparse_file_init(&sfm); OK_OR_RETURN(sparse_file_get_map_from_resource(item->resource, &sfm)); size_t expected_length = sparse_file_data_size(&sfm); ssize_t archive_length = archive_entry_size(ae); if (archive_length < 0) ERR_RETURN("Missing file length in archive for %s", file_resource_name); if ((size_t) archive_length != expected_length) ERR_RETURN("Length mismatch for %s", file_resource_name); char *expected_hash = cfg_getstr(item->resource, "blake2b-256"); if (!expected_hash || strlen(expected_hash) != crypto_generichash_BYTES * 2) ERR_RETURN("invalid blake2b-256 hash for '%s'", file_resource_name); crypto_generichash_state hash_state; crypto_generichash_init(&hash_state, NULL, 0, crypto_generichash_BYTES); size_t length_left = expected_length; while (length_left != 0) { char buffer[4096]; size_t to_read = sizeof(buffer); if (to_read > length_left) to_read = length_left; ssize_t len = archive_read_data(a, buffer, to_read); if (len <= 0) ERR_RETURN("Error reading '%s' in archive", archive_entry_pathname(ae)); crypto_generichash_update(&hash_state, (const unsigned char*) buffer, len); length_left -= len; } unsigned char hash[crypto_generichash_BYTES]; crypto_generichash_final(&hash_state, hash, sizeof(hash)); char hash_str[sizeof(hash) * 2 + 1]; bytes_to_hex(hash, hash_str, sizeof(hash)); if (memcmp(hash_str, expected_hash, sizeof(hash_str)) != 0) ERR_RETURN("Detected blake2b digest mismatch for %s", file_resource_name); return 0; }
int gs_start_app(PSERVER_DATA server, STREAM_CONFIGURATION *config, int appId, bool sops, bool localaudio) { int ret = GS_OK; uuid_t uuid; char* result = NULL; char uuid_str[37]; if (config->height >= 2160 && !server->supports4K) return GS_NOT_SUPPORTED_4K; RAND_bytes(config->remoteInputAesKey, 16); memset(config->remoteInputAesIv, 0, 16); srand(time(NULL)); char url[4096]; u_int32_t rikeyid = 0; char rikey_hex[33]; bytes_to_hex(config->remoteInputAesKey, rikey_hex, 16); PHTTP_DATA data = http_create_data(); if (data == NULL) return GS_OUT_OF_MEMORY; uuid_generate_random(uuid); uuid_unparse(uuid, uuid_str); if (server->currentGame == 0) { int channelCounnt = config->audioConfiguration == AUDIO_CONFIGURATION_STEREO ? CHANNEL_COUNT_STEREO : CHANNEL_COUNT_51_SURROUND; int mask = config->audioConfiguration == AUDIO_CONFIGURATION_STEREO ? CHANNEL_MASK_STEREO : CHANNEL_MASK_51_SURROUND; sprintf(url, "https://%s:47984/launch?uniqueid=%s&uuid=%s&appid=%d&mode=%dx%dx%d&additionalStates=1&sops=%d&rikey=%s&rikeyid=%d&localAudioPlayMode=%d&surroundAudioInfo=%d", server->address, unique_id, uuid_str, appId, config->width, config->height, config->fps, sops, rikey_hex, rikeyid, localaudio, (mask << 16) + channelCounnt); } else sprintf(url, "https://%s:47984/resume?uniqueid=%s&uuid=%s&rikey=%s&rikeyid=%d", server->address, unique_id, uuid_str, rikey_hex, rikeyid); if ((ret = http_request(url, data)) == GS_OK) server->currentGame = appId; else goto cleanup; if ((ret = xml_search(data->memory, data->size, "gamesession", &result)) != GS_OK) goto cleanup; if (!strcmp(result, "0")) { ret = GS_FAILED; goto cleanup; } cleanup: if (result != NULL) free(result); http_free_data(data); return ret; }
void kdf_login_key(const char *username, const char *password, int iterations, char hex[KDF_HEX_LEN]) { unsigned char hash[KDF_HASH_LEN]; size_t password_len; _cleanup_free_ char *user_lower = xstrlower(username); password_len = strlen(password); if (iterations < 1) iterations = 1; if (iterations == 1) { sha256_hash(user_lower, strlen(user_lower), password, password_len, hash); bytes_to_hex(hash, &hex, KDF_HASH_LEN); sha256_hash(hex, KDF_HEX_LEN - 1, password, password_len, hash); } else { pbkdf2_hash(user_lower, strlen(user_lower), password, password_len, iterations, hash); pbkdf2_hash(password, password_len, (char *)hash, KDF_HASH_LEN, 1, hash); } bytes_to_hex(hash, &hex, KDF_HASH_LEN); mlock(hex, KDF_HEX_LEN); }
/** @brief Print out the superblock struct to stdout * * @param sb Superblock */ void print_superblock(struct mint_superblock *sb){ char *buf = (char*)(malloc(4096)); const EVP_MD *md; md = EVP_get_digestbyname(sb->hash_algorithm); uint32_t hash_bytes = EVP_MD_size(md); printf("[ dm-mintegrity superblock ]\n"); printf("Magic: %#0x\n", sb->magic); printf("Version: %u\n", sb->version); bytes_to_hex(sb->uuid, 16, buf); printf("UUID: %s\n", buf); printf("Hash_Type: %s\n", sb->hash_algorithm); printf("Hmac_Type: %s\n", sb->hmac_algorithm); printf("Block_Size: %u\n", sb->block_size); printf("Data_Blocks: %ju\n", sb->data_blocks); printf("Hash_Blocks: %u\n", sb->hash_blocks); printf("JB_Blocks: %u\n", sb->jb_blocks); printf("Salt_Size: %u\n", sb->salt_size); bytes_to_hex(sb->salt, sb->salt_size, buf); printf("Salt: %s\n", buf); bytes_to_hex(sb->root, hash_bytes, buf); printf("Root_Hash: %s\n", buf); free(buf); }
void hexdump(const char *prefix, const size_t column_len, const void *value, size_t len) { assert(prefix != NULL); assert(column_len > 0); int row_count = (len / column_len) + 1; int i; size_t slen = column_len*3; char* s = malloc(slen * sizeof(char)); for (i = 0; i < row_count; ++i) { memset(s, 0, slen); bytes_to_hex(value, len, (char **)&s); printf("%s %s\n", prefix, s); } free(s); }
static char *stringify_fields(const struct field *field_head) { char *field_str, *fields = NULL; for (const struct field *field = field_head; field; field = field->next) { field_str = stringify_field(field); xstrappend(&fields, field_str); free(field_str); } if (fields) xstrappend(&fields, "0\taction\t\taction\n0\tmethod\t\tmethod\n"); else fields = xstrdup(""); field_str = NULL; bytes_to_hex(fields, &field_str, strlen(fields)); free(fields); return field_str; }
fawn::FawnDS<FawnDS_Flash>* node_mgr::createTempStore(const string& startid_str, const string& endid_str, const string& prefix_str) { DBID p_endid(endid_str); DBID p_startid(startid_str); string filename(filebase + prefix_str + bytes_to_hex(endid_str)); // truncate filename to 255 characters if (filename.size() > 255) filename.resize(255); cout << "Creating temporary file: " << filename << endl; fawn::FawnDS<FawnDS_Flash>* tempDS = fawn::FawnDS<FawnDS_Flash>::Create_FawnDS(filename.c_str(), NUM_RECORD_INIT_TEMP, 0.9, 0.8, TEXT_KEYS); tempDS->setStartID(p_startid); tempDS->setEndID(p_endid); return tempDS; }
void load_recovery_id_prop() { char fstab_filename[PROP_VALUE_MAX + sizeof(FSTAB_PREFIX)]; char propbuf[PROP_VALUE_MAX]; int ret = property_get("ro.hardware", propbuf); if (!ret) { ERROR("ro.hardware not set - unable to load recovery id\n"); return; } snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX "%s", propbuf); std::unique_ptr<fstab, void(*)(fstab*)> tab(fs_mgr_read_fstab(fstab_filename), fs_mgr_free_fstab); if (!tab) { ERROR("unable to read fstab %s: %s\n", fstab_filename, strerror(errno)); return; } fstab_rec* rec = fs_mgr_get_entry_for_mount_point(tab.get(), RECOVERY_MOUNT_POINT); if (rec == NULL) { ERROR("/recovery not specified in fstab\n"); return; } int fd = open(rec->blk_device, O_RDONLY); if (fd == -1) { ERROR("error opening block device %s: %s\n", rec->blk_device, strerror(errno)); return; } boot_img_hdr hdr; if (android::base::ReadFully(fd, &hdr, sizeof(hdr))) { std::string hex = bytes_to_hex(reinterpret_cast<uint8_t*>(hdr.id), sizeof(hdr.id)); property_set("ro.recovery_id", hex.c_str()); } else { ERROR("error reading /recovery: %s\n", strerror(errno)); } close(fd); }
void load_recovery_id_prop() { std::string ro_hardware = property_get("ro.hardware"); if (ro_hardware.empty()) { LOG(ERROR) << "ro.hardware not set - unable to load recovery id"; return; } std::string fstab_filename = FSTAB_PREFIX + ro_hardware; std::unique_ptr<fstab, void(*)(fstab*)> tab(fs_mgr_read_fstab(fstab_filename.c_str()), fs_mgr_free_fstab); if (!tab) { PLOG(ERROR) << "unable to read fstab " << fstab_filename; return; } fstab_rec* rec = fs_mgr_get_entry_for_mount_point(tab.get(), RECOVERY_MOUNT_POINT); if (rec == NULL) { LOG(ERROR) << "/recovery not specified in fstab"; return; } int fd = open(rec->blk_device, O_RDONLY); if (fd == -1) { PLOG(ERROR) << "error opening block device " << rec->blk_device; return; } boot_img_hdr hdr; if (android::base::ReadFully(fd, &hdr, sizeof(hdr))) { std::string hex = bytes_to_hex(reinterpret_cast<uint8_t*>(hdr.id), sizeof(hdr.id)); property_set("ro.recovery_id", hex.c_str()); } else { PLOG(ERROR) << "error reading /recovery"; } close(fd); }
int main() { try { std::cout << "load:\t"; { std::cout << "1, 12, 1.234, 5.678" << std::endl; boost::uint8_t n8(0); boost::uint32_t n32(0); boost::uint64_t n64(0); double ad64(0); double bd64(0); std::cout << "\tfrom little-endian:\t"; { std::string const hex_little("010C0000005839B4C876BEF33F83C0CAA145B61640"); std::cout << hex_little << std::endl; byte_array bytes; hex_to_bytes(hex_little, bytes); n8 = yatbinrw::load_little_endian<boost::uint8_t, sizeof(boost::uint8_t)>(bytes.begin()); std::cout << "\t\tn8 = " << (int)n8 << std::endl; n32 = yatbinrw::load_little_endian<boost::uint32_t, sizeof(boost::uint32_t)>(bytes.begin() + 1); std::cout << "\t\tn32 = " << n32 << std::endl; n64 = yatbinrw::load_little_endian<boost::uint64_t, sizeof(boost::uint64_t)>(bytes.begin() + 1 + 4); std::memcpy(&ad64, &n64, sizeof(double)); std::cout << "\t\tad64 = " << ad64 << " (" << n64 << " )" << std::endl; n64 = yatbinrw::load_little_endian<boost::uint64_t, sizeof(boost::uint64_t)>(bytes.begin() + 1 + 4 + 8); std::memcpy(&bd64, &n64, sizeof(double)); std::cout << "\t\tbd64 = " << bd64 << " (" << n64 << " )" << std::endl; } std::cout << "\tfrom big-endian:\t"; { std::string const hex_big("010000000C3FF3BE76C8B439584016B645A1CAC083"); std::cout << hex_big << std::endl; byte_array bytes; hex_to_bytes(hex_big, bytes); n8 = yatbinrw::load_big_endian<boost::uint8_t, sizeof(boost::uint8_t)>(bytes.begin()); std::cout << "\t\tn8 = " << (int)n8 << std::endl; n32 = yatbinrw::load_big_endian<boost::uint32_t, sizeof(boost::uint32_t)>(bytes.begin() + 1); std::cout << "\t\tn32 = " << n32 << std::endl; n64 = yatbinrw::load_big_endian<boost::uint64_t, sizeof(boost::uint64_t)>(bytes.begin() + 1 + 4); std::memcpy(&ad64, &n64, sizeof(double)); std::cout << "\t\tad64 = " << ad64 << " (" << n64 << " )" << std::endl; n64 = yatbinrw::load_big_endian<boost::uint64_t, sizeof(boost::uint64_t)>(bytes.begin() + 1 + 4 + 8); std::memcpy(&bd64, &n64, sizeof(double)); std::cout << "\t\tbd64 = " << bd64 << " (" << n64 << " )" << std::endl; } } // load std::cout << "store:\t"; { boost::uint8_t const n8(1); boost::uint32_t const n32(12); boost::uint64_t n64(0); double const ad64(1.234); double const bd64(5.678); std::cout << (int)n8 << ", " << n32 << ", " << ad64 << ", " << bd64 << std::endl; std::cout << "\tto little-endian:\t"; { byte_array bytes; //empty std::back_insert_iterator<byte_array> it(std::back_inserter(bytes)); yatbinrw::store_little_endian<boost::uint8_t, 1>(it, n8); yatbinrw::store_little_endian<boost::uint32_t, 4>(it, n32); std::memcpy(&n64, &ad64, sizeof(boost::uint64_t)); yatbinrw::store_little_endian<boost::uint64_t, 8>(it, n64); std::memcpy(&n64, &bd64, sizeof(boost::uint64_t)); yatbinrw::store_little_endian<boost::uint64_t, 8>(it, n64); std::string hex; bytes_to_hex(bytes, hex); std::cout << hex << std::endl; } std::cout << "\tto big-endian:"; { byte_array bytes(1 + 4 + 8 + 8); // non-empty yatbinrw::store_big_endian<boost::uint8_t, 1>(bytes.begin(), n8); yatbinrw::store_big_endian<boost::uint32_t, 4>(bytes.begin() + 1, n32); std::memcpy(&n64, &ad64, sizeof(boost::uint64_t)); yatbinrw::store_big_endian<boost::uint64_t, 8>(bytes.begin() + 1 + 4, n64); std::memcpy(&n64, &bd64, sizeof(boost::uint64_t)); yatbinrw::store_big_endian<boost::uint64_t, 8>(bytes.begin() + 1 + 4 + 8, n64); std::string hex; bytes_to_hex(bytes, hex); std::cout << '\t' << hex << std::endl; } } // store } catch (std::exception const& e) { std::cerr << e.what() << std::endl; } return 0; }
static void write_hex_string(struct buffer *buffer, char *bytes) { _cleanup_free_ char *hex = NULL; bytes_to_hex(bytes, &hex, strlen(bytes)); write_plain_string(buffer, hex); }
int gs_pair(const char* address, const char* pin) { int ret = GS_OK; char url[4096]; unsigned char salt_data[16]; char salt_hex[33]; RAND_bytes(salt_data, 16); bytes_to_hex(salt_data, salt_hex, 16); sprintf(url, "http://%s:47989/pair?uniqueid=%s&devicename=roth&updateState=1&phrase=getservercert&salt=%s&clientcert=%s", address, g_UniqueId, salt_hex, g_CertHex); PHTTP_DATA data = http_create_data(); if (data == NULL) return GS_OUT_OF_MEMORY; else if ((ret = http_request(url, data)) != GS_OK) goto cleanup; unsigned char salt_pin[20]; unsigned char aes_key_hash[20]; AES_KEY enc_key, dec_key; memcpy(salt_pin, salt_data, 16); memcpy(salt_pin+16, pin, 4); SHA1(salt_pin, 20, aes_key_hash); AES_set_encrypt_key((unsigned char *)aes_key_hash, 128, &enc_key); AES_set_decrypt_key((unsigned char *)aes_key_hash, 128, &dec_key); unsigned char challenge_data[16]; unsigned char challenge_enc[16]; char challenge_hex[33]; RAND_bytes(challenge_data, 16); AES_encrypt(challenge_data, challenge_enc, &enc_key); bytes_to_hex(challenge_enc, challenge_hex, 16); sprintf(url, "http://%s:47989/pair?uniqueid=%s&devicename=roth&updateState=1&clientchallenge=%s", address, g_UniqueId, challenge_hex); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; char *result; if (xml_search(data->memory, data->size, "challengeresponse", &result) != GS_OK) { ret = GS_INVALID; goto cleanup; } unsigned char challenge_response_data_enc[48]; unsigned char challenge_response_data[48]; for (int count = 0; count < strlen(result); count += 2) { sscanf(&result[count], "%2hhx", &challenge_response_data_enc[count / 2]); } free(result); for (int i = 0; i < 48; i += 16) { AES_decrypt(&challenge_response_data_enc[i], &challenge_response_data[i], &dec_key); } unsigned char client_secret_data[16]; RAND_bytes(client_secret_data, 16); unsigned char challenge_response[16 + 256 + 16]; unsigned char challenge_response_hash[32]; unsigned char challenge_response_hash_enc[32]; char challenge_response_hex[65]; memcpy(challenge_response, challenge_response_data + 20, 16); memcpy(challenge_response + 16, g_Cert->signature->data, 256); memcpy(challenge_response + 16 + 256, client_secret_data, 16); SHA1(challenge_response, 16 + 256 + 16, challenge_response_hash); for (int i = 0; i < 32; i += 16) { AES_encrypt(&challenge_response_hash[i], &challenge_response_hash_enc[i], &enc_key); } bytes_to_hex(challenge_response_hash_enc, challenge_response_hex, 32); sprintf(url, "http://%s:47989/pair?uniqueid=%s&devicename=roth&updateState=1&serverchallengeresp=%s", address, g_UniqueId, challenge_response_hex); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; if (xml_search(data->memory, data->size, "pairingsecret", &result) != GS_OK) { ret = GS_INVALID; goto cleanup; } unsigned char *signature = NULL; size_t s_len; if (sign_it(client_secret_data, 16, &signature, &s_len, g_PrivateKey) != GS_OK) { gs_error = "Failed to sign data"; ret = GS_FAILED; goto cleanup; } unsigned char client_pairing_secret[16 + 256]; char client_pairing_secret_hex[(16 + 256) * 2 + 1]; memcpy(client_pairing_secret, client_secret_data, 16); memcpy(client_pairing_secret + 16, signature, 256); bytes_to_hex(client_pairing_secret, client_pairing_secret_hex, 16 + 256); sprintf(url, "http://%s:47989/pair?uniqueid=%s&devicename=roth&updateState=1&clientpairingsecret=%s", address, g_UniqueId, client_pairing_secret_hex); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; sprintf(url, "https://%s:47984/pair?uniqueid=%s&devicename=roth&updateState=1&phrase=pairchallenge", address, g_UniqueId); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; cleanup: http_free_data(data); return ret; }
char *str_id( const UCHAR id[], char buf[] ) { return bytes_to_hex( buf, id, SHA1_BIN_LENGTH ); }
static int rehash_verity(const int meta_version, const int dm_verity_version, const char * data_device, const size_t block_size) { #if 0 int r = -1; char *table, *salt = NULL; salt = malloc(32); /* biggest length */ if (NULL == salt) { fprintf(stderr, "Failed to malloc mem for salt\n"); return -1; } #endif int ret = 0; uint64_t part_size; if(ext4_part_size(TARGET_DEV, &part_size)) { printf("failed to get part size.\n"); return -1; } const char * tmp_hash_file = TMP_HASH_FILE; const char * tmp_hash_table = TMP_HASH_TABLE; //unlink(tmp_hash_file); //unlink(tmp_hash_table); const char * hash_name = HASH_NAME; int i; char * table = NULL, *p; const long data_blocks = part_size / DMVERITY_BLOCK_SIZE; #ifdef USE_SHA256 const int digest_size = 32;//sha256 #elif USE_SHA1 const int digest_size = 20;//sha1 #else const int digest_size = 16;//md5 #endif char salt[digest_size]; char root_hash[digest_size]; const loff_t hash_start = (part_size + DMVERITY_META_SIZE)/DMVERITY_BLOCK_SIZE; const loff_t hash_position = DMVERITY_META_SIZE/DMVERITY_BLOCK_SIZE; struct verity_meta_header meta_header; FILE * fp; //0.1 generate random salt /* generate_salt(salt); */ if (generate_salt(salt, digest_size) != digest_size) { printf("Error generating random salt.\n"); // how to handle it better? now it will use whatever compiler gives: all 0's } // 1. generate hash, table and write to a tmp hash file if(VERITY_create_hash(dm_verity_version, \ hash_name, \ TMP_HASH_FILE, \ data_device, \ block_size, \ block_size, \ data_blocks, \ hash_position, \ (unsigned char *)root_hash, \ digest_size, \ (const unsigned char *)salt, \ digest_size)) { printf("failed to create hash tree\n"); ret = -1; goto rehash_out; } int table_size = nDigits(dm_verity_version) + 1 + strlen(TARGET_DEV) + 1 + strlen(TARGET_DEV) + 1 + nDigits(DMVERITY_BLOCK_SIZE) + 1 + nDigits(DMVERITY_BLOCK_SIZE) + 1 + nDigits(data_blocks) + 1 + nDigits(hash_start) + 1 + strlen(hash_name) + 1 + digest_size * 2 + 1 + digest_size * 2 + 1; table = malloc(table_size); if(NULL == table){ printf("malloc failed\n"); ret = -1; goto rehash_out; } table[table_size-1] = 0; i = sprintf(table, "%d %s %s %lld %lld %lld %lld %s ", dm_verity_version, TARGET_DEV, TARGET_DEV, (long long int) DMVERITY_BLOCK_SIZE, (long long int) DMVERITY_BLOCK_SIZE, (long long int) data_blocks, (long long int) hash_start, hash_name); if(i <= 0){ printf("sprintf error"); free(table); ret = -1; goto rehash_out; } //printf("Table: %s\n", table); p = table + i; bytes_to_hex(root_hash, p, digest_size); p += digest_size * 2; p += sprintf(p, " "); bytes_to_hex(salt, p, digest_size); printf("table: %s", table); // 2.1 generate meta_header meta_header.magic_number = VERITY_METADATA_MAGIC_NUMBER; meta_header.protocol_version = 0; meta_header.table_length = strlen(table);//not including trailing NULL memset(&meta_header.signature, 0, sizeof(meta_header.signature)); //tmp_hash_file it should have been created by generate_dm_verity_hash already. // 2.2 write table and meta_header to tmp hash file fp = fopen(tmp_hash_file, "r+"); if (NULL == fp) { printf("failed to open temp file\n"); ret = -1; goto rehash_out; } if(1 != fwrite(&meta_header, sizeof(struct verity_meta_header), 1, fp)){ printf("failed to write temp file\n"); fclose(fp); ret = -1; goto rehash_out; } printf("write meta_header %d\n", sizeof(struct verity_meta_header)); if(1 != fwrite(table, meta_header.table_length+1, 1, fp)){ printf("failed to write temp file\n"); fclose(fp); ret = -1; goto rehash_out; } printf("write table %d\n", meta_header.table_length+1); fflush(fp); fsync(fileno(fp)); fclose(fp); // 2.3 write table to tmp hash meta table file fp = fopen(tmp_hash_table, "w"); if (NULL == fp) { printf("failed to open temp meta table file\n"); ret = -1; goto rehash_out; } if(1 != fwrite(table, meta_header.table_length+1, 1, fp)){ printf("failed to write temp meta table file\n"); fclose(fp); ret = -1; goto rehash_out; } printf("write table %d\n", meta_header.table_length+1); fflush(fp); fsync(fileno(fp)); fclose(fp); // 3. write tmp hash file to the /system (not signed) /* if(file_to_device(tmp_hash_file, TARGET_DEV, 1024*1024, part_size)){ printf("failed to write hash 001\n"); goto rehash_out; } */ rehash_out: //unlink(tmp_hash_file); if(table) free(table); return ret; }
int gs_pair(PSERVER_DATA server, char* pin) { int ret = GS_OK; char url[4096]; uuid_t uuid; char uuid_str[37]; if (server->paired) { gs_error = "Already paired"; return GS_WRONG_STATE; } if (server->currentGame != 0) { gs_error = "The computer is currently in a game. You must close the game before pairing"; return GS_WRONG_STATE; } unsigned char salt_data[16]; char salt_hex[33]; RAND_bytes(salt_data, 16); bytes_to_hex(salt_data, salt_hex, 16); uuid_generate_random(uuid); uuid_unparse(uuid, uuid_str); sprintf(url, "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&phrase=getservercert&salt=%s&clientcert=%s", server->address, unique_id, uuid_str, salt_hex, cert_hex); PHTTP_DATA data = http_create_data(); if (data == NULL) return GS_OUT_OF_MEMORY; else if ((ret = http_request(url, data)) != GS_OK) goto cleanup; unsigned char salt_pin[20]; unsigned char aes_key_hash[20]; AES_KEY aes_key; memcpy(salt_pin, salt_data, 16); memcpy(salt_pin+16, salt_pin, 4); SHA1(salt_pin, 20, aes_key_hash); AES_set_encrypt_key((unsigned char *)aes_key_hash, 128, &aes_key); unsigned char challenge_data[16]; unsigned char challenge_enc[16]; char challenge_hex[33]; RAND_bytes(challenge_data, 16); AES_encrypt(challenge_data, challenge_enc, &aes_key); bytes_to_hex(challenge_enc, challenge_hex, 16); uuid_generate_random(uuid); uuid_unparse(uuid, uuid_str); sprintf(url, "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&clientchallenge=%s", server->address, unique_id, uuid_str, challenge_hex); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; char *result; if (xml_search(data->memory, data->size, "challengeresponse", &result) != GS_OK) { ret = GS_INVALID; goto cleanup; } char challenge_response_data_enc[48]; char challenge_response_data[48]; for (int count = 0; count < strlen(result); count++) { sscanf(&result[count], "%2hhx", &challenge_response_data_enc[count / 2]); } free(result); for (int i = 0; i < 48; i += 16) { AES_decrypt(&challenge_response_data_enc[i], &challenge_response_data[i], &aes_key); } char client_secret_data[16]; RAND_bytes(client_secret_data, 16); char challenge_response[16 + 256 + 16]; char challenge_response_hash[32]; char challenge_response_hash_enc[32]; char challenge_response_hex[33]; memcpy(challenge_response, challenge_response_data + 20, 16); memcpy(challenge_response + 16, cert->signature->data, 256); memcpy(challenge_response + 16 + 256, client_secret_data, 16); SHA1(challenge_response, 16 + 256 + 16, challenge_response_hash); for (int i = 0; i < 32; i += 16) { AES_encrypt(&challenge_response_hash[i], &challenge_response_hash_enc[i], &aes_key); } bytes_to_hex(challenge_response_hash_enc, challenge_response_hex, 32); uuid_generate_random(uuid); uuid_unparse(uuid, uuid_str); sprintf(url, "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&serverchallengeresp=%s", server->address, unique_id, uuid_str, challenge_response_hex); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; if (xml_search(data->memory, data->size, "pairingsecret", &result) != GS_OK) { ret = GS_INVALID; goto cleanup; } unsigned char *signature = NULL; size_t s_len; if (sign_it(client_secret_data, 16, &signature, &s_len, privateKey) != GS_OK) { gs_error = "Failed to sign data"; ret = GS_FAILED; goto cleanup; } char client_pairing_secret[16 + 256]; char client_pairing_secret_hex[(16 + 256) * 2 + 1]; memcpy(client_pairing_secret, client_secret_data, 16); memcpy(client_pairing_secret + 16, signature, 256); bytes_to_hex(client_pairing_secret, client_pairing_secret_hex, 16 + 256); uuid_generate_random(uuid); uuid_unparse(uuid, uuid_str); sprintf(url, "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&clientpairingsecret=%s", server->address, unique_id, uuid_str, client_pairing_secret_hex); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; uuid_generate_random(uuid); uuid_unparse(uuid, uuid_str); sprintf(url, "https://%s:47984/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&phrase=pairchallenge", server->address, unique_id, uuid_str); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; server->paired = true; cleanup: http_free_data(data); return ret; }
int gs_pair(PSERVER_DATA server, char* pin) { int ret = GS_OK; char* result = NULL; char url[4096]; uuid_t uuid; char uuid_str[37]; if (server->paired) { gs_error = "Already paired"; return GS_WRONG_STATE; } if (server->currentGame != 0) { gs_error = "The computer is currently in a game. You must close the game before pairing"; return GS_WRONG_STATE; } unsigned char salt_data[16]; char salt_hex[33]; RAND_bytes(salt_data, 16); bytes_to_hex(salt_data, salt_hex, 16); uuid_generate_random(uuid); uuid_unparse(uuid, uuid_str); sprintf(url, "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&phrase=getservercert&salt=%s&clientcert=%s", server->address, unique_id, uuid_str, salt_hex, cert_hex); PHTTP_DATA data = http_create_data(); if (data == NULL) return GS_OUT_OF_MEMORY; else if ((ret = http_request(url, data)) != GS_OK) goto cleanup; if ((ret = xml_search(data->memory, data->size, "paired", &result)) != GS_OK) goto cleanup; if (strcmp(result, "1") != 0) { gs_error = "Pairing failed"; ret = GS_FAILED; goto cleanup; } free(result); result = NULL; if ((ret = xml_search(data->memory, data->size, "plaincert", &result)) != GS_OK) goto cleanup; if (strlen(result)/2 > 8191) { gs_error = "Server certificate too big"; ret = GS_FAILED; goto cleanup; } char plaincert[8192]; for (int count = 0; count < strlen(result); count += 2) { sscanf(&result[count], "%2hhx", &plaincert[count / 2]); } plaincert[strlen(result)/2] = '\0'; printf("%d / %d\n", strlen(result)/2, strlen(plaincert)); unsigned char salt_pin[20]; unsigned char aes_key_hash[32]; AES_KEY enc_key, dec_key; memcpy(salt_pin, salt_data, 16); memcpy(salt_pin+16, pin, 4); int hash_length = server->serverMajorVersion >= 7 ? 32 : 20; if (server->serverMajorVersion >= 7) SHA256(salt_pin, 20, aes_key_hash); else SHA1(salt_pin, 20, aes_key_hash); AES_set_encrypt_key((unsigned char *)aes_key_hash, 128, &enc_key); AES_set_decrypt_key((unsigned char *)aes_key_hash, 128, &dec_key); unsigned char challenge_data[16]; unsigned char challenge_enc[16]; char challenge_hex[33]; RAND_bytes(challenge_data, 16); AES_encrypt(challenge_data, challenge_enc, &enc_key); bytes_to_hex(challenge_enc, challenge_hex, 16); uuid_generate_random(uuid); uuid_unparse(uuid, uuid_str); sprintf(url, "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&clientchallenge=%s", server->address, unique_id, uuid_str, challenge_hex); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; free(result); result = NULL; if ((ret = xml_search(data->memory, data->size, "paired", &result)) != GS_OK) goto cleanup; if (strcmp(result, "1") != 0) { gs_error = "Pairing failed"; ret = GS_FAILED; goto cleanup; } free(result); result = NULL; if (xml_search(data->memory, data->size, "challengeresponse", &result) != GS_OK) { ret = GS_INVALID; goto cleanup; } char challenge_response_data_enc[48]; char challenge_response_data[48]; for (int count = 0; count < strlen(result); count += 2) { sscanf(&result[count], "%2hhx", &challenge_response_data_enc[count / 2]); } for (int i = 0; i < 48; i += 16) { AES_decrypt(&challenge_response_data_enc[i], &challenge_response_data[i], &dec_key); } char client_secret_data[16]; RAND_bytes(client_secret_data, 16); char challenge_response[16 + 256 + 16]; char challenge_response_hash[32]; char challenge_response_hash_enc[32]; char challenge_response_hex[65]; memcpy(challenge_response, challenge_response_data + hash_length, 16); memcpy(challenge_response + 16, cert->signature->data, 256); memcpy(challenge_response + 16 + 256, client_secret_data, 16); if (server->serverMajorVersion >= 7) SHA256(challenge_response, 16 + 256 + 16, challenge_response_hash); else SHA1(challenge_response, 16 + 256 + 16, challenge_response_hash); for (int i = 0; i < 32; i += 16) { AES_encrypt(&challenge_response_hash[i], &challenge_response_hash_enc[i], &enc_key); } bytes_to_hex(challenge_response_hash_enc, challenge_response_hex, 32); uuid_generate_random(uuid); uuid_unparse(uuid, uuid_str); sprintf(url, "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&serverchallengeresp=%s", server->address, unique_id, uuid_str, challenge_response_hex); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; free(result); result = NULL; if ((ret = xml_search(data->memory, data->size, "paired", &result)) != GS_OK) goto cleanup; if (strcmp(result, "1") != 0) { gs_error = "Pairing failed"; ret = GS_FAILED; goto cleanup; } free(result); result = NULL; if (xml_search(data->memory, data->size, "pairingsecret", &result) != GS_OK) { ret = GS_INVALID; goto cleanup; } char pairing_secret[16 + 256]; for (int count = 0; count < strlen(result); count += 2) { sscanf(&result[count], "%2hhx", &pairing_secret[count / 2]); } if (!verifySignature(pairing_secret, 16, pairing_secret+16, 256, plaincert)) { gs_error = "MITM attack detected"; ret = GS_FAILED; goto cleanup; } unsigned char *signature = NULL; size_t s_len; if (sign_it(client_secret_data, 16, &signature, &s_len, privateKey) != GS_OK) { gs_error = "Failed to sign data"; ret = GS_FAILED; goto cleanup; } char client_pairing_secret[16 + 256]; char client_pairing_secret_hex[(16 + 256) * 2 + 1]; memcpy(client_pairing_secret, client_secret_data, 16); memcpy(client_pairing_secret + 16, signature, 256); bytes_to_hex(client_pairing_secret, client_pairing_secret_hex, 16 + 256); uuid_generate_random(uuid); uuid_unparse(uuid, uuid_str); sprintf(url, "http://%s:47989/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&clientpairingsecret=%s", server->address, unique_id, uuid_str, client_pairing_secret_hex); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; free(result); result = NULL; if ((ret = xml_search(data->memory, data->size, "paired", &result)) != GS_OK) goto cleanup; if (strcmp(result, "1") != 0) { gs_error = "Pairing failed"; ret = GS_FAILED; goto cleanup; } uuid_generate_random(uuid); uuid_unparse(uuid, uuid_str); sprintf(url, "https://%s:47984/pair?uniqueid=%s&uuid=%s&devicename=roth&updateState=1&phrase=pairchallenge", server->address, unique_id, uuid_str); if ((ret = http_request(url, data)) != GS_OK) goto cleanup; free(result); result = NULL; if ((ret = xml_search(data->memory, data->size, "paired", &result)) != GS_OK) goto cleanup; if (strcmp(result, "1") != 0) { gs_error = "Pairing failed"; ret = GS_FAILED; goto cleanup; } server->paired = true; cleanup: if (ret != GS_OK) gs_unpair(server); if (result != NULL) free(result); http_free_data(data); return ret; }
int main(int argc, char const *argv[]) { // Check for arguments if (argc < 8) { exit_error_f( "Usage:\n" "%s DEV BLOCK_SIZE JB_TRANSACTIONS HASH_TYPE SALT HMAC_TYPE SECRET lazy|nolazy\n" "%s MINT_DEV DATA_DEV BLOCK_SIZE JB_TRANSACTIONS HASH_TYPE SALT HMAC_TYPE SECRET lazy|nolazy\n", argv[0], argv[0]); } const char *dev, *dev2, *hash_type, *hmac_type, *salt_str, *secret_str; uint32_t block_size, journal_blocks; bool zero; if (!strcmp(argv[argc - 1], "lazy")) { zero = false; } else if (!strcmp(argv[argc - 1], "nolazy")) { zero = true; } else { exit_error_f("Unsupported optional argument: %s", argv[argc - 1]); } bool two_disks = (argc == 10); dev = argv[1]; dev2 = argv[2]; hash_type = argv[4 + two_disks]; salt_str = argv[5 + two_disks]; hmac_type = argv[6 + two_disks]; secret_str = argv[7 + two_disks]; // Open destination device int file, file2; if ((file = open(dev, O_RDWR)) < 0) { exit_error_f("Could not open: '%s' for writing, %s", dev, strerror(errno)); } // Get size // TODO: size of file in 512 chunks? struct stat file_stats, file_stats2; if (fstat(file, &file_stats) != 0) { exit_error_f("Could not get file stats for: '%s', %s", dev, strerror(errno)); } if (!(S_ISREG(file_stats.st_mode) || S_ISBLK(file_stats.st_mode))) { exit_error_f("File is neither a regular file nor block device"); } if (two_disks) { if ((file2 = open(dev2, O_RDWR)) < 0) { exit_error_f("Could not open: '%s' for writing, %s", dev2, strerror(errno)); } // Get size // TODO: size of file in 512 chunks? if (fstat(file2, &file_stats2) != 0) { exit_error_f("Could not get file stats for: '%s', %s", dev2, strerror(errno)); } if (!(S_ISREG(file_stats2.st_mode) || S_ISBLK(file_stats2.st_mode))) { exit_error_f("File is neither a regular file nor block device"); } } // Get block size if (sscanf(argv[2 + two_disks], "%u", &block_size) != 1) { exit_error_f("Invalid block size: '%s'", argv[2 + two_disks]); } if (block_size < 512) { exit_error_f("Invalid block size: '%u' < 512", block_size); } // Remainder check if (S_ISREG(file_stats.st_mode) && file_stats.st_size % block_size != 0) { warn("File is not a multiple of block_size: %d. %ju bytes left over", block_size, file_stats.st_size % block_size); } if (two_disks && S_ISREG(file_stats2.st_mode) && file_stats2.st_size % block_size != 0) { warn("File is not a multiple of block_size: %d. %ju bytes left over", block_size, file_stats.st_size % block_size); } // Number of journal blocks if (sscanf(argv[3 + two_disks], "%u", &journal_blocks) != 1) { exit_error_f("Invalid journal blocks number: '%s'", argv[3 + two_disks]); } OpenSSL_add_all_digests(); // Block hash algorithm EVP_MD_CTX *mdctx_hash = EVP_MD_CTX_create(); const EVP_MD *md_hash; md_hash = EVP_get_digestbyname(hash_type); if (!md_hash) { exit_error_f("Unsupported hash type: %s", hash_type); } uint32_t hash_bytes = EVP_MD_size(md_hash); // Hmac algorithm const EVP_MD *md_hmac; md_hmac = EVP_get_digestbyname(hmac_type); if (!md_hmac) { exit_error_f("Unsupported hmac type: %s", hmac_type); } // Parse and check salt char salt[128]; if (strlen(salt_str) % 2 != 0) { exit_error_f("Invalid hex salt: length not a multiple of 2"); } if (strlen(salt_str) > 256) { exit_error_f("Salt is too long. %lu > %d", strlen(salt_str), 256); } if (hex_to_bytes(salt_str, strlen(salt_str), (char*)salt) != 0) { exit_error_f("Invalid hex salt: '%s'", salt_str); } // Parse and check secrets char secret[hash_bytes]; if (strlen(secret_str) % 2 != 0) { exit_error_f("Invalid hex secret: length not a multiple of 2"); } if (hex_to_bytes(secret_str, strlen(secret_str), (char*)secret) != 0) { exit_error_f("Invalid hex inner pad: '%s'", secret_str); } // Calculate data size, hash block size, journal size // TODO: uh...this is 64 bits... uint64_t data_blocks = 0; uint32_t hash_blocks = 0; uint32_t jb_blocks = 0; uint32_t pad_blocks = 0; uint32_t *blocks_per_level = malloc(sizeof(uint32_t) * DM_MINTEGRITY_MAX_LEVELS); uint32_t levels = 0; uint64_t blocks, blocks2; if (S_ISREG(file_stats.st_mode)) { blocks = file_stats.st_size / block_size; } else if (S_ISBLK(file_stats.st_mode)) { if(ioctl(file, BLKGETSIZE64, &blocks) != 0){ exit_error_f("ioctl for block size failed: %s", strerror(errno)); } blocks = blocks / block_size; } if (two_disks) { if (S_ISREG(file_stats2.st_mode)) { blocks2 = file_stats2.st_size / block_size; } else if (S_ISBLK(file_stats2.st_mode)) { if(ioctl(file2, BLKGETSIZE64, &blocks2) != 0){ exit_error_f("ioctl for block size failed: %s", strerror(errno)); } blocks2 = blocks2 / block_size; } } // Fanout uint8_t fls, pls = 0; uint32_t fanout = block_size / hash_bytes; while (fanout > 0) { if ((fanout & 1) == 1) { fls = pls; } pls ++; fanout = fanout >> 1; } fanout = 1 << fls; // Use up entire block device if (!two_disks) { compute_block_numbers(blocks, block_size, fanout, journal_blocks, &data_blocks, &hash_blocks, &jb_blocks, &pad_blocks, &levels, blocks_per_level, hash_bytes); } else { jb_blocks = journal_blocks; data_blocks = blocks2; compute_hash_blocks(blocks2, fanout, &levels, &hash_blocks, blocks_per_level); if (hash_blocks + journal_blocks > blocks2) { exit_error_f("Need: %u hash + journal blocks, but %s only has %ju", hash_blocks + journal_blocks, dev, blocks); } } // Result info info("Blocks: %ju = Superblock: 1, Data: %ju, Hash: %u, JB: %u, Pad: %u, Levels: %u", blocks, data_blocks, hash_blocks, jb_blocks, pad_blocks, levels); // Calculate each hash block level char **hash_levels = (char**)malloc(sizeof(char*) * levels); char hash_output[EVP_MAX_MD_SIZE]; uint32_t hash_length; char *zero_block = (char*)malloc(block_size); char *temp_block = (char*)malloc(block_size); bzero(zero_block, block_size); char buf[128]; // Data hash hash(md_hash, mdctx_hash, zero_block, block_size, salt, strlen(salt_str) / 2, hash_output, &hash_length); // Now loop through each level for (uint32_t i = 0; i < levels; i++) { hash_levels[i] = (char*)malloc(block_size); // Fill block with hashes - padding is zeros bzero(hash_levels[i], block_size); for (uint32_t f = 0; f < fanout; f++) { for (int b = 0; b < hash_bytes; b++) { hash_levels[i][f * (block_size / (1 << fls)) + b] = hash_output[b]; } } // Compute hash of this level for next iteration/root hash(md_hash, mdctx_hash, hash_levels[i], block_size, salt, strlen(salt_str) / 2, hash_output, &hash_length); } // Write out hash superblock struct mint_superblock *msb = malloc(sizeof(struct mint_superblock)); // Zero out everything bzero(msb, sizeof(struct mint_superblock)); // Magic msb->magic = 0x796c694c; // Version msb->version = 1; // Make a new uuid! uuid_t uuid; uuid_generate(uuid); // TODO: is there a better way of doing this? memcpy(&msb->uuid, &uuid, 16); // Copy hash algorithm name strcpy(msb->hash_algorithm, hash_type); // Copy hmac algorithm name strcpy(msb->hmac_algorithm, hmac_type); // Block size! msb->block_size = block_size; // Set block numbers msb->data_blocks = data_blocks; msb->hash_blocks = hash_blocks; msb->jb_blocks = jb_blocks; // Set salt size msb->salt_size = strlen(salt_str) / 2; // Copy salt memcpy(msb->salt, salt, msb->salt_size); // Set root hash memcpy(msb->root, hash_output, hash_length); // Write it out! if (write(file, msb, sizeof(struct mint_superblock)) < 0) { exit_error_f("Failed to write MSB: %s", strerror(errno)); } if (write(file, zero_block, block_size - 512) < 0) { exit_error_f("Failed to write MSB pad: %s", strerror(errno)); } // Big block buffer uint32_t multiple = 1024; char *big_block = (char*)malloc(block_size * multiple); bzero(big_block, block_size * multiple); // Write out hash block levels uint8_t p = 0; info("Writing hash blocks..."); uint32_t h_written = 1; for (int i = levels - 1; i >= 0; i--) { // Copy into big buffer for (uint32_t m = 0; m < multiple; m++) { memcpy(big_block + m * block_size, hash_levels[i], block_size); } // Write out big buffer for (uint32_t j = 0; j < blocks_per_level[i] / multiple; j++) { h_written += multiple; p = progress(h_written, hash_blocks, 79, p); if(write(file, big_block, block_size * multiple) < 0){ exit_error_f("Failed to write hash block: %u, %s", h_written - 1, strerror(errno)); } } for (uint32_t j = 0; j < blocks_per_level[i] % multiple; j++) { p = progress(h_written++, hash_blocks, 79, p); if(write(file, hash_levels[i], block_size) < 0){ exit_error_f("Failed to write hash block: %u, %s", h_written - 1, strerror(errno)); } } } fprintf(stderr, "\n"); // Initialize journal struct mint_journal_superblock *mjsb = (struct mint_journal_superblock*) malloc(sizeof(struct mint_journal_superblock)); bzero(mjsb, sizeof(struct mint_journal_superblock)); // Magic mjsb->header.magic = MJ_MAGIC; // Superblock mjsb->header.type = TYPE_MJSB; // Number of blocks mjsb->blocks = jb_blocks; // Head, tail, and fill are 0 mjsb->head = 0; mjsb->tail = 0; mjsb->fill = 0; mjsb->sequence = 0; // Clean mjsb->state = 0; info("Writing journal..."); if (write(file, mjsb, sizeof(struct mint_journal_superblock)) < 0) { exit_error_f("Failed to write journal superblock:, %s", strerror(errno)); } if (write(file, zero_block, block_size - 512) < 0) { exit_error_f("Failed to write journal superblock pad: %s", strerror(errno)); } struct mint_journal_header *mjh = (struct mint_journal_header*) malloc(sizeof(struct mint_journal_header)); bzero(mjh, sizeof(struct mint_journal_header)); // Magic mjh->magic = MJ_MAGIC; // Nothing block mjh->type = TYPE_MJNB; // Copy headers into start of every block bzero(big_block, block_size * multiple); for (uint64_t i = 0; i < multiple; i++) { memcpy(big_block + i * block_size, mjh, sizeof(struct mint_journal_header)); } p = 0; for (uint64_t i = 0; i < (jb_blocks - 1) / multiple; i++) { if(write(file, big_block, block_size * multiple) < 0){ exit_error_f("Failed to write journal block: %ju, %s", i, strerror(errno)); } p = progress(i * multiple + 1, jb_blocks, 79, p); } for (uint64_t i = 0; i < (jb_blocks - 1) % multiple; i++) { if(write(file, big_block, block_size) < 0){ exit_error_f("Failed to write journal block: %ju, %s", i, strerror(errno)); } p = progress(jb_blocks - ((jb_blocks - 1) % multiple) + i + 2, jb_blocks, 79, p); } fprintf(stderr, "\n"); // Zero out data if (zero) { int f = two_disks ? file2 : file; bzero(big_block, block_size * multiple); info("Writing data blocks..."); p = 0; for (uint64_t i = 0; i < data_blocks / multiple; i++) { if(write(f, big_block, block_size * multiple) < 0){ exit_error_f("Failed to write data block: %ju, %s", i, strerror(errno)); } p = progress(i * multiple, data_blocks, 79, p); } for (uint64_t i = 0; i < data_blocks % multiple; i++) { if(write(f, zero_block, block_size) < 0){ exit_error_f("Failed to write data block: %ju, %s", i, strerror(errno)); } p = progress(data_blocks - (data_blocks % multiple) + i + 1, data_blocks, 79, p); } fprintf(stderr, "\n"); } else { info("Skipping disk zeroing..."); } close(file); if (two_disks) { close(file2); } print_superblock(msb); bytes_to_hex(msb->root, hash_bytes, buf); printf("dmsetup create meow --table \"%u %ju mintegrity %s%s%s %u %u %u %ju " "%s %s %s %s %s%s\"\n", 0, // Start is 0 data_blocks * (block_size / 512), // Size of device given to device mapper // Mintegrity options dev, // String of block device two_disks ? " " : "", two_disks ? dev2 : "", block_size, // Block size hash_blocks, // Number of hash blocks jb_blocks, // Number of journaling blocks data_blocks, // Number of data blocks hash_type, // Hash type buf, // Root digest to verity salt_str, // Salt hmac_type, // Hash type for hmac secret_str, // Hmac secret zero ? "" : " lazy" ); free(mjh); free(mjsb); free(msb); free(blocks_per_level); free(zero_block); free(big_block); free(temp_block); for (int i = 0; i < levels; i++) { free(hash_levels[i]); } free(hash_levels); EVP_MD_CTX_destroy(mdctx_hash); return 0; }