├── Makefile ├── LICENSE ├── sm.h ├── caam_keyblob.h ├── caam_tool.go ├── README.md └── caam_keyblob.c /Makefile: -------------------------------------------------------------------------------- 1 | ifneq ($(KERNELRELEASE),) 2 | 3 | # kbuild 4 | ccflags-y += -I$(srctree)/drivers/crypto/caam 5 | obj-m += caam_keyblob.o 6 | 7 | else 8 | 9 | KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build 10 | GO ?= go 11 | 12 | .PHONY: caam_tool 13 | 14 | all: 15 | make -C ${KERNEL_SRC} M=$(CURDIR) modules 16 | 17 | modules_install: 18 | make -C ${KERNEL_SRC} M=$(CURDIR) modules_install 19 | 20 | clean: 21 | make -C ${KERNEL_SRC} M=$(CURDIR) clean 22 | 23 | caam_tool: 24 | GOARCH=arm ${GO} build -ldflags "-s -w" -o caam_tool caam_tool.go 25 | endif 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | NXP Cryptographic Acceleration and Assurance Module (CAAM) - Linux driver 2 | https://github.com/usbarmory/caam-keyblob 3 | 4 | Copyright (c) The caam-keblob authors. 5 | Copyright (c) 2015 Freescale Semiconductor, Inc. 6 | 7 | This program is free software: you can redistribute it and/or modify it under 8 | the terms of the GNU General Public License as published by the Free Software 9 | Foundation under version 3 of the License. 10 | 11 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | -------------------------------------------------------------------------------- /sm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CAAM Secure Memory/Keywrap API Definitions 3 | * Copyright (C) 2008-2015 Freescale Semiconductor, Inc. 4 | */ 5 | 6 | #ifndef SM_H 7 | #define SM_H 8 | 9 | /* Storage access permissions */ 10 | #define SM_PERM_READ 0x01 11 | #define SM_PERM_WRITE 0x02 12 | #define SM_PERM_BLOB 0x03 13 | 14 | /* Define treatment of secure memory vs. general memory blobs */ 15 | #define SM_SECMEM 0 16 | #define SM_GENMEM 1 17 | 18 | /* Define treatment of red/black keys */ 19 | #define RED_KEY 0 20 | #define BLACK_KEY 1 21 | 22 | /* Define key encryption/covering options */ 23 | #define KEY_COVER_ECB 0 /* cover key in AES-ECB */ 24 | #define KEY_COVER_CCM 1 /* cover key with AES-CCM */ 25 | 26 | /* 27 | * Round a key size up to an AES blocksize boundary so to allow for 28 | * padding out to a full block 29 | */ 30 | #define AES_BLOCK_PAD(x) ((x % 16) ? ((x >> 4) + 1) << 4 : x) 31 | 32 | /* Define space required for BKEK + MAC tag storage in any blob */ 33 | #define BLOB_OVERHEAD (32 + 16) 34 | 35 | #endif /* SM_H */ 36 | -------------------------------------------------------------------------------- /caam_keyblob.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CAAM public-level include definitions for the key blob 3 | * 4 | * Copyright (C) 2015 Freescale Semiconductor, Inc. 5 | */ 6 | 7 | #ifndef CAAM_KEYBLOB_H 8 | #define CAAM_KEYBLOB_H 9 | 10 | #include 11 | #include 12 | 13 | /* Blob protocol protinfo bits */ 14 | #define OP_PCL_BLOB_TK 0x0200 15 | #define OP_PCL_BLOB_EKT 0x0100 16 | 17 | #define OP_PCL_BLOB_K2KR_MEM 0x0000 18 | #define OP_PCL_BLOB_K2KR_C1KR 0x0010 19 | #define OP_PCL_BLOB_K2KR_C2KR 0x0030 20 | #define OP_PCL_BLOB_K2KR_AFHAS 0x0050 21 | #define OP_PCL_BLOB_K2KR_C2KR_SPLIT 0x0070 22 | 23 | #define OP_PCL_BLOB_PTXT_SECMEM 0x0008 24 | #define OP_PCL_BLOB_BLACK 0x0004 25 | 26 | #define OP_PCL_BLOB_FMT_NORMAL 0x0000 27 | #define OP_PCL_BLOB_FMT_MSTR 0x0002 28 | #define OP_PCL_BLOB_FMT_TEST 0x0003 29 | 30 | struct caam_kb_data { 31 | char *rawkey; 32 | size_t rawkey_len; 33 | char *keyblob; 34 | size_t keyblob_len; 35 | char *keymod; 36 | size_t keymod_len; 37 | }; 38 | 39 | #define CAAM_KB_MAGIC 'I' 40 | 41 | /** 42 | * DOC: CAAM_KB_ENCRYPT - generate a key blob from raw key 43 | * 44 | * Takes an caam_kb_data struct and returns it with the key blob 45 | */ 46 | #define CAAM_KB_ENCRYPT _IOWR(CAAM_KB_MAGIC, 0, \ 47 | struct caam_kb_data) 48 | 49 | /** 50 | * DOC: CAAM_KB_DECRYPT - get keys from a key blob 51 | * 52 | * Takes an caam_kb_data struct and returns it with the raw key. 53 | */ 54 | #define CAAM_KB_DECRYPT _IOWR(CAAM_KB_MAGIC, 1, struct caam_kb_data) 55 | 56 | #ifndef GENMEM_KEYMOD_LEN 57 | #define GENMEM_KEYMOD_LEN 16 58 | #endif 59 | 60 | #endif /* CAAM_KEYBLOB_H */ 61 | -------------------------------------------------------------------------------- /caam_tool.go: -------------------------------------------------------------------------------- 1 | // NXP Cryptographic Acceleration and Assurance Module (CAAM) 2 | // https://github.com/usbarmory/caam-keyblob 3 | // 4 | // userspace driver reference example 5 | // 6 | // Copyright (c) The caam-keblob authors. 7 | // 8 | // This program is free software: you can redistribute it and/or modify it 9 | // under the terms of the GNU General Public License as published by the Free 10 | // Software Foundation under version 3 of the License. 11 | // 12 | // This program is distributed in the hope that it will be useful, but WITHOUT 13 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 | // more details. 16 | // 17 | // See accompanying LICENSE file for full details. 18 | // 19 | // IMPORTANT: the unique OTPMK internal key is available only when Secure Boot 20 | // (HAB) is enabled, otherwise a Non-volatile Test Key (NVTK), identical for 21 | // each SoC, is used. The secure operation of the CAAM and SNVS, in production 22 | // deployments, should always be paired with Secure Boot activation. 23 | // 24 | // +build linux 25 | 26 | package main 27 | 28 | import ( 29 | "bytes" 30 | "flag" 31 | "log" 32 | "os" 33 | "syscall" 34 | "unsafe" 35 | ) 36 | 37 | const CAAM_DEV = "/dev/caam_kb" 38 | 39 | const ( 40 | KEYMOD_LEN = 16 41 | BLOB_OVERHEAD = 32 + 16 42 | MAX_KEYBLOB_LEN = 65535 43 | MAX_RAWKEY_LEN = MAX_KEYBLOB_LEN - BLOB_OVERHEAD 44 | ) 45 | 46 | // Portability note: the 0x18 within the two CAAM_KB_* constants and the uint32 47 | // types in caam_kb_data reflect a 32-bit architecture. 48 | 49 | const ( 50 | // _IOWR(CAAM_KB_MAGIC, 0, struct caam_kb_data) 51 | CAAM_KB_ENCRYPT = 0xc0184900 52 | // _IOWR(CAAM_KB_MAGIC, 1, struct caam_kb_data) 53 | CAAM_KB_DECRYPT = 0xc0184901 54 | ) 55 | 56 | // C compatible struct of caam_kb_data from caam_keyblob.h 57 | type caam_kb_data struct { 58 | Text *byte 59 | TextLen uint32 60 | Blob *byte 61 | BlobLen uint32 62 | Keymod *byte 63 | KeymodLen uint32 64 | } 65 | 66 | func init() { 67 | log.SetFlags(0) 68 | log.SetOutput(os.Stdout) 69 | 70 | flag.Usage = func() { 71 | log.Println("usage: [enc|dec] [cleartext file] [blob file]") 72 | } 73 | } 74 | 75 | func main() { 76 | var err error 77 | var mode uint32 78 | 79 | var text []byte 80 | var blob []byte 81 | 82 | var output *os.File 83 | 84 | flag.Parse() 85 | 86 | if len(flag.Args()) != 3 { 87 | flag.Usage() 88 | os.Exit(1) 89 | } 90 | 91 | op := flag.Arg(0) 92 | textPath := flag.Arg(1) 93 | blobPath := flag.Arg(2) 94 | 95 | switch op { 96 | case "enc": 97 | mode = CAAM_KB_ENCRYPT 98 | case "dec": 99 | mode = CAAM_KB_DECRYPT 100 | default: 101 | log.Fatal("caam_tool: error, invalid operation") 102 | } 103 | 104 | defer func() { 105 | if err != nil { 106 | log.Fatalf("caam_tool: error, %v", err) 107 | } 108 | }() 109 | 110 | kb := &caam_kb_data{} 111 | 112 | // The key modifier is left empty in this reference example, it is 113 | // concatenated to the OTPMK to further differentiate derived keys. 114 | keymod := bytes.Repeat([]byte{0x00}, KEYMOD_LEN) 115 | kb.Keymod = &keymod[0] 116 | kb.KeymodLen = KEYMOD_LEN 117 | 118 | switch mode { 119 | case CAAM_KB_ENCRYPT: 120 | if text, err = os.ReadFile(textPath); err != nil { 121 | return 122 | } 123 | 124 | if len(text) == 0 || len(text) > MAX_RAWKEY_LEN { 125 | log.Fatal("caam_tool: error, invalid input size") 126 | } 127 | 128 | kb.TextLen = uint32(len(text)) 129 | kb.BlobLen = uint32(len(text) + BLOB_OVERHEAD) 130 | 131 | blob = make([]byte, kb.BlobLen) 132 | 133 | log.Printf("caam_tool: encrypting %d bytes from %s", kb.TextLen, textPath) 134 | case CAAM_KB_DECRYPT: 135 | if blob, err = os.ReadFile(blobPath); err != nil { 136 | return 137 | } 138 | 139 | if len(blob) == 0 || len(blob) > MAX_KEYBLOB_LEN { 140 | log.Fatal("caam_tool: error, invalid input size") 141 | } 142 | 143 | kb.BlobLen = uint32(len(blob)) 144 | kb.TextLen = uint32(len(blob) - BLOB_OVERHEAD) 145 | 146 | text = make([]byte, kb.TextLen) 147 | 148 | log.Printf("caam_tool: decrypting %d bytes from %s", kb.BlobLen, blobPath) 149 | } 150 | 151 | kb.Text = &text[0] 152 | kb.Blob = &blob[0] 153 | 154 | caam, err := os.OpenFile(CAAM_DEV, os.O_RDWR, 0600) 155 | 156 | if err != nil { 157 | return 158 | } 159 | 160 | syscall.Flock(int(caam.Fd()), syscall.LOCK_EX) 161 | defer syscall.Flock(int(caam.Fd()), syscall.LOCK_UN) 162 | defer caam.Close() 163 | 164 | log.Printf("caam_tool: caam_kb_data %+v", kb) 165 | log.Printf("caam_tool: issuing ioctl %x on %s", mode, CAAM_DEV) 166 | 167 | if err = ioctl(caam.Fd(), uintptr(mode), uintptr(unsafe.Pointer(kb))); err != nil { 168 | return 169 | } 170 | 171 | switch mode { 172 | case CAAM_KB_ENCRYPT: 173 | if output, err = os.OpenFile(blobPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_EXCL|os.O_SYNC, 0600); err != nil { 174 | return 175 | } 176 | 177 | log.Printf("caam_tool: encrypted %d bytes to %s", kb.BlobLen, blobPath) 178 | output.Write(blob) 179 | case CAAM_KB_DECRYPT: 180 | if output, err = os.OpenFile(textPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_EXCL|os.O_SYNC, 0600); err != nil { 181 | return 182 | } 183 | 184 | log.Printf("caam_tool: decrypted %d bytes to %s", kb.TextLen, textPath) 185 | output.Write(text) 186 | } 187 | 188 | output.Close() 189 | } 190 | 191 | func ioctl(fd, cmd, arg uintptr) (err error) { 192 | _, _, e := syscall.Syscall(syscall.SYS_IOCTL, fd, cmd, arg) 193 | 194 | if e != 0 { 195 | return syscall.Errno(e) 196 | } 197 | 198 | return 199 | } 200 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | NXP Cryptographic Acceleration and Assurance Module (CAAM) - Linux driver 2 | ========================================================================= 3 | 4 | The NXP Cryptographic Acceleration and Assurance Module (CAAM) is a built-in 5 | hardware module for NXP i.MX, QoriQ and Layerscape SoCs that implements secure 6 | RAM and a dedicated AES cryptographic engine for encryption/decryption 7 | operations. 8 | 9 | A device specific random 256-bit OTPMK key is fused in each SoC at 10 | manufacturing time, this key is unreadable and can only be used by the CAAM for 11 | AES encryption/decryption of user data, through the Secure Non-Volatile Storage 12 | (SNVS) companion block. 13 | 14 | This directory contains a Linux kernel driver for the CAAM, with the specific 15 | functionality of encrypting/decrypting a data blob (typically an encryption 16 | key) with the OTPMK made available by the SNVS. 17 | 18 | The module allocates character device `/dev/caam_kb` for userspace encryption 19 | and decryption operations. 20 | 21 | The kernel driver is a port of the original Freescale one for Linux 3.x with 22 | assorted bugfixes. 23 | 24 | Authors 25 | ======= 26 | 27 | Andrea Barisani 28 | andrea@inversepath.com 29 | 30 | Andrej Rosano 31 | andrej@inversepath.com 32 | 33 | Based on a driver from Freescale Semiconductor, Inc. 34 | 35 | Compiling 36 | ========= 37 | 38 | The following instructions assume compilation on a native architecture, when 39 | cross compiling adjust `ARCH` and `CROSS_COMPILE` variables accordingly. 40 | 41 | ``` 42 | # the Makefile attempts to locate your Linux kernel source tree, if this fails 43 | # it can be passed with a Makefile variable (e.g. `make KERNEL_SRC=path`) 44 | git clone https://github.com/usbarmory/caam_keyblob 45 | cd caam_keyblob 46 | make 47 | make modules_install 48 | ``` 49 | 50 | Once installed the resulting module can be loaded in the traditional manner: 51 | 52 | ``` 53 | modprobe caam_keyblob 54 | ``` 55 | 56 | The probing of the driver depends on the CAAM Device Tree (dts) inclusion in 57 | the running Linux kernel, versions >= 4.18 58 | [dts](https://github.com/torvalds/linux/blob/v4.20/arch/arm/boot/dts/imx6ul.dtsi#L770-L798) 59 | already include the base CAAM device entries for SoCs that support it (e.g. i.MX6UL). 60 | 61 | The base CAAM device entries must however be complemented with the following 62 | section, required by this driver: 63 | ``` 64 | caam_keyblob: caam-keyblob { 65 | compatible = "fsl,sec-v4.0-keyblob"; 66 | status = "okay"; 67 | }; 68 | ``` 69 | 70 | An example of all required entries can be found in the USB armory Mk II 71 | [dts](https://github.com/usbarmory/usbarmory/blob/master/software/kernel_conf/mark-two/imx6ul-usbarmory.dts). 72 | 73 | Finally the Linux CAAM Job Ring driver (`caam_jr`) must be enabled 74 | (`CRYPTO_DEV_FSL_CAAM_JR`) in the running kernel configuration, either built-in 75 | or as a module, as it is a required dependency for `caam_keyblob`. 76 | 77 | Operation 78 | ========= 79 | 80 | **IMPORTANT**: the unique OTPMK internal key is available only when Secure Boot 81 | (HAB) is enabled, otherwise a Non-volatile Test Key (NVTK), identical for each 82 | SoC, is used. The secure operation of the CAAM and SNVS, in production 83 | deployments, should always be paired with Secure Boot activation. 84 | 85 | The `caam_keyblob` module, when not in Trusted or Secure State, issues the 86 | following warning at load time: 87 | 88 | ``` 89 | caam_keyblob: WARNING - not in Trusted or Secure State, Non-volatile Test Key in effect 90 | ``` 91 | 92 | When in Trusted or Secure State the module issues a corresponding log message 93 | at load time: 94 | 95 | ``` 96 | caam_keyblob: Trusted State detected 97 | ``` 98 | 99 | The following IOCTL is defined for character device `/dev/caam_kb`: 100 | 101 | ``` 102 | ioctl(file, mode, (caam_kb_data *) kb) 103 | ``` 104 | 105 | The mode can be either `CAAM_KB_ENCRYPT` or `CAAM_KB_DECRYPT` to respectively 106 | select AES-256 encryption or decryption with CBC-MAC (CCM). The mode values and 107 | the `caam_kb_data` structure format are defined in 108 | [caam_keyblob.h](https://github.com/usbarmory/caam-keyblob/blob/master/caam_keyblob.h). 109 | 110 | The following steps, all taken internally within the CAAM, describe the 111 | encryption operation: 112 | 113 | 1. A random 256-bit blob encryption key (DEK) is generated within the CAAM, 114 | using its internal RNG. 115 | 116 | 2. The DEK is used to encrypt the desired data via the CAAM AES-CCM function, 117 | providing confidentiality and integrity protection. 118 | 119 | 3. The DEK is AES-ECB encrypted with a key derived from the OTPMK, using NIST 120 | SP 800-56A Single-step Key-Derivation Function (5.8.1). An optional key 121 | modifier can be passed, to be concatenated with the OTPMK and further 122 | differentiate the key derivation process. 123 | 124 | 4. The encrypted DEK and encrypted data are returned in a blob file. 125 | 126 | The decryption operation works in reverse, taking the blob file as input and 127 | returning the cleartext data. 128 | 129 | The CAAM uses the same nonce and counter block values for every operation, 130 | however each encryption operation uses a different DEK key, generated with the 131 | internal RNG, satisfying the need to avoid key re-use. 132 | 133 | The maximum data size is 65487 bytes, this limitation is consistent with the 134 | fact that such data typically consists of an encryption key. 135 | 136 | The [INTERLOCK](https://github.com/usbarmory/interlock) file encryption 137 | front-end supports the CAAM through this driver, providing a Go userspace 138 | implementation reference. 139 | 140 | A standalone Go tool, for encryption and decryption, is also available in the 141 | [caam_keyblob.go](https://github.com/usbarmory/caam-keyblob/blob/master/caam_tool.go) 142 | file. 143 | 144 | License 145 | ======= 146 | 147 | NXP Cryptographic Acceleration and Assurance Module (CAAM) - Linux driver 148 | https://github.com/usbarmory/caam-keyblob 149 | 150 | Copyright (c) The caam-keblob authors. 151 | Copyright (c) 2015 Freescale Semiconductor, Inc. 152 | 153 | This program is free software: you can redistribute it and/or modify it under 154 | the terms of the GNU General Public License as published by the Free Software 155 | Foundation under version 3 of the License. 156 | 157 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 158 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 159 | PARTICULAR PURPOSE. See the GNU General Public License for more details. 160 | 161 | See accompanying LICENSE file for full details. 162 | -------------------------------------------------------------------------------- /caam_keyblob.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Key blob driver based on CAAM hardware 3 | * 4 | * Copyright (C) 2015 Freescale Semiconductor, Inc. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "compat.h" 12 | #include "regs.h" 13 | #include "jr.h" 14 | #include "desc.h" 15 | #include "intern.h" 16 | #include "sm.h" 17 | #include "caam_keyblob.h" 18 | 19 | #define INITIAL_DESCSZ 16 /* size of tmp buffer for descriptor const. */ 20 | 21 | #define MAX_KEYBLOB_LEN 65535 22 | #define MAX_RAWKEY_LEN (MAX_KEYBLOB_LEN - BLOB_OVERHEAD) 23 | 24 | #define SNVS_HPSR_REG 0x020cc014 25 | #define SNVS_HPSR_SSM_STATE_MASK 0xf00 26 | #define SNVS_HPSR_SSM_STATE_TRUSTED 0xd00 27 | #define SNVS_HPSR_SSM_STATE_SECURE 0xf00 28 | 29 | /** 30 | * struct kb_device - the metadata of the caam key blob device node 31 | * @dev: the actual misc device 32 | */ 33 | struct kb_device { 34 | struct miscdevice misc_dev; 35 | struct device *jr_dev; 36 | }; 37 | 38 | /* 39 | * Pseudo-synchronous ring access functions for carrying out key 40 | * encapsulation and decapsulation 41 | */ 42 | 43 | struct sm_key_job_result { 44 | int error; 45 | struct completion completion; 46 | }; 47 | 48 | 49 | static struct kb_device *kb_dev; 50 | 51 | static struct kb_device *kb_device_create(void); 52 | static int kb_device_destroy(struct kb_device *kb_dev); 53 | static int kb_open(struct inode *inode, struct file *file); 54 | static int kb_release(struct inode *inode, struct file *file); 55 | static void sm_key_job_done(struct device *dev, u32 *desc, 56 | u32 err, void *context); 57 | static int gen_mem_encap(struct device *jr_dev, void __user *secretbuf, 58 | size_t keylen, void __user *kmodbuf, void __user *outbuf); 59 | static int gen_mem_decap(struct device *jr_dev, void __user *keyblobbuf, 60 | size_t bloblen, void __user *kmodbuf, void __user *outbuf); 61 | static long kb_ioctl(struct file *file, unsigned int cmd, unsigned long arg); 62 | static int caam_keyblob_probe(struct platform_device *pdev); 63 | static int caam_keyblob_remove(struct platform_device *pdev); 64 | 65 | static int kb_open(struct inode *inode, struct file *file) 66 | { 67 | struct miscdevice *miscdev = file->private_data; 68 | struct kb_device *dev = container_of(miscdev, struct kb_device, misc_dev); 69 | struct device *jr_dev; 70 | 71 | if (!dev->jr_dev) { 72 | jr_dev = caam_jr_alloc(); 73 | if (IS_ERR(jr_dev)) { 74 | pr_err("caam_keyblob: job ring device allocation for transform failed\n"); 75 | return -ENOMEM; 76 | } 77 | dev->jr_dev = jr_dev; 78 | } 79 | else { 80 | pr_err("caam_keyblob: job ring device already created"); 81 | return -EPERM; 82 | } 83 | 84 | return 0; 85 | } 86 | 87 | static int kb_release(struct inode *inode, struct file *file) 88 | { 89 | struct miscdevice *miscdev = file->private_data; 90 | struct kb_device *dev = container_of(miscdev, struct kb_device, misc_dev); 91 | 92 | if (dev && dev->jr_dev) { 93 | caam_jr_free(dev->jr_dev); 94 | dev->jr_dev = NULL; 95 | } 96 | return 0; 97 | } 98 | 99 | static void sm_key_job_done(struct device *dev, u32 *desc, 100 | u32 err, void *context) 101 | { 102 | struct sm_key_job_result *res = context; 103 | 104 | res->error = err; /* save off the error for postprocessing */ 105 | complete(&res->completion); /* mark us complete */ 106 | } 107 | 108 | /* 109 | * Construct a blob encapsulation job descriptor 110 | * 111 | * This function dynamically constructs a blob encapsulation job descriptor 112 | * from the following arguments: 113 | * 114 | * - desc pointer to a pointer to the descriptor generated by this 115 | * function. Caller will be responsible to kfree() this 116 | * descriptor after execution. 117 | * - keymod Physical pointer to a key modifier, which must reside in a 118 | * contiguous piece of memory. Modifier will be assumed to be 119 | * 8 bytes long for a blob of type SM_SECMEM, or 16 bytes long 120 | * for a blob of type SM_GENMEM (see blobtype argument). 121 | * - secretbuf Physical pointer to a secret, normally a black or red key, 122 | * possibly residing within an accessible secure memory page, 123 | * of the secret to be encapsulated to an output blob. 124 | * - outbuf Physical pointer to the destination buffer to receive the 125 | * encapsulated output. This buffer will need to be 48 bytes 126 | * larger than the input because of the added encapsulation data. 127 | * The generated descriptor will account for the increase in size, 128 | * but the caller must also account for this increase in the 129 | * buffer allocator. 130 | * - secretsz Size of input secret, in bytes. This is limited to 65536 131 | * less the size of blob overhead, since the length embeds into 132 | * DECO pointer in/out instructions. 133 | * - keycolor Determines if the source data is covered (black key) or 134 | * plaintext (red key). RED_KEY or BLACK_KEY are defined in 135 | * for this purpose. 136 | * - blobtype Determine if encapsulated blob should be a secure memory 137 | * blob (SM_SECMEM), with partition data embedded with key 138 | * material, or a general memory blob (SM_GENMEM). 139 | * - auth If BLACK_KEY source is covered via AES-CCM, specify 140 | * KEY_COVER_CCM, else uses AES-ECB (KEY_COVER_ECB). 141 | * 142 | * Upon completion, desc points to a buffer containing a CAAM job 143 | * descriptor which encapsulates data into an externally-storable blob 144 | * suitable for use across power cycles. 145 | * 146 | * This is an example of a black key encapsulation job into a general memory 147 | * blob. Notice the 16-byte key modifier in the LOAD instruction. Also note 148 | * the output 48 bytes longer than the input: 149 | * 150 | * [00] B0800008 jobhdr: stidx=0 len=8 151 | * [01] 14400010 ld: ccb2-key len=16 offs=0 152 | * [02] 08144891 ptr->@0x08144891 153 | * [03] F800003A seqoutptr: len=58 154 | * [04] 01000000 out_ptr->@0x01000000 155 | * [05] F000000A seqinptr: len=10 156 | * [06] 09745090 in_ptr->@0x09745090 157 | * [07] 870D0004 operation: encap blob reg=memory, black, format=normal 158 | * 159 | * This is an example of a red key encapsulation job for storing a red key 160 | * into a secure memory blob. Note the 8 byte modifier on the 12 byte offset 161 | * in the LOAD instruction; this accounts for blob permission storage: 162 | * 163 | * [00] B0800008 jobhdr: stidx=0 len=8 164 | * [01] 14400C08 ld: ccb2-key len=8 offs=12 165 | * [02] 087D0784 ptr->@0x087d0784 166 | * [03] F8000050 seqoutptr: len=80 167 | * [04] 09251BB2 out_ptr->@0x09251bb2 168 | * [05] F0000020 seqinptr: len=32 169 | * [06] 40000F31 in_ptr->@0x40000f31 170 | * [07] 870D0008 operation: encap blob reg=memory, red, sec_mem, 171 | * format=normal 172 | * 173 | * Note: this function only generates 32-bit pointers at present, and should 174 | * be refactored using a scheme that allows both 32 and 64 bit addressing 175 | */ 176 | 177 | static int blob_encap_jobdesc(u32 **desc, dma_addr_t keymod, 178 | void *secretbuf, dma_addr_t outbuf, 179 | u16 secretsz, u8 keycolor, u8 blobtype, u8 auth) 180 | { 181 | u32 *tdesc, tmpdesc[INITIAL_DESCSZ]; 182 | u16 dsize, idx; 183 | 184 | memset(tmpdesc, 0, INITIAL_DESCSZ * sizeof(u32)); 185 | idx = 1; 186 | 187 | /* 188 | * Key modifier works differently for secure/general memory blobs 189 | * This accounts for the permission/protection data encapsulated 190 | * within the blob if a secure memory blob is requested 191 | */ 192 | if (blobtype == SM_SECMEM) 193 | tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB | 194 | LDST_SRCDST_BYTE_KEY | 195 | ((12 << LDST_OFFSET_SHIFT) & LDST_OFFSET_MASK) 196 | | (8 & LDST_LEN_MASK); 197 | else /* is general memory blob */ 198 | tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB | 199 | LDST_SRCDST_BYTE_KEY | (16 & LDST_LEN_MASK); 200 | 201 | tmpdesc[idx++] = (u32)keymod; 202 | 203 | /* 204 | * Encapsulation output must include space for blob key encryption 205 | * key and MAC tag 206 | */ 207 | tmpdesc[idx++] = CMD_SEQ_OUT_PTR | (secretsz + BLOB_OVERHEAD); 208 | tmpdesc[idx++] = (u32)outbuf; 209 | 210 | /* Input data, should be somewhere in secure memory */ 211 | tmpdesc[idx++] = CMD_SEQ_IN_PTR | secretsz; 212 | tmpdesc[idx++] = (u32)secretbuf; 213 | 214 | /* Set blob encap, then color */ 215 | tmpdesc[idx] = CMD_OPERATION | OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB; 216 | 217 | if (blobtype == SM_SECMEM) 218 | tmpdesc[idx] |= OP_PCL_BLOB_PTXT_SECMEM; 219 | 220 | if (auth == KEY_COVER_CCM) 221 | tmpdesc[idx] |= OP_PCL_BLOB_EKT; 222 | 223 | if (keycolor == BLACK_KEY) 224 | tmpdesc[idx] |= OP_PCL_BLOB_BLACK; 225 | 226 | idx++; 227 | tmpdesc[0] = CMD_DESC_HDR | HDR_ONE | (idx & HDR_DESCLEN_MASK); 228 | dsize = idx * sizeof(u32); 229 | 230 | tdesc = kmalloc(dsize, GFP_KERNEL | GFP_DMA); 231 | if (tdesc == NULL) 232 | return 0; 233 | 234 | memcpy(tdesc, tmpdesc, dsize); 235 | *desc = tdesc; 236 | return dsize; 237 | } 238 | 239 | /* 240 | * Construct a blob decapsulation job descriptor 241 | * 242 | * This function dynamically constructs a blob decapsulation job descriptor 243 | * from the following arguments: 244 | * 245 | * - desc pointer to a pointer to the descriptor generated by this 246 | * function. Caller will be responsible to kfree() this 247 | * descriptor after execution. 248 | * - keymod Physical pointer to a key modifier, which must reside in a 249 | * contiguous piece of memory. Modifier will be assumed to be 250 | * 8 bytes long for a blob of type SM_SECMEM, or 16 bytes long 251 | * for a blob of type SM_GENMEM (see blobtype argument). 252 | * - blobbuf Physical pointer (into external memory) of the blob to 253 | * be decapsulated. Blob must reside in a contiguous memory 254 | * segment. 255 | * - outbuf Physical pointer of the decapsulated output, possibly into 256 | * a location within a secure memory page. Must be contiguous. 257 | * - secretsz Size of encapsulated secret in bytes (not the size of the 258 | * input blob). 259 | * - keycolor Determines if decapsulated content is encrypted (BLACK_KEY) 260 | * or left as plaintext (RED_KEY). 261 | * - blobtype Determine if encapsulated blob should be a secure memory 262 | * blob (SM_SECMEM), with partition data embedded with key 263 | * material, or a general memory blob (SM_GENMEM). 264 | * - auth If decapsulation path is specified by BLACK_KEY, then if 265 | * AES-CCM is requested for key covering use KEY_COVER_CCM, else 266 | * use AES-ECB (KEY_COVER_ECB). 267 | * 268 | * Upon completion, desc points to a buffer containing a CAAM job descriptor 269 | * that decapsulates a key blob from external memory into a black (encrypted) 270 | * key or red (plaintext) content. 271 | * 272 | * This is an example of a black key decapsulation job from a general memory 273 | * blob. Notice the 16-byte key modifier in the LOAD instruction. 274 | * 275 | * [00] B0800008 jobhdr: stidx=0 len=8 276 | * [01] 14400010 ld: ccb2-key len=16 offs=0 277 | * [02] 08A63B7F ptr->@0x08a63b7f 278 | * [03] F8000010 seqoutptr: len=16 279 | * [04] 01000000 out_ptr->@0x01000000 280 | * [05] F000003A seqinptr: len=58 281 | * [06] 01000010 in_ptr->@0x01000010 282 | * [07] 860D0004 operation: decap blob reg=memory, black, format=normal 283 | * 284 | * This is an example of a red key decapsulation job for restoring a red key 285 | * from a secure memory blob. Note the 8 byte modifier on the 12 byte offset 286 | * in the LOAD instruction: 287 | * 288 | * [00] B0800008 jobhdr: stidx=0 len=8 289 | * [01] 14400C08 ld: ccb2-key len=8 offs=12 290 | * [02] 01000000 ptr->@0x01000000 291 | * [03] F8000020 seqoutptr: len=32 292 | * [04] 400000E6 out_ptr->@0x400000e6 293 | * [05] F0000050 seqinptr: len=80 294 | * [06] 08F0C0EA in_ptr->@0x08f0c0ea 295 | * [07] 860D0008 operation: decap blob reg=memory, red, sec_mem, 296 | * format=normal 297 | * 298 | * Note: this function only generates 32-bit pointers at present, and should 299 | * be refactored using a scheme that allows both 32 and 64 bit addressing 300 | */ 301 | 302 | static int blob_decap_jobdesc(u32 **desc, dma_addr_t keymod, dma_addr_t blobbuf, 303 | u8 *outbuf, u16 secretsz, u8 keycolor, 304 | u8 blobtype, u8 auth) 305 | { 306 | u32 *tdesc, tmpdesc[INITIAL_DESCSZ]; 307 | u16 dsize, idx; 308 | 309 | memset(tmpdesc, 0, INITIAL_DESCSZ * sizeof(u32)); 310 | idx = 1; 311 | 312 | /* Load key modifier */ 313 | if (blobtype == SM_SECMEM) 314 | tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB | 315 | LDST_SRCDST_BYTE_KEY | 316 | ((12 << LDST_OFFSET_SHIFT) & LDST_OFFSET_MASK) 317 | | (8 & LDST_LEN_MASK); 318 | else /* is general memory blob */ 319 | tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB | 320 | LDST_SRCDST_BYTE_KEY | (16 & LDST_LEN_MASK); 321 | 322 | tmpdesc[idx++] = (u32)keymod; 323 | 324 | /* Compensate BKEK + MAC tag over size of encapsulated secret */ 325 | tmpdesc[idx++] = CMD_SEQ_IN_PTR | (secretsz + BLOB_OVERHEAD); 326 | tmpdesc[idx++] = (u32)blobbuf; 327 | tmpdesc[idx++] = CMD_SEQ_OUT_PTR | secretsz; 328 | tmpdesc[idx++] = (u32)outbuf; 329 | 330 | /* Decapsulate from secure memory partition to black blob */ 331 | tmpdesc[idx] = CMD_OPERATION | OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB; 332 | 333 | if (blobtype == SM_SECMEM) 334 | tmpdesc[idx] |= OP_PCL_BLOB_PTXT_SECMEM; 335 | 336 | if (auth == KEY_COVER_CCM) 337 | tmpdesc[idx] |= OP_PCL_BLOB_EKT; 338 | 339 | if (keycolor == BLACK_KEY) 340 | tmpdesc[idx] |= OP_PCL_BLOB_BLACK; 341 | 342 | idx++; 343 | tmpdesc[0] = CMD_DESC_HDR | HDR_ONE | (idx & HDR_DESCLEN_MASK); 344 | dsize = idx * sizeof(u32); 345 | 346 | tdesc = kmalloc(dsize, GFP_KERNEL | GFP_DMA); 347 | if (tdesc == NULL) 348 | return 0; 349 | 350 | memcpy(tdesc, tmpdesc, dsize); 351 | *desc = tdesc; 352 | return dsize; 353 | } 354 | 355 | static int gen_mem_encap(struct device *jr_dev, void __user *secretbuf, 356 | size_t keylen, void __user *kmodbuf, void __user *outbuf) 357 | { 358 | int retval = 0; 359 | u32 dsize; 360 | u32 __iomem *encapdesc = NULL; 361 | dma_addr_t secret_dma = 0, keymod_dma = 0, outbuf_dma = 0; 362 | u8 __iomem *lsecret = NULL, *lkeymod = NULL, *loutbuf = NULL; 363 | struct sm_key_job_result testres; 364 | 365 | /* Build/map/flush the scret */ 366 | lsecret = kmalloc(keylen, GFP_KERNEL | GFP_DMA); 367 | if (!lsecret) { 368 | dev_err(jr_dev, "caam_keyblob: %s can't alloc for key\n", __func__); 369 | retval = -ENOMEM; 370 | goto out; 371 | } 372 | if (copy_from_user(lsecret, secretbuf, keylen)) { 373 | dev_err(jr_dev, "caam_keyblob: %s can't copy for key\n", __func__); 374 | retval = -EFAULT; 375 | goto out; 376 | } 377 | secret_dma = dma_map_single(jr_dev, lsecret, keylen, 378 | DMA_TO_DEVICE); 379 | 380 | /* Build/map/flush the key modifier */ 381 | lkeymod = kmalloc(GENMEM_KEYMOD_LEN, GFP_KERNEL | GFP_DMA); 382 | if (!lkeymod) { 383 | dev_err(jr_dev, "caam_keyblob: %s can't alloc for keymod\n", __func__); 384 | retval = -ENOMEM; 385 | goto out; 386 | } 387 | if (copy_from_user(lkeymod, kmodbuf, GENMEM_KEYMOD_LEN)) { 388 | dev_err(jr_dev, "caam_keyblob: %s can't Copy for keymod\n", __func__); 389 | retval = -EFAULT; 390 | goto out; 391 | } 392 | keymod_dma = dma_map_single(jr_dev, lkeymod, GENMEM_KEYMOD_LEN, 393 | DMA_TO_DEVICE); 394 | 395 | loutbuf = kmalloc(keylen + BLOB_OVERHEAD, GFP_KERNEL | GFP_DMA); 396 | if (!lkeymod) { 397 | dev_err(jr_dev, "caam_keyblob: %s can't alloc for output\n", __func__); 398 | retval = -ENOMEM; 399 | goto out; 400 | } 401 | outbuf_dma = dma_map_single(jr_dev, loutbuf, keylen + BLOB_OVERHEAD, 402 | DMA_FROM_DEVICE); 403 | dsize = blob_encap_jobdesc(&encapdesc, keymod_dma, (void *)secret_dma, outbuf_dma, 404 | keylen, RED_KEY, SM_GENMEM, KEY_COVER_ECB); 405 | if (!dsize) { 406 | dev_err(jr_dev, "caam_keyblob: can't alloc an encapsulation descriptor\n"); 407 | retval = -ENOMEM; 408 | goto out; 409 | } 410 | 411 | init_completion(&testres.completion); 412 | 413 | retval = caam_jr_enqueue(jr_dev, encapdesc, sm_key_job_done, 414 | &testres); 415 | if (retval == 0 || retval == -EINPROGRESS) { 416 | retval = 0; 417 | wait_for_completion_interruptible(&testres.completion); 418 | 419 | if (testres.error) { 420 | retval = -EFAULT; 421 | dev_err(jr_dev, "caam_keyblob: job ring error\n"); 422 | goto out; 423 | } 424 | 425 | dma_sync_single_for_cpu(jr_dev, outbuf_dma, keylen + BLOB_OVERHEAD, 426 | DMA_FROM_DEVICE); 427 | 428 | if (copy_to_user(outbuf, loutbuf, keylen + BLOB_OVERHEAD)) { 429 | retval = -EFAULT; 430 | dev_err(jr_dev, "caam_keyblob: can't copy for output\n"); 431 | goto out; 432 | } 433 | } 434 | 435 | out: 436 | if (outbuf_dma) 437 | dma_unmap_single(jr_dev, outbuf_dma, keylen + BLOB_OVERHEAD, 438 | DMA_FROM_DEVICE); 439 | if (keymod_dma) 440 | dma_unmap_single(jr_dev, keymod_dma, GENMEM_KEYMOD_LEN, DMA_TO_DEVICE); 441 | 442 | if (secret_dma) 443 | dma_unmap_single(jr_dev, secret_dma, keylen, DMA_TO_DEVICE); 444 | 445 | kfree(encapdesc); 446 | kfree(lkeymod); 447 | kfree(lsecret); 448 | kfree(loutbuf); 449 | 450 | return retval; 451 | } 452 | 453 | static int gen_mem_decap(struct device *jr_dev, void __user *keyblobbuf, 454 | size_t bloblen, void __user *kmodbuf, void __user *outbuf) 455 | { 456 | int retval = 0; 457 | size_t keylen = bloblen - BLOB_OVERHEAD; 458 | u32 dsize; 459 | dma_addr_t keyblob_dma = 0, keymod_dma = 0, outbuf_dma = 0; 460 | u8 __iomem *lkeyblob = NULL, *lkeymod = NULL, *loutbuf = NULL; 461 | struct sm_key_job_result testres; 462 | u32 __iomem *decapdesc = NULL; 463 | 464 | /* Build/map/flush the scret */ 465 | lkeyblob = kmalloc(bloblen, GFP_KERNEL | GFP_DMA); 466 | if (!lkeyblob) { 467 | dev_err(jr_dev, "caam_keyblob: %s can't alloc for keylob\n", __func__); 468 | retval = -ENOMEM; 469 | goto out; 470 | } 471 | if (copy_from_user(lkeyblob, keyblobbuf, bloblen)) { 472 | dev_err(jr_dev, "caam_keyblob: %s can't copy for keyblob\n", __func__); 473 | retval = -EFAULT; 474 | goto out; 475 | } 476 | keyblob_dma = dma_map_single(jr_dev, lkeyblob, bloblen, 477 | DMA_TO_DEVICE); 478 | 479 | /* Build/map/flush the key modifier */ 480 | lkeymod = kmalloc(GENMEM_KEYMOD_LEN, GFP_KERNEL | GFP_DMA); 481 | if (!lkeymod) { 482 | dev_err(jr_dev, "caam_keyblob: %s can't alloc for keymod\n", __func__); 483 | retval = -ENOMEM; 484 | goto out; 485 | } 486 | if (copy_from_user(lkeymod, kmodbuf, GENMEM_KEYMOD_LEN)) { 487 | dev_err(jr_dev, "caam_keyblob: %s can't copy for keymod\n", __func__); 488 | retval = -EFAULT; 489 | goto out; 490 | } 491 | keymod_dma = dma_map_single(jr_dev, lkeymod, GENMEM_KEYMOD_LEN, 492 | DMA_TO_DEVICE); 493 | 494 | loutbuf = kmalloc(keylen, GFP_KERNEL | GFP_DMA); 495 | if (!loutbuf) { 496 | dev_err(jr_dev, "caam_keyblob: %s can't alloc for outbuf\n", __func__); 497 | retval = -ENOMEM; 498 | goto out; 499 | } 500 | outbuf_dma = dma_map_single(jr_dev, loutbuf, keylen, 501 | DMA_FROM_DEVICE); 502 | 503 | /* Build the encapsulation job descriptor */ 504 | dsize = blob_decap_jobdesc(&decapdesc, keymod_dma, keyblob_dma, (u8 *)outbuf_dma, 505 | keylen, RED_KEY, SM_GENMEM, KEY_COVER_ECB); 506 | if (!dsize) { 507 | dev_err(jr_dev, "caam_keyblob: can't alloc a decapsulation descriptor\n"); 508 | retval = -ENOMEM; 509 | goto out; 510 | } 511 | 512 | init_completion(&testres.completion); 513 | 514 | retval = caam_jr_enqueue(jr_dev, decapdesc, sm_key_job_done, 515 | &testres); 516 | if (retval == 0 || retval == -EINPROGRESS) { 517 | retval = 0; 518 | wait_for_completion_interruptible(&testres.completion); 519 | 520 | if (testres.error) { 521 | retval = -EFAULT; 522 | dev_err(jr_dev, "caam_keyblob: job ring error\n"); 523 | goto out; 524 | } 525 | 526 | dma_sync_single_for_cpu(jr_dev, outbuf_dma, keylen, 527 | DMA_FROM_DEVICE); 528 | 529 | if (copy_to_user(outbuf, loutbuf, keylen)) { 530 | retval = -EFAULT; 531 | dev_err(jr_dev, "caam_keyblob: can't copy for output\n"); 532 | goto out; 533 | } 534 | } 535 | 536 | out: 537 | if (outbuf_dma) 538 | dma_unmap_single(jr_dev, outbuf_dma, keylen, 539 | DMA_FROM_DEVICE); 540 | if (keymod_dma) 541 | dma_unmap_single(jr_dev, keymod_dma, GENMEM_KEYMOD_LEN, 542 | DMA_TO_DEVICE); 543 | if (keyblob_dma) 544 | dma_unmap_single(jr_dev, keyblob_dma, bloblen, 545 | DMA_TO_DEVICE); 546 | kfree(decapdesc); 547 | kfree(lkeymod); 548 | kfree(lkeyblob); 549 | kfree(loutbuf); 550 | 551 | return retval; 552 | } 553 | 554 | static long kb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 555 | { 556 | int retval = 0; 557 | struct caam_kb_data kb_data; 558 | struct miscdevice *miscdev = file->private_data; 559 | struct kb_device *dev = container_of(miscdev, struct kb_device, misc_dev); 560 | 561 | if (copy_from_user(&kb_data, (void *)arg, sizeof(kb_data))) { 562 | retval = -EFAULT; 563 | goto err; 564 | } 565 | 566 | if (!kb_data.rawkey || !kb_data.keyblob || 567 | (kb_data.rawkey_len + BLOB_OVERHEAD != kb_data.keyblob_len) || 568 | (kb_data.rawkey_len > MAX_RAWKEY_LEN) || 569 | (kb_data.keyblob_len > MAX_KEYBLOB_LEN) || 570 | (kb_data.keyblob_len <= BLOB_OVERHEAD) || 571 | (kb_data.keymod_len != GENMEM_KEYMOD_LEN)) { 572 | retval = -EINVAL; 573 | goto err; 574 | } 575 | 576 | printk(KERN_INFO "caam_keyblob: %s rawkey_len:%d keyblob_len:%d\n", 577 | __func__, kb_data.rawkey_len, kb_data.keyblob_len); 578 | 579 | switch (cmd) { 580 | case CAAM_KB_ENCRYPT: 581 | { 582 | retval = gen_mem_encap(dev->jr_dev, kb_data.rawkey, kb_data.rawkey_len, 583 | kb_data.keymod, kb_data.keyblob); 584 | break; 585 | } 586 | case CAAM_KB_DECRYPT: 587 | { 588 | retval = gen_mem_decap(dev->jr_dev, kb_data.keyblob, kb_data.keyblob_len, 589 | kb_data.keymod, kb_data.rawkey); 590 | break; 591 | } 592 | default: 593 | return -ENOTTY; 594 | } 595 | 596 | err: 597 | return retval; 598 | } 599 | 600 | static const struct file_operations kb_fops = { 601 | .owner = THIS_MODULE, 602 | .open = kb_open, 603 | .release = kb_release, 604 | .unlocked_ioctl = kb_ioctl, 605 | }; 606 | 607 | static struct kb_device *kb_device_create(void) 608 | { 609 | struct kb_device *idev; 610 | int ret; 611 | 612 | idev = kzalloc(sizeof(struct kb_device), GFP_KERNEL); 613 | if (!idev) 614 | return ERR_PTR(-ENOMEM); 615 | 616 | idev->misc_dev.minor = MISC_DYNAMIC_MINOR; 617 | idev->misc_dev.name = "caam_kb"; 618 | idev->misc_dev.fops = &kb_fops; 619 | idev->misc_dev.parent = NULL; 620 | ret = misc_register(&idev->misc_dev); 621 | if (ret) { 622 | pr_err("caam_keyblob: caam_kb, failed to register misc device.\n"); 623 | return ERR_PTR(ret); 624 | } 625 | 626 | return idev; 627 | } 628 | 629 | static int kb_device_destroy(struct kb_device *kb_dev) 630 | { 631 | if ((kb_dev) && (kb_dev->jr_dev)) { 632 | caam_jr_free(kb_dev->jr_dev); 633 | kb_dev->jr_dev = NULL; 634 | } 635 | 636 | if (kb_dev) 637 | misc_deregister(&kb_dev->misc_dev); 638 | 639 | return 0; 640 | } 641 | 642 | /* 643 | * Probe key blob device 644 | */ 645 | static int caam_keyblob_probe(struct platform_device *pdev) 646 | { 647 | int err; 648 | void __iomem *page; 649 | u32 ssm_state, offset; 650 | 651 | dev_dbg(&pdev->dev, "caam_keylob: %s enter\n", __func__); 652 | kb_dev = kb_device_create(); 653 | 654 | if (IS_ERR_OR_NULL(kb_dev)) { 655 | err = PTR_ERR(kb_dev); 656 | goto err; 657 | } 658 | 659 | dev_info(&pdev->dev, "caam_keyblob: initialized\n"); 660 | 661 | page = ioremap(SNVS_HPSR_REG & ~(SZ_4K - 1), SZ_4K); 662 | offset = SNVS_HPSR_REG & (SZ_4K - 1); 663 | ssm_state = (__raw_readl(page + offset) & SNVS_HPSR_SSM_STATE_MASK); 664 | 665 | if (ssm_state == SNVS_HPSR_SSM_STATE_TRUSTED) { 666 | printk(KERN_INFO "caam_keyblob: Trusted State detected\n"); 667 | } else if (ssm_state == SNVS_HPSR_SSM_STATE_SECURE) { 668 | printk(KERN_INFO "caam_keyblob: Secure State detected\n"); 669 | } else { 670 | printk(KERN_NOTICE "caam_keyblob: WARNING - not in Trusted or Secure State, Non-volatile Test Key in effect\n"); 671 | } 672 | 673 | return 0; 674 | err: 675 | return err; 676 | } 677 | 678 | /* 679 | * Remove key blob device 680 | */ 681 | static int caam_keyblob_remove(struct platform_device *pdev) 682 | { 683 | kb_device_destroy(kb_dev); 684 | return 0; 685 | } 686 | 687 | static struct of_device_id caam_keyblob_match[] = { 688 | { 689 | .compatible = "fsl,sec-v4.0-keyblob", 690 | }, 691 | { 692 | .compatible = "fsl,sec4.0-keyblob", 693 | }, 694 | {}, 695 | }; 696 | 697 | MODULE_DEVICE_TABLE(of, caam_keyblob_match); 698 | 699 | static struct platform_driver caam_keyblob_driver = { 700 | .driver = { 701 | .name = "caam_keyblob", 702 | .owner = THIS_MODULE, 703 | .of_match_table = caam_keyblob_match, 704 | }, 705 | .probe = caam_keyblob_probe, 706 | .remove = caam_keyblob_remove, 707 | }; 708 | 709 | static int __init keyblob_driver_init(void) 710 | { 711 | return platform_driver_register(&caam_keyblob_driver); 712 | } 713 | 714 | static void __exit keyblob_driver_exit(void) 715 | { 716 | platform_driver_unregister(&caam_keyblob_driver); 717 | } 718 | 719 | module_init(keyblob_driver_init); 720 | module_exit(keyblob_driver_exit); 721 | 722 | MODULE_LICENSE("Dual BSD/GPL"); 723 | MODULE_DESCRIPTION("FSL CAAM Secure Memory / Keystore"); 724 | MODULE_AUTHOR("Freescale Semiconductor - NMSG/MAD"); 725 | --------------------------------------------------------------------------------