2
0

xfm.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. /*
  2. * xfm.c
  3. *
  4. * Crypto transform implementation
  5. *
  6. * David A. McGrew
  7. * Cisco Systems, Inc.
  8. */
  9. #include "cryptoalg.h"
  10. #include "aes_cbc.h"
  11. #include "hmac.h"
  12. #include "crypto_kernel.h" /* for crypto_get_random() */
  13. #define KEY_LEN 16
  14. #define ENC_KEY_LEN 16
  15. #define MAC_KEY_LEN 16
  16. #define IV_LEN 16
  17. #define TAG_LEN 12
  18. #define MAX_EXPAND 27
  19. err_status_t
  20. aes_128_cbc_hmac_sha1_96_func(void *key,
  21. void *clear,
  22. unsigned clear_len,
  23. void *iv,
  24. void *opaque,
  25. unsigned *opaque_len,
  26. void *auth_tag) {
  27. aes_cbc_ctx_t aes_ctx;
  28. hmac_ctx_t hmac_ctx;
  29. unsigned char enc_key[ENC_KEY_LEN];
  30. unsigned char mac_key[MAC_KEY_LEN];
  31. err_status_t status;
  32. /* check if we're doing authentication only */
  33. if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
  34. /* perform authentication only */
  35. } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
  36. /*
  37. * bad parameter - we expect either all three pointers to be NULL,
  38. * or none of those pointers to be NULL
  39. */
  40. return err_status_fail;
  41. } else {
  42. /* derive encryption and authentication keys from the input key */
  43. status = hmac_init(&hmac_ctx, key, KEY_LEN);
  44. if (status) return status;
  45. status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key);
  46. if (status) return status;
  47. status = hmac_init(&hmac_ctx, key, KEY_LEN);
  48. if (status) return status;
  49. status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key);
  50. if (status) return status;
  51. /* perform encryption and authentication */
  52. /* set aes key */
  53. status = aes_cbc_context_init(&aes_ctx, key, ENC_KEY_LEN, direction_encrypt);
  54. if (status) return status;
  55. /* set iv */
  56. status = crypto_get_random(iv, IV_LEN);
  57. if (status) return status;
  58. status = aes_cbc_set_iv(&aes_ctx, iv);
  59. /* encrypt the opaque data */
  60. status = aes_cbc_nist_encrypt(&aes_ctx, opaque, opaque_len);
  61. if (status) return status;
  62. /* authenticate clear and opaque data */
  63. status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN);
  64. if (status) return status;
  65. status = hmac_start(&hmac_ctx);
  66. if (status) return status;
  67. status = hmac_update(&hmac_ctx, clear, clear_len);
  68. if (status) return status;
  69. status = hmac_compute(&hmac_ctx, opaque, *opaque_len, TAG_LEN, auth_tag);
  70. if (status) return status;
  71. }
  72. return err_status_ok;
  73. }
  74. err_status_t
  75. aes_128_cbc_hmac_sha1_96_inv(void *key,
  76. void *clear,
  77. unsigned clear_len,
  78. void *iv,
  79. void *opaque,
  80. unsigned *opaque_len,
  81. void *auth_tag) {
  82. aes_cbc_ctx_t aes_ctx;
  83. hmac_ctx_t hmac_ctx;
  84. unsigned char enc_key[ENC_KEY_LEN];
  85. unsigned char mac_key[MAC_KEY_LEN];
  86. unsigned char tmp_tag[TAG_LEN];
  87. unsigned char *tag = auth_tag;
  88. err_status_t status;
  89. int i;
  90. /* check if we're doing authentication only */
  91. if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
  92. /* perform authentication only */
  93. } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
  94. /*
  95. * bad parameter - we expect either all three pointers to be NULL,
  96. * or none of those pointers to be NULL
  97. */
  98. return err_status_fail;
  99. } else {
  100. /* derive encryption and authentication keys from the input key */
  101. status = hmac_init(&hmac_ctx, key, KEY_LEN);
  102. if (status) return status;
  103. status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key);
  104. if (status) return status;
  105. status = hmac_init(&hmac_ctx, key, KEY_LEN);
  106. if (status) return status;
  107. status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key);
  108. if (status) return status;
  109. /* perform encryption and authentication */
  110. /* set aes key */
  111. status = aes_cbc_context_init(&aes_ctx, key, ENC_KEY_LEN, direction_decrypt);
  112. if (status) return status;
  113. /* set iv */
  114. status = rand_source_get_octet_string(iv, IV_LEN);
  115. if (status) return status;
  116. status = aes_cbc_set_iv(&aes_ctx, iv);
  117. /* encrypt the opaque data */
  118. status = aes_cbc_nist_decrypt(&aes_ctx, opaque, opaque_len);
  119. if (status) return status;
  120. /* authenticate clear and opaque data */
  121. status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN);
  122. if (status) return status;
  123. status = hmac_start(&hmac_ctx);
  124. if (status) return status;
  125. status = hmac_update(&hmac_ctx, clear, clear_len);
  126. if (status) return status;
  127. status = hmac_compute(&hmac_ctx, opaque, *opaque_len, TAG_LEN, tmp_tag);
  128. if (status) return status;
  129. /* compare the computed tag with the one provided as input */
  130. for (i=0; i < TAG_LEN; i++)
  131. if (tmp_tag[i] != tag[i])
  132. return err_status_auth_fail;
  133. }
  134. return err_status_ok;
  135. }
  136. #define ENC 1
  137. #define DEBUG_PRINT 0
  138. err_status_t
  139. aes_128_cbc_hmac_sha1_96_enc(void *key,
  140. const void *clear,
  141. unsigned clear_len,
  142. void *iv,
  143. void *opaque,
  144. unsigned *opaque_len) {
  145. aes_cbc_ctx_t aes_ctx;
  146. hmac_ctx_t hmac_ctx;
  147. unsigned char enc_key[ENC_KEY_LEN];
  148. unsigned char mac_key[MAC_KEY_LEN];
  149. unsigned char *auth_tag;
  150. err_status_t status;
  151. /* check if we're doing authentication only */
  152. if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
  153. /* perform authentication only */
  154. } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
  155. /*
  156. * bad parameter - we expect either all three pointers to be NULL,
  157. * or none of those pointers to be NULL
  158. */
  159. return err_status_fail;
  160. } else {
  161. #if DEBUG_PRINT
  162. printf("ENC using key %s\n", octet_string_hex_string(key, KEY_LEN));
  163. #endif
  164. /* derive encryption and authentication keys from the input key */
  165. status = hmac_init(&hmac_ctx, key, KEY_LEN);
  166. if (status) return status;
  167. status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key);
  168. if (status) return status;
  169. status = hmac_init(&hmac_ctx, key, KEY_LEN);
  170. if (status) return status;
  171. status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key);
  172. if (status) return status;
  173. /* perform encryption and authentication */
  174. /* set aes key */
  175. status = aes_cbc_context_init(&aes_ctx, key, ENC_KEY_LEN, direction_encrypt);
  176. if (status) return status;
  177. /* set iv */
  178. status = rand_source_get_octet_string(iv, IV_LEN);
  179. if (status) return status;
  180. status = aes_cbc_set_iv(&aes_ctx, iv);
  181. if (status) return status;
  182. #if DEBUG_PRINT
  183. printf("plaintext len: %d\n", *opaque_len);
  184. printf("iv: %s\n", octet_string_hex_string(iv, IV_LEN));
  185. printf("plaintext: %s\n", octet_string_hex_string(opaque, *opaque_len));
  186. #endif
  187. #if ENC
  188. /* encrypt the opaque data */
  189. status = aes_cbc_nist_encrypt(&aes_ctx, opaque, opaque_len);
  190. if (status) return status;
  191. #endif
  192. #if DEBUG_PRINT
  193. printf("ciphertext len: %d\n", *opaque_len);
  194. printf("ciphertext: %s\n", octet_string_hex_string(opaque, *opaque_len));
  195. #endif
  196. /*
  197. * authenticate clear and opaque data, then write the
  198. * authentication tag to the location immediately following the
  199. * ciphertext
  200. */
  201. status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN);
  202. if (status) return status;
  203. status = hmac_start(&hmac_ctx);
  204. if (status) return status;
  205. status = hmac_update(&hmac_ctx, clear, clear_len);
  206. if (status) return status;
  207. #if DEBUG_PRINT
  208. printf("hmac input: %s\n",
  209. octet_string_hex_string(clear, clear_len));
  210. #endif
  211. auth_tag = (unsigned char *)opaque;
  212. auth_tag += *opaque_len;
  213. status = hmac_compute(&hmac_ctx, opaque, *opaque_len, TAG_LEN, auth_tag);
  214. if (status) return status;
  215. #if DEBUG_PRINT
  216. printf("hmac input: %s\n",
  217. octet_string_hex_string(opaque, *opaque_len));
  218. #endif
  219. /* bump up the opaque_len to reflect the authentication tag */
  220. *opaque_len += TAG_LEN;
  221. #if DEBUG_PRINT
  222. printf("prot data len: %d\n", *opaque_len);
  223. printf("prot data: %s\n", octet_string_hex_string(opaque, *opaque_len));
  224. #endif
  225. }
  226. return err_status_ok;
  227. }
  228. err_status_t
  229. aes_128_cbc_hmac_sha1_96_dec(void *key,
  230. const void *clear,
  231. unsigned clear_len,
  232. void *iv,
  233. void *opaque,
  234. unsigned *opaque_len) {
  235. aes_cbc_ctx_t aes_ctx;
  236. hmac_ctx_t hmac_ctx;
  237. unsigned char enc_key[ENC_KEY_LEN];
  238. unsigned char mac_key[MAC_KEY_LEN];
  239. unsigned char tmp_tag[TAG_LEN];
  240. unsigned char *auth_tag;
  241. unsigned ciphertext_len;
  242. err_status_t status;
  243. int i;
  244. /* check if we're doing authentication only */
  245. if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
  246. /* perform authentication only */
  247. } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
  248. /*
  249. * bad parameter - we expect either all three pointers to be NULL,
  250. * or none of those pointers to be NULL
  251. */
  252. return err_status_fail;
  253. } else {
  254. #if DEBUG_PRINT
  255. printf("DEC using key %s\n", octet_string_hex_string(key, KEY_LEN));
  256. #endif
  257. /* derive encryption and authentication keys from the input key */
  258. status = hmac_init(&hmac_ctx, key, KEY_LEN);
  259. if (status) return status;
  260. status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key);
  261. if (status) return status;
  262. status = hmac_init(&hmac_ctx, key, KEY_LEN);
  263. if (status) return status;
  264. status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key);
  265. if (status) return status;
  266. #if DEBUG_PRINT
  267. printf("prot data len: %d\n", *opaque_len);
  268. printf("prot data: %s\n", octet_string_hex_string(opaque, *opaque_len));
  269. #endif
  270. /*
  271. * set the protected data length to that of the ciphertext, by
  272. * subtracting out the length of the authentication tag
  273. */
  274. ciphertext_len = *opaque_len - TAG_LEN;
  275. #if DEBUG_PRINT
  276. printf("ciphertext len: %d\n", ciphertext_len);
  277. #endif
  278. /* verify the authentication tag */
  279. /*
  280. * compute the authentication tag for the clear and opaque data,
  281. * and write it to a temporary location
  282. */
  283. status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN);
  284. if (status) return status;
  285. status = hmac_start(&hmac_ctx);
  286. if (status) return status;
  287. status = hmac_update(&hmac_ctx, clear, clear_len);
  288. if (status) return status;
  289. #if DEBUG_PRINT
  290. printf("hmac input: %s\n",
  291. octet_string_hex_string(clear, clear_len));
  292. #endif
  293. status = hmac_compute(&hmac_ctx, opaque, ciphertext_len, TAG_LEN, tmp_tag);
  294. if (status) return status;
  295. #if DEBUG_PRINT
  296. printf("hmac input: %s\n",
  297. octet_string_hex_string(opaque, ciphertext_len));
  298. #endif
  299. /*
  300. * compare the computed tag with the one provided as input (which
  301. * immediately follows the ciphertext)
  302. */
  303. auth_tag = (unsigned char *)opaque;
  304. auth_tag += ciphertext_len;
  305. #if DEBUG_PRINT
  306. printf("auth_tag: %s\n", octet_string_hex_string(auth_tag, TAG_LEN));
  307. printf("tmp_tag: %s\n", octet_string_hex_string(tmp_tag, TAG_LEN));
  308. #endif
  309. for (i=0; i < TAG_LEN; i++) {
  310. if (tmp_tag[i] != auth_tag[i])
  311. return err_status_auth_fail;
  312. }
  313. /* bump down the opaque_len to reflect the authentication tag */
  314. *opaque_len -= TAG_LEN;
  315. /* decrypt the confidential data */
  316. status = aes_cbc_context_init(&aes_ctx, key, ENC_KEY_LEN, direction_decrypt);
  317. if (status) return status;
  318. status = aes_cbc_set_iv(&aes_ctx, iv);
  319. if (status) return status;
  320. #if DEBUG_PRINT
  321. printf("ciphertext: %s\n", octet_string_hex_string(opaque, *opaque_len));
  322. printf("iv: %s\n", octet_string_hex_string(iv, IV_LEN));
  323. #endif
  324. #if ENC
  325. status = aes_cbc_nist_decrypt(&aes_ctx, opaque, &ciphertext_len);
  326. if (status) return status;
  327. #endif
  328. #if DEBUG_PRINT
  329. printf("plaintext len: %d\n", ciphertext_len);
  330. printf("plaintext: %s\n",
  331. octet_string_hex_string(opaque, ciphertext_len));
  332. #endif
  333. /* indicate the length of the plaintext */
  334. *opaque_len = ciphertext_len;
  335. }
  336. return err_status_ok;
  337. }
  338. cryptoalg_ctx_t cryptoalg_ctx = {
  339. aes_128_cbc_hmac_sha1_96_enc,
  340. aes_128_cbc_hmac_sha1_96_dec,
  341. KEY_LEN,
  342. IV_LEN,
  343. TAG_LEN,
  344. MAX_EXPAND,
  345. };
  346. cryptoalg_t cryptoalg = &cryptoalg_ctx;
  347. #define NULL_TAG_LEN 12
  348. err_status_t
  349. null_enc(void *key,
  350. const void *clear,
  351. unsigned clear_len,
  352. void *iv,
  353. void *opaque,
  354. unsigned *opaque_len) {
  355. int i;
  356. unsigned char *auth_tag;
  357. unsigned char *init_vec = iv;
  358. /* check if we're doing authentication only */
  359. if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
  360. /* perform authentication only */
  361. } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
  362. /*
  363. * bad parameter - we expect either all three pointers to be NULL,
  364. * or none of those pointers to be NULL
  365. */
  366. return err_status_fail;
  367. } else {
  368. #if DEBUG_PRINT
  369. printf("NULL ENC using key %s\n", octet_string_hex_string(key, KEY_LEN));
  370. printf("NULL_TAG_LEN: %d\n", NULL_TAG_LEN);
  371. printf("plaintext len: %d\n", *opaque_len);
  372. #endif
  373. for (i=0; i < IV_LEN; i++)
  374. init_vec[i] = i + (i * 16);
  375. #if DEBUG_PRINT
  376. printf("iv: %s\n",
  377. octet_string_hex_string(iv, IV_LEN));
  378. printf("plaintext: %s\n",
  379. octet_string_hex_string(opaque, *opaque_len));
  380. #endif
  381. auth_tag = opaque;
  382. auth_tag += *opaque_len;
  383. for (i=0; i < NULL_TAG_LEN; i++)
  384. auth_tag[i] = i + (i * 16);
  385. *opaque_len += NULL_TAG_LEN;
  386. #if DEBUG_PRINT
  387. printf("protected data len: %d\n", *opaque_len);
  388. printf("protected data: %s\n",
  389. octet_string_hex_string(opaque, *opaque_len));
  390. #endif
  391. }
  392. return err_status_ok;
  393. }
  394. err_status_t
  395. null_dec(void *key,
  396. const void *clear,
  397. unsigned clear_len,
  398. void *iv,
  399. void *opaque,
  400. unsigned *opaque_len) {
  401. unsigned char *auth_tag;
  402. /* check if we're doing authentication only */
  403. if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) {
  404. /* perform authentication only */
  405. } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) {
  406. /*
  407. * bad parameter - we expect either all three pointers to be NULL,
  408. * or none of those pointers to be NULL
  409. */
  410. return err_status_fail;
  411. } else {
  412. #if DEBUG_PRINT
  413. printf("NULL DEC using key %s\n", octet_string_hex_string(key, KEY_LEN));
  414. printf("protected data len: %d\n", *opaque_len);
  415. printf("protected data: %s\n",
  416. octet_string_hex_string(opaque, *opaque_len));
  417. #endif
  418. auth_tag = opaque;
  419. auth_tag += (*opaque_len - NULL_TAG_LEN);
  420. #if DEBUG_PRINT
  421. printf("iv: %s\n", octet_string_hex_string(iv, IV_LEN));
  422. #endif
  423. *opaque_len -= NULL_TAG_LEN;
  424. #if DEBUG_PRINT
  425. printf("plaintext len: %d\n", *opaque_len);
  426. printf("plaintext: %s\n",
  427. octet_string_hex_string(opaque, *opaque_len));
  428. #endif
  429. }
  430. return err_status_ok;
  431. }
  432. cryptoalg_ctx_t null_cryptoalg_ctx = {
  433. null_enc,
  434. null_dec,
  435. KEY_LEN,
  436. IV_LEN,
  437. NULL_TAG_LEN,
  438. MAX_EXPAND,
  439. };
  440. cryptoalg_t null_cryptoalg = &null_cryptoalg_ctx;
  441. int
  442. cryptoalg_get_id(cryptoalg_t c) {
  443. if (c == cryptoalg)
  444. return 1;
  445. return 0;
  446. }
  447. cryptoalg_t
  448. cryptoalg_find_by_id(int id) {
  449. switch(id) {
  450. case 1:
  451. return cryptoalg;
  452. default:
  453. break;
  454. }
  455. return 0;
  456. }