* Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
* <dmitry.kasatkin@intel.com>
* <d.kasatkin@samsung.com>
+ * Pawel Polawski <p.polawski@samsung.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* then also delete it in the license file.
*
* File: libimaevm.c
- * IMA/EVM library
+ * IMA/EVM library
*/
/* should we use logger instead for library? */
#include <sys/param.h>
#include <sys/stat.h>
#include <asm/byteorder.h>
+#include <attr/xattr.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
return params.x509 ? sign_hash_v2(hashalgo, hash, size, keyfile, sig) :
sign_hash_v1(hashalgo, hash, size, keyfile, sig);
}
+
+#define IMA_STATE_PATH "/sys/kernel/security/ima/ima_state"
+#define IMA_XATTR "security.ima"
+
+#define EVM_STATE_PATH "/sys/kernel/security/evm/evm_state"
+#define EVM_XATTR "security.evm"
+
+int ima_get_state(int *state)
+{
+ int fd;
+ char buff;
+
+ if (!state) {
+ log_err("Error input param\n");
+ return LIB_ERROR_INPUT_PARAM;
+ }
+
+ fd = open(IMA_STATE_PATH, O_RDONLY);
+ if (fd < 0) {
+ log_err("Unable to open file\n");
+ return LIB_ERROR_SYSCALL;
+ }
+
+ if (read(fd, &buff, sizeof(buff)) < 0) {
+ log_err("Unable to read file\n");
+ close(fd);
+ return LIB_ERROR_SYSCALL;
+ }
+
+ close(fd);
+
+ switch (buff) {
+ case '0':
+ *state = IMA_STATE_DISABLED;
+ return LIB_SUCCESS;
+ case '1':
+ *state = IMA_STATE_ENABLED;
+ return LIB_SUCCESS;
+ case '2':
+ *state = IMA_STATE_FIX;
+ return LIB_SUCCESS;
+ default:
+ log_err("Unknown IMA state\n");
+ return LIB_ERROR_UNKNOWN;
+ }
+}
+
+int ima_set_state(int state)
+{
+ char buff;
+
+ int fd = open(IMA_STATE_PATH, O_RDWR);
+ if (fd < 0) {
+ log_err("Unable to open file\n");
+ return LIB_ERROR_SYSCALL;
+ }
+
+ switch (state) {
+ case IMA_STATE_DISABLED:
+ buff = '0';
+ break;
+ case IMA_STATE_ENABLED:
+ buff = '1';
+ break;
+ case IMA_STATE_FIX:
+ buff = '2';
+ break;
+ default:
+ log_err("Wrong IMA state\n");
+ close(fd);
+ return LIB_ERROR_UNKNOWN;
+ }
+
+ if (write(fd, &buff, sizeof(buff)) < 0) {
+ log_err("Unable to write file\n");
+ close(fd);
+ return LIB_ERROR_SYSCALL;
+ }
+
+ close(fd);
+ return LIB_SUCCESS;
+}
+
+int evm_get_state(int *state)
+{
+ int fd;
+ char buff;
+
+ if (!state) {
+ log_err("Error input param\n");
+ return LIB_ERROR_INPUT_PARAM;
+ }
+
+ fd = open(EVM_STATE_PATH, O_RDONLY);
+ if (fd < 0) {
+ log_err("Unable to open file\n");
+ return LIB_ERROR_SYSCALL;
+ }
+
+ if (read(fd, &buff, sizeof(buff)) < 0) {
+ log_err("Unable to read file\n");
+ close(fd);
+ return LIB_ERROR_SYSCALL;
+ }
+
+ close(fd);
+
+ switch (buff) {
+ case '0':
+ *state = EVM_STATE_DISABLED;
+ return LIB_SUCCESS;
+ case '1':
+ *state = EVM_STATE_ENABLED;
+ return LIB_SUCCESS;
+ case '2':
+ *state = EVM_STATE_FIX;
+ return LIB_SUCCESS;
+ default:
+ log_err("Unknown EVM state\n");
+ return LIB_ERROR_UNKNOWN;
+ }
+}
+
+int evm_set_state(int state)
+{
+ char buff;
+
+ int fd = open(EVM_STATE_PATH, O_RDWR);
+ if (fd < 0) {
+ log_err("Unable to open file\n");
+ return LIB_ERROR_SYSCALL;
+ }
+
+ switch (state) {
+ case EVM_STATE_DISABLED:
+ buff = '0';
+ break;
+ case EVM_STATE_ENABLED:
+ buff = '1';
+ break;
+ case EVM_STATE_FIX:
+ buff = '2';
+ break;
+ default:
+ log_err("Wrong EVM state\n");
+ close(fd);
+ return LIB_ERROR_UNKNOWN;
+ }
+
+ if (write(fd, &buff, sizeof(buff)) < 0) {
+ log_err("Unable to write file\n");
+ close(fd);
+ return LIB_ERROR_SYSCALL;
+ }
+
+ close(fd);
+ return LIB_SUCCESS;
+}
+
+int ima_set_xattr(const char *path)
+{
+ int ret;
+
+ if (!path) {
+ log_err("Error input param\n");
+ return LIB_ERROR_INPUT_PARAM;
+ }
+
+ ret = setxattr(path, IMA_XATTR, hash, strlen(hash), 0);
+ if (ret < 0) {
+ log_err("Unable to set xattr\n");
+ return LIB_ERROR_SYSCALL;
+ }
+
+ return LIB_SUCCESS;
+}
+
+int ima_get_xattr(const char *path, char **hash)
+{
+ int ret;
+
+ if (!path || !hash) {
+ log_err("Error input param\n");
+ return LIB_ERROR_INPUT_PARAM;
+ }
+
+ //read xattr size only
+ ret = getxattr(path, IMA_XATTR, NULL, 0);
+ if (ret < 0) {
+ if (errno == ENOATTR) {
+ log_err("Missing attribute or no access\n");
+ return LIB_ERROR_ATTRIBUTE;
+ }
+ log_err("Error in read xattr\n");
+ return LIB_ERROR_SYSCALL;
+ }
+
+ *hash = calloc(ret + 1, sizeof(char));
+ if (!(*hash)) {
+ log_err("Allocation error\n");
+ return LIB_ERROR_MEMORY;
+ }
+
+ ret = getxattr(path, IMA_XATTR, *hash, ret);
+ if (ret < 0) {
+ if (errno == ENOATTR) {
+ log_err("Missing attribute or no access\n");
+ return LIB_ERROR_ATTRIBUTE;
+ }
+ log_err("Error in read xattr\n");
+ free(*hash);
+ return LIB_ERROR_SYSCALL;
+ }
+
+ return LIB_SUCCESS;
+}
+
+int evm_set_xattr(const char *path, const char *evm)
+{
+ int ret;
+
+ if (!path || !evm) {
+ log_err("Error input param\n");
+ return LIB_ERROR_INPUT_PARAM;
+ }
+
+ ret = setxattr(path, EVM_XATTR, evm, strlen(evm), 0);
+ if (ret < 0) {
+ log_err("Unable to set xattr\n");
+ return LIB_ERROR_SYSCALL;
+ }
+
+ return LIB_SUCCESS;
+}
+
+int evm_get_xattr(const char *path, char **hash)
+{
+ int ret;
+
+ if (!path || !hash) {
+ log_err("Error input param\n");
+ return LIB_ERROR_INPUT_PARAM;
+ }
+
+ //read xattr size only
+ ret = getxattr(path, EVM_XATTR, NULL, 0);
+ if (ret < 0) {
+ if (errno == ENOATTR) {
+ log_err("Missing attribute or no access\n");
+ return LIB_ERROR_ATTRIBUTE;
+ }
+ log_err("Error in read xattr\n");
+ return LIB_ERROR_SYSCALL;
+ }
+
+ *hash = calloc(ret + 1, sizeof(char));
+ if (!(*hash)) {
+ log_err("Allocation error\n");
+ return LIB_ERROR_MEMORY;
+ }
+
+ ret = getxattr(path, EVM_XATTR, *hash, ret);
+ if (ret < 0) {
+ if (errno == ENOATTR) {
+ log_err("Missing attribute or no access\n");
+ return LIB_ERROR_ATTRIBUTE;
+ }
+ log_err("Error in read xattr\n");
+ free(*hash);
+ return LIB_ERROR_SYSCALL;
+ }
+
+ return LIB_SUCCESS;
+}