gcm.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #include <openssl/evp.h>
  2. #include <openssl/err.h>
  3. #include "gcm.h"
  4. /* Sample openssl GCM code lightly adapted from
  5. https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption
  6. */
  7. int gcm_encrypt(unsigned char *plaintext, int plaintext_len,
  8. unsigned char *aad, int aad_len,
  9. unsigned char *key,
  10. unsigned char *iv, int iv_len,
  11. unsigned char *ciphertext,
  12. unsigned char *tag)
  13. {
  14. EVP_CIPHER_CTX *ctx;
  15. int len;
  16. int ciphertext_len;
  17. /* Create and initialise the context */
  18. if(!(ctx = EVP_CIPHER_CTX_new())) {
  19. printf("EVP_CIPHER_CTX_new failed\n");
  20. return -1;
  21. }
  22. /* Initialise the encryption operation. */
  23. if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL)) {
  24. printf("EVP_EncryptInit_ex failed\n");
  25. return -1;
  26. }
  27. /*
  28. * Set IV length if default 12 bytes (96 bits) is not appropriate
  29. */
  30. if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL)) {
  31. printf("EVP_CTRL_GCM_SET_IVLEN failed\n");
  32. return -1;
  33. }
  34. /* Initialise key and IV */
  35. if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) {
  36. printf("Setting key and iv failed\n");
  37. return -1;
  38. }
  39. /*
  40. * Provide any AAD data. This can be called zero or more times as
  41. * required
  42. */
  43. if(aad_len && 1 != EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len)) {
  44. printf("EVP_EncryptUpdate AAD failed\n");
  45. return -1;
  46. }
  47. /*
  48. * Provide the message to be encrypted, and obtain the encrypted output.
  49. * EVP_EncryptUpdate can be called multiple times if necessary
  50. */
  51. int ret = EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len);
  52. if(1 != ret) {
  53. printf("EVP_EncryptUpdate failed\n");
  54. return -1;
  55. }
  56. ciphertext_len = len;
  57. /*
  58. * Finalise the encryption. Normally ciphertext bytes may be written at
  59. * this stage, but this does not occur in GCM mode
  60. */
  61. if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) {
  62. printf("EVP_EncryptFinal_ex failed\n");
  63. return -1;
  64. }
  65. ciphertext_len += len;
  66. /* Get the tag */
  67. if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag)) {
  68. printf("EVP_CTRL_GCM_GET_TAG failed\n");
  69. return -1;
  70. }
  71. /* Clean up */
  72. EVP_CIPHER_CTX_free(ctx);
  73. return ciphertext_len;
  74. }
  75. int gcm_decrypt(unsigned char *ciphertext, int ciphertext_len,
  76. unsigned char *aad, int aad_len,
  77. unsigned char *tag,
  78. unsigned char *key,
  79. unsigned char *iv, int iv_len,
  80. unsigned char *plaintext)
  81. {
  82. EVP_CIPHER_CTX *ctx;
  83. int len;
  84. int plaintext_len;
  85. int ret;
  86. /* Create and initialise the context */
  87. if(!(ctx = EVP_CIPHER_CTX_new())) {
  88. printf("EVP_CIPHER_CTX_new failed\n");
  89. return -1;
  90. }
  91. /* Initialise the decryption operation. */
  92. if(!EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL)) {
  93. printf("EVP_DecryptInit_ex failed\n");
  94. return -1;
  95. }
  96. /* Set IV length. Not necessary if this is 12 bytes (96 bits) */
  97. if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL)) {
  98. printf("EVP_CTRL_GCM_SET_IVLEN failed\n");
  99. return -1;
  100. }
  101. /* Initialise key and IV */
  102. if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) {
  103. printf("Setting key and iv failed\n");
  104. return -1;
  105. }
  106. /*
  107. * Provide any AAD data. This can be called zero or more times as
  108. * required
  109. */
  110. if(aad_len && !EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len)) {
  111. printf("EVP_DecryptUpdate AAD failed\n");
  112. return -1;
  113. }
  114. /*
  115. * Provide the message to be decrypted, and obtain the plaintext output.
  116. * EVP_DecryptUpdate can be called multiple times if necessary
  117. */
  118. if(!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) {
  119. printf("EVP_DecryptUpdate failed\n");
  120. return -1;
  121. }
  122. plaintext_len = len;
  123. /* Set expected tag value. Works in OpenSSL 1.0.1d and later */
  124. if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag)) {
  125. printf("EVP_CTRL_GCM_SET_TAG failed\n");
  126. return -1;
  127. }
  128. /*
  129. * Finalise the decryption. A positive return value indicates success,
  130. * anything else is a failure - the plaintext is not trustworthy.
  131. */
  132. ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
  133. /* Clean up */
  134. EVP_CIPHER_CTX_free(ctx);
  135. if(ret > 0) {
  136. /* Success */
  137. plaintext_len += len;
  138. return plaintext_len;
  139. } else {
  140. /* Verify failed */
  141. return -1;
  142. }
  143. }