cryptosk.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * cryptosk.c
  3. */
  4. #include <crypto/internal/skcipher.h>
  5. #include <linux/crypto.h>
  6. #include <linux/module.h>
  7. #include <linux/random.h>
  8. #include <linux/scatterlist.h>
  9. #define SYMMETRIC_KEY_LENGTH 32
  10. #define CIPHER_BLOCK_SIZE 16
  11. struct tcrypt_result {
  12. struct completion completion;
  13. int err;
  14. };
  15. struct skcipher_def {
  16. struct scatterlist sg;
  17. struct crypto_skcipher *tfm;
  18. struct skcipher_request *req;
  19. struct tcrypt_result result;
  20. char *scratchpad;
  21. char *ciphertext;
  22. char *ivdata;
  23. };
  24. static struct skcipher_def sk;
  25. static void test_skcipher_finish(struct skcipher_def *sk)
  26. {
  27. if (sk->tfm)
  28. crypto_free_skcipher(sk->tfm);
  29. if (sk->req)
  30. skcipher_request_free(sk->req);
  31. if (sk->ivdata)
  32. kfree(sk->ivdata);
  33. if (sk->scratchpad)
  34. kfree(sk->scratchpad);
  35. if (sk->ciphertext)
  36. kfree(sk->ciphertext);
  37. }
  38. static int test_skcipher_result(struct skcipher_def *sk, int rc)
  39. {
  40. switch (rc) {
  41. case 0:
  42. break;
  43. case -EINPROGRESS || -EBUSY:
  44. rc = wait_for_completion_interruptible(&sk->result.completion);
  45. if (!rc && !sk->result.err) {
  46. reinit_completion(&sk->result.completion);
  47. break;
  48. }
  49. pr_info("skcipher encrypt returned with %d result %d\n", rc,
  50. sk->result.err);
  51. break;
  52. default:
  53. pr_info("skcipher encrypt returned with %d result %d\n", rc,
  54. sk->result.err);
  55. break;
  56. }
  57. init_completion(&sk->result.completion);
  58. return rc;
  59. }
  60. static void test_skcipher_callback(struct crypto_async_request *req, int error)
  61. {
  62. struct tcrypt_result *result = req->data;
  63. if (error == -EINPROGRESS)
  64. return;
  65. result->err = error;
  66. complete(&result->completion);
  67. pr_info("Encryption finished successfully\n");
  68. /* decrypt data */
  69. #if 0
  70. memset((void*)sk.scratchpad, '-', CIPHER_BLOCK_SIZE);
  71. ret = crypto_skcipher_decrypt(sk.req);
  72. ret = test_skcipher_result(&sk, ret);
  73. if (ret)
  74. return;
  75. sg_copy_from_buffer(&sk.sg, 1, sk.scratchpad, CIPHER_BLOCK_SIZE);
  76. sk.scratchpad[CIPHER_BLOCK_SIZE-1] = 0;
  77. pr_info("Decryption request successful\n");
  78. pr_info("Decrypted: %s\n", sk.scratchpad);
  79. #endif
  80. }
  81. static int test_skcipher_encrypt(char *plaintext, char *password,
  82. struct skcipher_def *sk)
  83. {
  84. int ret = -EFAULT;
  85. unsigned char key[SYMMETRIC_KEY_LENGTH];
  86. if (!sk->tfm) {
  87. sk->tfm = crypto_alloc_skcipher("cbc-aes-aesni", 0, 0);
  88. if (IS_ERR(sk->tfm)) {
  89. pr_info("could not allocate skcipher handle\n");
  90. return PTR_ERR(sk->tfm);
  91. }
  92. }
  93. if (!sk->req) {
  94. sk->req = skcipher_request_alloc(sk->tfm, GFP_KERNEL);
  95. if (!sk->req) {
  96. pr_info("could not allocate skcipher request\n");
  97. ret = -ENOMEM;
  98. goto out;
  99. }
  100. }
  101. skcipher_request_set_callback(sk->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
  102. test_skcipher_callback, &sk->result);
  103. /* clear the key */
  104. memset((void *)key, '\0', SYMMETRIC_KEY_LENGTH);
  105. /* Use the world's favourite password */
  106. sprintf((char *)key, "%s", password);
  107. /* AES 256 with given symmetric key */
  108. if (crypto_skcipher_setkey(sk->tfm, key, SYMMETRIC_KEY_LENGTH)) {
  109. pr_info("key could not be set\n");
  110. ret = -EAGAIN;
  111. goto out;
  112. }
  113. pr_info("Symmetric key: %s\n", key);
  114. pr_info("Plaintext: %s\n", plaintext);
  115. if (!sk->ivdata) {
  116. /* see https://en.wikipedia.org/wiki/Initialization_vector */
  117. sk->ivdata = kmalloc(CIPHER_BLOCK_SIZE, GFP_KERNEL);
  118. if (!sk->ivdata) {
  119. pr_info("could not allocate ivdata\n");
  120. goto out;
  121. }
  122. get_random_bytes(sk->ivdata, CIPHER_BLOCK_SIZE);
  123. }
  124. if (!sk->scratchpad) {
  125. /* The text to be encrypted */
  126. sk->scratchpad = kmalloc(CIPHER_BLOCK_SIZE, GFP_KERNEL);
  127. if (!sk->scratchpad) {
  128. pr_info("could not allocate scratchpad\n");
  129. goto out;
  130. }
  131. }
  132. sprintf((char *)sk->scratchpad, "%s", plaintext);
  133. sg_init_one(&sk->sg, sk->scratchpad, CIPHER_BLOCK_SIZE);
  134. skcipher_request_set_crypt(sk->req, &sk->sg, &sk->sg, CIPHER_BLOCK_SIZE,
  135. sk->ivdata);
  136. init_completion(&sk->result.completion);
  137. /* encrypt data */
  138. ret = crypto_skcipher_encrypt(sk->req);
  139. ret = test_skcipher_result(sk, ret);
  140. if (ret)
  141. goto out;
  142. pr_info("Encryption request successful\n");
  143. out:
  144. return ret;
  145. }
  146. static int __init cryptoapi_init(void)
  147. {
  148. /* The world's favorite password */
  149. char *password = "password123";
  150. sk.tfm = NULL;
  151. sk.req = NULL;
  152. sk.scratchpad = NULL;
  153. sk.ciphertext = NULL;
  154. sk.ivdata = NULL;
  155. test_skcipher_encrypt("Testing", password, &sk);
  156. return 0;
  157. }
  158. static void __exit cryptoapi_exit(void)
  159. {
  160. test_skcipher_finish(&sk);
  161. }
  162. module_init(cryptoapi_init);
  163. module_exit(cryptoapi_exit);
  164. MODULE_DESCRIPTION("Symmetric key encryption example");
  165. MODULE_LICENSE("GPL");