virtio_blk_qti_crypto.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * virtio block crypto ops QTI implementation.
  4. *
  5. * Copyright (c) 2021, The Linux Foundation. All rights reserved.
  6. * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  7. */
  8. #include <linux/device.h>
  9. #include <linux/module.h>
  10. #include <linux/blkdev.h>
  11. #include <linux/crypto_qti_virt.h>
  12. #include <linux/blk-crypto-profile.h>
  13. /*keyslot manager for vrtual IO*/
  14. static struct blk_crypto_profile virtio_crypto_profile;
  15. /* initialize crypto profile only once */
  16. static bool is_crypto_profile_initalized;
  17. /*To get max ice slots for guest vm */
  18. static uint32_t num_ice_slots;
  19. void virtblk_crypto_qti_crypto_register(struct request_queue *q)
  20. {
  21. blk_crypto_register(&virtio_crypto_profile, q);
  22. }
  23. EXPORT_SYMBOL_GPL(virtblk_crypto_qti_crypto_register);
  24. static inline bool virtblk_keyslot_valid(unsigned int slot)
  25. {
  26. /*
  27. * slot numbers range from 0 to max available
  28. * slots for vm.
  29. */
  30. return slot < num_ice_slots;
  31. }
  32. static int virtblk_crypto_qti_keyslot_program(struct blk_crypto_profile *profile,
  33. const struct blk_crypto_key *key,
  34. unsigned int slot)
  35. {
  36. int err = 0;
  37. if (!virtblk_keyslot_valid(slot)) {
  38. pr_err("%s: key slot is not valid\n",
  39. __func__);
  40. return -EINVAL;
  41. }
  42. err = crypto_qti_virt_program_key(key, slot);
  43. if (err) {
  44. pr_err("%s: program key failed with error %d\n",
  45. __func__, err);
  46. err = crypto_qti_virt_invalidate_key(slot);
  47. if (err) {
  48. pr_err("%s: invalidate key failed with error %d\n",
  49. __func__, err);
  50. return err;
  51. }
  52. }
  53. return err;
  54. }
  55. static int virtblk_crypto_qti_keyslot_evict(struct blk_crypto_profile *profile,
  56. const struct blk_crypto_key *key,
  57. unsigned int slot)
  58. {
  59. int err = 0;
  60. if (!virtblk_keyslot_valid(slot)) {
  61. pr_err("%s: key slot is not valid\n",
  62. __func__);
  63. return -EINVAL;
  64. }
  65. err = crypto_qti_virt_invalidate_key(slot);
  66. if (err) {
  67. pr_err("%s: evict key failed with error %d\n",
  68. __func__, err);
  69. return err;
  70. }
  71. return err;
  72. }
  73. static int virtblk_crypto_qti_derive_raw_secret(struct blk_crypto_profile *profile,
  74. const u8 *eph_key,
  75. size_t eph_key_size,
  76. u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE])
  77. {
  78. int err = 0;
  79. if (eph_key_size <= BLK_CRYPTO_SW_SECRET_SIZE) {
  80. pr_err("%s: Invalid wrapped_key_size: %u\n",
  81. __func__, eph_key_size);
  82. err = -EINVAL;
  83. return err;
  84. }
  85. if (eph_key_size > 64) {
  86. err = crypto_qti_virt_derive_raw_secret_platform(eph_key,
  87. eph_key_size,
  88. sw_secret,
  89. BLK_CRYPTO_SW_SECRET_SIZE);
  90. } else {
  91. memcpy(sw_secret, eph_key, BLK_CRYPTO_SW_SECRET_SIZE);
  92. }
  93. return err;
  94. }
  95. static const struct blk_crypto_ll_ops virtio_blk_qti_crypto_ops = {
  96. .keyslot_program = virtblk_crypto_qti_keyslot_program,
  97. .keyslot_evict = virtblk_crypto_qti_keyslot_evict,
  98. .derive_sw_secret = virtblk_crypto_qti_derive_raw_secret,
  99. };
  100. int virtblk_init_crypto_qti_spec(struct device *dev)
  101. {
  102. int err = 0;
  103. unsigned int crypto_modes_supported[BLK_ENCRYPTION_MODE_MAX];
  104. memset(crypto_modes_supported, 0, sizeof(crypto_modes_supported));
  105. /* Actual determination of capabilities for UFS/EMMC for different
  106. * encryption modes are done in the back end (host operating system)
  107. * in case of virtualization driver, so will get crypto capabilities
  108. * from the back end. The received capabilities is feeded as input
  109. * parameter to keyslot manager
  110. */
  111. err = crypto_qti_virt_get_crypto_capabilities(crypto_modes_supported,
  112. sizeof(crypto_modes_supported));
  113. if (err) {
  114. pr_err("crypto_qti_virt_get_crypto_capabilities failed error = %d\n", err);
  115. return err;
  116. }
  117. /* Get max number of ice slots for guest vm */
  118. err = crypto_qti_virt_ice_get_info(&num_ice_slots);
  119. if (err) {
  120. pr_err("crypto_qti_virt_ice_get_info failed error = %d\n", err);
  121. return err;
  122. }
  123. /* Return from here incase keyslot manager is already initialized */
  124. if (is_crypto_profile_initalized)
  125. return 0;
  126. /* create keyslot manager and which will manage the keyslots for all
  127. * virtual disks
  128. */
  129. err = devm_blk_crypto_profile_init(dev, &virtio_crypto_profile, num_ice_slots);
  130. if (err) {
  131. pr_err("%s: crypto profile initialization failed\n", __func__);
  132. return err;
  133. }
  134. is_crypto_profile_initalized = true;
  135. virtio_crypto_profile.ll_ops = virtio_blk_qti_crypto_ops;
  136. /* This value suppose to get from host based on storage type
  137. * will remove hard code value later
  138. */
  139. virtio_crypto_profile.max_dun_bytes_supported = 8;
  140. virtio_crypto_profile.key_types_supported = BLK_CRYPTO_KEY_TYPE_HW_WRAPPED;
  141. virtio_crypto_profile.dev = dev;
  142. memcpy(virtio_crypto_profile.modes_supported, crypto_modes_supported,
  143. sizeof(crypto_modes_supported));
  144. pr_info("%s: crypto profile initialized.\n", __func__);
  145. return err;
  146. }
  147. EXPORT_SYMBOL_GPL(virtblk_init_crypto_qti_spec);
  148. MODULE_LICENSE("GPL");
  149. MODULE_DESCRIPTION("Crypto Virtual library for storage encryption");