Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Encryption Linux 2.6.18 SCSI旋转和喷口SG_IO ioctl';s连接到sg LTO5设备_Encryption_Linux Device Driver_Ioctl_Scsi - Fatal编程技术网

Encryption Linux 2.6.18 SCSI旋转和喷口SG_IO ioctl';s连接到sg LTO5设备

Encryption Linux 2.6.18 SCSI旋转和喷口SG_IO ioctl';s连接到sg LTO5设备,encryption,linux-device-driver,ioctl,scsi,Encryption,Linux Device Driver,Ioctl,Scsi,我试图利用fuse文件系统中使用的ioctl,对LTO5设备进行硬件加密。它应该非常简单,使用cdb设置io_hdr: 0xB5, 0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00 并根据选择的算法提供密钥页。当我执行SG_IOioctl时,我返回一个0的返回值,并带有所有0的SCSI感 现在,这里是它变得奇怪的地方。写入设备的数据从不加密。我把磁带换到另一个驱动器,进行SCSI读取,数据都是明文 因此,下一步是执

我试图利用fuse文件系统中使用的ioctl,对LTO5设备进行硬件加密。它应该非常简单,使用cdb设置io_hdr:

0xB5, 0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00
并根据选择的算法提供密钥页。当我执行SG_IOioctl时,我返回一个0的返回值,并带有所有0的SCSI感

现在,这里是它变得奇怪的地方。写入设备的数据从不加密。我把磁带换到另一个驱动器,进行SCSI读取,数据都是明文

因此,下一步是执行SCSI SPIN命令,查看SPOUT命令是否执行了,即使所有返回都说执行了。在喷口之后,我立即为安全状态页面(0x20)发送一个旋转:

同样,从SG_IOioctl返回值0,并表示为全零。然而,我返回的页面是我放入驱动器的喷口键页面。我确信这不是从驱动器中出来的,因为它有我发送的密钥,这绝对是SCSI规范编号。顺便说一句,我对SCSI命令和内存使用了完全不同的缓冲区。为了更好地测量,我将SPIN页设置为零。sg驱动程序提供此数据以响应旋转

有人能解释一下这种行为吗

Linux archive.xxxxx.xxx 2.6.18-274.7.1.el5#1 SMP周四10月20日16:21:01美国东部夏令时2011年x86_64 x86_64 x86_64 GNU/Linux

sg3_utils-libs-1.25-5.el5

sgpio-1.2.0_10-2.el5

mt-st-0.9b-2.2.2

我正在向/dev/sg5发送ioctl命令:

[root@archive bin]# sg_inq /dev/sg5
standard INQUIRY:
  PQual=0  Device_type=1  RMB=1  version=0x06  [SPC-4]
  [AERC=0]  [TrmTsk=0]  NormACA=0  HiSUP=0  Resp_data_format=2
  SCCS=0  ACC=0  TPGS=0  3PC=0  Protect=1  BQue=0
  EncServ=0  MultiP=1 (VS=0)  [MChngr=0]  [ACKREQQ=0]  Addr16=0
  [RelAdr=0]  WBus16=0  Sync=0  Linked=0  [TranDis=0]  CmdQue=1
  [SPI: Clocking=0x0  QAS=0  IUS=0]
    length=70 (0x46)   Peripheral device type: tape
 Vendor identification: IBM     
 Product identification: ULTRIUM-HH5     
 Product revision level: BAKG
 Unit serial number: 106xxxxxxxxxx
我发现Linux ioctl系统调用正在返回一个SG_ERR_DID_ERROR[0x07]内部错误,该错误在SG_io_hdr_t的host_status成员的主机适配器中检测到

setltokey.c代码也在这里:

