Path: blob/master/security/keys/trusted-keys/trusted_pkwm.c
121833 views
// SPDX-License-Identifier: GPL-2.0-only1/*2* Copyright (C) 2025 IBM Corporation, Srish Srinivasan <[email protected]>3*/45#include <keys/trusted_pkwm.h>6#include <keys/trusted-type.h>7#include <linux/build_bug.h>8#include <linux/key-type.h>9#include <linux/parser.h>10#include <asm/plpks.h>1112enum {13Opt_err,14Opt_wrap_flags,15};1617static const match_table_t key_tokens = {18{Opt_wrap_flags, "wrap_flags=%s"},19{Opt_err, NULL}20};2122static int getoptions(char *datablob, struct trusted_key_options *opt)23{24substring_t args[MAX_OPT_ARGS];25char *p = datablob;26int token;27int res;28u16 wrap_flags;29unsigned long token_mask = 0;30struct trusted_pkwm_options *pkwm;3132if (!datablob)33return 0;3435pkwm = opt->private;3637while ((p = strsep(&datablob, " \t"))) {38if (*p == '\0' || *p == ' ' || *p == '\t')39continue;4041token = match_token(p, key_tokens, args);42if (test_and_set_bit(token, &token_mask))43return -EINVAL;4445switch (token) {46case Opt_wrap_flags:47res = kstrtou16(args[0].from, 16, &wrap_flags);48if (res < 0 || wrap_flags > 2)49return -EINVAL;50pkwm->wrap_flags = wrap_flags;51break;52default:53return -EINVAL;54}55}56return 0;57}5859static struct trusted_key_options *trusted_options_alloc(void)60{61struct trusted_key_options *options;62struct trusted_pkwm_options *pkwm;6364options = kzalloc_obj(*options);6566if (options) {67pkwm = kzalloc_obj(*pkwm);6869if (!pkwm) {70kfree_sensitive(options);71options = NULL;72} else {73options->private = pkwm;74}75}7677return options;78}7980static int trusted_pkwm_seal(struct trusted_key_payload *p, char *datablob)81{82struct trusted_key_options *options = NULL;83struct trusted_pkwm_options *pkwm = NULL;84u8 *input_buf, *output_buf;85u32 output_len, input_len;86int rc;8788options = trusted_options_alloc();8990if (!options)91return -ENOMEM;9293rc = getoptions(datablob, options);94if (rc < 0)95goto out;96dump_options(options);9798input_len = p->key_len;99input_buf = kmalloc(ALIGN(input_len, 4096), GFP_KERNEL);100if (!input_buf) {101pr_err("Input buffer allocation failed. Returning -ENOMEM.");102rc = -ENOMEM;103goto out;104}105106memcpy(input_buf, p->key, p->key_len);107108pkwm = options->private;109110rc = plpks_wrap_object(&input_buf, input_len, pkwm->wrap_flags,111&output_buf, &output_len);112if (!rc) {113memcpy(p->blob, output_buf, output_len);114p->blob_len = output_len;115dump_payload(p);116} else {117pr_err("Wrapping of payload key failed: %d\n", rc);118}119120kfree(input_buf);121kfree(output_buf);122123out:124kfree_sensitive(options->private);125kfree_sensitive(options);126return rc;127}128129static int trusted_pkwm_unseal(struct trusted_key_payload *p, char *datablob)130{131u8 *input_buf, *output_buf;132u32 input_len, output_len;133int rc;134135input_len = p->blob_len;136input_buf = kmalloc(ALIGN(input_len, 4096), GFP_KERNEL);137if (!input_buf) {138pr_err("Input buffer allocation failed. Returning -ENOMEM.");139return -ENOMEM;140}141142memcpy(input_buf, p->blob, p->blob_len);143144rc = plpks_unwrap_object(&input_buf, input_len, &output_buf,145&output_len);146if (!rc) {147memcpy(p->key, output_buf, output_len);148p->key_len = output_len;149dump_payload(p);150} else {151pr_err("Unwrapping of payload failed: %d\n", rc);152}153154kfree(input_buf);155kfree(output_buf);156157return rc;158}159160static int trusted_pkwm_init(void)161{162int ret;163164if (!plpks_wrapping_is_supported()) {165pr_err("H_PKS_WRAP_OBJECT interface not supported\n");166return -ENODEV;167}168169ret = plpks_gen_wrapping_key();170if (ret) {171pr_err("Failed to generate default wrapping key\n");172return -EINVAL;173}174175return register_key_type(&key_type_trusted);176}177178static void trusted_pkwm_exit(void)179{180unregister_key_type(&key_type_trusted);181}182183struct trusted_key_ops pkwm_trusted_key_ops = {184.migratable = 0, /* non-migratable */185.init = trusted_pkwm_init,186.seal = trusted_pkwm_seal,187.unseal = trusted_pkwm_unseal,188.exit = trusted_pkwm_exit,189};190191192