www.pudn.com > cryptfs030905.rar > fist_cryptfs.c


/*
 * cryptfs.c
 * Do not edit by hand.
 * Automatically generated by fistgen.
 */

#ifdef HAVE_CONFIG_H
# include 
#endif /* HAVE_CONFIG_H */
#ifdef FISTGEN
# include "fist_cryptfs.h"
#endif /* FISTGEN */
#include "fist.h"
#include "cryptfs.h"

/* OPTIONAL CODE FOLLOWS */


unsigned char global_iv[8] = {
  0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10
};



int get_uid_key(const vfs_t *this_vfs, uid_t *uid, BF_KEY *key, dentry_t *dentry)
{
	attached_entry_t *ent;
	struct list_head *p;
	int find_uid=0;
	
	print_entry_location();


	read_lock(&(stopd(this_vfs)->attachlock));

	list_for_each(p, &(stopd(this_vfs)->attached)){
			
		ent=list_entry(p,attached_entry_t,list);
		
//		printk("uid:%d\n",ent->e_uid);

		if (ent->e_uid==*uid&&(&ent->e_key)==dtokey(dentry)){
			memcpy(key,&(ent->e_key),sizeof(BF_KEY));
			find_uid=1;
			break;
		}
	}

	read_unlock(&(stopd(this_vfs)->attachlock));

        if(!find_uid)
               fist_dprint(8,"The user (uid:%d) cannot get the key\n",(int)*uid);
	
        
	return find_uid;
						
}

int
cryptfs_encode_block(const char *from, char *to, int len, const vnode_t *this_vnode, const vfs_t *this_vfs, u_long pagenum)
{
  int n = 0;			/* internal blowfish variables */
  unsigned char iv[8];
  BF_KEY key;
  dentry_t *dentry;
  struct list_head *p;  

  memcpy(iv, global_iv, 8);	/* initialize from global IV */
  
  p=(struct list_head *)&(this_vnode->i_dentry);
  
  if(!list_empty(p)){
	   dentry=list_entry(p->next,dentry_t,d_alias);
	   //printk("try to encode_block in dentry:%s\n",dentry->d_name.name);
	   if(get_uid_key(this_vfs,¤t->fsuid,&key,dentry)){
		   BF_cfb64_encrypt((char *)from, to, len,
           				&key, iv, &n,
	           			BF_ENCRYPT);
	           goto out;
	   }
  }
 
  	printk("fail to encode block in inode\n");
	memcpy(to,(char*)from,len);
  
out:
	return len;
}


int
cryptfs_decode_block(const char *from, char *to, int len, const vnode_t *this_vnode, const vfs_t *this_vfs, u_long pagenum)
{
  int n = 0;			/* internal blowfish variables */
  unsigned char iv[8];
  
  BF_KEY key;
  struct list_head *p;
  dentry_t *dentry;
  
  memcpy(iv, global_iv, 8);	/* initialize from global IV */

  p=(struct list_head*) (&this_vnode->i_dentry);
  
  if(!list_empty(p))
  {
	  dentry=list_entry(p->next,dentry_t,d_alias);
	  printk("cryptfs_decode_block:before get_uid_key\n");
	  if(get_uid_key(this_vfs,&(current->fsuid),&key,dentry)){
	  	BF_cfb64_encrypt((char *) from, to, len,
			   &key, iv, &n,
			   BF_DECRYPT);
		goto out;
	  }
  }
  
	  memcpy(to,(char*)from,len);
  
  out:
	return len;
	
}


