cryspr-openssl-evp.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. /*
  2. * SRT - Secure, Reliable, Transport
  3. * Copyright (c) 2019 Haivision Systems Inc.
  4. *
  5. * This Source Code Form is subject to the terms of the Mozilla Public
  6. * License, v. 2.0. If a copy of the MPL was not distributed with this
  7. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  8. *
  9. */
  10. /*****************************************************************************
  11. written by
  12. Haivision Systems Inc.
  13. 2022-05-19 (jdube)
  14. OpenSSL EVP CRYSPR/4SRT (CRYypto Service PRovider for SRT).
  15. *****************************************************************************/
  16. #include "hcrypt.h"
  17. #include <string.h>
  18. typedef struct tag_crysprOpenSSL_EVP_cb
  19. {
  20. CRYSPR_cb ccb;
  21. /* Add cryptolib specific data here */
  22. } crysprOpenSSL_EVP_cb;
  23. int crysprOpenSSL_EVP_Prng(unsigned char* rn, int len)
  24. {
  25. return (RAND_bytes(rn, len) <= 0 ? -1 : 0);
  26. }
  27. const EVP_CIPHER* (*Xcipher_fnptr)(void) = EVP_aes_128_ecb;
  28. const EVP_CIPHER* (*_crysprOpenSSL_EVP_cipher_fnptr[][3])(void) = {
  29. {NULL, NULL, NULL}, // HCRYPT_CTX_MODE_CLRTXT
  30. {EVP_aes_128_ecb, EVP_aes_192_ecb, EVP_aes_256_ecb}, // HCRYPT_CTX_MODE_AESECB
  31. {EVP_aes_128_ctr, EVP_aes_192_ctr, EVP_aes_256_ctr}, // HCRYPT_CTX_MODE_AESCTR
  32. {NULL, NULL, NULL}, // HCRYPT_CTX_MODE_AESCBC
  33. {EVP_aes_128_gcm, EVP_aes_192_gcm, EVP_aes_256_gcm}, // HCRYPT_CTX_MODE_AESGCM
  34. };
  35. int crysprOpenSSL_EVP_AES_SetKey(
  36. int cipher_type, /* One of HCRYPT_CTX_MODE_[CLRTXT|AESECB|AESCTR] */
  37. bool bEncrypt, /* true Enxcrypt key, false: decrypt */
  38. const unsigned char* kstr, /* key sttring*/
  39. size_t kstr_len, /* kstr len in bytes (16, 24, or 32 bytes (for AES128, AES192, or AES256) */
  40. CRYSPR_AESCTX* aes_key) /* CRYpto Service PRovider AES Key context */
  41. {
  42. const EVP_CIPHER* cipher = NULL;
  43. int idxKlen = (int)((kstr_len / 8) - 2); /* key_len index in cipher_fnptr array in [0,1,2] range */
  44. switch (cipher_type)
  45. {
  46. case HCRYPT_CTX_MODE_CLRTXT:
  47. return 0;
  48. case HCRYPT_CTX_MODE_AESECB:
  49. break;
  50. case HCRYPT_CTX_MODE_AESCTR:
  51. #if !CRYSPR_HAS_AESCTR
  52. /* internal implementation of AES-CTR using crypto lib's AES-ECB */
  53. cipher_type = HCRYPT_CTX_MODE_AESECB;
  54. #endif
  55. break;
  56. case HCRYPT_CTX_MODE_AESGCM:
  57. break;
  58. default:
  59. HCRYPT_LOG(LOG_ERR,
  60. "invalid cipher type (%d). Expected: [%d..%d]\n",
  61. cipher_type,
  62. HCRYPT_CTX_MODE_AESECB,
  63. HCRYPT_CTX_MODE_AESCTR);
  64. return (-1);
  65. }
  66. switch (kstr_len)
  67. {
  68. case 128 / 8:
  69. case 192 / 8:
  70. case 256 / 8:
  71. break;
  72. default:
  73. HCRYPT_LOG(LOG_ERR, "invalid key length (%d). Expected: 16, 24, 32\n", (int)kstr_len);
  74. return -1;
  75. }
  76. cipher = _crysprOpenSSL_EVP_cipher_fnptr[cipher_type][idxKlen]();
  77. if (bEncrypt)
  78. { /* Encrypt key */
  79. if (!EVP_EncryptInit_ex(aes_key, cipher, NULL, kstr, NULL))
  80. {
  81. HCRYPT_LOG(LOG_ERR, "%s", "EVP_CipherInit_ex(kek) failed\n");
  82. return (-1);
  83. }
  84. }
  85. else
  86. { /* Decrypt key */
  87. if (!EVP_DecryptInit_ex(aes_key, cipher, NULL, kstr, NULL))
  88. {
  89. HCRYPT_LOG(LOG_ERR, "%s", "EVP_CipherInit_ex(kek) failed\n");
  90. return (-1);
  91. }
  92. }
  93. return (0);
  94. }
  95. static CRYSPR_cb* crysprOpenSSL_EVP_Open(CRYSPR_methods* cryspr, size_t max_len)
  96. {
  97. CRYSPR_cb* cryspr_cb = crysprHelper_Open(cryspr, sizeof(*cryspr_cb), max_len);
  98. if (NULL == cryspr_cb)
  99. {
  100. HCRYPT_LOG(LOG_ERR, "crysprFallback_Open(%p, %zd) failed\n", cryspr, max_len);
  101. return (NULL);
  102. }
  103. cryspr_cb->aes_kek = EVP_CIPHER_CTX_new();
  104. cryspr_cb->aes_sek[0] = EVP_CIPHER_CTX_new();
  105. cryspr_cb->aes_sek[1] = EVP_CIPHER_CTX_new();
  106. return (cryspr_cb);
  107. }
  108. static int crysprOpenSSL_EVP_Close(CRYSPR_cb* cryspr_cb)
  109. {
  110. if (NULL != cryspr_cb)
  111. {
  112. EVP_CIPHER_CTX_free(cryspr_cb->aes_sek[0]);
  113. EVP_CIPHER_CTX_free(cryspr_cb->aes_sek[1]);
  114. EVP_CIPHER_CTX_free(cryspr_cb->aes_kek);
  115. }
  116. return (crysprHelper_Close(cryspr_cb));
  117. }
  118. #if !(CRYSPR_HAS_AESCTR && CRYSPR_HAS_AESKWRAP)
  119. int crysprOpenSSL_EVP_AES_EcbCipher(bool bEncrypt, /* true:encrypt, false:decrypt */
  120. CRYSPR_AESCTX* aes_key, /* CRYpto Service PRovider AES Key context */
  121. const unsigned char* indata, /* src (clear text if encrypt, cipher text otherwise)*/
  122. size_t inlen, /* indata length */
  123. unsigned char* out_txt, /* dst (cipher text if encrypt, clear text otherwise) */
  124. size_t* outlen_p) /* in/out dst len */
  125. {
  126. int nmore = inlen % CRYSPR_AESBLKSZ; /* bytes in last incomplete block */
  127. int nblk = (int)(inlen / CRYSPR_AESBLKSZ + (nmore ? 1 : 0)); /* blocks including incomplete */
  128. size_t outsiz = (outlen_p ? *outlen_p : 0);
  129. int c_len = 0, f_len = 0;
  130. (void)bEncrypt; // not needed, alreadydefined in context
  131. if (outsiz % CRYSPR_AESBLKSZ)
  132. {
  133. HCRYPT_LOG(LOG_ERR, "%s\n", "EcbCipher() no room for PKCS7 padding");
  134. return (-1); /* output buf size must be a multiple of AES block size (16) */
  135. }
  136. if ((outsiz > 16) && ((int)outsiz < (nblk * CRYSPR_AESBLKSZ)))
  137. {
  138. HCRYPT_LOG(LOG_ERR, "%s\n", "EcbCipher() no room for PKCS7 padding");
  139. return (-1); /* output buf size must have room for PKCS7 padding */
  140. }
  141. /* allows reusing of 'e' for multiple encryption cycles */
  142. if (!EVP_CipherInit_ex(aes_key, NULL, NULL, NULL, NULL, bEncrypt))
  143. {
  144. HCRYPT_LOG(LOG_ERR, "EVP_CipherInit_ex(%p,NULL,...,-1) failed\n", aes_key);
  145. return -1;
  146. }
  147. if (!EVP_CIPHER_CTX_set_padding(aes_key, 0))
  148. {
  149. HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CIPHER_CTX_set_padding(%p) failed", aes_key);
  150. return -1;
  151. }
  152. /* update ciphertext, c_len is filled with the length of ciphertext generated,
  153. * cryptoPtr->cipher_in_len is the size of plain/cipher text in bytes
  154. */
  155. if (!EVP_CipherUpdate(aes_key, out_txt, &c_len, indata, (int)inlen))
  156. {
  157. HCRYPT_LOG(LOG_ERR, "EVP_CipherUpdate(%p, out, %d, in, %d) failed\n", aes_key, c_len, inlen);
  158. return -1;
  159. }
  160. /* update ciphertext with the final remaining bytes */
  161. /* Useless with pre-padding */
  162. f_len = 0;
  163. if (0 == EVP_CipherFinal_ex(aes_key, &out_txt[c_len], &f_len))
  164. {
  165. #if ENABLE_HAICRYPT_LOGGING
  166. char szErrBuf[256];
  167. HCRYPT_LOG(LOG_ERR,
  168. "EVP_CipherFinal_ex(ctx,&out[%d],%d)) failed: %s\n",
  169. c_len,
  170. f_len,
  171. ERR_error_string(ERR_get_error(), szErrBuf));
  172. #endif /*ENABLE_HAICRYPT_LOGGING*/
  173. return -1;
  174. }
  175. if (outlen_p != NULL) *outlen_p = nblk * CRYSPR_AESBLKSZ;
  176. return 0;
  177. }
  178. #endif /* !(CRYSPR_HAS_AESCTR && CRYSPR_HAS_AESKWRAP) */
  179. int crysprOpenSSL_EVP_AES_CtrCipher(bool bEncrypt, /* true:encrypt, false:decrypt */
  180. CRYSPR_AESCTX* aes_key, /* CRYpto Service PRovider AES Key context */
  181. unsigned char* iv, /* iv */
  182. const unsigned char* indata, /* src */
  183. size_t inlen, /* length */
  184. unsigned char* out_txt) /* dest */
  185. {
  186. int c_len, f_len;
  187. (void)bEncrypt;
  188. /* allows reusing of 'e' for multiple encryption cycles */
  189. if (!EVP_CipherInit_ex(aes_key, NULL, NULL, NULL, iv, -1))
  190. {
  191. HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CipherInit_ex() failed");
  192. return -1;
  193. }
  194. if (!EVP_CIPHER_CTX_set_padding(aes_key, 0))
  195. {
  196. HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CIPHER_CTX_set_padding() failed");
  197. return -1;
  198. }
  199. /* update ciphertext, c_len is filled with the length of ciphertext generated,
  200. * cryptoPtr->cipher_in_len is the size of plain/cipher text in bytes
  201. */
  202. if (!EVP_CipherUpdate(aes_key, out_txt, &c_len, indata, (int)inlen))
  203. {
  204. HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CipherUpdate() failed");
  205. return -1;
  206. }
  207. /* update ciphertext with the final remaining bytes */
  208. /* Useless with pre-padding */
  209. f_len = 0;
  210. if (0 == EVP_CipherFinal_ex(aes_key, &out_txt[c_len], &f_len))
  211. {
  212. #if ENABLE_HAICRYPT_LOGGING
  213. char szErrBuf[256];
  214. HCRYPT_LOG(LOG_ERR,
  215. "EVP_CipherFinal_ex(ctx,&out[%d],%d)) failed: %s\n",
  216. c_len,
  217. f_len,
  218. ERR_error_string(ERR_get_error(), szErrBuf));
  219. #endif /*ENABLE_HAICRYPT_LOGGING*/
  220. return -1;
  221. }
  222. return 0;
  223. }
  224. int crysprOpenSSL_EVP_AES_GCMCipher(bool bEncrypt, /* true:encrypt, false:decrypt */
  225. CRYSPR_AESCTX* aes_key, /* CRYpto Service PRovider AES Key context */
  226. unsigned char* iv, /* iv */
  227. const unsigned char* aad, /* associated data */
  228. size_t aadlen,
  229. const unsigned char* indata, /* src */
  230. size_t inlen, /* length */
  231. unsigned char* out_txt,
  232. unsigned char* out_tag) /* auth tag */
  233. {
  234. int c_len, f_len;
  235. /* allows reusing of 'e' for multiple encryption cycles */
  236. if (!EVP_CipherInit_ex(aes_key, NULL, NULL, NULL, iv, -1))
  237. {
  238. HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CipherInit_ex() failed");
  239. return -1;
  240. }
  241. if (!EVP_CIPHER_CTX_set_padding(aes_key, 0))
  242. {
  243. HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CIPHER_CTX_set_padding() failed");
  244. return -1;
  245. }
  246. /*
  247. * Provide any AAD data. This can be called zero or more times as
  248. * required
  249. */
  250. if (1 != EVP_CipherUpdate(aes_key, NULL, &c_len, aad, (int) aadlen))
  251. {
  252. ERR_print_errors_fp(stderr);
  253. HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_EncryptUpdate failed");
  254. return -1;
  255. }
  256. /* update ciphertext, c_len is filled with the length of ciphertext generated,
  257. * cryptoPtr->cipher_in_len is the size of plain/cipher text in bytes
  258. */
  259. if (!EVP_CipherUpdate(aes_key, out_txt, &c_len, indata, (int) inlen))
  260. {
  261. HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CipherUpdate() failed");
  262. return -1;
  263. }
  264. if (!bEncrypt && !EVP_CIPHER_CTX_ctrl(aes_key, EVP_CTRL_GCM_SET_TAG, HAICRYPT_AUTHTAG_MAX, out_tag)) {
  265. ERR_print_errors_fp(stderr);
  266. HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_EncryptUpdate failed");
  267. return -1;
  268. }
  269. /* update ciphertext with the final remaining bytes */
  270. /* Useless with pre-padding */
  271. f_len = 0;
  272. if (0 == EVP_CipherFinal_ex(aes_key, &out_txt[c_len], &f_len))
  273. {
  274. #if ENABLE_HAICRYPT_LOGGING
  275. char szErrBuf[256];
  276. HCRYPT_LOG(LOG_ERR,
  277. "EVP_CipherFinal_ex(ctx,&out[%d],%d)) failed: %s\n",
  278. c_len,
  279. f_len,
  280. ERR_error_string(ERR_get_error(), szErrBuf));
  281. #endif /*ENABLE_HAICRYPT_LOGGING*/
  282. return -1;
  283. }
  284. /* Get the tag if we are encrypting */
  285. if (bEncrypt && !EVP_CIPHER_CTX_ctrl(aes_key, EVP_CTRL_GCM_GET_TAG, HAICRYPT_AUTHTAG_MAX, out_tag))
  286. {
  287. ERR_print_errors_fp(stderr);
  288. HCRYPT_LOG(LOG_ERR, "%s\n", "EVP_CIPHER_CTX_ctrl(EVP_CTRL_GCM_GET_TAG) failed");
  289. return -1;
  290. }
  291. return 0;
  292. }
  293. /*
  294. * Password-based Key Derivation Function
  295. */
  296. int crysprOpenSSL_EVP_KmPbkdf2(CRYSPR_cb* cryspr_cb,
  297. char* passwd, /* passphrase */
  298. size_t passwd_len, /* passphrase len */
  299. unsigned char* salt, /* salt */
  300. size_t salt_len, /* salt_len */
  301. int itr, /* iterations */
  302. size_t key_len, /* key_len */
  303. unsigned char* out) /* derived key */
  304. {
  305. (void)cryspr_cb;
  306. int rc = PKCS5_PBKDF2_HMAC_SHA1(passwd, (int)passwd_len, salt, (int)salt_len, itr, (int)key_len, out);
  307. return (rc == 1 ? 0 : -1);
  308. }
  309. #if CRYSPR_HAS_AESKWRAP
  310. int crysprOpenSSL_EVP_KmWrap(CRYSPR_cb* cryspr_cb, unsigned char* wrap, const unsigned char* sek, unsigned int seklen)
  311. {
  312. crysprOpenSSL_EVP_cb* aes_data = (crysprOpenSSL_EVP_cb*)cryspr_cb;
  313. EVP_CIPHER_CTX* kek = CRYSPR_GETKEK(cryspr_cb); // key encrypting key
  314. return (((seklen + HAICRYPT_WRAPKEY_SIGN_SZ) == (unsigned int)AES_wrap_key(kek, NULL, wrap, sek, seklen)) ? 0 : -1);
  315. }
  316. int crysprOpenSSL_EVP_KmUnwrap(CRYSPR_cb* cryspr_cb,
  317. unsigned char* sek, // Stream encrypting key
  318. const unsigned char* wrap,
  319. unsigned int wraplen)
  320. {
  321. crysprOpenSSL_EVP_cb* aes_data = (crysprOpenSSL_EVP_cb*)cryspr_cb;
  322. EVP_CIPHER_CTX* kek = CRYSPR_GETKEK(cryspr_cb); // key encrypting key
  323. return (((wraplen - HAICRYPT_WRAPKEY_SIGN_SZ) == (unsigned int)AES_unwrap_key(kek, NULL, sek, wrap, wraplen)) ? 0
  324. : -1);
  325. }
  326. #endif /*CRYSPR_HAS_AESKWRAP*/
  327. static CRYSPR_methods crysprOpenSSL_EVP_methods;
  328. CRYSPR_methods* crysprOpenSSL_EVP(void)
  329. {
  330. if (NULL == crysprOpenSSL_EVP_methods.open)
  331. {
  332. crysprInit(&crysprOpenSSL_EVP_methods); // Default/fallback methods
  333. crysprOpenSSL_EVP_methods.prng = crysprOpenSSL_EVP_Prng;
  334. //--CryptoLib Primitive API-----------------------------------------------
  335. crysprOpenSSL_EVP_methods.aes_set_key = crysprOpenSSL_EVP_AES_SetKey;
  336. #if CRYSPR_HAS_AESCTR
  337. crysprOpenSSL_EVP_methods.aes_ctr_cipher = crysprOpenSSL_EVP_AES_CtrCipher;
  338. #endif
  339. crysprOpenSSL_EVP_methods.aes_gcm_cipher = crysprOpenSSL_EVP_AES_GCMCipher;
  340. #if !(CRYSPR_HAS_AESCTR && CRYSPR_HAS_AESKWRAP)
  341. /* AES-ECB only required if cryspr has no AES-CTR and no AES KeyWrap */
  342. /* OpenSSL has both AESCTR and AESKWRP and the AESECB wrapper is only used
  343. to test the falback methods */
  344. crysprOpenSSL_EVP_methods.aes_ecb_cipher = crysprOpenSSL_EVP_AES_EcbCipher;
  345. #endif
  346. #if !CRYSPR_HAS_PBKDF2
  347. crysprOpenSSL_EVP_methods.sha1_msg_digest = NULL; // Required to use eventual default/fallback KmPbkdf2
  348. #endif
  349. //--Crypto Session API-----------------------------------------
  350. crysprOpenSSL_EVP_methods.open = crysprOpenSSL_EVP_Open;
  351. crysprOpenSSL_EVP_methods.close = crysprOpenSSL_EVP_Close;
  352. //--Keying material (km) encryption
  353. #if CRYSPR_HAS_PBKDF2
  354. crysprOpenSSL_EVP_methods.km_pbkdf2 = crysprOpenSSL_EVP_KmPbkdf2;
  355. #else
  356. #error There is no default/fallback method for PBKDF2
  357. #endif
  358. // crysprOpenSSL_EVP_methods.km_setkey =
  359. #if CRYSPR_HAS_AESKWRAP
  360. crysprOpenSSL_EVP_methods.km_wrap = crysprOpenSSL_EVP_KmWrap;
  361. crysprOpenSSL_EVP_methods.km_unwrap = crysprOpenSSL_EVP_KmUnwrap;
  362. #endif
  363. //--Media stream (ms) encryption
  364. // crysprOpenSSL_EVP_methods.ms_setkey =
  365. // crysprOpenSSL_EVP_methods.ms_encrypt =
  366. // crysprOpenSSL_EVP_methods.ms_decrypt =
  367. }
  368. return (&crysprOpenSSL_EVP_methods);
  369. }