/** * ntfs_cat_decrypt - Decrypt the contents of an encrypted file to stdout. * @inode: An encrypted file's inode structure, as obtained by * ntfs_inode_open(). * @fek: A file encryption key. As obtained by ntfs_inode_fek_get(). */ static int ntfs_cat_decrypt(ntfs_inode *inode, ntfs_fek *fek) { int bufsize = 512; unsigned char *buffer; ntfs_attr *attr; s64 bytes_read, written, offset, total; s64 old_data_size, old_initialized_size; int i; buffer = malloc(bufsize); if (!buffer) return 1; attr = ntfs_attr_open(inode, AT_DATA, NULL, 0); if (!attr) { ntfs_log_error("Cannot cat a directory.\n"); free(buffer); return 1; } total = attr->data_size; // hack: make sure attr will not be commited to disk if you use this. // clear the encrypted bit, otherwise the library won't allow reading. NAttrClearEncrypted(attr); // extend the size, we may need to read past the end of the stream. old_data_size = attr->data_size; old_initialized_size = attr->initialized_size; attr->data_size = attr->initialized_size = attr->allocated_size; offset = 0; while (total > 0) { bytes_read = ntfs_attr_pread(attr, offset, 512, buffer); if (bytes_read == -1) { ntfs_log_perror("ERROR: Couldn't read file"); break; } if (!bytes_read) break; if ((i = ntfs_fek_decrypt_sector(fek, buffer, offset)) < bytes_read) { ntfs_log_perror("ERROR: Couldn't decrypt all data!"); ntfs_log_error("%u/%lld/%lld/%lld\n", i, (long long)bytes_read, (long long)offset, (long long)total); break; } if (bytes_read > total) bytes_read = total; written = fwrite(buffer, 1, bytes_read, stdout); if (written != bytes_read) { ntfs_log_perror("ERROR: Couldn't output all data!"); break; } offset += bytes_read; total -= bytes_read; } attr->data_size = old_data_size; attr->initialized_size = old_initialized_size; NAttrSetEncrypted(attr); ntfs_attr_close(attr); free(buffer); return 0; }
/** * ntfs_feed_encrypt - Encrypt the contents of stdin to an encrypted file * @inode: An encrypted file's inode structure, as obtained by * ntfs_inode_open(). * @fek: A file encryption key. As obtained by ntfs_inode_fek_get(). */ static int ntfs_feed_encrypt(ntfs_inode *inode, ntfs_fek *fek) { const int bufsize = 512; unsigned char *buffer; ntfs_attr *attr; s64 bytes_read, written, offset, total; unsigned char *b; long val; int count; int i; buffer = (unsigned char*)malloc(bufsize); if (!buffer) return 1; attr = ntfs_attr_open(inode, AT_DATA, NULL, 0); if (!attr) { ntfs_log_error("Cannot feed into a directory.\n"); goto rejected; } total = 0; if (!(attr->data_flags & ATTR_IS_ENCRYPTED)) { ntfs_log_error("The data stream was not encrypted\n"); goto rejected; } inode->vol->efs_raw = TRUE; if (ntfs_attr_truncate(attr, 0)) { ntfs_log_error("Failed to truncate the data stream\n"); goto rejected; } offset = 0; do { bytes_read = fread(buffer, 1, bufsize, stdin); if (bytes_read <= 0) { if (bytes_read < 0) ntfs_log_perror("ERROR: Couldn't read data"); } else { if (bytes_read < bufsize) { /* Fill with random data */ srandom((unsigned int)(sle64_to_cpu( inode->last_data_change_time) /100000000)); count = bufsize - bytes_read; b = &buffer[bytes_read]; do { val = random(); switch (count) { default : *b++ = val; val >>= 8; case 3 : *b++ = val; val >>= 8; case 2 : *b++ = val; val >>= 8; case 1 : *b++ = val; val >>= 8; } count -= 4; } while (count > 0); } if ((i = ntfs_fek_encrypt_sector(fek, buffer, offset)) < bufsize) { ntfs_log_perror("ERROR: Couldn't encrypt all data!"); ntfs_log_error("%u/%lld/%lld/%lld\n", i, (long long)bytes_read, (long long)offset, (long long)total); break; } written = ntfs_attr_pwrite(attr, offset, bufsize, buffer); if (written != bufsize) { ntfs_log_perror("ERROR: Couldn't output all data!"); break; } offset += bufsize; total += bytes_read; } } while (bytes_read == bufsize); ntfs_attr_truncate(attr, total); inode->last_data_change_time = ntfs_current_time(); NAttrSetEncrypted(attr); ntfs_attr_close(attr); free(buffer); return 0; rejected : free(buffer); return (-1); }