int
cryptfs_encode_filename(const char *name,
			int length,
			char **encoded_name,
			int skip_dots,
			const vnode_t *this_vnode,
			const vfs_t *this_vfs)
{
    char *crypted_name = NULL;
    const char *ptr;
    int rounded_length = 0, encoded_length, n, i, j;
    unsigned char iv[8];
    short csum;
    BF_KEY current_uid_key;
    void *key;
    //= &(vfs2priv(this_vfs)->key);
    dentry_t* dentry;
    struct list_head *p=(struct list_head*)&this_vnode->i_dentry;
    
    if (!list_empty(p))
    {
	    dentry=list_entry(p->next,dentry_t,d_alias);
	    //printk("cryptfs_encode_filename:dentry name is %s\n",dentry->d_name.name);
	    
	    if(get_uid_key(this_vfs,¤t->fsuid,¤t_uid_key,dentry)){
		    key=(void*) ¤t_uid_key;
		    goto encode_filename_getkey;
	    }
    }
   
//	    printk("encode filename :cannot find the key for uid:%d\n",(int)current->fsuid);
	   
	    encoded_length=-ENOMEM;
	   
	    goto out;
    
  encode_filename_getkey:
    
    fist_dprint(8, "ENCODEFILENAME: cleartext filename \"%s\"\n", name);

    if ((skip_dots && (name[0] == '.' &&
		       (length == 1 ||
			(name[1] == '.' && length == 2))))) {
	encoded_length = length + 1;
	if (encoded_length > MAXPATHLEN) { /* check for corruption */
	  encoded_length = -ENAMETOOLONG;
	  goto out;
	}
	*encoded_name = kmalloc(encoded_length, GFP_KERNEL);
	if (!*encoded_name) {
	  encoded_length = -ENOMEM;
	  goto out;
	}
	memcpy(*encoded_name, name, length);
	(*encoded_name)[length] = '\0';
	goto out;
    }
    for (csum = 0, i = 0, ptr = name; i < length; ptr++, i++)
	csum += *ptr;
    /*
     * rounded_length is an multiple of 3 rounded-up length
     * the encode algorithm processes 3 source bytes at a time
     * so we have to make sure we don't read past the memory
     * we have allocated
     *
     * it uses length + 3 to provide 2 bytes for the checksum
     * and one byte for the length
     */
    rounded_length = (((length + 3) + 2) / 3) * 3;
    if (rounded_length > MAXPATHLEN) { /* check for corruption */
      encoded_length = -ENAMETOOLONG;
      goto out;
    }
    crypted_name = kmalloc(rounded_length, GFP_KERNEL);
    if (!crypted_name) {
      encoded_length = -ENOMEM;
      goto out;
    }

    memcpy(iv, global_iv, 8);
    n = 0;
    *(short *) crypted_name = csum;
    crypted_name[2] = length;
    BF_cfb64_encrypt((char *) name, crypted_name + 3,
		     length, (BF_KEY *) key, iv, &n,
		     BF_ENCRYPT);
    /*
     * clear the last few unused bytes
     * so that we get consistent results from encode
     */
    for (i = length + 3; i < rounded_length; i++)
	crypted_name[i] = 0;

    encoded_length = (((length + 3) + 2) / 3) * 4 + 1;

    if (encoded_length > MAXPATHLEN) { /* check for corruption */
      encoded_length = -ENAMETOOLONG;
      goto out;
    }
    *encoded_name = kmalloc(encoded_length, GFP_KERNEL);
    if (!*encoded_name) {
      encoded_length = -ENOMEM;
      goto out;
    }

    for (i = 0, j = 0; i < rounded_length; i += 3, j += 4) {
	(*encoded_name)[j] = 48 + ((crypted_name[i] >> 2) & 63);
	(*encoded_name)[j + 1] = 48 + (((crypted_name[i] << 4) & 48) | ((crypted_name[i + 1] >> 4) & 15));
	(*encoded_name)[j + 2] = 48 + (((crypted_name[i + 1] << 2) & 60) | ((crypted_name[i + 2] >> 6) & 3));
	(*encoded_name)[j + 3] = 48 + (crypted_name[i + 2] & 63);
    }
    (*encoded_name)[j] = '\0';

 out:
    if (crypted_name)
      kfree_s(crypted_name, rounded_length);
    if(*encoded_name)
	fist_dprint(8, "ENCODEFILENAME: encoded filename \"%s\"\n", *encoded_name);
    return encoded_length;
}


