linux/security/integrity/digsig.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2011 Intel Corporation
   3 *
   4 * Author:
   5 * Dmitry Kasatkin <dmitry.kasatkin@intel.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation, version 2 of the License.
  10 *
  11 */
  12
  13#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  14
  15#include <linux/err.h>
  16#include <linux/sched.h>
  17#include <linux/slab.h>
  18#include <linux/cred.h>
  19#include <linux/key-type.h>
  20#include <linux/digsig.h>
  21
  22#include "integrity.h"
  23
  24static struct key *keyring[INTEGRITY_KEYRING_MAX];
  25
  26static const char *keyring_name[INTEGRITY_KEYRING_MAX] = {
  27        "_evm",
  28        "_module",
  29#ifndef CONFIG_IMA_TRUSTED_KEYRING
  30        "_ima",
  31#else
  32        ".ima",
  33#endif
  34};
  35
  36int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
  37                            const char *digest, int digestlen)
  38{
  39        if (id >= INTEGRITY_KEYRING_MAX)
  40                return -EINVAL;
  41
  42        if (!keyring[id]) {
  43                keyring[id] =
  44                        request_key(&key_type_keyring, keyring_name[id], NULL);
  45                if (IS_ERR(keyring[id])) {
  46                        int err = PTR_ERR(keyring[id]);
  47                        pr_err("no %s keyring: %d\n", keyring_name[id], err);
  48                        keyring[id] = NULL;
  49                        return err;
  50                }
  51        }
  52
  53        switch (sig[1]) {
  54        case 1:
  55                /* v1 API expect signature without xattr type */
  56                return digsig_verify(keyring[id], sig + 1, siglen - 1,
  57                                     digest, digestlen);
  58        case 2:
  59                return asymmetric_verify(keyring[id], sig, siglen,
  60                                         digest, digestlen);
  61        }
  62
  63        return -EOPNOTSUPP;
  64}
  65
  66int __init integrity_init_keyring(const unsigned int id)
  67{
  68        const struct cred *cred = current_cred();
  69        int err = 0;
  70
  71        keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0),
  72                                    KGIDT_INIT(0), cred,
  73                                    ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
  74                                     KEY_USR_VIEW | KEY_USR_READ |
  75                                     KEY_USR_WRITE | KEY_USR_SEARCH),
  76                                    KEY_ALLOC_NOT_IN_QUOTA, NULL);
  77        if (!IS_ERR(keyring[id]))
  78                set_bit(KEY_FLAG_TRUSTED_ONLY, &keyring[id]->flags);
  79        else {
  80                err = PTR_ERR(keyring[id]);
  81                pr_info("Can't allocate %s keyring (%d)\n",
  82                        keyring_name[id], err);
  83                keyring[id] = NULL;
  84        }
  85        return err;
  86}
  87
  88int __init integrity_load_x509(const unsigned int id, const char *path)
  89{
  90        key_ref_t key;
  91        char *data;
  92        int rc;
  93
  94        if (!keyring[id])
  95                return -EINVAL;
  96
  97        rc = integrity_read_file(path, &data);
  98        if (rc < 0)
  99                return rc;
 100
 101        key = key_create_or_update(make_key_ref(keyring[id], 1),
 102                                   "asymmetric",
 103                                   NULL,
 104                                   data,
 105                                   rc,
 106                                   ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
 107                                    KEY_USR_VIEW | KEY_USR_READ),
 108                                   KEY_ALLOC_NOT_IN_QUOTA | KEY_ALLOC_TRUSTED);
 109        if (IS_ERR(key)) {
 110                rc = PTR_ERR(key);
 111                pr_err("Problem loading X.509 certificate (%d): %s\n",
 112                       rc, path);
 113        } else {
 114                pr_notice("Loaded X.509 cert '%s': %s\n",
 115                          key_ref_to_ptr(key)->description, path);
 116                key_ref_put(key);
 117        }
 118        kfree(data);
 119        return 0;
 120}
 121