cryptosk.c 4.9 KB

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