问题
The program below XORs 2 files to create an output file using one time pad encryption. I have attempted to use mlockall
in order to avoid any traces of the keyfile being left on the hard drive when getting the keyfile from external memory sources.
From the mlockall man page:
mlock() and mlockall() respectively lock part or all of the calling process's
virtual address space into RAM, preventing that memory from being paged to the
swap area.
How I do check if it is working and have I used mlockall
correctly?
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/mman.h>
int main(int argc, char **argv)
{
struct stat statbuf;
struct stat keybuf;
char buffer [20];
int key;
int data;
int output;
int count;
char ans;
int * buf;
FILE * keyfile;
FILE * sourcefile;
FILE * destfile;
if(geteuid() !=0)
{
printf("Root access is required to run this program\n\n");
exit(0);
}
if(argc<4)
{
printf("OTP-Bunny 1.0\n");
printf("USAGE: OTP <source file> <output file> <keyfile>\n");
return (0);
}
/* Check number of arguments. */
if(argc>4)
{
printf("Too many arguments.\n");
printf("USAGE: OTP <source file> <output file> <keyfile>\n");
exit(1);
}
/* Allocate memory required by processes */
buf = (int*) malloc (sizeof(int));
if (buf == NULL)
{
perror("Error");
exit(1);
}
/* Lock down pages mapped to processes */
printf("Locking down processes\n");
if(mlockall (MCL_CURRENT | MCL_FUTURE) < 0)
{
perror("mlockall");
exit (1);
}
/* Check if sourcefile can be opened. */
if((sourcefile = fopen(argv[1], "rb"))== NULL)
{
printf("Can't open source file\n");
perror("Error");
printf("USAGE: OTP <source file> <output file> <keyfile>\n");
exit (1);
}
/* Get size of sourcefile */
fstat(fileno(sourcefile), &statbuf);
/* Check if keyfile can be opened. */
if((keyfile = fopen(argv[3], "rb"))== NULL)
{
printf("Can't open keyfile.\n");
perror("Error");
printf("USAGE: OTP <source file> <output file> <keyfile>\n");
exit(1);
}
/* Get size of keyfile */
fstat(fileno(keyfile), &keybuf);
/* Check if keyfile is the same size as, or bigger than the sourcefile */
if((keybuf.st_size) < (statbuf.st_size))
{
printf("Source file is larger than keyfile.\n");
printf("This significantly reduces cryptographic strength.\n");
printf("Do you wish to continue? (Y/N)\n");
fgets(buffer, 20, stdin);
sscanf(buffer, "%c", &ans);
if(ans == 'n' || ans == 'N')
{
exit (1);
}
if(ans == 'y' || ans == 'Y')
{
printf("Proceeding with Encryption/Decryption.\n");
}
else
{
printf("No option selected. Exiting...\n");
exit (1);
}
}
/* Check if destfile can be opened. */
if((destfile = fopen(argv[2], "wb"))== NULL)
{
printf("Can't open output file.\n");
perror("Error");
exit(1);
}
/* Encrypt/Decrypt and write to output file. */
while(count < (statbuf.st_size))
{
key=fgetc(keyfile);
data=fgetc(sourcefile);
output=(key^data);
fputc(output,destfile);
count++;
}
/* Close files. */
fclose(keyfile);
fclose(sourcefile);
fclose(destfile);
printf("Encryption/Decryption Complete.\n\n");
/* delete keyfile option. */
printf("Do you wish to delete the keyfile? (Y/N)\n");
fgets(buffer, 20, stdin);
sscanf(buffer, "%c", &ans);
if(ans == 'y' || ans == 'Y')
{
if ( remove(argv[3]) == 0)
{
printf("File deleted successfully.\n");
}
else
{
printf("Unable to delete the file.\n");
perror("Error");
exit(1);
}
}
/* cleanup */
printf("Releasing memory\n");
free (buf);
return(0);
}
回答1:
Your usage of mlockall
is probably correct. Since you gave MCL_FUTURE
any indirect malloc
(e.g. by fopen
) would also be concerned - but these malloc
-s might need to mmap
(and these mmap
syscalls might fail, e.g. because of lack of RAM).
But why don't you make your buf
a local int
variable?
And I don't understand why using mlockall
would "avoid any traces of the keyfile being left on the hard drive"; the keyfile is surely in a filesystem (and probably in some kernel file cache), which leave traces on some disk (unless you use e.g. a tmpfs filesystem for it). mlopckall(2) deals with the process' (virtual memory) address space, but files are related to the file systems, which on Linux usually have kernel buffers and cache.
Because of lack of indentation, I tend to find your program hard to read, and I don't understand exactly what it does and what is the relevance of mlockall
. It would be nice to edit your question to explain the intended purpose of your program.
You really should read a good book like e.g. Advanced Linux Programming and Advanced Unix Programming. It seems that you are missing some basic concepts; I don't understand why you are using mlockall
.
Perhaps you might use lower-level syscalls like mmap(2) to access your sensitive data (and munmap(2)
it as soon as possible, perhaps clearing it before). You don't know exactly what fopen
or fgetc
are doing, they are adding another buffer, which will keep your secret data, perhaps even after fclose
.
Also, you might want to define (at least in your head and in explicit comments) what is your trusted computing base.
Also, cryptography is a very difficult science. Please use existing cryptographic library instead of inventing your own encryption (which is really a child's play). If you want to become a cryptographer, please get a PhD on that domain. (I do recommend using some cryptographic library with your one time pad, not just an xor).
来源:https://stackoverflow.com/questions/12990214/is-this-usage-of-mlockall-correct