cryptosk.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  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,
  82. char *password,
  83. struct skcipher_def *sk)
  84. {
  85. int ret = -EFAULT;
  86. unsigned char key[SYMMETRIC_KEY_LENGTH];
  87. if (!sk->tfm) {
  88. sk->tfm = crypto_alloc_skcipher("cbc-aes-aesni", 0, 0);
  89. if (IS_ERR(sk->tfm)) {
  90. pr_info("could not allocate skcipher handle\n");
  91. return PTR_ERR(sk->tfm);
  92. }
  93. }
  94. if (!sk->req) {
  95. sk->req = skcipher_request_alloc(sk->tfm, GFP_KERNEL);
  96. if (!sk->req) {
  97. pr_info("could not allocate skcipher request\n");
  98. ret = -ENOMEM;
  99. goto out;
  100. }
  101. }
  102. skcipher_request_set_callback(sk->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
  103. test_skcipher_callback, &sk->result);
  104. /* clear the key */
  105. memset((void *) key, '\0', SYMMETRIC_KEY_LENGTH);
  106. /* Use the world's favourite password */
  107. sprintf((char *) key, "%s", password);
  108. /* AES 256 with given symmetric key */
  109. if (crypto_skcipher_setkey(sk->tfm, key, SYMMETRIC_KEY_LENGTH)) {
  110. pr_info("key could not be set\n");
  111. ret = -EAGAIN;
  112. goto out;
  113. }
  114. pr_info("Symmetric key: %s\n", key);
  115. pr_info("Plaintext: %s\n", plaintext);
  116. if (!sk->ivdata) {
  117. /* see https://en.wikipedia.org/wiki/Initialization_vector */
  118. sk->ivdata = kmalloc(CIPHER_BLOCK_SIZE, GFP_KERNEL);
  119. if (!sk->ivdata) {
  120. pr_info("could not allocate ivdata\n");
  121. goto out;
  122. }
  123. get_random_bytes(sk->ivdata, CIPHER_BLOCK_SIZE);
  124. }
  125. if (!sk->scratchpad) {
  126. /* The text to be encrypted */
  127. sk->scratchpad = kmalloc(CIPHER_BLOCK_SIZE, GFP_KERNEL);
  128. if (!sk->scratchpad) {
  129. pr_info("could not allocate scratchpad\n");
  130. goto out;
  131. }
  132. }
  133. sprintf((char *) sk->scratchpad, "%s", plaintext);
  134. sg_init_one(&sk->sg, sk->scratchpad, CIPHER_BLOCK_SIZE);
  135. skcipher_request_set_crypt(sk->req, &sk->sg, &sk->sg, CIPHER_BLOCK_SIZE,
  136. sk->ivdata);
  137. init_completion(&sk->result.completion);
  138. /* encrypt data */
  139. ret = crypto_skcipher_encrypt(sk->req);
  140. ret = test_skcipher_result(sk, ret);
  141. if (ret)
  142. goto out;
  143. pr_info("Encryption request successful\n");
  144. out:
  145. return ret;
  146. }
  147. int cryptoapi_init(void)
  148. {
  149. /* The world's favorite password */
  150. char *password = "password123";
  151. sk.tfm = NULL;
  152. sk.req = NULL;
  153. sk.scratchpad = NULL;
  154. sk.ciphertext = NULL;
  155. sk.ivdata = NULL;
  156. test_skcipher_encrypt("Testing", password, &sk);
  157. return 0;
  158. }
  159. void cryptoapi_exit(void)
  160. {
  161. test_skcipher_finish(&sk);
  162. }
  163. module_init(cryptoapi_init);
  164. module_exit(cryptoapi_exit);
  165. MODULE_DESCRIPTION("Symmetric key encryption example");
  166. MODULE_LICENSE("GPL");