cryptosk.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. #include <crypto/internal/skcipher.h>
  2. #include <linux/module.h>
  3. #include <linux/crypto.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(
  40. &sk->result.completion);
  41. if (!rc && !sk->result.err) {
  42. reinit_completion(&sk->result.completion);
  43. break;
  44. }
  45. pr_info("skcipher encrypt returned with %d result %d\n",
  46. rc, sk->result.err);
  47. break;
  48. default:
  49. pr_info("skcipher encrypt returned with %d result %d\n",
  50. rc, sk->result.err);
  51. break;
  52. }
  53. init_completion(&sk->result.completion);
  54. return rc;
  55. }
  56. static void test_skcipher_callback(struct crypto_async_request *req, int error)
  57. {
  58. struct tcrypt_result *result = req->data;
  59. /* int ret; */
  60. if (error == -EINPROGRESS)
  61. return;
  62. result->err = error;
  63. complete(&result->completion);
  64. pr_info("Encryption finished successfully\n");
  65. /* decrypt data */
  66. /*
  67. memset((void*)sk.scratchpad, '-', CIPHER_BLOCK_SIZE);
  68. ret = crypto_skcipher_decrypt(sk.req);
  69. ret = test_skcipher_result(&sk, ret);
  70. if (ret)
  71. return;
  72. sg_copy_from_buffer(&sk.sg, 1, sk.scratchpad, CIPHER_BLOCK_SIZE);
  73. sk.scratchpad[CIPHER_BLOCK_SIZE-1] = 0;
  74. pr_info("Decryption request successful\n");
  75. pr_info("Decrypted: %s\n", sk.scratchpad);
  76. */
  77. }
  78. static int test_skcipher_encrypt(char * plaintext, 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,
  100. &sk->result);
  101. /* clear the key */
  102. memset((void*)key,'\0',SYMMETRIC_KEY_LENGTH);
  103. /* Use the world's favourite password */
  104. sprintf((char*)key,"%s",password);
  105. /* AES 256 with given symmetric key */
  106. if (crypto_skcipher_setkey(sk->tfm, key, SYMMETRIC_KEY_LENGTH)) {
  107. pr_info("key could not be set\n");
  108. ret = -EAGAIN;
  109. goto out;
  110. }
  111. pr_info("Symmetric key: %s\n", key);
  112. pr_info("Plaintext: %s\n", plaintext);
  113. if (!sk->ivdata) {
  114. /* see https://en.wikipedia.org/wiki/Initialization_vector */
  115. sk->ivdata = kmalloc(CIPHER_BLOCK_SIZE, GFP_KERNEL);
  116. if (!sk->ivdata) {
  117. pr_info("could not allocate ivdata\n");
  118. goto out;
  119. }
  120. get_random_bytes(sk->ivdata, CIPHER_BLOCK_SIZE);
  121. }
  122. if (!sk->scratchpad) {
  123. /* The text to be encrypted */
  124. sk->scratchpad = kmalloc(CIPHER_BLOCK_SIZE, GFP_KERNEL);
  125. if (!sk->scratchpad) {
  126. pr_info("could not allocate scratchpad\n");
  127. goto out;
  128. }
  129. }
  130. sprintf((char*)sk->scratchpad,"%s",plaintext);
  131. sg_init_one(&sk->sg, sk->scratchpad, CIPHER_BLOCK_SIZE);
  132. skcipher_request_set_crypt(sk->req, &sk->sg, &sk->sg,
  133. CIPHER_BLOCK_SIZE, sk->ivdata);
  134. init_completion(&sk->result.completion);
  135. /* encrypt data */
  136. ret = crypto_skcipher_encrypt(sk->req);
  137. ret = test_skcipher_result(sk, ret);
  138. if (ret)
  139. goto out;
  140. pr_info("Encryption request successful\n");
  141. out:
  142. return ret;
  143. }
  144. int cryptoapi_init(void)
  145. {
  146. /* The world's favourite password */
  147. char * password = "password123";
  148. sk.tfm = NULL;
  149. sk.req = NULL;
  150. sk.scratchpad = NULL;
  151. sk.ciphertext = NULL;
  152. sk.ivdata = NULL;
  153. test_skcipher_encrypt("Testing", password, &sk);
  154. return 0;
  155. }
  156. void cryptoapi_exit(void)
  157. {
  158. test_skcipher_finish(&sk);
  159. }
  160. module_init(cryptoapi_init);
  161. module_exit(cryptoapi_exit);
  162. MODULE_AUTHOR("Bob Mottram");
  163. MODULE_DESCRIPTION("Symmetric key encryption example");
  164. MODULE_LICENSE("GPL");