FILE
trusted_caam.c
File preview with syntax highlighting.
linux-6.19.14/security/keys/trusted-keys/trusted_caam.c
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) 2021 Pengutronix, Ahmad Fatoum <kernel@pengutronix.de> 4 * Copyright 2025 NXP 5 */ 6 7#include <keys/trusted_caam.h> 8#include <keys/trusted-type.h> 9#include <linux/build_bug.h> 10#include <linux/key-type.h> 11#include <linux/parser.h> 12#include <soc/fsl/caam-blob.h> 13 14static struct caam_blob_priv *blobifier; 15 16#define KEYMOD "SECURE_KEY" 17 18static_assert(MAX_KEY_SIZE + CAAM_BLOB_OVERHEAD <= CAAM_BLOB_MAX_LEN); 19static_assert(MAX_BLOB_SIZE <= CAAM_BLOB_MAX_LEN); 20 21enum { 22 opt_err, 23 opt_key_enc_algo, 24}; 25 26static const match_table_t key_tokens = { 27 {opt_key_enc_algo, "key_enc_algo=%s"}, 28 {opt_err, NULL} 29}; 30 31#ifdef CAAM_DEBUG 32static inline void dump_options(const struct caam_pkey_info *pkey_info) 33{ 34 pr_info("key encryption algo %d\n", pkey_info->key_enc_algo); 35} 36#else 37static inline void dump_options(const struct caam_pkey_info *pkey_info) 38{ 39} 40#endif 41 42static int get_pkey_options(char *c, 43 struct caam_pkey_info *pkey_info) 44{ 45 substring_t args[MAX_OPT_ARGS]; 46 unsigned long token_mask = 0; 47 u16 key_enc_algo; 48 char *p = c; 49 int token; 50 int res; 51 52 if (!c) 53 return 0; 54 55 while ((p = strsep(&c, " \t"))) { 56 if (*p == '\0' || *p == ' ' || *p == '\t') 57 continue; 58 token = match_token(p, key_tokens, args); 59 if (test_and_set_bit(token, &token_mask)) 60 return -EINVAL; 61 62 switch (token) { 63 case opt_key_enc_algo: 64 res = kstrtou16(args[0].from, 16, &key_enc_algo); 65 if (res < 0) 66 return -EINVAL; 67 pkey_info->key_enc_algo = key_enc_algo; 68 break; 69 default: 70 return -EINVAL; 71 } 72 } 73 return 0; 74} 75 76static bool is_key_pkey(char **datablob) 77{ 78 char *c = NULL; 79 80 do { 81 /* Second argument onwards, 82 * determine if tied to HW 83 */ 84 c = strsep(datablob, " \t"); 85 if (c && (strcmp(c, "pk") == 0)) 86 return true; 87 } while (c); 88 89 return false; 90} 91 92static int trusted_caam_seal(struct trusted_key_payload *p, char *datablob) 93{ 94 int ret; 95 struct caam_blob_info info = { 96 .input = p->key, .input_len = p->key_len, 97 .output = p->blob, .output_len = MAX_BLOB_SIZE, 98 .key_mod = KEYMOD, .key_mod_len = sizeof(KEYMOD) - 1, 99 }; 100 101 /* 102 * If it is to be treated as protected key, 103 * read next arguments too. 104 */ 105 if (is_key_pkey(&datablob)) { 106 info.pkey_info.plain_key_sz = p->key_len; 107 info.pkey_info.is_pkey = 1; 108 ret = get_pkey_options(datablob, &info.pkey_info); 109 if (ret < 0) 110 return 0; 111 dump_options(&info.pkey_info); 112 } 113 114 ret = caam_encap_blob(blobifier, &info); 115 if (ret) 116 return ret; 117 118 p->blob_len = info.output_len; 119 if (info.pkey_info.is_pkey) { 120 p->key_len = p->blob_len + sizeof(struct caam_pkey_info); 121 memcpy(p->key, &info.pkey_info, sizeof(struct caam_pkey_info)); 122 memcpy(p->key + sizeof(struct caam_pkey_info), p->blob, p->blob_len); 123 } 124 125 return 0; 126} 127 128static int trusted_caam_unseal(struct trusted_key_payload *p, char *datablob) 129{ 130 int ret; 131 struct caam_blob_info info = { 132 .input = p->blob, .input_len = p->blob_len, 133 .output = p->key, .output_len = MAX_KEY_SIZE, 134 .key_mod = KEYMOD, .key_mod_len = sizeof(KEYMOD) - 1, 135 }; 136 137 if (is_key_pkey(&datablob)) { 138 info.pkey_info.plain_key_sz = p->blob_len - CAAM_BLOB_OVERHEAD; 139 info.pkey_info.is_pkey = 1; 140 ret = get_pkey_options(datablob, &info.pkey_info); 141 if (ret < 0) 142 return 0; 143 dump_options(&info.pkey_info); 144 145 p->key_len = p->blob_len + sizeof(struct caam_pkey_info); 146 memcpy(p->key, &info.pkey_info, sizeof(struct caam_pkey_info)); 147 memcpy(p->key + sizeof(struct caam_pkey_info), p->blob, p->blob_len); 148 149 return 0; 150 } 151 152 ret = caam_decap_blob(blobifier, &info); 153 if (ret) 154 return ret; 155 156 p->key_len = info.output_len; 157 158 return 0; 159} 160 161static int trusted_caam_init(void) 162{ 163 int ret; 164 165 blobifier = caam_blob_gen_init(); 166 if (IS_ERR(blobifier)) 167 return PTR_ERR(blobifier); 168 169 ret = register_key_type(&key_type_trusted); 170 if (ret) 171 caam_blob_gen_exit(blobifier); 172 173 return ret; 174} 175 176static void trusted_caam_exit(void) 177{ 178 unregister_key_type(&key_type_trusted); 179 caam_blob_gen_exit(blobifier); 180} 181 182struct trusted_key_ops trusted_key_caam_ops = { 183 .migratable = 0, /* non-migratable */ 184 .init = trusted_caam_init, 185 .seal = trusted_caam_seal, 186 .unseal = trusted_caam_unseal, 187 .exit = trusted_caam_exit, 188};
~/
Read-only file preview.