Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * POWER LPAR Platform KeyStore(PLPKS)
0004  * Copyright (C) 2022 IBM Corporation
0005  * Author: Nayna Jain <nayna@linux.ibm.com>
0006  *
0007  * Provides access to variables stored in Power LPAR Platform KeyStore(PLPKS).
0008  */
0009 
0010 #define pr_fmt(fmt) "plpks: " fmt
0011 
0012 #include <linux/delay.h>
0013 #include <linux/errno.h>
0014 #include <linux/io.h>
0015 #include <linux/printk.h>
0016 #include <linux/slab.h>
0017 #include <linux/string.h>
0018 #include <linux/types.h>
0019 #include <asm/hvcall.h>
0020 #include <asm/machdep.h>
0021 
0022 #include "plpks.h"
0023 
0024 #define PKS_FW_OWNER         0x1
0025 #define PKS_BOOTLOADER_OWNER 0x2
0026 #define PKS_OS_OWNER         0x3
0027 
0028 #define LABEL_VERSION       0
0029 #define MAX_LABEL_ATTR_SIZE 16
0030 #define MAX_NAME_SIZE       239
0031 #define MAX_DATA_SIZE       4000
0032 
0033 #define PKS_FLUSH_MAX_TIMEOUT 5000 //msec
0034 #define PKS_FLUSH_SLEEP       10 //msec
0035 #define PKS_FLUSH_SLEEP_RANGE 400
0036 
0037 static u8 *ospassword;
0038 static u16 ospasswordlength;
0039 
0040 // Retrieved with H_PKS_GET_CONFIG
0041 static u16 maxpwsize;
0042 static u16 maxobjsize;
0043 
0044 struct plpks_auth {
0045     u8 version;
0046     u8 consumer;
0047     __be64 rsvd0;
0048     __be32 rsvd1;
0049     __be16 passwordlength;
0050     u8 password[];
0051 } __packed __aligned(16);
0052 
0053 struct label_attr {
0054     u8 prefix[8];
0055     u8 version;
0056     u8 os;
0057     u8 length;
0058     u8 reserved[5];
0059 };
0060 
0061 struct label {
0062     struct label_attr attr;
0063     u8 name[MAX_NAME_SIZE];
0064     size_t size;
0065 };
0066 
0067 static int pseries_status_to_err(int rc)
0068 {
0069     int err;
0070 
0071     switch (rc) {
0072     case H_SUCCESS:
0073         err = 0;
0074         break;
0075     case H_FUNCTION:
0076         err = -ENXIO;
0077         break;
0078     case H_P1:
0079     case H_P2:
0080     case H_P3:
0081     case H_P4:
0082     case H_P5:
0083     case H_P6:
0084         err = -EINVAL;
0085         break;
0086     case H_NOT_FOUND:
0087         err = -ENOENT;
0088         break;
0089     case H_BUSY:
0090         err = -EBUSY;
0091         break;
0092     case H_AUTHORITY:
0093         err = -EPERM;
0094         break;
0095     case H_NO_MEM:
0096         err = -ENOMEM;
0097         break;
0098     case H_RESOURCE:
0099         err = -EEXIST;
0100         break;
0101     case H_TOO_BIG:
0102         err = -EFBIG;
0103         break;
0104     case H_STATE:
0105         err = -EIO;
0106         break;
0107     case H_R_STATE:
0108         err = -EIO;
0109         break;
0110     case H_IN_USE:
0111         err = -EEXIST;
0112         break;
0113     case H_ABORTED:
0114         err = -EINTR;
0115         break;
0116     default:
0117         err = -EINVAL;
0118     }
0119 
0120     return err;
0121 }
0122 
0123 static int plpks_gen_password(void)
0124 {
0125     unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 };
0126     u8 *password, consumer = PKS_OS_OWNER;
0127     int rc;
0128 
0129     password = kzalloc(maxpwsize, GFP_KERNEL);
0130     if (!password)
0131         return -ENOMEM;
0132 
0133     rc = plpar_hcall(H_PKS_GEN_PASSWORD, retbuf, consumer, 0,
0134              virt_to_phys(password), maxpwsize);
0135 
0136     if (!rc) {
0137         ospasswordlength = maxpwsize;
0138         ospassword = kzalloc(maxpwsize, GFP_KERNEL);
0139         if (!ospassword) {
0140             kfree(password);
0141             return -ENOMEM;
0142         }
0143         memcpy(ospassword, password, ospasswordlength);
0144     } else {
0145         if (rc == H_IN_USE) {
0146             pr_warn("Password is already set for POWER LPAR Platform KeyStore\n");
0147             rc = 0;
0148         } else {
0149             goto out;
0150         }
0151     }
0152 out:
0153     kfree(password);
0154 
0155     return pseries_status_to_err(rc);
0156 }
0157 
0158 static struct plpks_auth *construct_auth(u8 consumer)
0159 {
0160     struct plpks_auth *auth;
0161 
0162     if (consumer > PKS_OS_OWNER)
0163         return ERR_PTR(-EINVAL);
0164 
0165     auth = kmalloc(struct_size(auth, password, maxpwsize), GFP_KERNEL);
0166     if (!auth)
0167         return ERR_PTR(-ENOMEM);
0168 
0169     auth->version = 1;
0170     auth->consumer = consumer;
0171     auth->rsvd0 = 0;
0172     auth->rsvd1 = 0;
0173 
0174     if (consumer == PKS_FW_OWNER || consumer == PKS_BOOTLOADER_OWNER) {
0175         auth->passwordlength = 0;
0176         return auth;
0177     }
0178 
0179     memcpy(auth->password, ospassword, ospasswordlength);
0180 
0181     auth->passwordlength = cpu_to_be16(ospasswordlength);
0182 
0183     return auth;
0184 }
0185 
0186 /**
0187  * Label is combination of label attributes + name.
0188  * Label attributes are used internally by kernel and not exposed to the user.
0189  */
0190 static struct label *construct_label(char *component, u8 varos, u8 *name,
0191                      u16 namelen)
0192 {
0193     struct label *label;
0194     size_t slen;
0195 
0196     if (!name || namelen > MAX_NAME_SIZE)
0197         return ERR_PTR(-EINVAL);
0198 
0199     slen = strlen(component);
0200     if (component && slen > sizeof(label->attr.prefix))
0201         return ERR_PTR(-EINVAL);
0202 
0203     label = kzalloc(sizeof(*label), GFP_KERNEL);
0204     if (!label)
0205         return ERR_PTR(-ENOMEM);
0206 
0207     if (component)
0208         memcpy(&label->attr.prefix, component, slen);
0209 
0210     label->attr.version = LABEL_VERSION;
0211     label->attr.os = varos;
0212     label->attr.length = MAX_LABEL_ATTR_SIZE;
0213     memcpy(&label->name, name, namelen);
0214 
0215     label->size = sizeof(struct label_attr) + namelen;
0216 
0217     return label;
0218 }
0219 
0220 static int _plpks_get_config(void)
0221 {
0222     unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 };
0223     struct {
0224         u8 version;
0225         u8 flags;
0226         __be32 rsvd0;
0227         __be16 maxpwsize;
0228         __be16 maxobjlabelsize;
0229         __be16 maxobjsize;
0230         __be32 totalsize;
0231         __be32 usedspace;
0232         __be32 supportedpolicies;
0233         __be64 rsvd1;
0234     } __packed config;
0235     size_t size;
0236     int rc;
0237 
0238     size = sizeof(config);
0239 
0240     rc = plpar_hcall(H_PKS_GET_CONFIG, retbuf, virt_to_phys(&config), size);
0241 
0242     if (rc != H_SUCCESS)
0243         return pseries_status_to_err(rc);
0244 
0245     maxpwsize = be16_to_cpu(config.maxpwsize);
0246     maxobjsize = be16_to_cpu(config.maxobjsize);
0247 
0248     return 0;
0249 }
0250 
0251 static int plpks_confirm_object_flushed(struct label *label,
0252                     struct plpks_auth *auth)
0253 {
0254     unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 };
0255     u64 timeout = 0;
0256     u8 status;
0257     int rc;
0258 
0259     do {
0260         rc = plpar_hcall(H_PKS_CONFIRM_OBJECT_FLUSHED, retbuf,
0261                  virt_to_phys(auth), virt_to_phys(label),
0262                  label->size);
0263 
0264         status = retbuf[0];
0265         if (rc) {
0266             if (rc == H_NOT_FOUND && status == 1)
0267                 rc = 0;
0268             break;
0269         }
0270 
0271         if (!rc && status == 1)
0272             break;
0273 
0274         usleep_range(PKS_FLUSH_SLEEP,
0275                  PKS_FLUSH_SLEEP + PKS_FLUSH_SLEEP_RANGE);
0276         timeout = timeout + PKS_FLUSH_SLEEP;
0277     } while (timeout < PKS_FLUSH_MAX_TIMEOUT);
0278 
0279     rc = pseries_status_to_err(rc);
0280 
0281     return rc;
0282 }
0283 
0284 int plpks_write_var(struct plpks_var var)
0285 {
0286     unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 };
0287     struct plpks_auth *auth;
0288     struct label *label;
0289     int rc;
0290 
0291     if (!var.component || !var.data || var.datalen <= 0 ||
0292         var.namelen > MAX_NAME_SIZE || var.datalen > MAX_DATA_SIZE)
0293         return -EINVAL;
0294 
0295     if (var.policy & SIGNEDUPDATE)
0296         return -EINVAL;
0297 
0298     auth = construct_auth(PKS_OS_OWNER);
0299     if (IS_ERR(auth))
0300         return PTR_ERR(auth);
0301 
0302     label = construct_label(var.component, var.os, var.name, var.namelen);
0303     if (IS_ERR(label)) {
0304         rc = PTR_ERR(label);
0305         goto out;
0306     }
0307 
0308     rc = plpar_hcall(H_PKS_WRITE_OBJECT, retbuf, virt_to_phys(auth),
0309              virt_to_phys(label), label->size, var.policy,
0310              virt_to_phys(var.data), var.datalen);
0311 
0312     if (!rc)
0313         rc = plpks_confirm_object_flushed(label, auth);
0314 
0315     if (rc)
0316         pr_err("Failed to write variable %s for component %s with error %d\n",
0317                var.name, var.component, rc);
0318 
0319     rc = pseries_status_to_err(rc);
0320     kfree(label);
0321 out:
0322     kfree(auth);
0323 
0324     return rc;
0325 }
0326 
0327 int plpks_remove_var(char *component, u8 varos, struct plpks_var_name vname)
0328 {
0329     unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 };
0330     struct plpks_auth *auth;
0331     struct label *label;
0332     int rc;
0333 
0334     if (!component || vname.namelen > MAX_NAME_SIZE)
0335         return -EINVAL;
0336 
0337     auth = construct_auth(PKS_OS_OWNER);
0338     if (IS_ERR(auth))
0339         return PTR_ERR(auth);
0340 
0341     label = construct_label(component, varos, vname.name, vname.namelen);
0342     if (IS_ERR(label)) {
0343         rc = PTR_ERR(label);
0344         goto out;
0345     }
0346 
0347     rc = plpar_hcall(H_PKS_REMOVE_OBJECT, retbuf, virt_to_phys(auth),
0348              virt_to_phys(label), label->size);
0349 
0350     if (!rc)
0351         rc = plpks_confirm_object_flushed(label, auth);
0352 
0353     if (rc)
0354         pr_err("Failed to remove variable %s for component %s with error %d\n",
0355                vname.name, component, rc);
0356 
0357     rc = pseries_status_to_err(rc);
0358     kfree(label);
0359 out:
0360     kfree(auth);
0361 
0362     return rc;
0363 }
0364 
0365 static int plpks_read_var(u8 consumer, struct plpks_var *var)
0366 {
0367     unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 };
0368     struct plpks_auth *auth;
0369     struct label *label;
0370     u8 *output;
0371     int rc;
0372 
0373     if (var->namelen > MAX_NAME_SIZE)
0374         return -EINVAL;
0375 
0376     auth = construct_auth(PKS_OS_OWNER);
0377     if (IS_ERR(auth))
0378         return PTR_ERR(auth);
0379 
0380     label = construct_label(var->component, var->os, var->name,
0381                 var->namelen);
0382     if (IS_ERR(label)) {
0383         rc = PTR_ERR(label);
0384         goto out_free_auth;
0385     }
0386 
0387     output = kzalloc(maxobjsize, GFP_KERNEL);
0388     if (!output) {
0389         rc = -ENOMEM;
0390         goto out_free_label;
0391     }
0392 
0393     rc = plpar_hcall(H_PKS_READ_OBJECT, retbuf, virt_to_phys(auth),
0394              virt_to_phys(label), label->size, virt_to_phys(output),
0395              maxobjsize);
0396 
0397     if (rc != H_SUCCESS) {
0398         pr_err("Failed to read variable %s for component %s with error %d\n",
0399                var->name, var->component, rc);
0400         rc = pseries_status_to_err(rc);
0401         goto out_free_output;
0402     }
0403 
0404     if (var->datalen == 0 || var->datalen > retbuf[0])
0405         var->datalen = retbuf[0];
0406 
0407     var->data = kzalloc(var->datalen, GFP_KERNEL);
0408     if (!var->data) {
0409         rc = -ENOMEM;
0410         goto out_free_output;
0411     }
0412     var->policy = retbuf[1];
0413 
0414     memcpy(var->data, output, var->datalen);
0415     rc = 0;
0416 
0417 out_free_output:
0418     kfree(output);
0419 out_free_label:
0420     kfree(label);
0421 out_free_auth:
0422     kfree(auth);
0423 
0424     return rc;
0425 }
0426 
0427 int plpks_read_os_var(struct plpks_var *var)
0428 {
0429     return plpks_read_var(PKS_OS_OWNER, var);
0430 }
0431 
0432 int plpks_read_fw_var(struct plpks_var *var)
0433 {
0434     return plpks_read_var(PKS_FW_OWNER, var);
0435 }
0436 
0437 int plpks_read_bootloader_var(struct plpks_var *var)
0438 {
0439     return plpks_read_var(PKS_BOOTLOADER_OWNER, var);
0440 }
0441 
0442 static __init int pseries_plpks_init(void)
0443 {
0444     int rc;
0445 
0446     rc = _plpks_get_config();
0447 
0448     if (rc) {
0449         pr_err("POWER LPAR Platform KeyStore is not supported or enabled\n");
0450         return rc;
0451     }
0452 
0453     rc = plpks_gen_password();
0454     if (rc)
0455         pr_err("Failed setting POWER LPAR Platform KeyStore Password\n");
0456     else
0457         pr_info("POWER LPAR Platform KeyStore initialized successfully\n");
0458 
0459     return rc;
0460 }
0461 machine_arch_initcall(pseries, pseries_plpks_init);