fips_integrity.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. /*
  2. * Perform FIPS Integrity test on Kernel Crypto API
  3. *
  4. * At build time, hmac(sha256) of crypto code, avaiable in different ELF sections
  5. * of vmlinux file, is generated. vmlinux file is updated with built-time hmac
  6. * in a read-only data variable, so that it is available at run-time
  7. *
  8. * At run time, hmac(sha256) is again calculated using crypto bytes of a running
  9. * kernel.
  10. * Run time hmac is compared to built time hmac to verify the integrity.
  11. *
  12. *
  13. * Author : Rohit Kothari (r.kothari@samsung.com)
  14. * Date : 11 Feb 2014
  15. *
  16. * Copyright (c) 2014 Samsung Electronics
  17. *
  18. */
  19. #include <linux/crypto.h>
  20. #include <linux/kallsyms.h>
  21. #include <linux/err.h>
  22. #include <linux/scatterlist.h>
  23. #include "internal.h" /* For Functional test macros */
  24. static const char *
  25. symtab[][3] = {{".text", "first_crypto_text", "last_crypto_text" },
  26. {".rodata", "first_crypto_rodata", "last_crypto_rodata"},
  27. {".init.text", "first_crypto_init", "last_crypto_init" },
  28. {".exit.text", "first_crypto_exit", "last_crypto_exit" },
  29. {"asm.text", "first_crypto_asm_text", "last_crypto_asm_text" },
  30. {"asm.rodata", "first_crypto_asm_rodata", "last_crypto_asm_rodata"},
  31. {"asm.init.text", "first_crypto_asm_init", "last_crypto_asm_init" },
  32. {"asm.exit.text", "first_crypto_asm_exit", "last_crypto_asm_exit" }};
  33. extern const char * get_builtime_crypto_hmac(void);
  34. #ifdef FIPS_DEBUG
  35. static int
  36. dump_bytes(const char * section_name, const char * first_symbol, const char * last_symbol)
  37. {
  38. u8 * start_addr = (u8 *) kallsyms_lookup_name (first_symbol);
  39. u8 * end_addr = (u8 *) kallsyms_lookup_name (last_symbol);
  40. if (!start_addr || !end_addr || start_addr >= end_addr)
  41. {
  42. printk(KERN_ERR "FIPS(%s): Error Invalid Addresses in Section : %s, Start_Addr : %p , End_Addr : %p",
  43. __FUNCTION__,section_name, start_addr, end_addr);
  44. return -1;
  45. }
  46. printk(KERN_INFO "FIPS CRYPTO RUNTIME : Section - %s, %s : %p, %s : %p \n", section_name, first_symbol, start_addr, last_symbol, end_addr);
  47. print_hex_dump_bytes ("FIPS CRYPTO RUNTIME : ",DUMP_PREFIX_NONE, start_addr, end_addr - start_addr);
  48. return 0;
  49. }
  50. #endif
  51. static int
  52. query_symbol_addresses (const char * first_symbol, const char * last_symbol,
  53. unsigned long * start_addr,unsigned long * end_addr)
  54. {
  55. unsigned long start = kallsyms_lookup_name (first_symbol);
  56. unsigned long end = kallsyms_lookup_name (last_symbol);
  57. #ifdef FIPS_DEBUG
  58. printk(KERN_INFO "FIPS CRYPTO RUNTIME : %s : %p, %s : %p\n", first_symbol, (u8*)start, last_symbol, (u8*)end);
  59. #endif
  60. if (!start || !end || start >= end)
  61. {
  62. printk(KERN_ERR "FIPS(%s): Error Invalid Addresses.", __FUNCTION__);
  63. return -1;
  64. }
  65. *start_addr = start;
  66. *end_addr = end;
  67. return 0;
  68. }
  69. static int
  70. init_hash (struct hash_desc * desc)
  71. {
  72. struct crypto_hash * tfm = NULL;
  73. int ret = -1;
  74. /* Same as build time */
  75. const unsigned char * key = "The quick brown fox jumps over the lazy dog";
  76. tfm = crypto_alloc_hash ("hmac(sha256)", 0, 0);
  77. if (IS_ERR(tfm)) {
  78. printk(KERN_ERR "FIPS(%s): integ failed to allocate tfm %ld", __FUNCTION__, PTR_ERR(tfm));
  79. return -1;
  80. }
  81. ret = crypto_hash_setkey (tfm, key, strlen(key));
  82. if (ret) {
  83. printk(KERN_ERR "FIPS(%s): fail at crypto_hash_setkey", __FUNCTION__);
  84. return -1;
  85. }
  86. desc->tfm = tfm;
  87. desc->flags = 0;
  88. ret = crypto_hash_init (desc);
  89. if (ret) {
  90. printk(KERN_ERR "FIPS(%s): fail at crypto_hash_init", __FUNCTION__);
  91. return -1;
  92. }
  93. return 0;
  94. }
  95. static int
  96. finalize_hash (struct hash_desc *desc, unsigned char * out, unsigned int out_size)
  97. {
  98. int ret = -1;
  99. if (!desc || !desc->tfm || !out || !out_size)
  100. {
  101. printk(KERN_ERR "FIPS(%s): Invalid args", __FUNCTION__);
  102. return ret;
  103. }
  104. if (crypto_hash_digestsize(desc->tfm) > out_size)
  105. {
  106. printk(KERN_ERR "FIPS(%s): Not enough space for digest", __FUNCTION__);
  107. return ret;
  108. }
  109. ret = crypto_hash_final (desc, out);
  110. if (ret)
  111. {
  112. printk(KERN_ERR "FIPS(%s): crypto_hash_final failed", __FUNCTION__);
  113. return -1;
  114. }
  115. return 0;
  116. }
  117. static int
  118. update_hash (struct hash_desc * desc, unsigned char * start_addr, unsigned int size)
  119. {
  120. struct scatterlist sg;
  121. unsigned char * buf = NULL;
  122. unsigned char * cur = NULL;
  123. unsigned int bytes_remaining;
  124. unsigned int bytes;
  125. int ret = -1;
  126. #if FIPS_FUNC_TEST == 2
  127. static int total = 0;
  128. #endif
  129. buf = kmalloc (PAGE_SIZE, GFP_KERNEL);
  130. if (!buf)
  131. {
  132. printk(KERN_ERR "FIPS(%s): kmalloc failed", __FUNCTION__);
  133. return ret;
  134. }
  135. bytes_remaining = size;
  136. cur = start_addr;
  137. while (bytes_remaining > 0)
  138. {
  139. if (bytes_remaining >= PAGE_SIZE)
  140. bytes = PAGE_SIZE;
  141. else
  142. bytes = bytes_remaining;
  143. memcpy (buf, cur, bytes);
  144. sg_init_one (&sg, buf, bytes);
  145. #if FIPS_FUNC_TEST == 2
  146. if (total == 0)
  147. {
  148. printk(KERN_INFO "FIPS : Failing Integrity Test");
  149. buf[bytes / 2] += 1;
  150. }
  151. #endif
  152. ret = crypto_hash_update (desc, &sg, bytes);
  153. if (ret)
  154. {
  155. printk(KERN_ERR "FIPS(%s): crypto_hash_update failed", __FUNCTION__);
  156. kfree(buf);
  157. buf = 0;
  158. return -1;
  159. }
  160. cur += bytes;
  161. bytes_remaining -= bytes;
  162. #if FIPS_FUNC_TEST == 2
  163. total += bytes;
  164. #endif
  165. }
  166. //printk(KERN_INFO "FIPS : total bytes = %d\n", total);
  167. if (buf)
  168. {
  169. kfree(buf);
  170. buf = 0;
  171. }
  172. return 0;
  173. }
  174. int
  175. do_integrity_check (void)
  176. {
  177. int i,rows, err;
  178. unsigned long start_addr = 0;
  179. unsigned long end_addr = 0;
  180. unsigned char runtime_hmac[32];
  181. struct hash_desc desc;
  182. const char * builtime_hmac = 0;
  183. unsigned int size = 0;
  184. err = init_hash (&desc);
  185. if (err)
  186. {
  187. printk (KERN_ERR "FIPS(%s): init_hash failed", __FUNCTION__);
  188. return -1;
  189. }
  190. rows = (unsigned int) sizeof (symtab) / sizeof (symtab[0]);
  191. for (i = 0; i < rows; i++)
  192. {
  193. err = query_symbol_addresses (symtab[i][1], symtab[i][2], &start_addr, &end_addr);
  194. if (err)
  195. {
  196. printk (KERN_ERR "FIPS(%s): Error to get start / end addresses", __FUNCTION__);
  197. crypto_free_hash (desc.tfm);
  198. return -1;
  199. }
  200. #ifdef FIPS_DEBUG
  201. dump_bytes(symtab[i][0], symtab[i][1], symtab[i][2]);
  202. #endif
  203. size = end_addr - start_addr;
  204. err = update_hash (&desc, (unsigned char *)start_addr, size);
  205. if (err)
  206. {
  207. printk (KERN_ERR "FIPS(%s): Error to update hash", __FUNCTION__);
  208. crypto_free_hash (desc.tfm);
  209. return -1;
  210. }
  211. }
  212. err = finalize_hash (&desc, runtime_hmac, sizeof(runtime_hmac));
  213. crypto_free_hash (desc.tfm);
  214. if (err)
  215. {
  216. printk (KERN_ERR "FIPS(%s): Error in finalize", __FUNCTION__);
  217. return -1;
  218. }
  219. builtime_hmac = get_builtime_crypto_hmac();
  220. if (!builtime_hmac)
  221. {
  222. printk (KERN_ERR "FIPS(%s): Unable to retrieve builtime_hmac", __FUNCTION__);
  223. return -1;
  224. }
  225. #ifdef FIPS_DEBUG
  226. print_hex_dump_bytes ("FIPS CRYPTO RUNTIME : runtime hmac = ",DUMP_PREFIX_NONE, runtime_hmac, sizeof(runtime_hmac));
  227. print_hex_dump_bytes ("FIPS CRYPTO RUNTIME : builtime_hmac = ",DUMP_PREFIX_NONE, builtime_hmac , sizeof(runtime_hmac));
  228. #endif
  229. if (!memcmp (builtime_hmac, runtime_hmac, sizeof(runtime_hmac)))
  230. {
  231. printk (KERN_INFO "FIPS: Integrity Check Passed");
  232. return 0;
  233. }
  234. else
  235. {
  236. printk (KERN_ERR "FIPS(%s): Integrity Check Failed", __FUNCTION__);
  237. set_in_fips_err();
  238. return -1;
  239. }
  240. return -1;
  241. }
  242. EXPORT_SYMBOL_GPL(do_integrity_check);
  243. #ifdef CONFIG_CRYPTO_FIPS_OLD_INTEGRITY_CHECK
  244. /*
  245. * Integrity check code for crypto module.
  246. *
  247. * This program is free software; you can redistribute it and/or modify it
  248. * under the terms of the GNU General Public License as published by the Free
  249. * Software Foundation; either version 2 of the License, or (at your option)
  250. * any later version.
  251. *
  252. */
  253. #include <crypto/hash.h>
  254. #include <crypto/sha.h>
  255. #include <linux/err.h>
  256. #include <linux/scatterlist.h>
  257. #include <asm-generic/sections.h>
  258. #include <linux/vmalloc.h>
  259. #include <linux/slab.h>
  260. #include "internal.h"
  261. static bool need_integrity_check = true;
  262. extern long integrity_mem_reservoir;
  263. //extern void free_bootmem(unsigned long addr, unsigned long size);
  264. void do_integrity_check(void)
  265. {
  266. u8 *rbuf = 0;
  267. u32 len;
  268. u8 hmac[SHA256_DIGEST_SIZE];
  269. struct hash_desc desc;
  270. struct scatterlist sg;
  271. u8 *key = "12345678";
  272. int i, step_len = PAGE_SIZE, err;
  273. u8 *pAllocBuf = 0;
  274. printk(KERN_INFO "FIPS: integrity start\n");
  275. if (unlikely(!need_integrity_check || in_fips_err())) {
  276. printk(KERN_INFO "FIPS: integrity check not needed\n");
  277. return;
  278. }
  279. rbuf = (u8*)phys_to_virt((unsigned long)CONFIG_CRYPTO_FIPS_INTEG_COPY_ADDRESS);
  280. if (*((u32 *) &rbuf[36]) != 0x016F2818) {
  281. printk(KERN_ERR "FIPS: invalid zImage magic number.");
  282. set_in_fips_err();
  283. goto err1;
  284. }
  285. if (*(u32 *) &rbuf[44] <= *(u32 *) &rbuf[40]) {
  286. printk(KERN_ERR "FIPS: invalid zImage calculated len");
  287. set_in_fips_err();
  288. goto err1;
  289. }
  290. len = *(u32 *) &rbuf[44] - *(u32 *) &rbuf[40];
  291. printk(KERN_INFO "FIPS: integrity actual zImageLen = %d\n", len);
  292. printk(KERN_INFO "FIPS: do kernel integrity check address: %lx \n", (unsigned long)rbuf);
  293. desc.tfm = crypto_alloc_hash("hmac(sha256)", 0, 0);
  294. if (IS_ERR(desc.tfm)) {
  295. printk(KERN_ERR "FIPS: integ failed to allocate tfm %ld\n",
  296. PTR_ERR(desc.tfm));
  297. set_in_fips_err();
  298. goto err1;
  299. }
  300. #if FIPS_FUNC_TEST == 2
  301. rbuf[1024] = rbuf[1024] + 1;
  302. #endif
  303. crypto_hash_setkey(desc.tfm, key, strlen(key));
  304. pAllocBuf = kmalloc(step_len,GFP_KERNEL);
  305. if (!pAllocBuf) {
  306. printk(KERN_INFO "Fail to alloc memory, length %d\n", step_len);
  307. set_in_fips_err();
  308. goto err1;
  309. }
  310. err = crypto_hash_init(&desc);
  311. if (err) {
  312. printk(KERN_INFO "fail at crypto_hash_init\n");
  313. set_in_fips_err();
  314. kfree(pAllocBuf);
  315. goto err1;
  316. }
  317. for (i = 0; i < len; i += step_len) {
  318. //last is reached
  319. if (i + step_len >= len - 1) {
  320. memcpy(pAllocBuf, &rbuf[i], len - i);
  321. sg_init_one(&sg, pAllocBuf, len - i);
  322. err = crypto_hash_update(&desc, &sg, len - i);
  323. if (err) {
  324. printk(KERN_INFO "Fail to crypto_hash_update1\n");
  325. set_in_fips_err();
  326. goto err;
  327. }
  328. err = crypto_hash_final(&desc, hmac);
  329. if (err) {
  330. printk(KERN_INFO "Fail to crypto_hash_final\n");
  331. set_in_fips_err();
  332. goto err;
  333. }
  334. } else {
  335. memcpy(pAllocBuf, &rbuf[i], step_len);
  336. sg_init_one(&sg, pAllocBuf, step_len);
  337. err = crypto_hash_update(&desc, &sg, step_len);
  338. if (err) {
  339. printk(KERN_INFO "Fail to crypto_hash_update\n");
  340. set_in_fips_err();
  341. goto err;
  342. }
  343. }
  344. }
  345. #if FIPS_FUNC_TEST == 2
  346. rbuf[1024] = rbuf[1024] - 1;
  347. #endif
  348. if (!strncmp(hmac, &rbuf[len], SHA256_DIGEST_SIZE)) {
  349. printk(KERN_INFO "FIPS: integrity check passed\n");
  350. } else {
  351. printk(KERN_ERR "FIPS: integrity check failed. hmac:%lx, buf:%lx.\n",(long) hmac, (long)rbuf[len] );
  352. set_in_fips_err();
  353. }
  354. err:
  355. kfree(pAllocBuf);
  356. crypto_free_hash(desc.tfm);
  357. err1:
  358. need_integrity_check = false;
  359. /* if(integrity_mem_reservoir != 0) {
  360. printk(KERN_NOTICE "FIPS free integrity_mem_reservoir = %ld\n", integrity_mem_reservoir);
  361. free_bootmem((unsigned long)CONFIG_CRYPTO_FIPS_INTEG_COPY_ADDRESS, integrity_mem_reservoir);
  362. }
  363. */
  364. }
  365. EXPORT_SYMBOL_GPL(do_integrity_check);
  366. #endif //CONFIG_CRYPTO_FIPS_OLD_INTEGRITY_CHECK