int
cryptfs_decode_filename(const char *name,
			int length,
			char **decrypted_name,
			int skip_dots,
			const vnode_t *this_vnode,
			const vfs_t *this_vfs)
{
    int n, i, j, saved_length, saved_csum, csum;
    int uudecoded_length, error = 0;
    unsigned char iv[8];
    char *uudecoded_name;
    
    BF_KEY current_uid_key;
    void *key;
   //= &(vfs2priv(this_vfs)->key);
    dentry_t* dentry;
    struct list_head* p=(struct list_head*)&this_vnode->i_dentry;

    if(!list_empty(p)){

	    dentry=list_entry(p->next,dentry_t,d_alias);
	    	    
	    if(get_uid_key(this_vfs,¤t->fsuid,¤t_uid_key,dentry)){
		    key=(void*) ¤t_uid_key;
		    goto decode_filename_getkey;
	    }
    }
    //          printk("decode filename :cannot find the key for uid:%d\n",(int)current->fsuid);
              error=-ENOMEM;
	      goto out;

    decode_filename_getkey:

    if ((skip_dots && (name[0] == '.' &&
		       (length == 1 ||
			(name[1] == '.' && length == 2))))) {
	if (length > MAXPATHLEN) { /* check for corruption */
	  error = -ENAMETOOLONG;
	  goto out;
	}
	*decrypted_name = kmalloc(length, GFP_KERNEL);
	if (!*decrypted_name) {
	  error = -ENOMEM;
	  goto out;
	}

	for (i = 0; i < length; i++)
	    (*decrypted_name)[i] = name[i];
	error = length;
	goto out;
    }
    if (key == NULL) {
	error = -EACCES;
	goto out;
    }
    uudecoded_length = ((length + 3) / 4) * 3;
    if (uudecoded_length > MAXPATHLEN) { /* check for corruption */
      error = -ENAMETOOLONG;
      goto out;
    }
    uudecoded_name = kmalloc(uudecoded_length, GFP_KERNEL);
    if (!uudecoded_name) {
      error = -ENOMEM;
      goto out;
    }

    for (i = 0, j = 0; i < length; i += 4, j += 3) {
	uudecoded_name[j] = ((name[i] - 48) <<2) | ((name[i + 1] - 48) >>4);
	uudecoded_name[j + 1] = (((name[i + 1] - 48) <<4) & 240) | ((name[i + 2] - 48) >>2);
	uudecoded_name[j + 2] = (((name[i + 2] - 48) <<6) & 192) | ((name[i + 3] - 48) &63);
    }
    saved_csum = *(short *) uudecoded_name;
    saved_length = uudecoded_name[2];

    if ((saved_length<1) || (saved_length+1 > MAXPATHLEN)) { /* check for corruption */
      error = -ENAMETOOLONG;
      goto out_free;
    }

    if (saved_length > uudecoded_length) {
	fist_dprint(7, "Problems with the length - too big: %d", saved_length);
	error = -EACCES;
	goto out_free;
    }
   
    *decrypted_name = (char *) kmalloc(saved_length+1, GFP_KERNEL); /* +1 for null */
    if (!*decrypted_name) {
      error = -ENOMEM;
      goto out_free;
    }
    (*decrypted_name)[saved_length] = '\0'; /* null terminate */
    memcpy(iv, global_iv, 8);
    n = 0;
    BF_cfb64_encrypt(uudecoded_name + 3, *decrypted_name,
		     saved_length, (BF_KEY *) key, iv, &n,
		     BF_DECRYPT);
    for (csum = 0, i = 0; i < saved_length; i++)
	csum += (*decrypted_name)[i];
    if (csum != saved_csum) {
	fist_dprint(7, "Checksum error\n");
	kfree_s(*decrypted_name, saved_length);
	error = -EACCES;
	goto out_free;
    }
    error = saved_length + 1;
 out_free:
    kfree_s(uudecoded_name, uudecoded_length);
 out:
    return error;
}


int
fist_get_ioctl_data_SETKEY_ukey(char *buf, int buflen,uid_t *uid, void *arg)
{
  int ret;
  struct _fist_ioctl_SETKEY this_ioctl;

  ret = copy_from_user((char *)&this_ioctl, arg, sizeof(this_ioctl));
 if (ret != 0)
   ret = -EFAULT;;
  if (ret >= 0){
    memcpy(buf, &this_ioctl.ukey, buflen);
    memcpy(uid, &this_ioctl.uid, sizeof(uid_t));
  }
  return ret;
}


int
fist_set_ioctl_data_GETIV_outiv(void *in, int len, void *arg)
{
  int ret;
  struct _fist_ioctl_GETIV this_ioctl;

  memcpy(&this_ioctl.outiv, in, len);
  ret = copy_to_user(arg,(char *)&this_ioctl, sizeof(this_ioctl));
 if (ret != 0)
   ret = -EFAULT;;
  return ret;
}