• Aurelien Aptel's avatar
    cifs: change format of CIFS_FULL_KEY_DUMP ioctl · 1bb56810
    Aurelien Aptel authored
    Make CIFS_FULL_KEY_DUMP ioctl able to return variable-length keys.
    
    * userspace needs to pass the struct size along with optional
      session_id and some space at the end to store keys
    * if there is enough space kernel returns keys in the extra space and
      sets the length of each key via xyz_key_length fields
    
    This also fixes the build error for get_user() on ARM.
    
    Sample program:
    
    	#include <stdlib.h>
    	#include <stdio.h>
    	#include <stdint.h>
    	#include <sys/fcntl.h>
    	#include <sys/ioctl.h>
    
    	struct smb3_full_key_debug_info {
    	        uint32_t   in_size;
    	        uint64_t   session_id;
    	        uint16_t   cipher_type;
    	        uint8_t    session_key_length;
    	        uint8_t    server_in_key_length;
    	        uint8_t    server_out_key_length;
    	        uint8_t    data[];
    	        /*
    	         * return this struct with the keys appended at the end:
    	         * uint8_t session_key[session_key_length];
    	         * uint8_t server_in_key[server_in_key_length];
    	         * uint8_t server_out_key[server_out_key_length];
    	         */
    	} __attribute__((packed));
    
    	#define CIFS_IOCTL_MAGIC 0xCF
    	#define CIFS_DUMP_FULL_KEY _IOWR(CIFS_IOCTL_MAGIC, 10, struct smb3_full_key_debug_info)
    
    	void dump(const void *p, size_t len) {
    	        const char *hex = "0123456789ABCDEF";
    	        const uint8_t *b = p;
    	        for (int i = 0; i < len; i++)
    	                printf("%c%c ", hex[(b[i]>>4)&0xf], hex[b[i]&0xf]);
    	        putchar('\n');
    	}
    
    	int main(int argc, char **argv)
    	{
    	        struct smb3_full_key_debug_info *keys;
    	        uint8_t buf[sizeof(*keys)+1024] = {0};
    	        size_t off = 0;
    	        int fd, rc;
    
    	        keys = (struct smb3_full_key_debug_info *)&buf;
    	        keys->in_size = sizeof(buf);
    
    	        fd = open(argv[1], O_RDONLY);
    	        if (fd < 0)
    	                perror("open"), exit(1);
    
    	        rc = ioctl(fd, CIFS_DUMP_FULL_KEY, keys);
    	        if (rc < 0)
    	                perror("ioctl"), exit(1);
    
    	        printf("SessionId      ");
    	        dump(&keys->session_id, 8);
    	        printf("Cipher         %04x\n", keys->cipher_type);
    
    	        printf("SessionKey     ");
    	        dump(keys->data+off, keys->session_key_length);
    	        off += keys->session_key_length;
    
    	        printf("ServerIn Key   ");
    	        dump(keys->data+off, keys->server_in_key_length);
    	        off += keys->server_in_key_length;
    
    	        printf("ServerOut Key  ");
    	        dump(keys->data+off, keys->server_out_key_length);
    
    	        return 0;
    	}
    
    Usage:
    
    	$ gcc -o dumpkeys dumpkeys.c
    
    Against Windows Server 2020 preview (with AES-256-GCM support):
    
    	# mount.cifs //$ip/test /mnt -o "username=administrator,password=foo,vers=3.0,seal"
    	# ./dumpkeys /mnt/somefile
    	SessionId      0D 00 00 00 00 0C 00 00
    	Cipher         0002
    	SessionKey     AB CD CC 0D E4 15 05 0C 6F 3C 92 90 19 F3 0D 25
    	ServerIn Key   73 C6 6A C8 6B 08 CF A2 CB 8E A5 7D 10 D1 5B DC
    	ServerOut Key  6D 7E 2B A1 71 9D D7 2B 94 7B BA C4 F0 A5 A4 F8
    	# umount /mnt
    
    	With 256 bit keys:
    
    	# echo 1 > /sys/module/cifs/parameters/require_gcm_256
    	# mount.cifs //$ip/test /mnt -o "username=administrator,password=foo,vers=3.11,seal"
    	# ./dumpkeys /mnt/somefile
    	SessionId      09 00 00 00 00 0C 00 00
    	Cipher         0004
    	SessionKey     93 F5 82 3B 2F B7 2A 50 0B B9 BA 26 FB 8C 8B 03
    	ServerIn Key   6C 6A 89 B2 CB 7B 78 E8 04 93 37 DA 22 53 47 DF B3 2C 5F 02 26 70 43 DB 8D 33 7B DC 66 D3 75 A9
    	ServerOut Key  04 11 AA D7 52 C7 A8 0F ED E3 93 3A 65 FE 03 AD 3F 63 03 01 2B C0 1B D7 D7 E5 52 19 7F CC 46 B4
    Signed-off-by: default avatarAurelien Aptel <aaptel@suse.com>
    Reviewed-by: default avatarRonnie Sahlberg <lsahlber@redhat.com>
    Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
    1bb56810
cifspdu.h 84.2 KB