166dbc325SMimi Zohar /* 266dbc325SMimi Zohar * Copyright (C) 2010 IBM Corporation 366dbc325SMimi Zohar * 466dbc325SMimi Zohar * Authors: 566dbc325SMimi Zohar * Mimi Zohar <zohar@us.ibm.com> 666dbc325SMimi Zohar * 766dbc325SMimi Zohar * This program is free software; you can redistribute it and/or modify 866dbc325SMimi Zohar * it under the terms of the GNU General Public License as published by 966dbc325SMimi Zohar * the Free Software Foundation, version 2 of the License. 1066dbc325SMimi Zohar * 1166dbc325SMimi Zohar * File: evm_secfs.c 1266dbc325SMimi Zohar * - Used to signal when key is on keyring 1366dbc325SMimi Zohar * - Get the key and enable EVM 1466dbc325SMimi Zohar */ 1566dbc325SMimi Zohar 1620ee451fSJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1720ee451fSJoe Perches 1866dbc325SMimi Zohar #include <linux/uaccess.h> 1966dbc325SMimi Zohar #include <linux/module.h> 2066dbc325SMimi Zohar #include "evm.h" 2166dbc325SMimi Zohar 2266dbc325SMimi Zohar static struct dentry *evm_init_tpm; 2366dbc325SMimi Zohar 2466dbc325SMimi Zohar /** 2566dbc325SMimi Zohar * evm_read_key - read() for <securityfs>/evm 2666dbc325SMimi Zohar * 2766dbc325SMimi Zohar * @filp: file pointer, not actually used 2866dbc325SMimi Zohar * @buf: where to put the result 2966dbc325SMimi Zohar * @count: maximum to send along 3066dbc325SMimi Zohar * @ppos: where to start 3166dbc325SMimi Zohar * 3266dbc325SMimi Zohar * Returns number of bytes read or error code, as appropriate 3366dbc325SMimi Zohar */ 3466dbc325SMimi Zohar static ssize_t evm_read_key(struct file *filp, char __user *buf, 3566dbc325SMimi Zohar size_t count, loff_t *ppos) 3666dbc325SMimi Zohar { 3766dbc325SMimi Zohar char temp[80]; 3866dbc325SMimi Zohar ssize_t rc; 3966dbc325SMimi Zohar 4066dbc325SMimi Zohar if (*ppos != 0) 4166dbc325SMimi Zohar return 0; 4266dbc325SMimi Zohar 43f00d7975SMatthew Garrett sprintf(temp, "%d", (evm_initialized & ~EVM_SETUP)); 4466dbc325SMimi Zohar rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp)); 4566dbc325SMimi Zohar 4666dbc325SMimi Zohar return rc; 4766dbc325SMimi Zohar } 4866dbc325SMimi Zohar 4966dbc325SMimi Zohar /** 5066dbc325SMimi Zohar * evm_write_key - write() for <securityfs>/evm 5166dbc325SMimi Zohar * @file: file pointer, not actually used 5266dbc325SMimi Zohar * @buf: where to get the data from 5366dbc325SMimi Zohar * @count: bytes sent 5466dbc325SMimi Zohar * @ppos: where to start 5566dbc325SMimi Zohar * 5666dbc325SMimi Zohar * Used to signal that key is on the kernel key ring. 5766dbc325SMimi Zohar * - get the integrity hmac key from the kernel key ring 5866dbc325SMimi Zohar * - create list of hmac protected extended attributes 5966dbc325SMimi Zohar * Returns number of bytes written or error code, as appropriate 6066dbc325SMimi Zohar */ 6166dbc325SMimi Zohar static ssize_t evm_write_key(struct file *file, const char __user *buf, 6266dbc325SMimi Zohar size_t count, loff_t *ppos) 6366dbc325SMimi Zohar { 64f00d7975SMatthew Garrett int i, ret; 6566dbc325SMimi Zohar 66f00d7975SMatthew Garrett if (!capable(CAP_SYS_ADMIN) || (evm_initialized & EVM_SETUP)) 6766dbc325SMimi Zohar return -EPERM; 6866dbc325SMimi Zohar 69f00d7975SMatthew Garrett ret = kstrtoint_from_user(buf, count, 0, &i); 70f00d7975SMatthew Garrett 71f00d7975SMatthew Garrett if (ret) 72f00d7975SMatthew Garrett return ret; 73f00d7975SMatthew Garrett 74f00d7975SMatthew Garrett /* Reject invalid values */ 75f00d7975SMatthew Garrett if (!i || (i & ~EVM_INIT_MASK) != 0) 7666dbc325SMimi Zohar return -EINVAL; 7766dbc325SMimi Zohar 78f00d7975SMatthew Garrett if (i & EVM_INIT_HMAC) { 79f00d7975SMatthew Garrett ret = evm_init_key(); 80f00d7975SMatthew Garrett if (ret != 0) 81f00d7975SMatthew Garrett return ret; 82f00d7975SMatthew Garrett /* Forbid further writes after the symmetric key is loaded */ 83f00d7975SMatthew Garrett i |= EVM_SETUP; 84f00d7975SMatthew Garrett } 8566dbc325SMimi Zohar 86f00d7975SMatthew Garrett evm_initialized |= i; 8776266763SDmitry Kasatkin 8866dbc325SMimi Zohar return count; 8966dbc325SMimi Zohar } 9066dbc325SMimi Zohar 9166dbc325SMimi Zohar static const struct file_operations evm_key_ops = { 9266dbc325SMimi Zohar .read = evm_read_key, 9366dbc325SMimi Zohar .write = evm_write_key, 9466dbc325SMimi Zohar }; 9566dbc325SMimi Zohar 9666dbc325SMimi Zohar int __init evm_init_secfs(void) 9766dbc325SMimi Zohar { 9866dbc325SMimi Zohar int error = 0; 9966dbc325SMimi Zohar 10066dbc325SMimi Zohar evm_init_tpm = securityfs_create_file("evm", S_IRUSR | S_IRGRP, 10166dbc325SMimi Zohar NULL, NULL, &evm_key_ops); 10266dbc325SMimi Zohar if (!evm_init_tpm || IS_ERR(evm_init_tpm)) 10366dbc325SMimi Zohar error = -EFAULT; 10466dbc325SMimi Zohar return error; 10566dbc325SMimi Zohar } 106