summaryrefslogtreecommitdiffstats
path: root/certdata2pem.sh
diff options
context:
space:
mode:
authorPatrick McDermott <patrick.mcdermott@libiquity.com>2020-07-17 21:50:30 (EDT)
committer Patrick McDermott <patrick.mcdermott@libiquity.com>2020-07-18 00:18:06 (EDT)
commit8ab1665575137e607ead3fa34982b6279373c39c (patch)
tree18cc5376d40217de15127e4a7e530a292dab8124 /certdata2pem.sh
Initial commit
Diffstat (limited to 'certdata2pem.sh')
-rwxr-xr-xcertdata2pem.sh176
1 files changed, 176 insertions, 0 deletions
diff --git a/certdata2pem.sh b/certdata2pem.sh
new file mode 100755
index 0000000..e12fc67
--- /dev/null
+++ b/certdata2pem.sh
@@ -0,0 +1,176 @@
+#!/bin/sh
+#
+# Converts NSS certdata objects text into a concatenated PEM bundle.
+#
+# Copyright (C) 2020 Patrick McDermott
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+set -eu
+
+error()
+{
+ local fmt="${1}"
+ shift 1
+
+ printf "Error: ${fmt}\n" "${@}" 1>&2
+}
+
+parse()
+{
+ local txt_input="${1}"
+ local trust_type="${2}"
+ local pem_output="${3}"
+ shift 3
+ local attr=
+ local type=
+ local val=
+ local class=
+ local label=
+ local value=
+ local trust=
+ local trusted=
+
+ if [ x"${txt_input}" != x'-' ]; then
+ exec 0<"${txt_input}"
+ fi
+ if [ x"${pem_output}" != x'-' ]; then
+ exec 1>"${pem_output}"
+ fi
+
+ while read -r attr && [ x"${attr}" != x'BEGINDATA' ]; do :; done
+
+ while read -r attr type val; do
+ case "${attr}" in
+ '#'*)
+ continue
+ ;;
+ 'CKA_CLASS')
+ class="${val}"
+ ;;
+ 'CKA_LABEL')
+ val="${val#\"}"
+ val="${val%\"}"
+ label="$(printf '%s' "${val}" | \
+ tr -C 'A-Za-z0-9_' '_')"
+ ;;
+ 'CKA_VALUE')
+ if [ x"${type}" != x'MULTILINE_OCTAL' ]; then
+ error 'Unsupported value type'
+ return 1
+ fi
+ value=
+ while read -r val; do
+ case "${val}" in
+ 'END')
+ break
+ ;;
+ *[!0-7\\]*)
+ error "Invalid $(: \
+ )multiline $(: \
+ )octal value"
+ return 1
+ ;;
+ *)
+ value="${value}$(printf\
+ "${val}")"
+ ;;
+ esac
+ done
+ ;;
+ "CKA_TRUST_${trust_type}")
+ trust="${val}"
+ ;;
+ '')
+ if [ -z "${class}" ]; then
+ error 'Object missing class'
+ return 1
+ fi
+ if [ -z "${label}" ]; then
+ error 'Object missing label'
+ return 1
+ fi
+ if [ x"${class}" = x'CKO_CERTIFICATE' ]; then
+ if [ -z "${value}" ]; then
+ error 'Object missing value'
+ return 1
+ fi
+ eval "certificate_${label}=\${value}"
+ elif [ x"${class}" = x'CKO_NSS_TRUST' ]; then
+ if [ -z "${trust}" ]; then
+ error 'Object missing trust'
+ return 1
+ fi
+ if [ x"${trust}" = \
+ x'CKT_NSS_TRUSTED_DELEGATOR' ]
+ then
+ trusted="${trusted} ${label}"
+ fi
+ elif [ x"${class}" = \
+ x'CKO_NSS_BUILTIN_ROOT_LIST' ]
+ then
+ :
+ else
+ error 'Unknown class "%s"' "${val}"
+ return 1
+ fi
+ class=
+ label=
+ value=
+ trust=
+ esac
+ done <<-EOF
+ $(cat)
+
+ EOF
+ # Extra newline in input to trigger final empty line block in parser.
+
+ for label in ${trusted}; do
+ printf '%s\n' '-----BEGIN CERTIFICATE-----'
+ eval "printf '%s' \"\${certificate_${label}}\"" | base64 -
+ printf '%s\n' '-----END CERTIFICATE-----'
+ done
+
+ return 0
+}
+
+usage()
+{
+ printf 'Usage: %s <txt-input> <trust-type> <pem-output>\n' "${0}"
+ printf 'Example: %s certdata.txt SERVER_AUTH certdata.pem\n' "${0}"
+
+ return 0
+}
+
+main()
+{
+ local txt_input=
+ local trust_type=
+ local pem_output=
+
+ if [ ${#} -ne 3 ]; then
+ usage 1>&2
+ return 1
+ fi
+ txt_input="${1}"
+ trust_type="${2}"
+ pem_output="${3}"
+ shift 3
+
+ parse "${txt_input}" "${trust_type}" "${pem_output}" || return 1
+
+ return 0
+}
+
+main "${@}"