RootPtr initFS( EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts ) { RootPtr rootInfo; EncfsConfig config; if(readConfig( opts->rootDir, config ) != Config_None) { if(opts->reverseEncryption) { if (config.block_mac_bytes() != 0 || config.block_mac_rand_bytes() != 0 || config.unique_iv() || config.external_iv() || config.chained_iv() ) { cout << _("The configuration loaded is not compatible with --reverse\n"); return rootInfo; } } // first, instanciate the cipher. shared_ptr<CipherV1> cipher = getCipher(config); if(!cipher) { Interface iface = config.cipher(); LOG(ERROR) << "Unable to find cipher " << iface.name() << ", version " << iface.major() << ":" << iface.minor() << ":" << iface.age(); // xgroup(diag) cout << _("The requested cipher interface is not available\n"); return rootInfo; } // get user key CipherKey userKey; if(opts->passwordProgram.empty()) { if (opts->annotate) cerr << "$PROMPT$ passwd" << endl; userKey = getUserKey( config, opts->useStdin ); } else userKey = getUserKey( config, opts->passwordProgram, opts->rootDir ); if(!userKey.valid()) return rootInfo; cipher->setKey(userKey); VLOG(1) << "cipher encoded key size = " << cipher->encodedKeySize(); // decode volume key.. CipherKey volumeKey = cipher->readKey( (const unsigned char *)config.key().ciphertext().data(), opts->checkKey); userKey.reset(); if(!volumeKey.valid()) { // xgroup(diag) cout << _("Error decoding volume key, password incorrect\n"); return rootInfo; } cipher->setKey(volumeKey); shared_ptr<NameIO> nameCoder = NameIO::New( config.naming(), cipher ); if(!nameCoder) { Interface iface = config.naming(); LOG(ERROR) << "Unable to find nameio interface " << iface.name() << ", version " << iface.major() << ":" << iface.minor() << ":" << iface.age(); // xgroup(diag) cout << _("The requested filename coding interface is " "not available\n"); return rootInfo; } nameCoder->setChainedNameIV( config.chained_iv() ); nameCoder->setReverseEncryption( opts->reverseEncryption ); FSConfigPtr fsConfig( new FSConfig ); fsConfig->cipher = cipher; fsConfig->key = volumeKey; fsConfig->nameCoding = nameCoder; fsConfig->config = shared_ptr<EncfsConfig>(new EncfsConfig(config)); fsConfig->forceDecode = opts->forceDecode; fsConfig->reverseEncryption = opts->reverseEncryption; fsConfig->opts = opts; rootInfo = RootPtr( new EncFS_Root ); rootInfo->cipher = cipher; rootInfo->volumeKey = volumeKey; rootInfo->root = shared_ptr<DirNode>( new DirNode( ctx, opts->rootDir, fsConfig )); } else { if(opts->createIfNotFound) { // creating a new encrypted filesystem rootInfo = createConfig( ctx, opts ); } } return rootInfo; }
void showFSInfo( const EncfsConfig &config ) { shared_ptr<CipherV1> cipher = CipherV1::New( config.cipher(), config.key().size() ); { cout << autosprintf( // xgroup(diag) _("Filesystem cipher: \"%s\", version %i:%i:%i"), config.cipher().name().c_str(), config.cipher().major(), config.cipher().minor(), config.cipher().age()); // check if we support this interface.. if(!cipher) cout << _(" (NOT supported)\n"); else { // if we're using a newer interface, show the version number if( config.cipher() != cipher->interface() ) { Interface iface = cipher->interface(); // xgroup(diag) cout << autosprintf(_(" (using %i:%i:%i)\n"), iface.major(), iface.minor(), iface.age()); } else cout << "\n"; } } // xgroup(diag) cout << autosprintf(_("Filename encoding: \"%s\", version %i:%i:%i"), config.naming().name().c_str(), config.naming().major(), config.naming().minor(), config.naming().age()); if (!cipher) { cout << "\n"; } else { // check if we support the filename encoding interface.. shared_ptr<NameIO> nameCoder = NameIO::New( config.naming(), cipher ); if(!nameCoder) { // xgroup(diag) cout << _(" (NOT supported)\n"); } else { // if we're using a newer interface, show the version number if( config.naming() != nameCoder->interface() ) { Interface iface = nameCoder->interface(); cout << autosprintf(_(" (using %i:%i:%i)\n"), iface.major(), iface.minor(), iface.age()); } else cout << "\n"; } } const EncryptedKey &key = config.key(); { cout << autosprintf(_("Key Size: %i bits"), 8 * key.size()); cipher = getCipher(config); if(!cipher) { // xgroup(diag) cout << _(" (NOT supported)\n"); } else cout << "\n"; } if(key.kdf_iterations() > 0 && key.salt().size() > 0) { cout << autosprintf(_("Using PBKDF2, with %i iterations"), key.kdf_iterations()) << "\n"; cout << autosprintf(_("Salt Size: %i bits"), 8*(int)key.salt().size()) << "\n"; } if(config.block_mac_bytes() || config.block_mac_rand_bytes()) { if(config.revision() < V5Latest) { cout << autosprintf( // xgroup(diag) _("Block Size: %i bytes + %i byte MAC header"), config.block_size(), config.block_mac_bytes() + config.block_mac_rand_bytes()) << endl; } else { // new version stores the header as part of that block size.. cout << autosprintf( // xgroup(diag) _("Block Size: %i bytes, including %i byte MAC header"), config.block_size(), config.block_mac_bytes() + config.block_mac_rand_bytes()) << endl; } } else { // xgroup(diag) cout << autosprintf(_("Block Size: %i bytes"), config.block_size()); cout << "\n"; } if(config.unique_iv()) { // xgroup(diag) cout << _("Each file contains 8 byte header with unique IV data.\n"); } if(config.chained_iv()) { // xgroup(diag) cout << _("Filenames encoded using IV chaining mode.\n"); } if(config.external_iv()) { // xgroup(diag) cout << _("File data IV is chained to filename IV.\n"); } if(config.allow_holes()) { // xgroup(diag) cout << _("File holes passed through to ciphertext.\n"); } cout << "\n"; }