#!/bin/bash
# Smart Card Management Tool (c) 2009 Timothy Pearson
#
# 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 .
# The [secure] temporary directory for authentication
SECURE_DIRECTORY=/tmp/smartauth
# Create the secure directory and lock it down
mkdir -p $SECURE_DIRECTORY
chown root $SECURE_DIRECTORY
chgrp root $SECURE_DIRECTORY
chmod 600 $SECURE_DIRECTORY
SECURE_DIRECTORY=$(mktemp /tmp/smartauth/setupcard.XXXXXXXXXX)
rm -rf $SECURE_DIRECTORY
mkdir -p $SECURE_DIRECTORY
chown root $SECURE_DIRECTORY
chgrp root $SECURE_DIRECTORY
chmod 600 $SECURE_DIRECTORY
# See if required programs are installed
scriptor=$(whereis scriptor)
if [[ $scriptor == "scriptor:" ]]; then
echo "ERROR: scriptor is not installed! This program cannot continue!"
zenity --error --text "ERROR: scriptor is not installed!\nThis program cannot continue!\n\nUsually, scriptor is part of the pcsc-tools package."
exit
fi
opensc=$(whereis opensc-explorer)
if [[ $opensc == "opensc-explorer:" ]]; then
echo "ERROR: opensc-explorer is not installed! This program cannot continue!"
zenity --error --text "ERROR: opensc-explorer is not installed!\nThis program cannot continue!\n\nUsually, opensc-explorer is part of the opensc package."
exit
fi
if [[ $# -eq 0 ]]; then
# Get card ATR
FOUND_SUPPORTED_CARD=0
echo "RESET" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
authokresponse="OK: "
response1=$(cat $SECURE_DIRECTORY/response2 | grep "$authokresponse")
if [[ $response1 != "" ]]; then
cat $SECURE_DIRECTORY/response2 | tr -d '\n' > $SECURE_DIRECTORY/response4
stringtoreplace="Using T=0 protocolRESET> RESET< OK: "
newstring=""
sed -i "s#${stringtoreplace}#${newstring}#g" $SECURE_DIRECTORY/response4
smartatr=$(cat $SECURE_DIRECTORY/response4)
echo "Got ATR: $smartatr"
if [[ $smartatr == "3B BE 18 00 00 41 05 10 00 00 00 00 00 00 00 00 00 90 00 " ]]; then
echo "Detected ACOS5 card"
COMMAND_MODE="acos"
CARD_NICE_NAME="ACOS5"
FOUND_SUPPORTED_CARD=1
fi
if [[ $smartatr == "3B 02 14 50 " ]]; then
echo "Detected Schlumberger CryptoFlex card"
COMMAND_MODE="cryptoflex"
CARD_NICE_NAME="Schlumberger CryptoFlex"
FOUND_SUPPORTED_CARD=1
fi
else
echo "No card detected!"
zenity --error --text "ERROR: No SmartCard detected!"
exit 1
fi
if [[ $FOUND_SUPPORTED_CARD -eq 0 ]]; then
echo "Unsupported SmartCard detected! ATR: $smartatr"
zenity --error --text "ERROR: Unsupported SmartCard detected!\n\nATR: $smartatr"
exit 1
fi
if [[ $COMMAND_MODE == "cryptoflex" ]]; then
GET_CHALLENGE="C0 84 00 00 08"
EXTERNAL_AUTH="C0 82 00 00 07 01"
SELECT_FILE="C0 A4 00 00 02"
DELETE_FILE="F0 E4 00 00 02"
fi
if [[ $COMMAND_MODE == "acos" ]]; then
GET_CHALLENGE="00 84 00 00 08"
EXTERNAL_AUTH1="00 82 00 81 08"
EXTERNAL_AUTH2="00 82 00 82 08"
EXTERNAL_AUTH3="00 82 00 83 08"
SELECT_FILE="00 A4 00 00 02"
DELETE_FILE="00 E4 00 00 00"
READ_BINARY="00 B0 00 00 FF"
UPDATE_BINARY="00 D6 00 00 FF"
ACTIVATE_FILE="00 44 00 00 02"
fi
fi
CREATE_LIFE_CYCLE="01"
createfile ()
{
if [[ $COMMAND_MODE == "cryptoflex" ]]; then
# Create transparent file with permissions:
# delete, terminate, activate, deactivate, update, read for Key 1 and Key 2 only
echo "F0 E0 00 FF 10 FF FF 00 $1 $2 01 3F 44 FF 44 01 03 11 FF 11" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 2>/dev/null
fi
if [[ $COMMAND_MODE == "acos" ]]; then
# Create transparent file with permissions:
# delete, terminate, activate, deactivate, update, read for Key 1, Key 2, and Key 3 only (SE 04)
# created in DF 1000 under MF, SE file is 10FE
# SIZE TRANSPARENT
echo "00 E0 00 00 1A 62 18 80 02 00 $1 82 01 01 83 02 $2 8A 01 $CREATE_LIFE_CYCLE 8C 08 7F 04 04 04 04 04 04 04" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 2>/dev/null
echo $(cat $SECURE_DIRECTORY/response2)
fi
}
updatekey ()
{
if [[ $COMMAND_MODE == "cryptoflex" ]]; then
echo "$SELECT_FILE 00 11" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 2>/dev/null
echo "C0 D6 00 0D 0C 08 00 $1 05 05" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 2>/dev/null
fi
}
hexcvt ()
{
echo ""$1" "16" o p" | dc
}
initializeacos () {
if [[ $COMMAND_MODE == "acos" ]]; then
# Set MF Offset
echo "00 D6 30 86 02 80 00" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Set EEPROM Limit
echo "00 D6 30 8C 02 FF FF" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Enable Clear Card
echo "00 D6 30 88 01 00" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Create MF
echo "00 E0 00 00 0A 62 08 82 02 3F FF 83 02 3F 00" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Select MF
echo "00 A4 00 00 00" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Create DF 1000 under MF, SE file is 10FE
echo "00 E0 00 00 2C 62 2A 82 01 38 83 02 10 00 84 10 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8A 01 $CREATE_LIFE_CYCLE 8C 08 7F 04 04 04 04 04 04 04 8D 02 10 FE" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Select DF 1000 under MF
echo "$SELECT_FILE 10 00" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Under DF 1000, create Key File EF2, file ID 10FD, read access never, SFI 02
echo "00 E0 00 00 1D 62 1B 82 05 0C 01 00 15 04 83 02 10 FD 88 01 02 8A 01 $CREATE_LIFE_CYCLE 8C 08 7F 04 04 04 04 04 04 FF" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Select EF 10FD under DF 1000
echo "$SELECT_FILE 10 FD" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Initialize key records in file 10FD
# Key 1, 8-byte 1DES authentication only
autkey=""
while [[ ${#autkey} != 16 ]]; do
autkey=$(zenity --entry --hide-text --title="SmartCard Transport Key" --text="Please enter the new 16-character Smart Card transport key [AUT1] in hexidecimal. Example: 0123456789abcdef")
done
autkey2=${autkey:0:2}
autkey2="${autkey2} ${autkey:2:2}"
autkey2="${autkey2} ${autkey:4:2}"
autkey2="${autkey2} ${autkey:6:2}"
autkey2="${autkey2} ${autkey:8:2}"
autkey2="${autkey2} ${autkey:10:2}"
autkey2="${autkey2} ${autkey:12:2}"
autkey2="${autkey2} ${autkey:14:2}"
echo "00 DC 00 00 0C 81 01 55 05 $autkey2" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Key 2, 8-byte 1DES authentication only
autkey=""
while [[ ${#autkey} != 16 ]]; do
autkey=$(zenity --entry --hide-text --title="SmartCard Transport Key" --text="Please enter the new 16-character Smart Card transport key [AUT2] in hexidecimal. Example: 0123456789abcdef")
done
autkey2=${autkey:0:2}
autkey2="${autkey2} ${autkey:2:2}"
autkey2="${autkey2} ${autkey:4:2}"
autkey2="${autkey2} ${autkey:6:2}"
autkey2="${autkey2} ${autkey:8:2}"
autkey2="${autkey2} ${autkey:10:2}"
autkey2="${autkey2} ${autkey:12:2}"
autkey2="${autkey2} ${autkey:14:2}"
echo "00 DC 00 02 0C 82 01 55 05 $autkey2" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Key 3, 8-byte 1DES authentication only
autkey=""
while [[ ${#autkey} != 16 ]]; do
autkey=$(zenity --entry --hide-text --title="SmartCard Transport Key" --text="Please enter the new 16-character Smart Card transport key [AUT3] in hexidecimal. Example: 0123456789abcdef")
done
autkey2=${autkey:0:2}
autkey2="${autkey2} ${autkey:2:2}"
autkey2="${autkey2} ${autkey:4:2}"
autkey2="${autkey2} ${autkey:6:2}"
autkey2="${autkey2} ${autkey:8:2}"
autkey2="${autkey2} ${autkey:10:2}"
autkey2="${autkey2} ${autkey:12:2}"
autkey2="${autkey2} ${autkey:14:2}"
echo "00 DC 00 02 0C 83 01 55 05 $autkey2" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Create SE file 10FE, SFI 03
echo "00 E0 00 00 1C 62 1A 82 05 0C 01 00 11 04 83 02 10 FE 88 01 03 8A 01 $CREATE_LIFE_CYCLE 8C 07 7E 04 04 04 04 04 04" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Select MF
echo "00 A4 00 00 00" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Select DF 1000 under MF
echo "$SELECT_FILE 10 00" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Select EF 10FE under DF 1000
echo "$SELECT_FILE 10 FE" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Initialize SE file 10FE
# SE 01: External authentication of local key 1
echo "00 DC 00 00 0B 80 01 01 A4 06 83 01 81 95 01 80" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# SE 02: External authentication of local key 2
echo "00 DC 00 02 0B 80 01 02 A4 06 83 01 82 95 01 80" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# SE 03: External authentication of local key 3
echo "00 DC 00 02 0B 80 01 03 A4 06 83 01 83 95 01 80" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# SE 04: External authentication of local key 1, 2, or 3
echo "00 DC 00 02 11 80 01 04 A4 0C 83 01 81 83 01 82 83 01 83 95 01 80" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Create authentication files
createfile "FF" "10 01"
createfile "FF" "10 02"
createfile "FF" "10 03"
createfile "FF" "10 04"
createfile "FF" "10 05"
createfile "FF" "10 06"
createfile "FF" "10 07"
createfile "FF" "10 08"
createfile "FF" "10 09"
createfile "FF" "10 0A"
# Activate security on files
echo "$ACTIVATE_FILE 10 01" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
echo "$ACTIVATE_FILE 10 02" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
echo "$ACTIVATE_FILE 10 03" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
echo "$ACTIVATE_FILE 10 04" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
echo "$ACTIVATE_FILE 10 05" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
echo "$ACTIVATE_FILE 10 06" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
echo "$ACTIVATE_FILE 10 07" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
echo "$ACTIVATE_FILE 10 08" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
echo "$ACTIVATE_FILE 10 09" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
echo "$ACTIVATE_FILE 10 0A" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
echo "$ACTIVATE_FILE 10 FD" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
echo "$ACTIVATE_FILE 10 FE" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
fi
}
authenticatecard () {
if [[ $authenticated != "1" ]]; then
autkey=$(zenity --entry --hide-text --title="SmartCard Transport Key" --text="Please enter the 16-character Smart Card transport key [$1] in hexidecimal. Example: 0123456789abcdef")
if [[ ${#autkey} -eq 16 ]]; then
if [[ $COMMAND_MODE == "acos" ]]; then
# Select MF
echo "00 A4 00 00 00" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Make sure DF 1000 is selected
echo "$SELECT_FILE 10 00" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
fi
# Authenticate card
echo $GET_CHALLENGE > $SECURE_DIRECTORY/authscript
scriptor $SECURE_DIRECTORY/authscript | grep 'Normal processing' > $SECURE_DIRECTORY/challenge
perl -pi -e 's/ //g' $SECURE_DIRECTORY/challenge
perl -pi -e 's/:Normalprocessing.//g' $SECURE_DIRECTORY/challenge
perl -pi -e 's//g' $SECURE_DIRECTORY/challenge
xxd -r -p $SECURE_DIRECTORY/challenge $SECURE_DIRECTORY/challenge
# Now DES encrypt the challenge
# Later, change the initialization vector to random if possible
openssl des-ecb -in $SECURE_DIRECTORY/challenge -out $SECURE_DIRECTORY/response -K $autkey -iv 1
if [[ $COMMAND_MODE == "acos" ]]; then
# Truncate to 8 bytes
dd if=$SECURE_DIRECTORY/response of=$SECURE_DIRECTORY/response2 bs=1 count=8
# Expand to standard hex listing format
xxd -g 1 $SECURE_DIRECTORY/response2 $SECURE_DIRECTORY/response
dd if=$SECURE_DIRECTORY/response of=$SECURE_DIRECTORY/response2 bs=1 count=23 skip=9
fi
if [[ $COMMAND_MODE == "cryptoflex" ]]; then
# Truncate to 6 bytes
dd if=$SECURE_DIRECTORY/response of=$SECURE_DIRECTORY/response2 bs=1 count=6
# Expand to standard hex listing format
xxd -g 1 $SECURE_DIRECTORY/response2 $SECURE_DIRECTORY/response
dd if=$SECURE_DIRECTORY/response of=$SECURE_DIRECTORY/response2 bs=1 count=17 skip=9
fi
# Assemble the response file
response2=$(cat $SECURE_DIRECTORY/response2)
if [[ $COMMAND_MODE == "acos" ]]; then
if [[ $1 == "AUT1" ]]; then
response1="$EXTERNAL_AUTH1 ${response2}"
fi
if [[ $1 == "AUT2" ]]; then
response1="$EXTERNAL_AUTH2 ${response2}"
fi
if [[ $1 == "AUT3" ]]; then
response1="$EXTERNAL_AUTH3 ${response2}"
fi
fi
if [[ $COMMAND_MODE == "cryptoflex" ]]; then
response1="$EXTERNAL_AUTH ${response2}"
fi
echo $response1 > $SECURE_DIRECTORY/response
# Send the response!
scriptor $SECURE_DIRECTORY/response > $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Get the result
authokresponse="< 90 00 : Normal processing"
response1=$(cat $SECURE_DIRECTORY/response2 | grep "$authokresponse")
echo $response1
if [[ $response1 != "" ]]; then
echo "Smart card validation successfull!"
echo "Smart card login successfull!"
authenticated="1"
else
echo "Login failed"
zenity --error --text "That transport key is incorrect!\n\nPlease remember that there are a limited number\nof failed login attempts for this key,\nafter which your SmartCard will become useless."
fi
else
echo "AUT1 key not 16 characters!"
zenity --error --text "That transport key is invalid!"
fi
fi
}
get_file () {
if [[ $COMMAND_MODE == "acos" ]]; then
# Select EF $1 under DF 1000
echo "$SELECT_FILE $1" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Read binary
echo "$READ_BINARY" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
authokresponse="90 00 : Normal processing"
response1=$(cat $SECURE_DIRECTORY/response2 | grep "$authokresponse")
if [[ $response1 != "" ]]; then
cat $SECURE_DIRECTORY/response2 | tr -d '\n' > $SECURE_DIRECTORY/response4
stringtoreplace="Using T=0 protocol00 B0 00 00 FF> 00 B0 00 00 FF< "
newstring=""
sed -i "s#${stringtoreplace}#${newstring}#g" $SECURE_DIRECTORY/response4
stringtoreplace=" 90 00 : Normal processing."
newstring=""
sed -i "s#${stringtoreplace}#${newstring}#g" $SECURE_DIRECTORY/response4
if [[ $2 == "text" ]]; then
stringtoreplace=" 00"
newstring=""
sed -i "s#${stringtoreplace}#${newstring}#g" $SECURE_DIRECTORY/response4
fi
echo $(cat $SECURE_DIRECTORY/response4)
rm -f $SECURE_DIRECTORY/lukskey
xxd -r -p $SECURE_DIRECTORY/response4 $SECURE_DIRECTORY/lukskey
RESPONSE=$SECURE_DIRECTORY/lukskey
fi
fi
if [[ $COMMAND_MODE == "cryptoflex" ]]; then
FILE=${1/ /}
echo "get $FILE" | opensc-explorer
RESPONSE="3F00_$FILE"
fi
}
update_file () {
if [[ $COMMAND_MODE == "acos" ]]; then
# Select EF $1 under DF 1000
echo "$SELECT_FILE $1" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Update existing file
# Zero pad input file
dd if=/dev/zero of=$SECURE_DIRECTORY/response2 bs=1 count=255
dd if=$2 of=$SECURE_DIRECTORY/response2 bs=1 count=255 conv=notrunc
# Truncate to 255 bytes and expand to standard hex listing format
xxd -l 255 -ps -c 1 $SECURE_DIRECTORY/response2 > $SECURE_DIRECTORY/response
cat $SECURE_DIRECTORY/response | tr '\n' ' ' > $SECURE_DIRECTORY/hexready
echo "$UPDATE_BINARY $(cat $SECURE_DIRECTORY/hexready)" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 2>/dev/null
echo $(cat $SECURE_DIRECTORY/response2)
fi
if [[ $COMMAND_MODE == "cryptoflex" ]]; then
# Delete old file
echo "$DELETE_FILE $1" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2 2>/dev/null
echo $(cat $SECURE_DIRECTORY/response2)
# Create new file
createfile "FF" $1
FILE=${1/ /}
echo "put $FILE $2" | opensc-explorer
fi
}
insertnewtext () {
FOUNDTEXT=$(cat $2 | grep $1)
echo $FOUNDTEXT;
if [[ $FOUNDTEXT != "" ]]; then
echo "$1 already exists in $2"
else
echo $1 >> $2
fi
}
getcolumn () {
perl -ne '@cols = split; print "$cols['$1']\n"' ;
}
function createlukskey {
ROOTPARTITION=$(mount | grep 'on / ' | getcolumn 0)
if [ -e $ROOTPARTITION ]; then
ROOTPARTITION=$(echo $ROOTPARTITION | sed 's/\/dev\/mapper\///')
CRYPTPARTITION=$(cat /etc/crypttab | grep $ROOTPARTITION | getcolumn 1)
if [ -e $CRYPTPARTITION ]; then
zenity --question --ok-label="Yes" --cancel-label="No" --text="I have detected that $ROOTPARTITION is your root partition, \nand therefore $CRYPTPARTITION is your encrypted root partition. \nIs this correct?"
correct=$?
if [[ correct -eq 0 ]] ; then
echo "Confirmed--proceeding"
insertnewtext dm_mod /etc/initramfs-tools/modules
insertnewtext dm_crypt /etc/initramfs-tools/modules
insertnewtext aes_x86_64 /etc/initramfs-tools/modules
insertnewtext sha256 /etc/initramfs-tools/modules
insertnewtext vfat /etc/initramfs-tools/modules
insertnewtext fat /etc/initramfs-tools/modules
insertnewtext nls_cp437 /etc/initramfs-tools/modules
insertnewtext nls_iso8859_1 /etc/initramfs-tools/modules
insertnewtext hci_usb /etc/initramfs-tools/modules
insertnewtext usb_storage /etc/initramfs-tools/modules
insertnewtext libusual /etc/initramfs-tools/modules
insertnewtext ehci_hcd /etc/initramfs-tools/modules
insertnewtext uhci_hcd /etc/initramfs-tools/modules
insertnewtext usbcore /etc/initramfs-tools/modules
insertnewtext ext2 /etc/initramfs-tools/modules
insertnewtext reiserfs /etc/initramfs-tools/modules
echo "/etc/initramfs-tools/modules updated"
mkdir -p /etc/crypto
head -c 255 /dev/urandom > /etc/crypto/smart.key
chown -R root /etc/crypto
chgrp -R root /etc/crypto
chmod -R 600 /etc/crypto
echo "$(zenity --entry --hide-text --title="LUKS Password" --text="Please enter the LUKS password for $CRYPTPARTITION")" > $SECURE_DIRECTORY/lukspass
cat $SECURE_DIRECTORY/lukspass | cryptsetup luksAddKey $CRYPTPARTITION /etc/crypto/smart.key
rm $SECURE_DIRECTORY/lukspass
correct=$?
if [[ correct -eq 0 ]] ; then
echo "OK!"
OLDCRYPTLINE=$(cat /etc/crypttab | grep $ROOTPARTITION)
NEWCRYPTLINE="$ROOTPARTITION $CRYPTPARTITION smart.key luks,keyscript=/usr/bin/cryptosmartcard.sh"
sed -i "s#${OLDCRYPTLINE}#${NEWCRYPTLINE}#g" /etc/crypttab
echo "Crypttab updated"
cp -Rp /etc/smartauth/smartauth.sh.in /usr/bin/smartauth.sh
OLDKEY=""
authenticatecard "AUT3"
if [[ $authenticated = "1" ]]; then
NEWKEY=$autkey
echo $NEWKEY > /etc/smartauth/smartauth.key
sed -i "s#${OLDKEY}#${NEWKEY}#g" /usr/bin/smartauth.sh
chmod 600 /usr/bin/smartauth.sh
chmod a+x /usr/bin/smartauth.sh
echo "Updating initramfs"
update-initramfs -u -k all
echo "Securing directories..."
chmod 600 "/boot/initrd.img-$(uname -r)"
chmod -R 600 /etc/smartauth
else
rm -rf /etc/crypto/smart.key
rm -rf /usr/share/initramfs-tools/hooks/cryptlukssc
rm -f /usr/bin/smartauth.sh
fi
else
echo "LUKS add key failed!"
zenity --error --text "Failed to add LUKS key!\nReverting all changes..."
rm -rf /etc/crypto/smart.key
rm -rf /usr/share/initramfs-tools/hooks/cryptlukssc
fi
fi
else
zenity --error --text "Either I am unable to properly detect your encrypted partition,\nor your hard disk is not encrypted.\nNo changes to your system have been made."
fi
else
zenity --error --text "I am unable to properly detect your root partition.\nNo changes to your system have been made."
fi
}
function importlukskey {
ROOTPARTITION=$(mount | grep 'on / ' | getcolumn 0)
if [ -e $ROOTPARTITION ]; then
ROOTPARTITION=$(echo $ROOTPARTITION | sed 's/\/dev\/mapper\///')
CRYPTPARTITION=$(cat /etc/crypttab | grep $ROOTPARTITION | getcolumn 1)
if [ -e $CRYPTPARTITION ]; then
zenity --question --ok-label="Yes" --cancel-label="No" --text="I have detected that $ROOTPARTITION is your root partition, \nand therefore $CRYPTPARTITION is your encrypted root partition. \nIs this correct?"
correct=$?
if [[ correct -eq 0 ]] ; then
echo "Confirmed--proceeding"
FILE=$(zenity --file-selection --title="Select the new LUKS encryption key file")
case $? in
0)
continueluksupdate=1;;
1)
continueluksupdate=0;;
-1)
continueluksupdate=0;;
esac
if [[ $continueluksupdate -eq 1 ]]; then
echo "File selected--proceeding"
insertnewtext dm_mod /etc/initramfs-tools/modules
insertnewtext dm_crypt /etc/initramfs-tools/modules
insertnewtext aes_x86_64 /etc/initramfs-tools/modules
insertnewtext sha256 /etc/initramfs-tools/modules
insertnewtext vfat /etc/initramfs-tools/modules
insertnewtext fat /etc/initramfs-tools/modules
insertnewtext nls_cp437 /etc/initramfs-tools/modules
insertnewtext nls_iso8859_1 /etc/initramfs-tools/modules
insertnewtext hci_usb /etc/initramfs-tools/modules
insertnewtext usb_storage /etc/initramfs-tools/modules
insertnewtext libusual /etc/initramfs-tools/modules
insertnewtext ehci_hcd /etc/initramfs-tools/modules
insertnewtext uhci_hcd /etc/initramfs-tools/modules
insertnewtext usbcore /etc/initramfs-tools/modules
insertnewtext ext2 /etc/initramfs-tools/modules
insertnewtext reiserfs /etc/initramfs-tools/modules
echo "/etc/initramfs-tools/modules updated"
mkdir -p /etc/crypto
cp -Rp $FILE /etc/crypto/smart.key
chown -R root /etc/crypto
chgrp -R root /etc/crypto
chmod -R 600 /etc/crypto
echo "$(zenity --entry --hide-text --title="LUKS Password" --text="Please enter the LUKS password for $CRYPTPARTITION")" > $SECURE_DIRECTORY/lukspass
cat $SECURE_DIRECTORY/lukspass | cryptsetup luksAddKey $CRYPTPARTITION /etc/crypto/smart.key
rm $SECURE_DIRECTORY/lukspass
correct=$?
if [[ correct -eq 0 ]] ; then
echo "OK!"
OLDCRYPTLINE=$(cat /etc/crypttab | grep $ROOTPARTITION)
NEWCRYPTLINE="$ROOTPARTITION $CRYPTPARTITION smart.key luks,keyscript=/usr/bin/cryptosmartcard.sh"
sed -i "s#${OLDCRYPTLINE}#${NEWCRYPTLINE}#g" /etc/crypttab
echo "Crypttab updated"
cp -Rp /etc/smartauth/smartauth.sh.in /usr/bin/smartauth.sh
OLDKEY=""
authenticatecard "AUT3"
if [[ $authenticated = "1" ]]; then
NEWKEY=$autkey
echo $NEWKEY > /etc/smartauth/smartauth.key
sed -i "s#${OLDKEY}#${NEWKEY}#g" /usr/bin/smartauth.sh
chmod 600 /usr/bin/smartauth.sh
chmod a+x /usr/bin/smartauth.sh
echo "Updating initramfs"
update-initramfs -u -k all
echo "Securing directories..."
chmod 600 "/boot/initrd.img-$(uname -r)"
chmod -R 600 /etc/smartauth
else
rm -rf /etc/crypto/smart.key
rm -rf /usr/share/initramfs-tools/hooks/cryptlukssc
rm -f /usr/bin/smartauth.sh
fi
else
echo "LUKS add key failed!"
zenity --error --text "Failed to add LUKS key!\nReverting all changes..."
rm -rf /etc/crypto/smart.key
rm -rf /usr/share/initramfs-tools/hooks/cryptlukssc
fi
else
zenity --error --text "No changes to your system have been made."
fi
fi
else
zenity --error --text "Either I am unable to properly detect your encrypted partition,\nor your hard disk is not encrypted.\nNo changes to your system have been made."
fi
else
zenity --error --text "I am unable to properly detect your root partition.\nNo changes to your system have been made."
fi
}
function loadlukskey {
echo "Loading LUKS key..."
authenticatecard "AUT1"
if [[ $authenticated = "1" ]]; then
update_file "10 01" "/etc/crypto/smart.key"
fi
}
function loadusername {
echo "Loading username..."
authenticatecard "AUT1"
if [[ $authenticated = "1" ]]; then
zenity --entry --title="SmartCard Username" --text="Please enter the username of the account to be associated with this SmartCard" > $SECURE_DIRECTORY/username
update_file "10 02" "$SECURE_DIRECTORY/username"
rm -f $SECURE_DIRECTORY/username
fi
}
function loadpassword {
echo "Loading password..."
authenticatecard "AUT1"
if [[ $authenticated = "1" ]]; then
zenity --entry --hide-text --title="SmartCard Password" --text="Please enter the password of the account that is associated with this SmartCard" > $SECURE_DIRECTORY/password
update_file "10 03" "$SECURE_DIRECTORY/password"
rm -f $SECURE_DIRECTORY/password
fi
}
GREETER="Welcome to the SmartCard authentication setup utility!\n\nAUT1 is the manual update key\nAUT2 is the login key\nAUT3 is the LUKS decrypt key\n\nCard ATR: $smartatr\nDetected: $CARD_NICE_NAME\n\nPlease select an action from the list below:"
while [[ 1 -eq 1 ]]; do
if [ -e "/etc/smartauth/smartauthmon.key" ]; then
LOGINOPTION="Disable automatic login for TDE"
else
LOGINOPTION="Enable automatic login for TDE"
fi
if [[ $COMMAND_MODE == "acos" ]]; then
ACOS_INIT_OPTION="FALSE Initialize-blank-ACOS"
# See if the card has an MF yet
# Select MF
echo "00 A4 00 00 00" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
authokresponse="< 61 "
response1=$(cat $SECURE_DIRECTORY/response2 | grep "$authokresponse")
echo $response1
if [[ $response1 != "" ]]; then
echo "MF exists, checking for DF 1000"
# MF exists, check for DF 1000
echo "00 A4 00 00 02 10 00" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
authokresponse="< 61 "
response1=$(cat $SECURE_DIRECTORY/response2 | grep "$authokresponse")
echo $response1
if [[ $response1 != "" ]]; then
echo "DF 1000 exists, this card was already initialized!"
ACOS_INIT_OPTION=""
fi
fi
fi
if [[ $COMMAND_MODE == "cryptoflex" ]]; then
ACOS_INIT_OPTION=""
fi
if [[ $# -eq 0 ]]; then
if [ -e "/etc/crypto/smart.key" ]; then
selection=$(zenity --width=400 --height=550 --list --radiolist --title="SmartCard Authentication Setup" \
--text="$GREETER" \
--column="" --column="Action" \
TRUE "Update LUKS Initramfs Transport Key [AUT3]" \
FALSE "Import LUKS encryption key from file to system" \
FALSE "Get LUKS encryption key from Smart Card [File 1001]" \
FALSE "Load LUKS encryption key into Smart Card [File 1001]" \
FALSE "Load username into Smart Card [File 1002]" \
FALSE "Load password into Smart Card [File 1003]" \
FALSE "Update Smart Card Transport Keys [AUT1-AUT3]" \
FALSE "$LOGINOPTION" \
$ACOS_INIT_OPTION);
else
selection=$(zenity --width=400 --height=550 --list --radiolist --title="SmartCard Authentication Setup" \
--text="$GREETER" \
--column="" --column="Action" \
TRUE "First-Time Setup Wizard" \
FALSE "Create New LUKS Key" \
FALSE "Update LUKS Initramfs Transport Key [AUT3]" \
FALSE "Import LUKS encryption key from file to system" \
FALSE "Get LUKS encryption key from Smart Card [File 1001]" \
FALSE "Load LUKS encryption key into Smart Card [File 1001]" \
FALSE "Load username into Smart Card [File 1002]" \
FALSE "Load password into Smart Card [File 1003]" \
FALSE "Update Smart Card Transport Keys [AUT1-AUT3]" \
FALSE "$LOGINOPTION" \
$ACOS_INIT_OPTION);
fi
else
if [[ $1 = "upgrade" ]]; then
echo "Upgrade mode"
if [ -e "/etc/smartauth/smartauth.key" ]; then
OLDKEY=""
NEWKEY=$(cat /etc/smartauth/smartauth.key)
cp -Rp /etc/smartauth/smartauth.sh.in /usr/bin/smartauth.sh
sed -i "s#${OLDKEY}#${NEWKEY}#g" /usr/bin/smartauth.sh
chmod 600 /usr/bin/smartauth.sh
chmod a+x /usr/bin/smartauth.sh
echo "Updating initramfs"
update-initramfs -u -k all
echo "Securing directories..."
chmod 600 "/boot/initrd.img-$(uname -r)"
chmod -R 600 /etc/smartauth
fi
if [ -e "/etc/smartauth/smartauthmon.key" ]; then
OLDKEY=""
NEWKEY=$(cat /etc/smartauth/smartauthmon.key)
fi
fi
fi
if [[ $selection = "Import LUKS encryption key from file to system" ]]; then
importlukskey
fi
if [[ $selection = "First-Time Setup Wizard" ]]; then
echo "Running first-time setup wizard..."
zenity --info --text "This setup wizard will prepare your encrypted computer for automatic LUKS unlock and login via SmartCard"
createlukskey
if [[ $authenticated = "1" ]]; then
loadlukskey
loadusername
loadpassword
fi
fi
if [[ $selection = "Create New LUKS Key" ]]; then
echo "Creating new LUKS key..."
createlukskey
fi
if [[ $selection = "Get LUKS encryption key from Smart Card [File 1001]" ]]; then
echo "Getting LUKS key..."
authenticatecard "AUT1"
if [[ $authenticated = "1" ]]; then
get_file "10 01"
zenity --info --text "LUKS key is currently in file:\n$RESPONSE\n\nThis file will be deleted upon completion of this script."
fi
fi
if [[ $selection = "Load LUKS encryption key into Smart Card [File 1001]" ]]; then
loadlukskey
fi
if [[ $selection = "Load username into Smart Card [File 1002]" ]]; then
loadusername
fi
if [[ $selection = "Load password into Smart Card [File 1003]" ]]; then
loadpassword
fi
if [[ $selection = "Update LUKS Initramfs Transport Key [AUT3]" ]]; then
cp -Rp /etc/smartauth/smartauth.sh.in /usr/bin/smartauth.sh
OLDKEY=""
authenticatecard "AUT3"
if [[ $authenticated = "1" ]]; then
NEWKEY=$autkey
echo $NEWKEY > /etc/smartauth/smartauth.key
sed -i "s#${OLDKEY}#${NEWKEY}#g" /usr/bin/smartauth.sh
chmod 600 /usr/bin/smartauth.sh
chmod a+x /usr/bin/smartauth.sh
echo "Updating initramfs"
update-initramfs -u -k all
echo "Securing directories..."
chmod 600 "/boot/initrd.img-$(uname -r)"
chmod -R 600 /etc/smartauth
if [ -e "/etc/smartauth/smartauthmon.key" ]; then
echo "TDE login disabled; not altering"
else
selection="Enable automatic login for TDE"
fi
else
zenity --error --text "A SmartCard authentication error has occurred.\nNo changes have been made to your system."
fi
fi
if [[ $selection = "Update Smart Card Transport Keys [AUT1-AUT3]" ]]; then
echo "Updating AUT1..."
authenticatecard "AUT1"
if [[ $authenticated = "1" ]]; then
if [[ $COMMAND_MODE == "acos" ]]; then
# Select EF 10FD under DF 1000
echo "$SELECT_FILE 10 FD" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Initialize key records in file 10FD
# Key 1, 8-byte 1DES authentication only
autkey=""
while [[ ${#autkey} != 16 ]]; do
autkey=$(zenity --entry --hide-text --title="SmartCard Transport Key" --text="Please enter the new 16-character Smart Card transport key [AUT1] in hexidecimal. Example: 0123456789abcdef")
done
autkey2=${autkey:0:2}
autkey2="${autkey2} ${autkey:2:2}"
autkey2="${autkey2} ${autkey:4:2}"
autkey2="${autkey2} ${autkey:6:2}"
autkey2="${autkey2} ${autkey:8:2}"
autkey2="${autkey2} ${autkey:10:2}"
autkey2="${autkey2} ${autkey:12:2}"
autkey2="${autkey2} ${autkey:14:2}"
echo "00 DC 00 00 0C 81 01 55 05 $autkey2" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Key 2, 8-byte 1DES authentication only
autkey=""
while [[ ${#autkey} != 16 ]]; do
autkey=$(zenity --entry --hide-text --title="SmartCard Transport Key" --text="Please enter the new 16-character Smart Card transport key [AUT2] in hexidecimal. Example: 0123456789abcdef")
done
autkey2=${autkey:0:2}
autkey2="${autkey2} ${autkey:2:2}"
autkey2="${autkey2} ${autkey:4:2}"
autkey2="${autkey2} ${autkey:6:2}"
autkey2="${autkey2} ${autkey:8:2}"
autkey2="${autkey2} ${autkey:10:2}"
autkey2="${autkey2} ${autkey:12:2}"
autkey2="${autkey2} ${autkey:14:2}"
echo "00 DC 00 02 0C 82 01 55 05 $autkey2" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
# Key 3, 8-byte 1DES authentication only
autkey=""
while [[ ${#autkey} != 16 ]]; do
autkey=$(zenity --entry --hide-text --title="SmartCard Transport Key" --text="Please enter the new 16-character Smart Card transport key [AUT3] in hexidecimal. Example: 0123456789abcdef")
done
autkey2=${autkey:0:2}
autkey2="${autkey2} ${autkey:2:2}"
autkey2="${autkey2} ${autkey:4:2}"
autkey2="${autkey2} ${autkey:6:2}"
autkey2="${autkey2} ${autkey:8:2}"
autkey2="${autkey2} ${autkey:10:2}"
autkey2="${autkey2} ${autkey:12:2}"
autkey2="${autkey2} ${autkey:14:2}"
echo "00 DC 00 02 0C 83 01 55 05 $autkey2" > $SECURE_DIRECTORY/query
scriptor $SECURE_DIRECTORY/query 1> $SECURE_DIRECTORY/response2
echo $(cat $SECURE_DIRECTORY/response2)
fi
if [[ $COMMAND_MODE == "cryptoflex" ]]; then
autkey4=$(zenity --entry --hide-text --title="SmartCard Transport Key" --text="Please enter the new 16-character Smart Card transport key [AUT1] in hexidecimal. Example: 0123456789abcdef")
if [[ ${#autkey4} -eq 16 ]]; then
autkey2=${autkey4:0:2}
autkey2="${autkey2} ${autkey4:2:2}"
autkey2="${autkey2} ${autkey4:4:2}"
autkey2="${autkey2} ${autkey4:6:2}"
autkey2="${autkey2} ${autkey4:8:2}"
autkey2="${autkey2} ${autkey4:10:2}"
autkey2="${autkey2} ${autkey4:12:2}"
autkey2="${autkey2} ${autkey4:14:2}"
echo "Attempting Smart Card key update..."
updatekey ${autkey2}
autkey=$autkey4
if [[ $authenticated = "1" ]]; then
cp -Rp /etc/smartauth/smartauth.sh.in /usr/bin/smartauth.sh
OLDKEY=""
authenticatecard "AUT3"
if [[ $authenticated = "1" ]]; then
NEWKEY=$autkey
echo $NEWKEY > /etc/smartauth/smartauth.key
sed -i "s#${OLDKEY}#${NEWKEY}#g" /usr/bin/smartauth.sh
chmod 600 /usr/bin/smartauth.sh
chmod a+x /usr/bin/smartauth.sh
echo "Updating initramfs"
update-initramfs -u -k all
echo "Securing directories..."
chmod 600 "/boot/initrd.img-$(uname -r)"
chmod -R 600 /etc/smartauth
if [ -e "/etc/smartauth/smartauthmon.key" ]; then
selection="Enable automatic login for TDE"
else
echo "TDE login disabled; not altering"
fi
else
zenity --error --text "A SmartCard authentication error has occurred."
fi
else
zenity --error --text "A SmartCard authentication error has occurred."
fi
else
echo "AUT1 key not 16 characters!"
zenity --error --text "The new transport key is invalid!"
fi
fi
fi
fi
if [[ $selection = "Enable automatic login for TDE" ]]; then
OLDKEY=""
authenticatecard "AUT2"
if [[ $authenticated = "1" ]]; then
NEWKEY=$autkey
echo $NEWKEY > /etc/smartauth/smartauthmon.key
update-rc.d smartauthlogin defaults
/etc/init.d/smartauthlogin stop
/etc/init.d/smartauthlogin start
fi
fi
if [[ $selection = "Disable automatic login for TDE" ]]; then
/etc/init.d/smartauthlogin stop
rm -rf /etc/smartauth/smartauthmon.key
update-rc.d -f smartauthlogin remove
fi
#if [[ $selection = "Initialize blank ACOS card" ]]; then
if [[ $selection = "Initialize-blank-ACOS" ]]; then
initializeacos
fi
if [[ $selection = "" ]]; then
echo "Exiting!"
rm -rf $SECURE_DIRECTORY
chmod -R 600 /etc/smartauth
chown -R root /etc/smartauth
chmod a+x /usr/bin/smartauth.sh
chmod 600 "/boot/initrd.img-$(uname -r)"
chown root "/boot/initrd.img-$(uname -r)"
exit
fi
done