cryptosk.c 4.9 KB

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