Guest User

Untitled

a guest
Nov 17th, 2018
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.36 KB | None | 0 0
  1. // The MIT License (MIT)
  2. //
  3. // Copyright (c) 2013 Patrick Van Oosterwijck
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy of
  6. // this software and associated documentation files (the "Software"), to deal in
  7. // the Software without restriction, including without limitation the rights to
  8. // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  9. // the Software, and to permit persons to whom the Software is furnished to do so,
  10. // subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in all
  13. // copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  17. // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  18. // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  19. // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  20. // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. //
  22.  
  23. #include <node.h>
  24. #include <nan.h>
  25. #include <openssl/evp.h>
  26.  
  27. using namespace v8;
  28. using namespace node;
  29.  
  30.  
  31. // Authentication tag length
  32.  
  33. #define AUTH_TAG_LEN 16
  34.  
  35. // Different versions of OpenSSL use different IV length defines
  36.  
  37. #ifndef EVP_CTRL_GCM_SET_IVLEN
  38. #define EVP_CTRL_GCM_SET_IVLEN EVP_CTRL_AEAD_SET_IVLEN
  39. #endif
  40.  
  41.  
  42. // Perform GCM mode AES-128, AES-192 or AES-256 encryption using the
  43. // provided key, IV, plaintext and auth_data buffers, and return an object
  44. // containing "ciphertext" and "auth_tag" buffers.
  45. // The key length determines the encryption bit level used.
  46.  
  47. void GcmEncrypt(const Nan::FunctionCallbackInfo<v8::Value>& info) {
  48. Nan::HandleScope scope;
  49. const EVP_CIPHER *cipher_type = NULL;
  50. int key_len = 0;
  51.  
  52. // The key needs to be 16, 24 or 32 bytes and determines the encryption
  53. // bit level used
  54. if (info.Length() >= 1 && Buffer::HasInstance(info[0])) {
  55. key_len = (int)Buffer::Length(info[0]);
  56. switch (key_len) {
  57. case 16:
  58. cipher_type = EVP_aes_128_gcm();
  59. break;
  60. case 24:
  61. cipher_type = EVP_aes_192_gcm();
  62. break;
  63. case 32:
  64. cipher_type = EVP_aes_256_gcm();
  65. break;
  66. default:
  67. break;
  68. }
  69. }
  70.  
  71. // We want 4 buffer arguments, key needs to be 16, 24 or 32 bytes
  72. if (info.Length() < 4 || !cipher_type ||
  73. !Buffer::HasInstance(info[1]) || !Buffer::HasInstance(info[2]) ||
  74. !Buffer::HasInstance(info[3])) {
  75. Nan::ThrowError("encrypt requires a 16, 24 or 32-byte key Buffer, " \
  76. "an IV Buffer, a plaintext Buffer and an " \
  77. "auth_data Buffer parameter");
  78. return;
  79. }
  80.  
  81. // Make a buffer for the ciphertext that is the same size as the
  82. // plaintext, but padded to key size increments
  83. int plaintext_len = (int)Buffer::Length(info[2]);
  84. int ciphertext_len = (((plaintext_len - 1) / key_len) + 1) * key_len;
  85. unsigned char *ciphertext = (unsigned char *)malloc(ciphertext_len);
  86. // Make a authentication tag buffer
  87. unsigned char *auth_tag = (unsigned char *)malloc(AUTH_TAG_LEN);
  88.  
  89. // Create the OpenSSL context
  90. int outl;
  91. EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
  92. // Init the OpenSSL interface with the selected AES GCM cipher
  93. EVP_EncryptInit_ex(ctx, cipher_type, NULL, NULL, NULL);
  94. // Set the IV length
  95. EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN,
  96. (int)Buffer::Length(info[1]), NULL);
  97. // Init OpenSSL interace with the key and IV
  98. EVP_EncryptInit_ex(ctx, NULL, NULL,
  99. (unsigned char *)Buffer::Data(info[0]),
  100. (unsigned char *)Buffer::Data(info[1]));
  101. // Pass additional authenticated data
  102. // There is some extra complication here because Buffer::Data seems to
  103. // return NULL for empty buffers, and NULL makes update not work as we
  104. // expect it to. So we force a valid non-NULL pointer for empty buffers.
  105. EVP_EncryptUpdate(ctx, NULL, &outl, Buffer::Length(info[3]) ?
  106. (unsigned char *)Buffer::Data(info[3]) : auth_tag,
  107. (int)Buffer::Length(info[3]));
  108. // Encrypt plaintext
  109. EVP_EncryptUpdate(ctx, ciphertext, &outl,
  110. (unsigned char *)Buffer::Data(info[2]),
  111. (int)Buffer::Length(info[2]));
  112. // Finalize
  113. EVP_EncryptFinal_ex(ctx, ciphertext + outl, &outl);
  114. // Get the authentication tag
  115. EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, AUTH_TAG_LEN, auth_tag);
  116. // Free the OpenSSL interface structure
  117. EVP_CIPHER_CTX_free(ctx);
  118.  
  119. // Create the return buffers and object
  120. // We strip padding from the ciphertext
  121. Nan::MaybeLocal<Object> ciphertext_buf = Nan::NewBuffer((char*)ciphertext,
  122. (uint32_t)plaintext_len);
  123. Nan::MaybeLocal<Object> auth_tag_buf = Nan::NewBuffer((char*)auth_tag,
  124. AUTH_TAG_LEN);
  125. Local<Object> return_obj = Nan::New<Object>();
  126. Nan::Set(return_obj, Nan::New<String>("ciphertext").ToLocalChecked(),
  127. ciphertext_buf.ToLocalChecked());
  128. Nan::Set(return_obj, Nan::New<String>("auth_tag").ToLocalChecked(),
  129. auth_tag_buf.ToLocalChecked());
  130.  
  131. // Return it
  132. info.GetReturnValue().Set(return_obj);
  133. }
  134.  
  135. // Perform GCM mode AES-128, AES-192 or AES-256 decryption using the
  136. // provided key, IV, ciphertext, auth_data and auth_tag buffers, and return
  137. // an object containing a "plaintext" buffer and an "auth_ok" boolean.
  138. // The key length determines the encryption bit level used.
  139.  
  140. void GcmDecrypt(const Nan::FunctionCallbackInfo<v8::Value>& info) {
  141. Nan::HandleScope scope;
  142. const EVP_CIPHER *cipher_type = NULL;
  143. int key_len = 0;
  144.  
  145. // The key needs to be 16, 24 or 32 bytes and determines the encryption
  146. // bit level used
  147. if (info.Length() >= 1 && Buffer::HasInstance(info[0])) {
  148. key_len = (int)Buffer::Length(info[0]);
  149. switch (key_len) {
  150. case 16:
  151. cipher_type = EVP_aes_128_gcm();
  152. break;
  153. case 24:
  154. cipher_type = EVP_aes_192_gcm();
  155. break;
  156. case 32:
  157. cipher_type = EVP_aes_256_gcm();
  158. break;
  159. default:
  160. break;
  161. }
  162. }
  163.  
  164. // We want 5 buffer arguments, key needs to be 16, 24 or 32 bytes,
  165. // auth_tag needs to be 16 bytes
  166. if (info.Length() < 4 || !cipher_type ||
  167. !Buffer::HasInstance(info[1]) || !Buffer::HasInstance(info[2]) ||
  168. !Buffer::HasInstance(info[3])) {
  169. Nan::ThrowError("decrypt requires a 16, 24 or 32-byte key Buffer, " \
  170. "an IV Buffer, a ciphertext Buffer, an auth_data " \
  171. "Buffer and a 16-byte auth_tag Buffer parameter");
  172. return;
  173. }
  174.  
  175. // Make a buffer for the plaintext that is the same size as the
  176. // ciphertext, but padded to key size increments
  177. int ciphertext_len = (int)Buffer::Length(info[2]);
  178. int plaintext_len = (((ciphertext_len - 1) / key_len) + 1) * key_len;
  179. unsigned char *plaintext = (unsigned char *)malloc(plaintext_len);
  180.  
  181. // Create the OpenSSL context
  182. int outl;
  183. EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
  184. // Init the OpenSSL interface with the selected AES GCM cipher
  185. EVP_DecryptInit_ex(ctx, cipher_type, NULL, NULL, NULL);
  186. // Set the IV length
  187. EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN,
  188. (int)Buffer::Length(info[1]), NULL);
  189. // Init OpenSSL interace with the key and IV
  190. EVP_DecryptInit_ex(ctx, NULL, NULL,
  191. (unsigned char *)Buffer::Data(info[0]),
  192. (unsigned char *)Buffer::Data(info[1]));
  193. // Pass additional authenticated data
  194. // There is some extra complication here because Buffer::Data seems to
  195. // return NULL for empty buffers, and NULL makes update not work as we
  196. // expect it to. So we force a valid non-NULL pointer for empty buffers.
  197. EVP_DecryptUpdate(ctx, NULL, &outl, Buffer::Length(info[3]) ?
  198. (unsigned char *)Buffer::Data(info[3]) : plaintext,
  199. (int)Buffer::Length(info[3]));
  200. // Decrypt ciphertext
  201. EVP_DecryptUpdate(ctx, plaintext, &outl,
  202. Buffer::Length(info[2]) ?
  203. (unsigned char *)Buffer::Data(info[2]) : plaintext,
  204. (int)Buffer::Length(info[2]));
  205. // Set the input reference authentication tag
  206. /* EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, AUTH_TAG_LEN,
  207. Buffer::Data(info[4]));*/
  208. // Finalize
  209. bool auth_ok = EVP_DecryptFinal_ex(ctx, plaintext + outl, &outl);
  210. // Free the OpenSSL interface structure
  211. EVP_CIPHER_CTX_free(ctx);
  212.  
  213. // Create the return buffer and object
  214. // We strip padding from the plaintext
  215. Nan::MaybeLocal<Object> plaintext_buf = Nan::NewBuffer((char*)plaintext,
  216. (uint32_t)ciphertext_len);
  217. Local<Object> return_obj = Nan::New<Object>();
  218. Nan::Set(return_obj, Nan::New<String>("plaintext").ToLocalChecked(),
  219. plaintext_buf.ToLocalChecked());
  220. /*
  221. Nan::Set(return_obj, Nan::New<String>("auth_ok").ToLocalChecked(),
  222. Nan::New<Boolean>(auth_ok));
  223. */
  224. // Return it
  225. info.GetReturnValue().Set(return_obj);
  226. }
  227.  
  228. // Module init function
  229. void InitAll(Handle<Object> exports) {
  230. Nan::Set(exports, Nan::New<String>("encrypt").ToLocalChecked(),
  231. Nan::GetFunction(Nan::New<FunctionTemplate>(GcmEncrypt))
  232. .ToLocalChecked());
  233. Nan::Set(exports, Nan::New<String>("decrypt").ToLocalChecked(),
  234. Nan::GetFunction(Nan::New<FunctionTemplate>(GcmDecrypt))
  235. .ToLocalChecked());
  236. }
  237.  
  238. NODE_MODULE(node_aes_gcm, InitAll)
Add Comment
Please, Sign In to add comment