clevis-luks-bind 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #!/bin/bash -e
  2. # vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
  3. #
  4. # Copyright (c) 2016 Red Hat, Inc.
  5. # Author: Harald Hoyer <harald@redhat.com>
  6. # Author: Nathaniel McCallum <npmccallum@redhat.com>
  7. #
  8. # This program is free software: you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License as published by
  10. # the Free Software Foundation, either version 3 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU General Public License
  19. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. #
  21. . clevis-luks-common-functions
  22. SUMMARY="Binds a LUKS device using the specified policy"
  23. usage() {
  24. exec >&2
  25. echo
  26. echo "Usage: clevis luks bind [-y] [-f] [-s SLT] [-k KEY] [-t TOKEN_ID] [-e EXISTING_TOKEN_ID] -d DEV PIN CFG"
  27. echo
  28. echo "$SUMMARY":
  29. echo
  30. echo " -f Do not prompt for LUKSMeta initialization"
  31. echo
  32. echo " -d DEV The LUKS device on which to perform binding"
  33. echo
  34. echo " -y Automatically answer yes for all questions"
  35. echo
  36. echo " -s SLT The LUKS slot to use"
  37. echo
  38. echo " -t TKN_ID The LUKS token ID to use; only available for LUKS2"
  39. echo
  40. echo " -k KEY Non-interactively read LUKS password from KEY file"
  41. echo " -k - Non-interactively read LUKS password from standard input"
  42. echo
  43. echo " -e E_TKN_ID Existing LUKS token ID for existing passphrase; only available for LUKS2"
  44. echo
  45. exit 2
  46. }
  47. if [ $# -eq 1 ] && [ "$1" = "--summary" ]; then
  48. echo "$SUMMARY"
  49. exit 0
  50. fi
  51. FRC=
  52. YES=
  53. while getopts ":hfyd:s:k:t:e:" o; do
  54. case "$o" in
  55. f) FRC='-f';;
  56. d) DEV="$OPTARG";;
  57. s) SLT="$OPTARG";;
  58. k) KEY="$OPTARG";;
  59. t) TOKEN_ID="$OPTARG";;
  60. e) EXISTING_TOKEN_ID="$OPTARG";;
  61. y) FRC='-f'
  62. YES='-y';;
  63. *) usage;;
  64. esac
  65. done
  66. if [ -z "$DEV" ]; then
  67. echo "Did not specify a device!" >&2
  68. usage
  69. fi
  70. if ! luks_type="$(clevis_luks_type "${DEV}")"; then
  71. echo "${DEV} is not a supported LUKS device" >&2
  72. exit 1
  73. fi
  74. if ! PIN="${@:$((OPTIND++)):1}" || [ -z "$PIN" ]; then
  75. echo "Did not specify a pin!" >&2
  76. usage
  77. elif ! EXE=$(command -v clevis-encrypt-"${PIN}") || [ -z "${EXE}" ]; then
  78. echo "'${PIN}' is not a valid pin!" >&2
  79. usage
  80. fi
  81. if ! CFG="${@:$((OPTIND++)):1}" || [ -z "$CFG" ]; then
  82. echo "Did not specify a pin config!" >&2
  83. usage
  84. fi
  85. # Check whether the config is valid JSON.
  86. if ! jose fmt --json="${CFG}" --object 2>/dev/null; then
  87. echo "Configuration is malformed; it should be valid JSON" >&2
  88. exit 1
  89. fi
  90. if [ "${luks_type}" = "luks1" ] && [ -n "${TOKEN_ID}" ]; then
  91. echo "${DEV} is a LUKS1 device; -t is only supported in LUKS2" >&2
  92. exit 1
  93. fi
  94. if [ -n "${EXISTING_TOKEN_ID}" ] && ! clevis_luks_luks2_existing_token_id_supported; then
  95. echo "Existing token ID not supported in this cryptsetup version" >&2
  96. exit 1
  97. fi
  98. # Get the existing passphrase/keyfile.
  99. existing_key=
  100. keyfile=
  101. case "${KEY}" in
  102. "")
  103. if [ -z "${EXISTING_TOKEN_ID}" ] ; then
  104. IFS= read -r -s -p "Enter existing LUKS password: " existing_key; echo >&2
  105. fi
  106. ;;
  107. -) IFS= read -r -s -p "" existing_key ||:
  108. if [ "${luks_type}" = "luks1" ] && ! luksmeta test -d "${DEV}" \
  109. && [ -z "${FRC}" ]; then
  110. echo "Cannot use '-k-' without '-f' or '-y' unless already initialized!" >&2
  111. usage
  112. fi
  113. ;;
  114. *) keyfile="${KEY}"
  115. if [ ! -r "${keyfile}" ]; then
  116. echo "Cannot read key file '${keyfile}'" >&2
  117. exit 1
  118. fi
  119. ;;
  120. esac
  121. # Check if existing token id for keyring read is provided
  122. # If so, keyfile is not allowed
  123. if [ -n "${EXISTING_TOKEN_ID}" ] && [ -n "${keyfile}" ] ; then
  124. echo "Cannot specify kernel keyring description together with key file" >&2
  125. exit 1
  126. fi
  127. # If necessary, initialize the LUKS volume.
  128. if [ "${luks_type}" = "luks1" ] && ! luksmeta test -d "${DEV}"; then
  129. luksmeta init -d "${DEV}" ${FRC}
  130. fi
  131. if ! clevis_luks_do_bind "${DEV}" "${SLT}" "${TOKEN_ID}" \
  132. "${PIN}" "${CFG}" \
  133. "${YES}" "" \
  134. "${existing_key}" "${keyfile}" "${EXISTING_TOKEN_ID}"; then
  135. echo "Error adding new binding to ${DEV}" >&2
  136. exit 1
  137. fi