Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Turris Mox rWTM firmware driver
0004  *
0005  * Copyright (C) 2019 Marek BehĂșn <kabel@kernel.org>
0006  */
0007 
0008 #include <linux/armada-37xx-rwtm-mailbox.h>
0009 #include <linux/completion.h>
0010 #include <linux/debugfs.h>
0011 #include <linux/dma-mapping.h>
0012 #include <linux/hw_random.h>
0013 #include <linux/mailbox_client.h>
0014 #include <linux/module.h>
0015 #include <linux/mutex.h>
0016 #include <linux/of.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/slab.h>
0019 
0020 #define DRIVER_NAME     "turris-mox-rwtm"
0021 
0022 /*
0023  * The macros and constants below come from Turris Mox's rWTM firmware code.
0024  * This firmware is open source and it's sources can be found at
0025  * https://gitlab.labs.nic.cz/turris/mox-boot-builder/tree/master/wtmi.
0026  */
0027 
0028 #define MBOX_STS_SUCCESS    (0 << 30)
0029 #define MBOX_STS_FAIL       (1 << 30)
0030 #define MBOX_STS_BADCMD     (2 << 30)
0031 #define MBOX_STS_ERROR(s)   ((s) & (3 << 30))
0032 #define MBOX_STS_VALUE(s)   (((s) >> 10) & 0xfffff)
0033 #define MBOX_STS_CMD(s)     ((s) & 0x3ff)
0034 
0035 enum mbox_cmd {
0036     MBOX_CMD_GET_RANDOM = 1,
0037     MBOX_CMD_BOARD_INFO = 2,
0038     MBOX_CMD_ECDSA_PUB_KEY  = 3,
0039     MBOX_CMD_HASH       = 4,
0040     MBOX_CMD_SIGN       = 5,
0041     MBOX_CMD_VERIFY     = 6,
0042 
0043     MBOX_CMD_OTP_READ   = 7,
0044     MBOX_CMD_OTP_WRITE  = 8,
0045 };
0046 
0047 struct mox_kobject;
0048 
0049 struct mox_rwtm {
0050     struct device *dev;
0051     struct mbox_client mbox_client;
0052     struct mbox_chan *mbox;
0053     struct mox_kobject *kobj;
0054     struct hwrng hwrng;
0055 
0056     struct armada_37xx_rwtm_rx_msg reply;
0057 
0058     void *buf;
0059     dma_addr_t buf_phys;
0060 
0061     struct mutex busy;
0062     struct completion cmd_done;
0063 
0064     /* board information */
0065     int has_board_info;
0066     u64 serial_number;
0067     int board_version, ram_size;
0068     u8 mac_address1[6], mac_address2[6];
0069 
0070     /* public key burned in eFuse */
0071     int has_pubkey;
0072     u8 pubkey[135];
0073 
0074 #ifdef CONFIG_DEBUG_FS
0075     /*
0076      * Signature process. This is currently done via debugfs, because it
0077      * does not conform to the sysfs standard "one file per attribute".
0078      * It should be rewritten via crypto API once akcipher API is available
0079      * from userspace.
0080      */
0081     struct dentry *debugfs_root;
0082     u32 last_sig[34];
0083     int last_sig_done;
0084 #endif
0085 };
0086 
0087 struct mox_kobject {
0088     struct kobject kobj;
0089     struct mox_rwtm *rwtm;
0090 };
0091 
0092 static inline struct kobject *rwtm_to_kobj(struct mox_rwtm *rwtm)
0093 {
0094     return &rwtm->kobj->kobj;
0095 }
0096 
0097 static inline struct mox_rwtm *to_rwtm(struct kobject *kobj)
0098 {
0099     return container_of(kobj, struct mox_kobject, kobj)->rwtm;
0100 }
0101 
0102 static void mox_kobj_release(struct kobject *kobj)
0103 {
0104     kfree(to_rwtm(kobj)->kobj);
0105 }
0106 
0107 static struct kobj_type mox_kobj_ktype = {
0108     .release    = mox_kobj_release,
0109     .sysfs_ops  = &kobj_sysfs_ops,
0110 };
0111 
0112 static int mox_kobj_create(struct mox_rwtm *rwtm)
0113 {
0114     rwtm->kobj = kzalloc(sizeof(*rwtm->kobj), GFP_KERNEL);
0115     if (!rwtm->kobj)
0116         return -ENOMEM;
0117 
0118     kobject_init(rwtm_to_kobj(rwtm), &mox_kobj_ktype);
0119     if (kobject_add(rwtm_to_kobj(rwtm), firmware_kobj, "turris-mox-rwtm")) {
0120         kobject_put(rwtm_to_kobj(rwtm));
0121         return -ENXIO;
0122     }
0123 
0124     rwtm->kobj->rwtm = rwtm;
0125 
0126     return 0;
0127 }
0128 
0129 #define MOX_ATTR_RO(name, format, cat)              \
0130 static ssize_t                          \
0131 name##_show(struct kobject *kobj, struct kobj_attribute *a, \
0132         char *buf)                      \
0133 {                               \
0134     struct mox_rwtm *rwtm = to_rwtm(kobj);  \
0135     if (!rwtm->has_##cat)                   \
0136         return -ENODATA;                \
0137     return sprintf(buf, format, rwtm->name);        \
0138 }                               \
0139 static struct kobj_attribute mox_attr_##name = __ATTR_RO(name)
0140 
0141 MOX_ATTR_RO(serial_number, "%016llX\n", board_info);
0142 MOX_ATTR_RO(board_version, "%i\n", board_info);
0143 MOX_ATTR_RO(ram_size, "%i\n", board_info);
0144 MOX_ATTR_RO(mac_address1, "%pM\n", board_info);
0145 MOX_ATTR_RO(mac_address2, "%pM\n", board_info);
0146 MOX_ATTR_RO(pubkey, "%s\n", pubkey);
0147 
0148 static int mox_get_status(enum mbox_cmd cmd, u32 retval)
0149 {
0150     if (MBOX_STS_CMD(retval) != cmd)
0151         return -EIO;
0152     else if (MBOX_STS_ERROR(retval) == MBOX_STS_FAIL)
0153         return -(int)MBOX_STS_VALUE(retval);
0154     else if (MBOX_STS_ERROR(retval) == MBOX_STS_BADCMD)
0155         return -ENOSYS;
0156     else if (MBOX_STS_ERROR(retval) != MBOX_STS_SUCCESS)
0157         return -EIO;
0158     else
0159         return MBOX_STS_VALUE(retval);
0160 }
0161 
0162 static const struct attribute *mox_rwtm_attrs[] = {
0163     &mox_attr_serial_number.attr,
0164     &mox_attr_board_version.attr,
0165     &mox_attr_ram_size.attr,
0166     &mox_attr_mac_address1.attr,
0167     &mox_attr_mac_address2.attr,
0168     &mox_attr_pubkey.attr,
0169     NULL
0170 };
0171 
0172 static void mox_rwtm_rx_callback(struct mbox_client *cl, void *data)
0173 {
0174     struct mox_rwtm *rwtm = dev_get_drvdata(cl->dev);
0175     struct armada_37xx_rwtm_rx_msg *msg = data;
0176 
0177     rwtm->reply = *msg;
0178     complete(&rwtm->cmd_done);
0179 }
0180 
0181 static void reply_to_mac_addr(u8 *mac, u32 t1, u32 t2)
0182 {
0183     mac[0] = t1 >> 8;
0184     mac[1] = t1;
0185     mac[2] = t2 >> 24;
0186     mac[3] = t2 >> 16;
0187     mac[4] = t2 >> 8;
0188     mac[5] = t2;
0189 }
0190 
0191 static int mox_get_board_info(struct mox_rwtm *rwtm)
0192 {
0193     struct armada_37xx_rwtm_tx_msg msg;
0194     struct armada_37xx_rwtm_rx_msg *reply = &rwtm->reply;
0195     int ret;
0196 
0197     msg.command = MBOX_CMD_BOARD_INFO;
0198     ret = mbox_send_message(rwtm->mbox, &msg);
0199     if (ret < 0)
0200         return ret;
0201 
0202     ret = wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2);
0203     if (ret < 0)
0204         return ret;
0205 
0206     ret = mox_get_status(MBOX_CMD_BOARD_INFO, reply->retval);
0207     if (ret == -ENODATA) {
0208         dev_warn(rwtm->dev,
0209              "Board does not have manufacturing information burned!\n");
0210     } else if (ret == -ENOSYS) {
0211         dev_notice(rwtm->dev,
0212                "Firmware does not support the BOARD_INFO command\n");
0213     } else if (ret < 0) {
0214         return ret;
0215     } else {
0216         rwtm->serial_number = reply->status[1];
0217         rwtm->serial_number <<= 32;
0218         rwtm->serial_number |= reply->status[0];
0219         rwtm->board_version = reply->status[2];
0220         rwtm->ram_size = reply->status[3];
0221         reply_to_mac_addr(rwtm->mac_address1, reply->status[4],
0222                   reply->status[5]);
0223         reply_to_mac_addr(rwtm->mac_address2, reply->status[6],
0224                   reply->status[7]);
0225         rwtm->has_board_info = 1;
0226 
0227         pr_info("Turris Mox serial number %016llX\n",
0228             rwtm->serial_number);
0229         pr_info("           board version %i\n", rwtm->board_version);
0230         pr_info("           burned RAM size %i MiB\n", rwtm->ram_size);
0231     }
0232 
0233     msg.command = MBOX_CMD_ECDSA_PUB_KEY;
0234     ret = mbox_send_message(rwtm->mbox, &msg);
0235     if (ret < 0)
0236         return ret;
0237 
0238     ret = wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2);
0239     if (ret < 0)
0240         return ret;
0241 
0242     ret = mox_get_status(MBOX_CMD_ECDSA_PUB_KEY, reply->retval);
0243     if (ret == -ENODATA) {
0244         dev_warn(rwtm->dev, "Board has no public key burned!\n");
0245     } else if (ret == -ENOSYS) {
0246         dev_notice(rwtm->dev,
0247                "Firmware does not support the ECDSA_PUB_KEY command\n");
0248     } else if (ret < 0) {
0249         return ret;
0250     } else {
0251         u32 *s = reply->status;
0252 
0253         rwtm->has_pubkey = 1;
0254         sprintf(rwtm->pubkey,
0255             "%06x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x",
0256             ret, s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7],
0257             s[8], s[9], s[10], s[11], s[12], s[13], s[14], s[15]);
0258     }
0259 
0260     return 0;
0261 }
0262 
0263 static int check_get_random_support(struct mox_rwtm *rwtm)
0264 {
0265     struct armada_37xx_rwtm_tx_msg msg;
0266     int ret;
0267 
0268     msg.command = MBOX_CMD_GET_RANDOM;
0269     msg.args[0] = 1;
0270     msg.args[1] = rwtm->buf_phys;
0271     msg.args[2] = 4;
0272 
0273     ret = mbox_send_message(rwtm->mbox, &msg);
0274     if (ret < 0)
0275         return ret;
0276 
0277     ret = wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2);
0278     if (ret < 0)
0279         return ret;
0280 
0281     return mox_get_status(MBOX_CMD_GET_RANDOM, rwtm->reply.retval);
0282 }
0283 
0284 static int mox_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
0285 {
0286     struct mox_rwtm *rwtm = (struct mox_rwtm *) rng->priv;
0287     struct armada_37xx_rwtm_tx_msg msg;
0288     int ret;
0289 
0290     if (max > 4096)
0291         max = 4096;
0292 
0293     msg.command = MBOX_CMD_GET_RANDOM;
0294     msg.args[0] = 1;
0295     msg.args[1] = rwtm->buf_phys;
0296     msg.args[2] = (max + 3) & ~3;
0297 
0298     if (!wait) {
0299         if (!mutex_trylock(&rwtm->busy))
0300             return -EBUSY;
0301     } else {
0302         mutex_lock(&rwtm->busy);
0303     }
0304 
0305     ret = mbox_send_message(rwtm->mbox, &msg);
0306     if (ret < 0)
0307         goto unlock_mutex;
0308 
0309     ret = wait_for_completion_interruptible(&rwtm->cmd_done);
0310     if (ret < 0)
0311         goto unlock_mutex;
0312 
0313     ret = mox_get_status(MBOX_CMD_GET_RANDOM, rwtm->reply.retval);
0314     if (ret < 0)
0315         goto unlock_mutex;
0316 
0317     memcpy(data, rwtm->buf, max);
0318     ret = max;
0319 
0320 unlock_mutex:
0321     mutex_unlock(&rwtm->busy);
0322     return ret;
0323 }
0324 
0325 #ifdef CONFIG_DEBUG_FS
0326 static int rwtm_debug_open(struct inode *inode, struct file *file)
0327 {
0328     file->private_data = inode->i_private;
0329 
0330     return nonseekable_open(inode, file);
0331 }
0332 
0333 static ssize_t do_sign_read(struct file *file, char __user *buf, size_t len,
0334                 loff_t *ppos)
0335 {
0336     struct mox_rwtm *rwtm = file->private_data;
0337     ssize_t ret;
0338 
0339     /* only allow one read, of 136 bytes, from position 0 */
0340     if (*ppos != 0)
0341         return 0;
0342 
0343     if (len < 136)
0344         return -EINVAL;
0345 
0346     if (!rwtm->last_sig_done)
0347         return -ENODATA;
0348 
0349     /* 2 arrays of 17 32-bit words are 136 bytes */
0350     ret = simple_read_from_buffer(buf, len, ppos, rwtm->last_sig, 136);
0351     rwtm->last_sig_done = 0;
0352 
0353     return ret;
0354 }
0355 
0356 static ssize_t do_sign_write(struct file *file, const char __user *buf,
0357                  size_t len, loff_t *ppos)
0358 {
0359     struct mox_rwtm *rwtm = file->private_data;
0360     struct armada_37xx_rwtm_rx_msg *reply = &rwtm->reply;
0361     struct armada_37xx_rwtm_tx_msg msg;
0362     loff_t dummy = 0;
0363     ssize_t ret;
0364 
0365     /* the input is a SHA-512 hash, so exactly 64 bytes have to be read */
0366     if (len != 64)
0367         return -EINVAL;
0368 
0369     /* if last result is not zero user has not read that information yet */
0370     if (rwtm->last_sig_done)
0371         return -EBUSY;
0372 
0373     if (!mutex_trylock(&rwtm->busy))
0374         return -EBUSY;
0375 
0376     /*
0377      * Here we have to send:
0378      *   1. Address of the input to sign.
0379      *      The input is an array of 17 32-bit words, the first (most
0380      *      significat) is 0, the rest 16 words are copied from the SHA-512
0381      *      hash given by the user and converted from BE to LE.
0382      *   2. Address of the buffer where ECDSA signature value R shall be
0383      *      stored by the rWTM firmware.
0384      *   3. Address of the buffer where ECDSA signature value S shall be
0385      *      stored by the rWTM firmware.
0386      */
0387     memset(rwtm->buf, 0, 4);
0388     ret = simple_write_to_buffer(rwtm->buf + 4, 64, &dummy, buf, len);
0389     if (ret < 0)
0390         goto unlock_mutex;
0391     be32_to_cpu_array(rwtm->buf, rwtm->buf, 17);
0392 
0393     msg.command = MBOX_CMD_SIGN;
0394     msg.args[0] = 1;
0395     msg.args[1] = rwtm->buf_phys;
0396     msg.args[2] = rwtm->buf_phys + 68;
0397     msg.args[3] = rwtm->buf_phys + 2 * 68;
0398     ret = mbox_send_message(rwtm->mbox, &msg);
0399     if (ret < 0)
0400         goto unlock_mutex;
0401 
0402     ret = wait_for_completion_interruptible(&rwtm->cmd_done);
0403     if (ret < 0)
0404         goto unlock_mutex;
0405 
0406     ret = MBOX_STS_VALUE(reply->retval);
0407     if (MBOX_STS_ERROR(reply->retval) != MBOX_STS_SUCCESS)
0408         goto unlock_mutex;
0409 
0410     /*
0411      * Here we read the R and S values of the ECDSA signature
0412      * computed by the rWTM firmware and convert their words from
0413      * LE to BE.
0414      */
0415     memcpy(rwtm->last_sig, rwtm->buf + 68, 136);
0416     cpu_to_be32_array(rwtm->last_sig, rwtm->last_sig, 34);
0417     rwtm->last_sig_done = 1;
0418 
0419     mutex_unlock(&rwtm->busy);
0420     return len;
0421 unlock_mutex:
0422     mutex_unlock(&rwtm->busy);
0423     return ret;
0424 }
0425 
0426 static const struct file_operations do_sign_fops = {
0427     .owner  = THIS_MODULE,
0428     .open   = rwtm_debug_open,
0429     .read   = do_sign_read,
0430     .write  = do_sign_write,
0431     .llseek = no_llseek,
0432 };
0433 
0434 static int rwtm_register_debugfs(struct mox_rwtm *rwtm)
0435 {
0436     struct dentry *root, *entry;
0437 
0438     root = debugfs_create_dir("turris-mox-rwtm", NULL);
0439 
0440     if (IS_ERR(root))
0441         return PTR_ERR(root);
0442 
0443     entry = debugfs_create_file_unsafe("do_sign", 0600, root, rwtm,
0444                        &do_sign_fops);
0445     if (IS_ERR(entry))
0446         goto err_remove;
0447 
0448     rwtm->debugfs_root = root;
0449 
0450     return 0;
0451 err_remove:
0452     debugfs_remove_recursive(root);
0453     return PTR_ERR(entry);
0454 }
0455 
0456 static void rwtm_unregister_debugfs(struct mox_rwtm *rwtm)
0457 {
0458     debugfs_remove_recursive(rwtm->debugfs_root);
0459 }
0460 #else
0461 static inline int rwtm_register_debugfs(struct mox_rwtm *rwtm)
0462 {
0463     return 0;
0464 }
0465 
0466 static inline void rwtm_unregister_debugfs(struct mox_rwtm *rwtm)
0467 {
0468 }
0469 #endif
0470 
0471 static int turris_mox_rwtm_probe(struct platform_device *pdev)
0472 {
0473     struct mox_rwtm *rwtm;
0474     struct device *dev = &pdev->dev;
0475     int ret;
0476 
0477     rwtm = devm_kzalloc(dev, sizeof(*rwtm), GFP_KERNEL);
0478     if (!rwtm)
0479         return -ENOMEM;
0480 
0481     rwtm->dev = dev;
0482     rwtm->buf = dmam_alloc_coherent(dev, PAGE_SIZE, &rwtm->buf_phys,
0483                     GFP_KERNEL);
0484     if (!rwtm->buf)
0485         return -ENOMEM;
0486 
0487     ret = mox_kobj_create(rwtm);
0488     if (ret < 0) {
0489         dev_err(dev, "Cannot create turris-mox-rwtm kobject!\n");
0490         return ret;
0491     }
0492 
0493     ret = sysfs_create_files(rwtm_to_kobj(rwtm), mox_rwtm_attrs);
0494     if (ret < 0) {
0495         dev_err(dev, "Cannot create sysfs files!\n");
0496         goto put_kobj;
0497     }
0498 
0499     platform_set_drvdata(pdev, rwtm);
0500 
0501     mutex_init(&rwtm->busy);
0502 
0503     rwtm->mbox_client.dev = dev;
0504     rwtm->mbox_client.rx_callback = mox_rwtm_rx_callback;
0505 
0506     rwtm->mbox = mbox_request_channel(&rwtm->mbox_client, 0);
0507     if (IS_ERR(rwtm->mbox)) {
0508         ret = PTR_ERR(rwtm->mbox);
0509         if (ret != -EPROBE_DEFER)
0510             dev_err(dev, "Cannot request mailbox channel: %i\n",
0511                 ret);
0512         goto remove_files;
0513     }
0514 
0515     init_completion(&rwtm->cmd_done);
0516 
0517     ret = mox_get_board_info(rwtm);
0518     if (ret < 0)
0519         dev_warn(dev, "Cannot read board information: %i\n", ret);
0520 
0521     ret = check_get_random_support(rwtm);
0522     if (ret < 0) {
0523         dev_notice(dev,
0524                "Firmware does not support the GET_RANDOM command\n");
0525         goto free_channel;
0526     }
0527 
0528     rwtm->hwrng.name = DRIVER_NAME "_hwrng";
0529     rwtm->hwrng.read = mox_hwrng_read;
0530     rwtm->hwrng.priv = (unsigned long) rwtm;
0531     rwtm->hwrng.quality = 1024;
0532 
0533     ret = devm_hwrng_register(dev, &rwtm->hwrng);
0534     if (ret < 0) {
0535         dev_err(dev, "Cannot register HWRNG: %i\n", ret);
0536         goto free_channel;
0537     }
0538 
0539     ret = rwtm_register_debugfs(rwtm);
0540     if (ret < 0) {
0541         dev_err(dev, "Failed creating debugfs entries: %i\n", ret);
0542         goto free_channel;
0543     }
0544 
0545     dev_info(dev, "HWRNG successfully registered\n");
0546 
0547     return 0;
0548 
0549 free_channel:
0550     mbox_free_channel(rwtm->mbox);
0551 remove_files:
0552     sysfs_remove_files(rwtm_to_kobj(rwtm), mox_rwtm_attrs);
0553 put_kobj:
0554     kobject_put(rwtm_to_kobj(rwtm));
0555     return ret;
0556 }
0557 
0558 static int turris_mox_rwtm_remove(struct platform_device *pdev)
0559 {
0560     struct mox_rwtm *rwtm = platform_get_drvdata(pdev);
0561 
0562     rwtm_unregister_debugfs(rwtm);
0563     sysfs_remove_files(rwtm_to_kobj(rwtm), mox_rwtm_attrs);
0564     kobject_put(rwtm_to_kobj(rwtm));
0565     mbox_free_channel(rwtm->mbox);
0566 
0567     return 0;
0568 }
0569 
0570 static const struct of_device_id turris_mox_rwtm_match[] = {
0571     { .compatible = "cznic,turris-mox-rwtm", },
0572     { .compatible = "marvell,armada-3700-rwtm-firmware", },
0573     { },
0574 };
0575 
0576 MODULE_DEVICE_TABLE(of, turris_mox_rwtm_match);
0577 
0578 static struct platform_driver turris_mox_rwtm_driver = {
0579     .probe  = turris_mox_rwtm_probe,
0580     .remove = turris_mox_rwtm_remove,
0581     .driver = {
0582         .name       = DRIVER_NAME,
0583         .of_match_table = turris_mox_rwtm_match,
0584     },
0585 };
0586 module_platform_driver(turris_mox_rwtm_driver);
0587 
0588 MODULE_LICENSE("GPL v2");
0589 MODULE_DESCRIPTION("Turris Mox rWTM firmware driver");
0590 MODULE_AUTHOR("Marek Behun <kabel@kernel.org>");