/*
setLTO4key:设置LTO4加密密钥
版权所有(c)2008安德鲁·施雷特
根据GPL许可证提供
添加了清晰的加密,
感知键和
打印输出错误-Gerard J.Cerchio
*/
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#从lto规范中定义SENSE_BUFF_LEN 96/**/
/*
*这是一个示例密钥-使用以下十六进制数字创建文件:
4418AFCD046F2535B2E996123CE7DE3D418A15915A091C4BA12BDC85D4069A77
*/
/*
*一个好的sg\u io\u hdr\t参考:http://tldp.org/HOWTO/SCSI-Generic-HOWTO/sg_io_hdr_t.html
*/
/*打印数据块的十六进制转储*/
void hextump(void*数据,整数大小)
{
无符号字符*p=数据;
无符号字符c;
int n;
char bytestr[4]={0};
char addrstr[10]={0};
char-hexstr[16*3+5]={0};
char charstr[16*1+5]={0};
对于(n=1;n0){
/*如果缓冲区不为空,则打印剩余缓冲区*/
printf(“[%4.4s]-49.49s%s\n”,addrstr,hexstr,charstr);
}
}
/*发送SCSI命令块并显示结果*/
void do_read_命令(int-fd,char*desc,unsigned char*cmd,int-len)
{
无符号字符检测[sense_BUFF_LEN];
memset(sense,0,sense\u BUFF\u LEN);
sg_io_hdr_t io;
无符号字符buf[512];
memset(buf,0,sizeof(buf));
memset(&io,0,sizeof(io));
io.interface_id='S';
io.cmd_len=len;
io.mx_sb_len=0;
io.dxfer\U方向=SG\U dxfer\U来自\U DEV;
io.dxfer_len=尺寸(buf);
io.dxferp=buf;
io.cmdp=cmd;
printf(“命令:%s\n”,desc);
hextump(cmd,len);
如果(ioctl(fd、SG_IO和IO)<0){
printf(“错误:%s\n”,strerror(errno));
返回;
}
如果(io.sb_len_wr){
printf(“Sense\n”);
hextump(sense,sense\u BUFF\u LEN);
}
其他的
printf(“无意义”);
如果((io.info&SG\u info\u OK\u MASK)!=SG\u info\u OK){
printf(“失败,信息0x%02x掩码状态0x%02x消息状态0x%02x主机状态0x%02x驱动程序状态0x%02x\n”、io.info、io.masked\u状态、io.msg\u状态、io.host\u状态、io.driver\u状态);
返回;
}
len=io.dxfer\u len-io.resid;
printf(“响应:%d%s\n”,len,(len==1)?“字节”:“字节”);
hextump(buf,len);
}
void do_write_命令(int fd,char*desc,unsigned char*cmd,int len,char*data_desc,unsigned char*data,int datalen)
{
无符号字符检测[sense_BUFF_LEN];
memset(sense,0,sense\u BUFF\u LEN);
sg_io_hdr_t io;
memset(&io,0,sizeof(io));
io.interface_id='S';
io.cmd_len=len;
io.mx_sb_len=感觉_BUFF_len;
io.dxfer\U方向=SG\U dxfer\U至\U DEV;
io.dxfer_len=数据len;
io.dxferp=数据;
io.cmdp=cmd;
io.sbp=感觉;
printf(“命令:%s\n”,desc);
hextump(cmd,len);
printf(“数据:%s\n”,数据描述);
hextump(数据,datalen);
如果(ioctl(fd、SG_IO和IO)<0){
printf(“错误:%s\n”,strerror(errno));
返回;
}
如果(io.sb_len_wr){
printf(“Sense\n”);
hextump(sense,sense\u BUFF\u LEN);
}
其他的
printf(“无意义”);
如果((io.info&SG\u info\u OK\u MASK)!=SG\u info\u OK){
printf(“失败,信息0x%02x掩码状态0x%02x消息状态0x%02x主机状态0x%02x驱动程序状态0x%02x\n”、io.info、io.masked\u状态、io.msg\u状态、io.host\u状态、io.driver\u状态);
返回;
}
len=io.dxfer\u len-io.resid;
printf(“响应:%d%s\n”,len,(len==1)?“字节”:“字节”);
//hextump(buf,len);
}
结构{
字符*描述;
内伦;
无符号字符cmd[16];
}命令[]={
{“SCSI查询”,6,
{0x12,0x00,0x00,0x00,0xFF,0x00},
{“SCSI喷口集加密密钥”,12,
{0xb5,0x20,0x00,0x10,0x00,0x00,
0x00,0x00,0x00,0x34,0x00,0x00},
{“SCSI自旋读取状态”,12,
{0xa2,0
[root@archive bin]# sg_inq /dev/sg5
standard INQUIRY:
  PQual=0  Device_type=1  RMB=1  version=0x06  [SPC-4]
  [AERC=0]  [TrmTsk=0]  NormACA=0  HiSUP=0  Resp_data_format=2
  SCCS=0  ACC=0  TPGS=0  3PC=0  Protect=1  BQue=0
  EncServ=0  MultiP=1 (VS=0)  [MChngr=0]  [ACKREQQ=0]  Addr16=0
  [RelAdr=0]  WBus16=0  Sync=0  Linked=0  [TranDis=0]  CmdQue=1
  [SPI: Clocking=0x0  QAS=0  IUS=0]
    length=70 (0x46)   Peripheral device type: tape
 Vendor identification: IBM     
 Product identification: ULTRIUM-HH5     
 Product revision level: BAKG
 Unit serial number: 106xxxxxxxxxx
/*
   setLTO4key: Set LTO4 Encryption Key

   Copyright (c) 2008  Andrew Schretter <schrett@math.duke.edu>
   Provided under GPL license

   added clear encryption,
     sense key and
     error printouts - Gerard J. Cerchio <gjpc@circlesoft.com>
*/

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <scsi/sg.h>
#include <scsi/scsi.h>
#include <ctype.h>
#include <sys/ioctl.h>
#include <unistd.h>

#define SENSE_BUFF_LEN  96          /* from lto spec */

/*
 * here is a sample key - create a file with these HEX digits:
   4418AFCD046F2535B2E996123CE7DE3D418A15915A091C4BA12BDC85D4069A77
 */

/*
 * A good sg_io_hdr_t reference: http://tldp.org/HOWTO/SCSI-Generic-HOWTO/sg_io_hdr_t.html
 */

/* Print a hexadecimal dump of a block of data */
void hexdump(void *data, int size)
{
    unsigned char *p = data;
    unsigned char c;
    int n;
    char bytestr[4] = {0};
    char addrstr[10] = {0};
    char hexstr[ 16*3 + 5] = {0};
    char charstr[16*1 + 5] = {0};
    for(n=1;n<=size;n++) {
        if (n%16 == 1) {
            /* store address for this line */
            snprintf(addrstr, sizeof(addrstr), "%.4x",
               ((unsigned int)p-(unsigned int)data) );
        }

        c = *p;
        if (isalnum(c) == 0) {
            c = '.';
        }

        /* store hex str (for left side) */
        snprintf(bytestr, sizeof(bytestr), "%02X ", *p);
        strncat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1);

        /* store char str (for right side) */
        snprintf(bytestr, sizeof(bytestr), "%c", c);
        strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1);

        if(n%16 == 0) {
            /* line completed */
            printf("  [%4.4s]  %-49.49s %s\n", addrstr, hexstr, charstr);
            hexstr[0] = 0;
            charstr[0] = 0;
        } else if(n%8 == 0) {
            /* half line: add whitespaces */
            strncat(hexstr, " ", sizeof(hexstr)-strlen(hexstr)-1);
        }
        p++; /* next byte */
    }

    if (strlen(hexstr) > 0) {
        /* print rest of buffer if not empty */
        printf("  [%4.4s]  %-49.49s %s\n", addrstr, hexstr, charstr);
    }
}

/* Send a SCSI command block and display the result. */
void do_read_command(int fd, char *desc, unsigned char *cmd, int len)
{
        unsigned char sense[SENSE_BUFF_LEN];
        memset( sense, 0, SENSE_BUFF_LEN );

        sg_io_hdr_t io;
        unsigned char buf[512];

        memset(buf, 0, sizeof(buf));

        memset(&io, 0, sizeof(io));
        io.interface_id = 'S';
        io.cmd_len = len;
        io.mx_sb_len = 0;
        io.dxfer_direction = SG_DXFER_FROM_DEV;
        io.dxfer_len = sizeof(buf);
        io.dxferp = buf;
        io.cmdp = cmd;

        printf("Command: %s\n", desc);
        hexdump(cmd, len);

        if (ioctl(fd, SG_IO, &io) < 0) {
                printf("Error: %s\n", strerror(errno));
                return;
        }

        if ( io.sb_len_wr ){
            printf("Sense\n");
            hexdump( sense, SENSE_BUFF_LEN );
        }
        else
            printf( "No Sense\n" );

        if ((io.info & SG_INFO_OK_MASK) != SG_INFO_OK) {
            printf("Failed with info 0x%02x  mask status 0x%02x  msg status 0x%02x  host status 0x%02x driver status 0x%02x\n", io.info, io.masked_status, io.msg_status, io.host_status, io.driver_status );
            return;
        }

        len = io.dxfer_len - io.resid;
        printf("Response: %d %s\n", len, (len == 1) ? "byte" : "bytes");
        hexdump(buf, len);
}

void do_write_command(int fd, char *desc, unsigned char *cmd, int len, char *data_desc, unsigned char *data, int datalen)
{
        unsigned char sense[SENSE_BUFF_LEN];
        memset( sense, 0, SENSE_BUFF_LEN );

        sg_io_hdr_t io;
        memset(&io, 0, sizeof(io));
        io.interface_id = 'S';
        io.cmd_len = len;
        io.mx_sb_len = SENSE_BUFF_LEN;
        io.dxfer_direction = SG_DXFER_TO_DEV;
        io.dxfer_len = datalen;
        io.dxferp = data;
        io.cmdp = cmd;
        io.sbp = sense;

        printf("Command: %s\n", desc);
        hexdump(cmd, len);
        printf("Data: %s\n", data_desc);
        hexdump(data, datalen);

        if (ioctl(fd, SG_IO, &io) < 0) {
                printf("Error: %s\n", strerror(errno));
                return;
        }

        if ( io.sb_len_wr ){
            printf("Sense\n");
            hexdump( sense, SENSE_BUFF_LEN );
        }
        else
            printf( "No Sense\n" );

        if ((io.info & SG_INFO_OK_MASK) != SG_INFO_OK) {
            printf("Failed with info 0x%02x  mask status 0x%02x  msg status 0x%02x  host status 0x%02x driver status 0x%02x\n", io.info, io.masked_status, io.msg_status, io.host_status, io.driver_status );
                return;
        }

        len = io.dxfer_len - io.resid;
        printf("Response: %d %s\n", len, (len == 1) ? "byte" : "bytes");

        //hexdump(buf, len);
}

struct {
        char *description;
        int len;
        unsigned char cmd[16];
} commands[] = {
        { "SCSI Inquiry", 6,
          { 0x12, 0x00, 0x00, 0x00, 0xFF, 0x00 } },
        { "SCSI SPOUT Set Encryption Key", 12,
          { 0xb5, 0x20, 0x00, 0x10, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x34, 0x00, 0x00 } },
        { "SCSI SPIN Read Status", 12,
          { 0xa2, 0x20, 0x00, 0x20, 0x00, 0x00,
            0xff, 0xff, 0xff, 0xff, 0x00, 0x00 } },
        { NULL, 0, { 0 } },
};

struct {
        char *description;
        int len;
        unsigned char cmd[64];
} data[] = {
        { "SCSI SPOUT Send Encryption Key Page", 52,
          { 0x00, 0x10, 0x00, 0x30, 0x40, 0x00,
            0x02, 0x03, 0x01, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x20,
          } },
        { "SCSI SPOUT Clear Encryption Mode Page", 52,
          { 0x00, 0x10, 0x00, 0x30, 0x40, 0x00,
            0x00, 0x00, 0x01, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x20,
          } },
        { NULL, 0, { 0 } },
};

int main(int argc, char **argv)
{
        FILE *fd2;
        int fd;
        int i = 0;

        if (argc < 2) {
                fprintf(stderr, "usage: %s /dev/sda < <keyfile.txt> | clear >\n", *argv);
                return 1;
        }

        if ((fd = open(argv[1], O_RDWR)) < 0) {
                perror(argv[1]);
                return 1;
        }

        if ((ioctl(fd, SG_GET_VERSION_NUM, &i) < 0) || (i < 30000)) {
                fprintf(stderr,"%s is not a sg device\n", argv[1]);
                close(fd);
                return 1;
        }

        printf("Opened %s\n", argv[1]);
        /* Send query command */
        do_read_command(fd, commands[0].description, commands[0].cmd, commands[0].len);

        if(argc > 2) {

        if ( strcasecmp( argv[2], "clear" ) == 0 ) {
            do_write_command(fd, commands[1].description, commands[1].cmd, commands[1].len, data[1].description, data[1].cmd, data[1].len);

        }
        else
        {
            if ((fd2 = fopen(argv[2], "r")) < 0) {
                perror(argv[2]);
                return 1;
                }

            for (i = 0; i < 32; i++) {
                if( fscanf(fd2, "%2x ", (unsigned int *) &data[0].cmd[i + 20]) != 1 ) {
                    fprintf(stderr, "Keyfile Error reading %s\n", argv[2]);
                    return 1;
                    }
                }
            fclose(fd2);
            /* Set Encryption key*/
            do_write_command(fd, commands[1].description, commands[1].cmd, commands[1].len, data[0].description, data[0].cmd, data[0].len);
            }
        }

        /* Query encryption status */
        do_read_command(fd, commands[2].description, commands[2].cmd, commands[2].len);
        close(fd);
        return 0;
}