asmlinkage long xconcat(void *arg) { /* dummy syscall: returns 0 for non null, -EINVAL for NULL */ int i; struct file_details *details=(struct file_details *)arg; int len=5; int read_bytes=len; int startPos=0; int write_bytes=0; char *buf; int total_bytes_written=0; int total_bytes_read=0; int percent_data_written=0; int total_files_written=0; printk("Creating file %s",details->outfile); wrapfs_create_file(details->outfile,details->oflags,details->mode); for(i=0;i<details->infile_count;i++){ printk("Reading file %s\n", details->infiles[i]); startPos=0; read_bytes=len; while(read_bytes==len){ buf=vmalloc(len); read_bytes=wrapfs_read_file(details->infiles[i],(void *) buf,len,startPos ); printk("%s %d\n",buf,read_bytes); write_bytes=wrapfs_write_file(details->outfile,(void *)buf,len); startPos+=read_bytes; total_bytes_read+=read_bytes; total_bytes_written+=write_bytes; vfree(buf); } total_files_written+=1; } if(details->flags==0x00){ return total_bytes_written; }else if(details->flags==0x01){ return total_files_written; }else if(details->flags==0x02){ percent_data_written=(total_bytes_written/total_bytes_read)*100; return percent_data_written; } }
int encrypt_file_helper(struct file *input, struct file *output, char *key, int keylen,int flag, char *algo_name) { //mm_segment_t oldfs; //loff_t offset=0; //loff_t pos=0; int readBytes = 0; int writtenBytes = 0; int size_of_input_file = 0; int actual_length_to_be_used = 0; int return_value = 0; int i; /* 0 means don't clean, 1 means clean */ int clean_output_file = 0; ssize_t *length_encrypted = kmalloc(sizeof(ssize_t), GFP_KERNEL); /* buffers for transfers */ char *from = kmalloc(PAGE_SIZE, GFP_KERNEL); char *to = kmalloc(PAGE_SIZE, GFP_KERNEL); /* let's check if kmalloc has worked */ if(from == NULL || to == NULL) { return_value = -ENOMEM; printk("Error in allocating space for buffers\n"); goto cleanup_this_house; } size_of_input_file = input->f_dentry->d_inode->i_size; /* When decrypting, we move the input file pointer 16 spaces and also verify the key as well */ if (flag == 0) { memset(from,'\0', PAGE_SIZE); readBytes = wrapfs_read_file(input, from, 16); if(readBytes <= 0) { return_value = readBytes; //error returned by the read method. clean_output_file = 1; //remove partial output file goto cleanup_this_house; } /* Let's compare the key */ for (i = 0; i < SIZE_OF_KEY_BUFFER; i++) { if (from[i] != key[i]) { printk(KERN_CRIT "Key entered and preamble on the input file don't match\n"); return_value = -EINVAL; clean_output_file = 1; goto cleanup_this_house; } } input->f_pos = 16; printk(KERN_CRIT "Key matched successfully\n"); } /* This is the preamble portion, where we write the key on the file */ if (flag == 1) { printk(KERN_CRIT "Writing key on the output file\n"); if ((writtenBytes = wrapfs_write_file(output, key, 16)) <1) { printk(KERN_CRIT "Error while writing key on the output file.\n"); return_value = -EIO; clean_output_file = 1; goto cleanup_this_house; } output->f_pos = 16; printk(KERN_CRIT "Preamble written successfully on the output file\n"); } /* if decryption, then total bytes are reduced by 16, coz 16 is the preamble */ if(flag == 0) size_of_input_file = size_of_input_file - 16; printk(KERN_CRIT "*******************************\n"); printk(KERN_CRIT "We are ready to encrypt/decrypt\n"); printk(KERN_CRIT "*******************************\n"); /* Main while loop, that reads, en/de crypt and then writes */ while(size_of_input_file > 0) { actual_length_to_be_used = 0; readBytes = 0; writtenBytes = 0; memset(from, '0', PAGE_SIZE); memset(to, '0', PAGE_SIZE); /* if decryption flag is specified */ if (flag == 0) { if (size_of_input_file > (PAGE_SIZE)) { actual_length_to_be_used = PAGE_SIZE; size_of_input_file = size_of_input_file - actual_length_to_be_used ; } else { actual_length_to_be_used = size_of_input_file; size_of_input_file = 0; } } /* 16 bytes are used for preamble, so set the buffer that will be en/de crypted according to the flag */ if (flag == 1) { if (size_of_input_file > (PAGE_SIZE - 16)) { actual_length_to_be_used = PAGE_SIZE - 16; size_of_input_file = size_of_input_file - actual_length_to_be_used ; } else { actual_length_to_be_used = size_of_input_file; size_of_input_file = 0; } } /* reading bytes depending upon the appropriate size */ readBytes = wrapfs_read_file(input, from, actual_length_to_be_used); if(readBytes <= 0) { return_value = readBytes; //error returned by the read method. clean_output_file = 1; goto cleanup_this_house; } /* encrypt */ if(flag ==1) { printk(KERN_CRIT "Encrypting...\n"); return_value = encrypt_data(key, keylen, to, from, length_encrypted, actual_length_to_be_used, algo_name); if(return_value < 0) { printk(KERN_CRIT "cypto_blkcipher Encryption Failed.\n"); clean_output_file = 1; goto cleanup_this_house; } } /* dencrypt */ if(flag ==0) { printk(KERN_CRIT "Decrypting...\n"); return_value = decrypt_data(key, keylen, to, from, length_encrypted, actual_length_to_be_used, algo_name); if(return_value < 0) { printk(KERN_CRIT "cypto_blkcipher Decryption Failed.\n"); clean_output_file = 1; goto cleanup_this_house; } } writtenBytes = wrapfs_write_file(output, to, *length_encrypted); if(writtenBytes <=0) { return_value = writtenBytes; //error returned by the write method. clean_output_file = 1; goto cleanup_this_house; } } cleanup_this_house: kfree(to); kfree(from); //set_fs(oldfs); return return_value; }
asmlinkage long xcrypt(void *arg) { if (arg == NULL) { printk("User level argument is NULL\n"); return -EINVAL; } else { struct myargs *arguments; int result, paddedresult, padvalue, preambleWritten, temp, paddingWritten, paddingRead; struct file *filp=NULL, *filp1=NULL; struct dentry *dentry=NULL, *olddentry=NULL, *newdentry=NULL; long int inputFileLen=-1, outputFileLen=-1, keyLen=-1; char *srcbuffer, *destbuffer, *padding, *keyFromFile=NULL, *md5_hash=NULL, *tempOutFile; umode_t inputFileMode, outputFileMode; bool outFileCreated=false, renamed=false, success = false; int err=0; arguments = (struct myargs *)kmalloc(sizeof(struct myargs), GFP_KERNEL); if (arguments==NULL) { printk("Failed to allocate kernel memory\n"); err = -ENOMEM; goto out1; } result = copy_from_user((void *)arguments, arg, sizeof(struct myargs)); if(result!=0) { printk("Copying from user failed\n"); err = -EFAULT; goto out2; } if (((struct myargs*)arg)->inputFile == NULL) { /*Checking whether user passed NULL input File*/ printk("user level input file argument is NULL\n"); err = -EINVAL; goto out2; } inputFileLen = strnlen_user(((struct myargs*)arg)->inputFile, 32767); //TODO get the maximum value from getname if (inputFileLen == -1) { printk("Finding User inputFile string length Failed\n"); err = -EFAULT; goto out2; } arguments->inputFile = (char *)kmalloc(inputFileLen*sizeof(char), GFP_KERNEL); if ((arguments->inputFile)==NULL) { printk("Failed to allocate kernel memory for input file\n"); err = -ENOMEM; goto out2; } result = strncpy_from_user(arguments->inputFile, ((struct myargs*)arg)->inputFile, inputFileLen); if(result!=(inputFileLen-1)) { printk("Copying input file string from user failed\n"); err = -EFAULT; goto out3; } if((arguments->inputFile)==NULL) { printk("Copying input file string from user failed\n"); err = -EFAULT; goto out3; } if (((struct myargs*)arg)->outputFile == NULL) { printk("user level output file argument is NULL\n"); err = -EINVAL; goto out3; } outputFileLen = strnlen_user(((struct myargs*)arg)->outputFile, 32767); //TODO get the maximum value from getname if (outputFileLen == -1) { printk("Finding User outputFile string length Failed\n"); err = -EFAULT; goto out3; } arguments->outputFile = (char *)kmalloc(outputFileLen*sizeof(char), GFP_KERNEL); if ((arguments->outputFile)==NULL) { printk("Failed to allocate kernel memory for outputfile\n"); err = -ENOMEM; goto out3; } result = strncpy_from_user(arguments->outputFile, ((struct myargs*)arg)->outputFile, outputFileLen); if(result!=(outputFileLen-1)) { printk("Copying output file string from user failed\n"); err = -EFAULT; goto out4; } if((arguments->outputFile)==NULL) { printk("Copying output file string from user failed\n"); err = -EFAULT; goto out4; } if (((struct myargs*)arg)->keyBuf == NULL) { printk("user level key buffer argument is NULL\n"); err = -EINVAL; goto out4; } keyLen = strnlen_user(((struct myargs*)arg)->keyBuf, 32767); //TODO get the maximum value from getname if (keyLen == -1) { printk("Finding User keyBuf string length Failed\n"); err = -EFAULT; goto out4; } arguments->keyBuf = (char *)kmalloc(keyLen*sizeof(char), GFP_KERNEL); if ((arguments->keyBuf)==NULL) { printk("Failed to allocate kernel memory\n"); err = -ENOMEM; goto out4; } result = strncpy_from_user(arguments->keyBuf, ((struct myargs*)arg)->keyBuf, keyLen); if(result!=(keyLen-1)) { printk("Copying key buf string from user failed\n"); err = -EFAULT; goto out5; } if((arguments->keyBuf)==NULL) { printk("Copying key buf string from user failed\n"); err = -EFAULT; goto out5; } if (strlen(arguments->keyBuf) != arguments->keyLen) { printk("User key buffer length and kernel key buffer lengths differ\n"); err = -EINVAL; goto out5; } if((arguments->flags)!=0 && (arguments->flags)!=1) { printk("Invalid values for flag argument, it should be either 1 or 0\n"); err = -EINVAL; goto out5; } srcbuffer = (char *)kmalloc((PAGE_SIZE+1)*sizeof(char), GFP_KERNEL); if (srcbuffer==NULL) { printk("Failed to allocate kernel memory for srcbuffer\n"); err = -ENOMEM; goto out5; } destbuffer = (char *)kmalloc((PAGE_SIZE+1)*sizeof(char), GFP_KERNEL); if (destbuffer==NULL) { printk("Failed to allocate kernel memory for destbuffer\n"); err = -ENOMEM; goto out6; } padding = (char *)kmalloc(4*sizeof(char), GFP_KERNEL); if (padding==NULL) { printk("Failed to allocate kernel memory for padding\n"); err = -ENOMEM; goto out7; } initialisePadding(padding); /*Initialising the padding array to all 0's */ result=PAGE_SIZE; filp = filp_open(arguments->inputFile, O_RDONLY, 0); if (PTR_ERR(filp)==-ENOENT) { printk("Input File doesnot exists\n"); err = -ENOENT; goto out8; } else { printk("Input File exists\n"); } if (!filp || IS_ERR(filp)) { printk("Read error for input file %d\n", (int) PTR_ERR(filp)); err = PTR_ERR(filp); goto out8; } inputFileMode = filp->f_inode->i_mode; if(!S_ISREG(inputFileMode)) { printk("Input File is not a regular file\n"); err = -EISDIR; goto out9; } if (!filp->f_op->read) { printk("Error in reading input file\n"); err = PTR_ERR(filp); goto out9; } filp1 = filp_open(arguments->outputFile, O_WRONLY, 0); if (PTR_ERR(filp1)==-ENOENT) { printk("Output File doesnot exists, creating it\n"); filp1 = filp_open(arguments->outputFile, O_CREAT, inputFileMode); /*Creating output file if it doesnot exists with input file permissions*/ if(!filp1 || IS_ERR(filp1)) { printk("Error in creating output file\n"); err = PTR_ERR(filp1); goto out8_1; } else { printk("Output File created succesfully\n"); outFileCreated = true; } } else { printk("Output File exists\n"); } if(!outFileCreated) { if(!filp1 || IS_ERR(filp1)) { printk("Error in opening output file\n"); err = PTR_ERR(filp1); goto out8_1; } } if(!outFileCreated) { outputFileMode = filp1->f_inode->i_mode; if(!S_ISREG(outputFileMode)) { printk("Output File is not a regular file\n"); err = -EISDIR; goto out9; } } if(!outFileCreated) { if (filp->f_inode->i_ino == filp1->f_inode->i_ino) { printk("Both input and output files are same, they should be different\n"); err = -EPERM; goto out9; } } if(!outFileCreated) { olddentry = filp1->f_path.dentry; filp_close(filp1, NULL); tempOutFile = (char *)kmalloc((strlen(arguments->outputFile)+5)*sizeof(char), GFP_KERNEL); strncpy(tempOutFile, arguments->outputFile, strlen(arguments->outputFile)); strcat(tempOutFile, ".tmp"); tempOutFile[(strlen(arguments->outputFile)+5)]='\0'; filp1 = filp_open(tempOutFile, O_WRONLY, 0); if (PTR_ERR(filp1)==-ENOENT || IS_ERR(filp1)) { printk("temp Output File doesnot exists, creating it\n"); } else { printk("temp output File exists, truncating and creating new one\n"); dentry = filp1->f_path.dentry; filp_close(filp1, NULL); err = file_unlink(dentry->d_parent->d_inode, dentry); if(err != 0) { printk("unlink of already existing temporary file failed\n"); err = -EBUSY; goto out9; } printk("unlink function returned : %d\n", err); } filp1 = filp_open(tempOutFile, O_CREAT, outputFileMode); if(!filp1 || IS_ERR(filp1)) { printk("Error in creating temp output file\n"); err = PTR_ERR(filp1); goto out8_1; } else { printk("temp output File created succesfully\n"); } } newdentry = filp1->f_path.dentry; if (!filp1 || IS_ERR(filp1)) { printk("Write error for output file %d\n", (int) PTR_ERR(filp1)); err = PTR_ERR(filp1); goto out10; } if (!filp1->f_op->write) { printk("Error in writing to temp output file\n"); err = PTR_ERR(filp1); goto out10; } md5_hash = kmalloc(17*sizeof(char), GFP_KERNEL); if (md5_hash==NULL) { printk("Failed to allocate kernel memory for key from file\n"); err = -ENOMEM; goto out10; } err = generate_md5(arguments->keyBuf, md5_hash, strlen(arguments->keyBuf)); if(err != 0) { printk("kernel MD5 generation failed\n"); goto out11; } md5_hash[strlen(arguments->keyBuf)] = '\0'; if (arguments->flags) { //ENCRYPTION preambleWritten = wrapfs_write_file(filp1, (void *)(md5_hash), strlen(md5_hash)); /*Writing Key hash to the file*/ if(preambleWritten < 0) { printk("Writing preamble failed\n"); err = -EFAULT; goto out11; } paddingWritten = wrapfs_write_file(filp1, (void *)(padding), 4); /*Writing Inital Padding to the file*/ if (paddingWritten < 0) { printk("Writing padding failed\n"); err = -EFAULT; goto out11; } while(result==PAGE_SIZE) { result = wrapfs_read_file(filp, (void *)srcbuffer, PAGE_SIZE); if(result < 0) { printk("Reading from input file failed\n"); err = -EFAULT; goto out11; } err = encrypt_Cipher(arguments->keyBuf, srcbuffer, destbuffer, result, &paddedresult); if (err < 0) { printk("Error occured while encrypting\n"); goto out11; } if(paddedresult!=result) { padvalue = paddedresult - result; buildPadding(padding, padvalue); result = paddedresult; } result = wrapfs_write_file(filp1, (void *)destbuffer, result); if (result < 0) { printk("Writing to output file failed\n"); err = -EFAULT; goto out11; } } paddingWritten = wrapfs_write_file_pos(filp1, (void *)padding, 4, preambleWritten); if (paddingWritten < 0) { printk("Writing padding failed\n"); err = -EFAULT; goto out11; } } else { //DECRYPTION keyFromFile = kmalloc(16*sizeof(char), GFP_KERNEL); if (keyFromFile==NULL) { printk("Failed to allocate kernel memory for key from file\n"); err = -ENOMEM; goto out11; } temp = wrapfs_read_file(filp, (void *)keyFromFile, strlen(md5_hash)); if (temp != strlen(md5_hash)) { printk("reading key from file failed\n"); err = -EFAULT; goto out12; } if (compareKeys(md5_hash, keyFromFile, temp)) { printk("Both Keys Match\n"); } else { printk("Both keys doesnot match\n"); err = -EINVAL; //TODO : Return proper error Value. goto out12; } paddingRead = wrapfs_read_file(filp, (void *)padding, 4); if(paddingRead < 0) { printk("Reading padding failed\n"); err = -EFAULT; goto out12; } padvalue = reconstructPadding(padding); if (padvalue < 0) { printk("Reconstructing padding value failed(negative value not acceptable)\n"); err = -EFAULT; goto out12; } printk("Pad value returned : %d\n", padvalue); while(result==PAGE_SIZE) { result = wrapfs_read_file(filp, (void *)srcbuffer, PAGE_SIZE); if (result < 0) { printk("Reading from input file failed\n"); err = -EFAULT; goto out12; } printk("result read from file : %u\n", result); err = decrypt_Cipher(arguments->keyBuf, srcbuffer, destbuffer, result); if (err < 0) { printk("Error occured while encrypting\n"); goto out12; } if (result<PAGE_SIZE) { result = result - padvalue; } result = wrapfs_write_file(filp1, (void *)destbuffer, result); if(result < 0) { printk("writing to output file failed\n"); err = -EFAULT; //TODO goto goto out12; } } } if(!outFileCreated) { err = file_rename(newdentry->d_parent->d_inode, newdentry, olddentry->d_parent->d_inode, olddentry); if(err!=0) { printk("renaming of tempfile to output file failed\n"); err = -EBUSY; goto out12; } else renamed = true; } else success = true; out12: if(keyFromFile) kfree(keyFromFile); out11: kfree(md5_hash); out10: if(filp1) filp_close(filp1, NULL); if((!renamed && !outFileCreated)||(!success && outFileCreated)) file_unlink(newdentry->d_parent->d_inode, newdentry); out9: if(filp1) filp_close(filp1, NULL); out8_1: if(filp) filp_close(filp, NULL); out8: kfree(padding); out7: kfree(destbuffer); out6: kfree(srcbuffer); out5: kfree(arguments->keyBuf); out4: kfree(arguments->outputFile); out3: kfree(arguments->inputFile); out2: kfree(arguments); out1: return err; } }