ima_keys.sh 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #!/bin/sh
  2. # SPDX-License-Identifier: GPL-2.0-or-later
  3. # Copyright (c) 2020 Microsoft Corporation
  4. # Copyright (c) 2020 Petr Vorel <pvorel@suse.cz>
  5. # Author: Lachlan Sneff <t-josne@linux.microsoft.com>
  6. #
  7. # Verify that keys are measured correctly based on policy.
  8. TST_NEEDS_CMDS="cmp cut grep sed xxd"
  9. TST_CNT=2
  10. TST_NEEDS_DEVICE=1
  11. TST_SETUP=setup
  12. TST_CLEANUP=cleanup
  13. . ima_setup.sh
  14. FUNC_KEYCHECK='func=KEY_CHECK'
  15. TEMPLATE_BUF='template=ima-buf'
  16. REQUIRED_POLICY="^measure.*($FUNC_KEYCHECK.*$TEMPLATE_BUF|$TEMPLATE_BUF.*$FUNC_KEYCHECK)"
  17. setup()
  18. {
  19. require_ima_policy_content "$REQUIRED_POLICY" '-E' > $TST_TMPDIR/policy.txt
  20. }
  21. cleanup()
  22. {
  23. tst_is_num $KEYRING_ID && keyctl clear $KEYRING_ID
  24. }
  25. check_keys_policy()
  26. {
  27. local pattern="$1"
  28. if ! grep -E "$pattern" $TST_TMPDIR/policy.txt; then
  29. tst_res TCONF "IMA policy must specify $pattern, $FUNC_KEYCHECK, $TEMPLATE_BUF"
  30. return 1
  31. fi
  32. return 0
  33. }
  34. # Based on https://lkml.org/lkml/2019/12/13/564.
  35. # (450d0fd51564 - "IMA: Call workqueue functions to measure queued keys")
  36. test1()
  37. {
  38. local keycheck_lines i keyrings templates
  39. local pattern='keyrings=[^[:space:]]+'
  40. local test_file="file.txt" tmp_file="file2.txt"
  41. tst_res TINFO "verify key measurement for keyrings and templates specified in IMA policy"
  42. check_keys_policy "$pattern" > $tmp_file || return
  43. keycheck_lines=$(cat $tmp_file)
  44. keyrings=$(for i in $keycheck_lines; do echo "$i" | grep "keyrings" | \
  45. sed "s/\./\\\./g" | cut -d'=' -f2; done | sed ':a;N;$!ba;s/\n/|/g')
  46. if [ -z "$keyrings" ]; then
  47. tst_res TCONF "IMA policy has a keyring key-value specifier, but no specified keyrings"
  48. return
  49. fi
  50. templates=$(for i in $keycheck_lines; do echo "$i" | grep "template" | \
  51. cut -d'=' -f2; done | sed ':a;N;$!ba;s/\n/|/g')
  52. tst_res TINFO "keyrings: '$keyrings'"
  53. tst_res TINFO "templates: '$templates'"
  54. grep -E "($templates).*($keyrings)" $ASCII_MEASUREMENTS | while read line
  55. do
  56. local digest expected_digest algorithm
  57. digest=$(echo "$line" | cut -d' ' -f4 | cut -d':' -f2)
  58. algorithm=$(echo "$line" | cut -d' ' -f4 | cut -d':' -f1)
  59. keyring=$(echo "$line" | cut -d' ' -f5)
  60. echo "$line" | cut -d' ' -f6 | xxd -r -p > $test_file
  61. if ! expected_digest="$(compute_digest $algorithm $test_file)"; then
  62. tst_res TCONF "cannot compute digest for $algorithm"
  63. return
  64. fi
  65. if [ "$digest" != "$expected_digest" ]; then
  66. tst_res TFAIL "incorrect digest was found for $keyring keyring"
  67. return
  68. fi
  69. done
  70. tst_res TPASS "specified keyrings were measured correctly"
  71. }
  72. # Create a new keyring, import a certificate into it, and verify
  73. # that the certificate is measured correctly by IMA.
  74. test2()
  75. {
  76. tst_require_cmds evmctl keyctl openssl
  77. local cert_file="$TST_DATAROOT/x509_ima.der"
  78. local keyring_name="key_import_test"
  79. local pattern="keyrings=[^[:space:]]*$keyring_name"
  80. local temp_file="file.txt"
  81. tst_res TINFO "verify measurement of certificate imported into a keyring"
  82. check_keys_policy "$pattern" >/dev/null || return
  83. KEYRING_ID=$(keyctl newring $keyring_name @s) || \
  84. tst_brk TBROK "unable to create a new keyring"
  85. if ! tst_is_num $KEYRING_ID; then
  86. tst_brk TBROK "unable to parse the new keyring id ('$KEYRING_ID')"
  87. fi
  88. evmctl import $cert_file $KEYRING_ID > /dev/null || \
  89. tst_brk TBROK "unable to import a certificate into $keyring_name keyring"
  90. grep $keyring_name $ASCII_MEASUREMENTS | tail -n1 | cut -d' ' -f6 | \
  91. xxd -r -p > $temp_file
  92. if [ ! -s $temp_file ]; then
  93. tst_res TFAIL "keyring $keyring_name not found in $ASCII_MEASUREMENTS"
  94. return
  95. fi
  96. if ! openssl x509 -in $temp_file -inform der > /dev/null; then
  97. tst_res TFAIL "logged certificate is not a valid x509 certificate"
  98. return
  99. fi
  100. if cmp -s $temp_file $cert_file; then
  101. tst_res TPASS "logged certificate matches the original"
  102. else
  103. tst_res TFAIL "logged certificate does not match original"
  104. fi
  105. }
  106. tst_run