Compare commits
298 Commits
0.21.0
...
golem/tess
Author | SHA1 | Date |
---|---|---|
giomba | 932bd27549 | |
giomba | b965e20bfd | |
giomba | 060d8ddb19 | |
giomba | 5167b30043 | |
giomba | 606edadb13 | |
Jakub Jelen | c902e19921 | |
Vesa Jääskeläinen | e97fec4d91 | |
Vesa Jääskeläinen | cababca4d5 | |
Vesa Jääskeläinen | 63a5a493a6 | |
Vesa Jääskeläinen | 1b344a4847 | |
Vesa Jääskeläinen | 7007eda0ba | |
Vesa Jääskeläinen | 1991fa24ae | |
Vesa Jääskeläinen | 6431f69dcc | |
Frank Morgner | 7d315b5546 | |
Doug Engert | 4c923c637c | |
Jakub Jelen | b67261ab27 | |
Jakub Jelen | 68b7efb591 | |
Jakub Jelen | 3048156db0 | |
Jakub Jelen | 1e43a6a1af | |
Doug Engert | c6a9b5699a | |
Doug Engert | 445a6324de | |
Doug Engert | 456ac56693 | |
Jakub Jelen | 8453c0d99a | |
Jakub Jelen | d47f42b12a | |
Jakub Jelen | 01cf556ba2 | |
Jakub Jelen | f43d3f8042 | |
Jakub Jelen | 5d338739ac | |
Jakub Jelen | e683c531f6 | |
Jakub Jelen | 1b329093f7 | |
Jakub Jelen | bc9b9df869 | |
Frank Morgner | 99656deaf4 | |
Jakub Jelen | 9a5a008093 | |
Jakub Jelen | d34e84c78d | |
Frank Morgner | d90048e5bb | |
Jakub Jelen | aa6574b60e | |
Jakub Jelen | fd6b64b91b | |
Alessio Di Mauro | 2f94a6b155 | |
Doug Engert | aebebac432 | |
Frank Morgner | c42792c216 | |
Stephan Mühlstrasser | 151583ce26 | |
Jakub Jelen | 9be6dc6606 | |
Jakub Jelen | 9d1a214340 | |
Jakub Jelen | fc2fecc80e | |
Jakub Jelen | ffd6e2a576 | |
Jaime Hablutzel | 465375bda2 | |
Jakub Jelen | 33426df3ff | |
Jakub Jelen | 8e4134841d | |
Jakub Jelen | a8a4bddfad | |
Jakub Jelen | a69ab7c70c | |
Jakub Jelen | fd96d2c960 | |
Jakub Jelen | 1b92501ef9 | |
Jakub Jelen | 07f5e63abf | |
Jakub Jelen | 12be677cb8 | |
Jakub Jelen | e4cf0e7b39 | |
Jakub Jelen | 0b45e78e4f | |
Yaroslav Isakov | fc08818f6f | |
Yaroslav Isakov | 23dc52c903 | |
Yaroslav Isakov | 29410c170e | |
Yaroslav Isakov | f356d301b9 | |
Doug Engert | 48a11c0634 | |
Doug Engert | f1bc07dec1 | |
Doug Engert | 8dfafe4fc2 | |
Vincent JARDIN | 5256bc3d3d | |
Vincent JARDIN | 180737d1b6 | |
Vincent JARDIN | f0c059ede8 | |
Vincent JARDIN | 46c50dc51d | |
Georgi Kirichkov | ca01d2c5e2 | |
Georgi Kirichkov | 5ae0ef4f41 | |
Georgi Kirichkov | 072c64aaed | |
Alon Bar-Lev | 35a8a1d7e1 | |
Ludovic Rousseau | 2ea5ed8ddd | |
Jakub Jelen | 2f145f5804 | |
Jakub Jelen | 613b56ee55 | |
Jakub Jelen | d0b847c6cf | |
Jakub Jelen | 835cee2e5a | |
Jakub Jelen | 06ac408bb4 | |
divinehawk | 98663528cf | |
ihsinme | 50eaa6bf57 | |
Frank Morgner | 32004e74ce | |
Anton Logachev | 570fc56c47 | |
Doug Engert | 19611682bd | |
Vincent JARDIN | a21bcf4b41 | |
Vincent JARDIN | e93bd3983c | |
Frank Morgner | 3f19991556 | |
Frank Morgner | 4ecb4b39ac | |
Frank Morgner | 75f24d2af7 | |
Frank Morgner | 2063a1d334 | |
Vincent JARDIN | e3a3722ad1 | |
Vincent JARDIN | fcd2e665fe | |
Vincent JARDIN | 405ecfc402 | |
Vincent JARDIN | 544aa4cc6b | |
Vincent JARDIN | 137286858f | |
Vincent JARDIN | 39b4472f38 | |
Vincent JARDIN | 396cbc46cf | |
Frank Morgner | 4912f05701 | |
Peter Marschall | 344ac0abe6 | |
Jakub Jelen | d6ec00c870 | |
Peter Popovec | dd48facd38 | |
Peter Popovec | 7d274a0d72 | |
Jakub Jelen | ef17b3fb89 | |
Jakub Jelen | cae5c71f90 | |
Jakub Jelen | 4b3c6dec07 | |
Frank Morgner | 991bb8a141 | |
Frank Morgner | a83069b89f | |
Carsten Blüggel | edb7ed25e4 | |
Frank Morgner | 545e47b29e | |
Vincent JARDIN | 1a3666364d | |
Vincent JARDIN | 0df0f80b55 | |
Philip Prindeville | b9c0addf88 | |
yehj | c3c5f2d518 | |
Frank Morgner | 83162c5c87 | |
Frank Morgner | ce0d409205 | |
Jakub Jelen | 7114fb71b5 | |
Jakub Jelen | 9cc942fd47 | |
Jakub Jelen | 7d0abdc192 | |
Jakub Jelen | 370eda4bd8 | |
Frank Morgner | 5f9085fedb | |
Marco Trevisan (Treviño) | 845eac4250 | |
Vincent JARDIN | 40e9a9c830 | |
Vincent JARDIN | b18234a7d9 | |
Jakub Jelen | 5d4daf6c92 | |
Jakub Jelen | 715c17c469 | |
Jakub Jelen | d5dea2dd1b | |
Jakub Jelen | 16b7c60fd3 | |
Frank Morgner | 05648b0604 | |
Vincent JARDIN | fc0df4e5d5 | |
Vincent JARDIN | 76507508d7 | |
Vincent JARDIN | 4119b2c3e7 | |
Vincent JARDIN | b508349010 | |
Vincent JARDIN | 20f359ea04 | |
Vincent JARDIN | c581d1b26f | |
Vincent JARDIN | fd83e885f7 | |
Vincent JARDIN | 6efd7b3029 | |
Vincent JARDIN | 41edcaa413 | |
Vincent JARDIN | 7cd713d15d | |
Vincent JARDIN | fd97f49a84 | |
Vincent JARDIN | 560692221b | |
Vincent JARDIN | acb8822444 | |
Jakub Jelen | 40c50a3a42 | |
Frank Morgner | 4512676795 | |
Frank Morgner | 26fac9592d | |
Raul Metsma | b9080c16d6 | |
Frank Morgner | aae9254018 | |
Raul Metsma | 578128e464 | |
Frank Morgner | 1325d5c333 | |
Raul Metsma | 85c5610d39 | |
Frank Morgner | 63e6683384 | |
Peter Popovec | f46b617397 | |
Frank Morgner | 8e614bfe6e | |
Jakub Jelen | 8d61d0d20d | |
Jakub Jelen | 1ef79e99f7 | |
Jakub Jelen | 60632100a0 | |
Jakub Jelen | 63031b2193 | |
Jakub Jelen | 544dcc6827 | |
Jakub Jelen | 2fa6700599 | |
Jakub Jelen | 45e262f537 | |
Jakub Jelen | b5f26051bb | |
Jakub Jelen | b8266a4c86 | |
Jakub Jelen | 0ce245a411 | |
Jakub Jelen | 56af7de137 | |
Jakub Jelen | c39e31b274 | |
Jakub Jelen | ae771a135f | |
Jakub Jelen | cb8c7647ca | |
Jakub Jelen | a020b85d94 | |
Jakub Jelen | 73e283b4b1 | |
Jakub Jelen | 64b61a7556 | |
Jakub Jelen | 9bd139d1e4 | |
Jakub Jelen | 8c4d325576 | |
Doug Engert | 0380142482 | |
Jakub Jelen | 091b7670eb | |
Jakub Jelen | 35cfc291ce | |
Jakub Jelen | 485b6cff44 | |
Jakub Jelen | 32ec1f92b9 | |
Jakub Jelen | e7d390f9dd | |
Jakub Jelen | a965829f52 | |
Jakub Jelen | 5d5c391793 | |
Jakub Jelen | 5178e74e1b | |
Jakub Jelen | 2fb688683e | |
Jakub Jelen | b351bf5ea4 | |
Jakub Jelen | caae75758c | |
Jakub Jelen | 80f80317d1 | |
Jakub Jelen | 095c28e372 | |
Jakub Jelen | 0455a5665e | |
Jakub Jelen | c78fa164c9 | |
Jakub Jelen | a30bf95eed | |
Jakub Jelen | a5a6757d10 | |
Jakub Jelen | e82f875047 | |
Jakub Jelen | 86e01d7c47 | |
Jakub Jelen | f726d4f201 | |
Frank Morgner | 5b42a62ec0 | |
Frank Morgner | fe6864c5f3 | |
Frank Morgner | c2670b0787 | |
Frank Morgner | 881dca94ef | |
Frank Morgner | d353a46d04 | |
Peter Popovec | 6738d456ac | |
Frank Morgner | 999874fb1c | |
Luka Logar | c80375eb4c | |
Frank Morgner | a322c95d35 | |
Jakub Jelen | 5f7c91e54f | |
Jakub Jelen | 46cfe89b3c | |
Jakub Jelen | a567ab9dca | |
Jakub Jelen | cee431a3ce | |
Jakub Jelen | ffed34663d | |
Jakub Jelen | 3b556ef618 | |
Jakub Jelen | 1dbe4b5a5b | |
Jakub Jelen | 2f232f217b | |
Jakub Jelen | ae1cf0be90 | |
Jakub Jelen | 1252aca9f1 | |
Jakub Jelen | 17d8980cde | |
Jakub Jelen | 9c91a4327e | |
Jakub Jelen | 7ba89daae6 | |
Jakub Jelen | 251c4f6b76 | |
alt3r 3go | 3044557299 | |
ihsinme | 6372adeb20 | |
ihsinme | 0a3d7a28a7 | |
Zhang Xiaohui | 49788678fe | |
Zhang Xiaohui | 1c4a01d766 | |
Vincent JARDIN | 66e5600b27 | |
Jakub Jelen | 8a6026abf5 | |
Jakub Jelen | da247384e7 | |
Jakub Jelen | 176b20f339 | |
Jakub Jelen | cb074c5fa0 | |
Jakub Jelen | 5633129bd8 | |
Jakub Jelen | 0d693f63cb | |
Doug Engert | b5ddaf6e02 | |
Doug Engert | f704e4f23e | |
Doug Engert | 1b4e9f1d4a | |
Doug Engert | d369965a7f | |
Jakub Jelen | e1c8361ff3 | |
Jakub Jelen | 44d429c3ad | |
Jakub Jelen | edaf921eb6 | |
Jakub Jelen | ac81764308 | |
Jakub Jelen | a6ed34bbb5 | |
Peter Popovec | 26adaf519c | |
Peter Popovec | a3ca7613cd | |
Doug Engert | 0b0deae4be | |
Doug Engert | 521d420c42 | |
Doug Engert | 285db1ef29 | |
Peter Popovec | 6049cb926c | |
Jakub Jelen | 5f16ffae84 | |
Jakub Jelen | 03cbf91be5 | |
Jakub Jelen | b820bdf5b3 | |
Jakub Jelen | 1db88374bb | |
Peter Popovec | ba85ae75e3 | |
Peter Popovec | ce7fa42958 | |
Frank Morgner | 7a090b994e | |
Jakub Jelen | 219c6cc494 | |
Jakub Jelen | 96ae693d5a | |
Jakub Jelen | db18a72c64 | |
Jakub Jelen | 7f9e8ba85c | |
Jakub Jelen | d224b2612d | |
Jakub Jelen | 03079a9413 | |
Jakub Jelen | 6e25924eb0 | |
Jakub Jelen | 224e265266 | |
Jakub Jelen | 8e71118cd4 | |
Jakub Jelen | 7f0166ab12 | |
Jakub Jelen | 95122abe2e | |
Jakub Jelen | 47151e9335 | |
Jakub Jelen | e58e7e1428 | |
Jakub Jelen | 23eb606d86 | |
Jakub Jelen | c7c689c74d | |
Jakub Jelen | 910020aeec | |
Jakub Jelen | 9cda87e200 | |
Jakub Jelen | d25009cde6 | |
Jakub Jelen | 3135fccdca | |
Jakub Jelen | 049b2a8754 | |
Jakub Jelen | 66f274dcaf | |
Jakub Jelen | b48696539d | |
Jakub Jelen | 88543529a2 | |
Jakub Jelen | f7b0ce3dac | |
Doug Engert | f443c391b0 | |
Carsten Blüggel | f8af905574 | |
Jakub Jelen | 1ae8b60425 | |
Jakub Jelen | 5df913b7f5 | |
Jakub Jelen | 69544553c3 | |
Jakub Jelen | 196bf9e574 | |
Peter Popovec | a089353e1f | |
Jakub Jelen | f015746d22 | |
Jakub Jelen | 78cdab949f | |
Jakub Jelen | 3ffe24cfb6 | |
Jakub Jelen | fb83cd0439 | |
Jakub Jelen | 61eb4e487e | |
Frank Morgner | 175c357c37 | |
Jakub Jelen | 85e08ae675 | |
rickyepoderi | 3ce249f365 | |
Frank Morgner | 98beb86a38 | |
Frank Morgner | 480da424a5 | |
Jakub Jelen | 0365c3ce6c | |
Jakub Jelen | 3d257410b2 | |
Jakub Jelen | 63bb85b050 | |
Jakub Jelen | 871e4f2ac6 | |
Jakub Jelen | 55a5556949 | |
Jakub Jelen | af2fb6938c | |
Jakub Jelen | 8a6708c163 | |
Jakub Jelen | d0e5d62bf5 | |
Jakub Jelen | 3eae6a031c | |
Jakub Jelen | 00ad8644e6 | |
Doug Engert | 483e153182 |
|
@ -0,0 +1,3 @@
|
|||
BasedOnStyle: Google
|
||||
IndentWidth: 4
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig;
|
||||
|
||||
if [ "$GITHUB_EVENT_NAME" == "pull_request" ]; then
|
||||
PR_NUMBER=$(echo $GITHUB_REF | awk 'BEGIN { FS = "/" } ; { print $3 }')
|
||||
if [ "$GITHUB_BASE_REF" == "master" ]; then
|
||||
./bootstrap.ci -s "-pr$PR_NUMBER"
|
||||
else
|
||||
./bootstrap.ci -s "$GITHUB_BASE_REF-pr$PR_NUMBER"
|
||||
fi
|
||||
else
|
||||
BRANCH=$(echo $GITHUB_REF | awk 'BEGIN { FS = "/" } ; { print $3 }')
|
||||
if [ "$BRANCH" == "master" ]; then
|
||||
./bootstrap
|
||||
else
|
||||
./bootstrap.ci -s "$BRANCH"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$RUNNER_OS" == "macOS" ]; then
|
||||
./MacOSX/build
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [ "$1" == "mingw" -o "$1" == "mingw32" ]; then
|
||||
if [ "$1" == "mingw" ]; then
|
||||
HOST=x86_64-w64-mingw32
|
||||
elif [ "$1" == "mingw32" ]; then
|
||||
HOST=i686-w64-mingw32
|
||||
fi
|
||||
unset CC
|
||||
unset CXX
|
||||
./configure --host=$HOST --with-completiondir=/tmp --disable-openssl --disable-readline --disable-zlib --disable-notify --prefix=$PWD/win32/opensc || cat config.log;
|
||||
make -j 2
|
||||
# no point in running tests on mingw
|
||||
else
|
||||
# normal procedure
|
||||
./configure --disable-dependency-tracking
|
||||
make -j 2
|
||||
make check
|
||||
fi
|
||||
|
||||
# this is broken in old ubuntu
|
||||
if [ "$1" == "dist" ]; then
|
||||
make distcheck
|
||||
make dist
|
||||
fi
|
||||
|
||||
sudo make install
|
||||
if [ "$1" == "mingw" -o "$1" == "mingw32" ]; then
|
||||
# pack installed files
|
||||
wine "C:/Program Files/Inno Setup 5/ISCC.exe" win32/OpenSC.iss
|
||||
fi
|
|
@ -6,7 +6,7 @@ BUILDPATH=${PWD}
|
|||
BRANCH="`git log --max-count=1 --date=short --abbrev=8 --pretty=format:"%cd_%h"`"
|
||||
|
||||
git clone --single-branch https://${GH_TOKEN}@github.com/OpenSC/Nightly.git > /dev/null 2>&1
|
||||
cd Nightly
|
||||
pushd Nightly
|
||||
git checkout -b "${BRANCH}"
|
||||
|
||||
for file in ${BUILDPATH}/win32/Output/OpenSC*.exe ${BUILDPATH}/opensc*.tar.gz ${BUILDPATH}/OpenSC*.dmg ${BUILDPATH}/OpenSC*.msi ${BUILDPATH}/OpenSC*.zip
|
||||
|
@ -30,6 +30,7 @@ i=0
|
|||
while [ $i -le 10 ] && ! git push --quiet --set-upstream origin "${BRANCH}"
|
||||
do
|
||||
sleep $[ ( $RANDOM % 32 ) + 1 ]s
|
||||
git pull --rebase origin "${BRANCH}"
|
||||
git pull --rebase origin --strategy-option ours "${BRANCH}"
|
||||
i=$(( $i + 1 ))
|
||||
done
|
||||
popd
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
# Select the right java
|
||||
sudo update-java-alternatives -s java-1.8.0-openjdk-amd64
|
||||
sudo update-alternatives --get-selections | grep ^java
|
||||
export PATH="/usr/lib/jvm/java-8-openjdk-amd64/bin/:$PATH"
|
||||
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/
|
||||
env | grep -i openjdk
|
||||
|
||||
# VSmartcard
|
||||
./.github/setup-vsmartcard.sh
|
||||
|
||||
# Javacard SDKs
|
||||
git clone https://github.com/martinpaljak/oracle_javacard_sdks.git
|
||||
export JC_HOME=$PWD/oracle_javacard_sdks/jc222_kit
|
||||
export JC_CLASSIC_HOME=$PWD/oracle_javacard_sdks/jc305u3_kit
|
||||
|
||||
# jCardSim
|
||||
git clone https://github.com/arekinath/jcardsim.git
|
||||
pushd jcardsim
|
||||
env | grep -i openjdk
|
||||
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/
|
||||
mvn initialize && mvn clean install
|
||||
popd
|
|
@ -0,0 +1,42 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
DEPS="docbook-xsl libpcsclite-dev xsltproc gengetopt libcmocka-dev help2man pcscd check softhsm2 pcsc-tools libtool make autoconf autoconf-archive automake libssl-dev zlib1g-dev pkg-config libreadline-dev openssl git"
|
||||
|
||||
if [ "$1" == "clang-tidy" ]; then
|
||||
DEPS="$DEPS clang-tidy"
|
||||
elif [ "$1" == "cac" ]; then
|
||||
DEPS="$DEPS libglib2.0-dev libnss3-dev gnutls-bin libusb-dev libudev-dev flex libnss3-tools"
|
||||
elif [ "$1" == "oseid" ]; then
|
||||
DEPS="$DEPS socat gawk xxd"
|
||||
elif [ "$1" == "piv" -o "$1" == "isoapplet" -o "$1" == "gidsapplet" -o "$1" == "openpgp" ]; then
|
||||
if [ "$1" == "piv" ]; then
|
||||
DEPS="$DEPS cmake"
|
||||
fi
|
||||
DEPS="$DEPS ant openjdk-8-jdk"
|
||||
elif [ "$1" == "mingw" -o "$1" == "mingw32" ]; then
|
||||
DEPS="$DEPS wine wine32 xvfb wget"
|
||||
sudo dpkg --add-architecture i386
|
||||
if [ "$1" == "mingw" ]; then
|
||||
DEPS="$DEPS binutils-mingw-w64-x86-64 gcc-mingw-w64-x86-64 mingw-w64"
|
||||
elif [ "$1" == "mingw32" ]; then
|
||||
DEPS="$DEPS binutils-mingw-w64-i686 gcc-mingw-w64-i686"
|
||||
fi
|
||||
fi
|
||||
|
||||
# make sure we do not get prompts
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential $DEPS
|
||||
|
||||
if [ "$1" == "mingw" -o "$1" == "mingw32" ]; then
|
||||
if [ ! -f "$(winepath 'C:/Program Files/Inno Setup 5/ISCC.exe')" ]; then
|
||||
/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16
|
||||
export DISPLAY=:99.0
|
||||
[ -d isetup ] || mkdir isetup
|
||||
pushd isetup
|
||||
[ -f isetup-5.5.6.exe ] || wget http://files.jrsoftware.org/is/5/isetup-5.5.6.exe
|
||||
sleep 5 # make sure the X server is ready ?
|
||||
wine isetup-5.5.6.exe /SILENT /VERYSILENT /SP- /SUPPRESSMSGBOXES /NORESTART
|
||||
popd
|
||||
fi
|
||||
fi
|
|
@ -0,0 +1,32 @@
|
|||
#!/bin/bash
|
||||
|
||||
brew install automake
|
||||
|
||||
# gengetopt
|
||||
curl https://ftp.gnu.org/gnu/gengetopt/gengetopt-2.23.tar.xz -L --output gengetopt-2.23.tar.xz
|
||||
tar xfj gengetopt-2.23.tar.xz
|
||||
pushd gengetopt-2.23
|
||||
./configure && make
|
||||
sudo make install
|
||||
popd
|
||||
|
||||
# help2man
|
||||
curl https://ftp.gnu.org/gnu/help2man/help2man-1.47.16.tar.xz -L --output help2man-1.47.16.tar.xz
|
||||
tar xjf help2man-1.47.16.tar.xz
|
||||
pushd help2man-1.47.16
|
||||
./configure && make
|
||||
sudo make install
|
||||
popd
|
||||
|
||||
# openSCToken
|
||||
export PATH="/usr/local/opt/ccache/libexec:$PATH"
|
||||
git clone https://github.com/frankmorgner/OpenSCToken.git
|
||||
sudo rm -rf /Library/Developer/CommandLineTools;
|
||||
|
||||
# TODO make the encrypted key working in github
|
||||
if [ "$GITHUB_EVENT_NAME" == "pull_request" -a -n "$encrypted_3b9f0b9d36d1_key" ]; then
|
||||
openssl aes-256-cbc -K $encrypted_3b9f0b9d36d1_key -iv $encrypted_3b9f0b9d36d1_iv -in .github/secrets.tar.enc -out .github/secrets.tar -d;
|
||||
.github/add_signing_key.sh;
|
||||
else
|
||||
unset CODE_SIGN_IDENTITY INSTALLER_SIGN_IDENTITY;
|
||||
fi
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [ ! -d "vsmartcard" ]; then
|
||||
git clone https://github.com/frankmorgner/vsmartcard.git
|
||||
fi
|
||||
pushd vsmartcard/virtualsmartcard
|
||||
autoreconf -vis && ./configure && make -j2 && sudo make install
|
||||
popd
|
|
@ -0,0 +1,47 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
# install the opensc
|
||||
sudo make install
|
||||
export LD_LIBRARY_PATH=/usr/local/lib
|
||||
|
||||
# VSmartcard
|
||||
./.github/setup-vsmartcard.sh
|
||||
|
||||
# libcacard
|
||||
if [ ! -d "libcacard" ]; then
|
||||
git clone https://gitlab.freedesktop.org/spice/libcacard.git
|
||||
fi
|
||||
pushd libcacard
|
||||
./autogen.sh --prefix=/usr && make -j2 && sudo make install
|
||||
popd
|
||||
|
||||
# virt_cacard
|
||||
if [ ! -d "virt_cacard" ]; then
|
||||
git clone https://github.com/Jakuje/virt_cacard.git
|
||||
fi
|
||||
pushd virt_cacard
|
||||
./autogen.sh && ./configure && make
|
||||
popd
|
||||
|
||||
sudo /etc/init.d/pcscd restart
|
||||
|
||||
pushd src/tests/p11test/
|
||||
./p11test -s 0 -p 12345678 -i -o virt_cacard.json &
|
||||
sleep 5
|
||||
popd
|
||||
|
||||
# virt_cacard startup
|
||||
pushd virt_cacard
|
||||
./setup-softhsm2.sh
|
||||
export SOFTHSM2_CONF=$PWD/softhsm2.conf
|
||||
./virt_cacard &
|
||||
wait $(ps aux | grep '[p]11test'| awk '{print $2}')
|
||||
kill -9 $(ps aux | grep '[v]irt_cacard'| awk '{print $2}')
|
||||
popd
|
||||
|
||||
# cleanup -- this would break later uses of pcscd
|
||||
pushd vsmartcard/virtualsmartcard
|
||||
sudo make uninstall
|
||||
popd
|
||||
|
||||
diff -u3 src/tests/p11test/virt_cacard{_ref,}.json
|
|
@ -0,0 +1,36 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
# install the opensc
|
||||
sudo make install
|
||||
export LD_LIBRARY_PATH=/usr/local/lib
|
||||
|
||||
# setup java stuff
|
||||
. .github/setup-java.sh
|
||||
|
||||
# GidsApplet
|
||||
git clone https://github.com/vletoux/GidsApplet.git;
|
||||
javac -classpath jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar GidsApplet/src/com/mysmartlogon/gidsApplet/*.java;
|
||||
echo "com.licel.jcardsim.card.applet.0.AID=A000000397425446590201" > gids_jcardsim.cfg;
|
||||
echo "com.licel.jcardsim.card.applet.0.Class=com.mysmartlogon.gidsApplet.GidsApplet" >> gids_jcardsim.cfg;
|
||||
echo "com.licel.jcardsim.card.ATR=3B80800101" >> gids_jcardsim.cfg;
|
||||
echo "com.licel.jcardsim.vsmartcard.host=localhost" >> gids_jcardsim.cfg;
|
||||
echo "com.licel.jcardsim.vsmartcard.port=35963" >> gids_jcardsim.cfg;
|
||||
|
||||
# log errors from pcscd to console
|
||||
sudo systemctl stop pcscd.service pcscd.socket
|
||||
sudo /usr/sbin/pcscd -f &
|
||||
PCSCD_PID=$!
|
||||
|
||||
|
||||
# start the applet and run couple of commands against that
|
||||
java -noverify -cp GidsApplet/src/:jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar com.licel.jcardsim.remote.VSmartCard gids_jcardsim.cfg >/dev/null &
|
||||
PID=$!;
|
||||
sleep 5;
|
||||
opensc-tool --card-driver default --send-apdu 80b80000190bA0000003974254465902010bA00000039742544659020100;
|
||||
opensc-tool -n;
|
||||
gids-tool --initialize --pin 123456 --admin-key 000000000000000000000000000000000000000000000000 --serial 00000000000000000000000000000000;
|
||||
kill -9 $PID
|
||||
|
||||
|
||||
# cleanup
|
||||
sudo kill -9 $PCSCD_PID
|
|
@ -0,0 +1,41 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
# install the opensc
|
||||
sudo make install
|
||||
export LD_LIBRARY_PATH=/usr/local/lib
|
||||
|
||||
# setup java stuff
|
||||
./.github/setup-java.sh
|
||||
|
||||
# The ISO applet
|
||||
git clone https://github.com/philipWendland/IsoApplet.git;
|
||||
javac -classpath jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar IsoApplet/src/net/pwendland/javacard/pki/isoapplet/*.java;
|
||||
echo "com.licel.jcardsim.card.applet.0.AID=F276A288BCFBA69D34F31001" > isoapplet_jcardsim.cfg;
|
||||
echo "com.licel.jcardsim.card.applet.0.Class=net.pwendland.javacard.pki.isoapplet.IsoApplet" >> isoapplet_jcardsim.cfg;
|
||||
echo "com.licel.jcardsim.card.ATR=3B80800101" >> isoapplet_jcardsim.cfg;
|
||||
echo "com.licel.jcardsim.vsmartcard.host=localhost" >> isoapplet_jcardsim.cfg;
|
||||
echo "com.licel.jcardsim.vsmartcard.port=35963" >> isoapplet_jcardsim.cfg;
|
||||
|
||||
# log errors from pcscd to console
|
||||
sudo systemctl stop pcscd.service pcscd.socket
|
||||
sudo /usr/sbin/pcscd -f &
|
||||
PCSCD_PID=$!
|
||||
|
||||
# start the applet and run couple of commands against that
|
||||
java -noverify -cp IsoApplet/src/:jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar com.licel.jcardsim.remote.VSmartCard isoapplet_jcardsim.cfg >/dev/null &
|
||||
PID=$!;
|
||||
sleep 5;
|
||||
opensc-tool --card-driver default --send-apdu 80b800001a0cf276a288bcfba69d34f310010cf276a288bcfba69d34f3100100;
|
||||
opensc-tool -n;
|
||||
pkcs15-init --create-pkcs15 --so-pin 123456 --so-puk 0123456789abcdef;
|
||||
pkcs15-tool --change-pin --pin 123456 --new-pin 654321;
|
||||
pkcs15-tool --unblock-pin --puk 0123456789abcdef --new-pin 123456;
|
||||
pkcs15-init --generate-key rsa/2048 --id 1 --key-usage decrypt,sign --auth-id FF --pin 123456;
|
||||
pkcs15-init --generate-key rsa/2048 --id 2 --key-usage decrypt --auth-id FF --pin 123456;
|
||||
pkcs15-init --generate-key ec/secp256r1 --id 3 --key-usage sign --auth-id FF --pin 123456;
|
||||
pkcs15-tool -D;
|
||||
pkcs11-tool -l -t -p 123456;
|
||||
kill -9 $PID;
|
||||
|
||||
# cleanup
|
||||
sudo kill -9 $PCSCD_PID
|
|
@ -0,0 +1,40 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
# install the opensc
|
||||
sudo make install
|
||||
export LD_LIBRARY_PATH=/usr/local/lib
|
||||
|
||||
# setup java stuff
|
||||
. .github/setup-java.sh
|
||||
|
||||
# The OpenPGP applet
|
||||
git clone --recursive https://github.com/Yubico/ykneo-openpgp.git;
|
||||
cd ykneo-openpgp;
|
||||
ant -DJAVACARD_HOME=${JC_HOME};
|
||||
cd $TRAVIS_BUILD_DIR;
|
||||
echo "com.licel.jcardsim.card.applet.0.AID=D2760001240102000000000000010000" > openpgp_jcardsim.cfg;
|
||||
echo "com.licel.jcardsim.card.applet.0.Class=openpgpcard.OpenPGPApplet" >> openpgp_jcardsim.cfg;
|
||||
echo "com.licel.jcardsim.card.ATR=3B80800101" >> openpgp_jcardsim.cfg;
|
||||
echo "com.licel.jcardsim.vsmartcard.host=localhost" >> openpgp_jcardsim.cfg;
|
||||
echo "com.licel.jcardsim.vsmartcard.port=35963" >> openpgp_jcardsim.cfg;
|
||||
|
||||
# log errors from pcscd to console
|
||||
sudo systemctl stop pcscd.service pcscd.socket
|
||||
sudo /usr/sbin/pcscd -f &
|
||||
PCSCD_PID=$!
|
||||
|
||||
|
||||
# start the applet and run couple of commands against that
|
||||
java -noverify -cp ykneo-openpgp/applet/bin:jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar com.licel.jcardsim.remote.VSmartCard openpgp_jcardsim.cfg >/dev/null &
|
||||
PID=$!;
|
||||
sleep 5;
|
||||
opensc-tool --card-driver default --send-apdu 80b800002210D276000124010200000000000001000010D276000124010200000000000001000000;
|
||||
opensc-tool -n;
|
||||
openpgp-tool --verify CHV3 --pin 12345678 --gen-key 2;
|
||||
pkcs15-init --verify --auth-id 3 --pin 12345678 --delete-objects privkey,pubkey --id 2 --generate-key rsa/2048;
|
||||
pkcs11-tool -l -t -p 123456;
|
||||
kill -9 $PID
|
||||
|
||||
|
||||
# cleanup
|
||||
sudo kill -9 $PCSCD_PID
|
|
@ -0,0 +1,54 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
# install the opensc
|
||||
sudo make install
|
||||
export LD_LIBRARY_PATH=/usr/local/lib
|
||||
|
||||
if [ ! -d oseid ]; then
|
||||
git clone https://github.com/popovec/oseid
|
||||
fi
|
||||
pushd oseid/src/
|
||||
make -f Makefile.console
|
||||
if [ ! -d tmp ]; then
|
||||
mkdir tmp
|
||||
fi
|
||||
socat -d -d pty,link=tmp/OsEIDsim.socket,raw,echo=0 "exec:build/console/console ...,pty,raw,echo=0" &
|
||||
PID=$!
|
||||
sleep 1
|
||||
echo "# OsEIDsim" > tmp/reader.conf
|
||||
echo 'FRIENDLYNAME "OsEIDsim"' >> tmp/reader.conf
|
||||
echo "DEVICENAME $PWD/tmp/OsEIDsim.socket" >> tmp/reader.conf
|
||||
echo "LIBPATH $PWD/build/console/libOsEIDsim.so.0.0.1" >> tmp/reader.conf
|
||||
echo "CHANNELID 1" >> tmp/reader.conf
|
||||
sudo mv tmp/reader.conf /etc/reader.conf.d/reader.conf
|
||||
cat /etc/reader.conf.d/reader.conf
|
||||
popd
|
||||
|
||||
sudo /etc/init.d/pcscd restart
|
||||
|
||||
# Needed for tput to not report warnings
|
||||
export TERM=xterm-256color
|
||||
|
||||
pushd oseid/tools
|
||||
echo | ./OsEID-tool INIT
|
||||
./OsEID-tool RSA-CREATE-KEYS
|
||||
./OsEID-tool RSA-UPLOAD-KEYS
|
||||
./OsEID-tool RSA-DECRYPT-TEST
|
||||
./OsEID-tool RSA-SIGN-PKCS11-TEST
|
||||
./OsEID-tool EC-CREATE-KEYS
|
||||
./OsEID-tool EC-UPLOAD-KEYS
|
||||
./OsEID-tool EC-SIGN-TEST
|
||||
./OsEID-tool EC-SIGN-PKCS11-TEST
|
||||
./OsEID-tool EC-ECDH-TEST
|
||||
popd
|
||||
|
||||
# this does not work as we have random key IDs in here
|
||||
#pushd src/tests/p11test/
|
||||
#./p11test -s 0 -p 11111111 -o oseid.json || true
|
||||
#diff -u3 oseid_ref.json oseid.json
|
||||
#popd
|
||||
|
||||
# cleanup -- this would break later uses of pcscd
|
||||
kill -9 $PID
|
||||
rm oseid/src/card_mem
|
||||
sudo rm /etc/reader.conf.d/reader.conf
|
|
@ -0,0 +1,45 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
# install the opensc
|
||||
sudo make install
|
||||
export LD_LIBRARY_PATH=/usr/local/lib
|
||||
|
||||
# setup java stuff
|
||||
. .github/setup-java.sh
|
||||
|
||||
# The PIV Applet
|
||||
git clone --recursive https://github.com/arekinath/PivApplet.git
|
||||
pushd PivApplet
|
||||
JC_HOME=${JC_CLASSIC_HOME} ant dist
|
||||
popd
|
||||
|
||||
# yubico-piv-tool is needed for PIV Applet management
|
||||
git clone https://github.com/Yubico/yubico-piv-tool.git
|
||||
pushd yubico-piv-tool
|
||||
mkdir build
|
||||
pushd build
|
||||
cmake .. && make && sudo make install
|
||||
popd
|
||||
popd
|
||||
|
||||
|
||||
# log errors from pcscd to console
|
||||
sudo systemctl stop pcscd.service pcscd.socket
|
||||
sudo /usr/sbin/pcscd -f &
|
||||
PCSCD_PID=$!
|
||||
|
||||
|
||||
# start the applet and run couple of commands against that
|
||||
java -noverify -cp PivApplet/bin/:jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar com.licel.jcardsim.remote.VSmartCard PivApplet/test/jcardsim.cfg >/dev/null &
|
||||
PID=$!
|
||||
sleep 5
|
||||
opensc-tool --card-driver default --send-apdu 80b80000120ba000000308000010000100050000020F0F7f
|
||||
opensc-tool -n
|
||||
yubico-piv-tool -v 9999 -r 'Virtual PCD 00 00' -P 123456 -s 9e -a generate -A RSA2048
|
||||
yubico-piv-tool -v 9999 -r 'Virtual PCD 00 00' -P 123456 -s 9a -a generate -A ECCP256
|
||||
pkcs11-tool -l -t -p 123456
|
||||
kill -9 $PID
|
||||
|
||||
|
||||
# cleanup
|
||||
sudo kill -9 $PCSCD_PID
|
|
@ -0,0 +1,28 @@
|
|||
name: CIFuzz
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.c'
|
||||
- '**.h'
|
||||
jobs:
|
||||
Fuzzing:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Build Fuzzers
|
||||
id: build
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'opensc'
|
||||
dry-run: false
|
||||
- name: Run Fuzzers
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'opensc'
|
||||
fuzz-seconds: 600
|
||||
dry-run: false
|
||||
- name: Upload Crash
|
||||
uses: actions/upload-artifact@v1
|
||||
if: failure() && steps.build.outcome == 'success'
|
||||
with:
|
||||
name: artifacts
|
||||
path: ./out/artifacts
|
|
@ -0,0 +1,176 @@
|
|||
name: Linux
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.c'
|
||||
- '**.h'
|
||||
push:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: .github/setup-linux.sh
|
||||
- run: .github/build.sh dist
|
||||
- uses: actions/cache@v2
|
||||
id: cache-build
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ runner.os }}-${{ github.sha }}
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: opensc-build
|
||||
path:
|
||||
opensc*.tar.gz
|
||||
|
||||
build-ubuntu-18:
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: .github/setup-linux.sh
|
||||
- run: .github/build.sh
|
||||
- uses: actions/cache@v2
|
||||
id: cache-build
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ runner.os }}-18-${{ github.sha }}
|
||||
|
||||
build-mingw:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: .github/setup-linux.sh mingw
|
||||
- run: .github/build.sh mingw
|
||||
- name: Cache build artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: opensc-build-mingw
|
||||
path:
|
||||
win32/Output/OpenSC*.exe
|
||||
|
||||
build-mingw32:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: .github/setup-linux.sh mingw32
|
||||
- run: .github/build.sh mingw32
|
||||
- name: Cache build artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: opensc-build-mingw32
|
||||
path:
|
||||
win32/Output/OpenSC*.exe
|
||||
|
||||
test-piv:
|
||||
runs-on: ubuntu-18.04
|
||||
needs: [build-ubuntu-18]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/cache@v2
|
||||
id: cache-build
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ runner.os }}-18-${{ github.sha }}
|
||||
- run: .github/setup-linux.sh piv
|
||||
- run: .github/test-piv.sh
|
||||
|
||||
test-isoapplet:
|
||||
runs-on: ubuntu-18.04
|
||||
needs: [build-ubuntu-18]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/cache@v2
|
||||
id: cache-build
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ runner.os }}-18-${{ github.sha }}
|
||||
- run: .github/setup-linux.sh isoapplet
|
||||
- run: .github/test-isoapplet.sh
|
||||
|
||||
test-gidsapplet:
|
||||
runs-on: ubuntu-18.04
|
||||
needs: [build-ubuntu-18]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/cache@v2
|
||||
id: cache-build
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ runner.os }}-18-${{ github.sha }}
|
||||
- run: .github/setup-linux.sh gidsapplet
|
||||
- run: .github/test-gidsapplet.sh
|
||||
|
||||
test-openpgp:
|
||||
runs-on: ubuntu-18.04
|
||||
needs: [build-ubuntu-18]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/cache@v2
|
||||
id: cache-build
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ runner.os }}-18-${{ github.sha }}
|
||||
- run: .github/setup-linux.sh openpgp
|
||||
# the openpgp sometimes fails
|
||||
- run: .github/test-openpgp.sh || true
|
||||
|
||||
build-clang-tidy:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/cache@v2
|
||||
id: cache-build
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ runner.os }}-${{ github.sha }}
|
||||
- run: .github/setup-linux.sh clang-tidy
|
||||
- run: .github/build.sh
|
||||
|
||||
test-cac:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/cache@v2
|
||||
id: cache-build
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ runner.os }}-${{ github.sha }}
|
||||
- run: .github/setup-linux.sh cac
|
||||
- run: .github/test-cac.sh
|
||||
|
||||
test-oseid:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/cache@v2
|
||||
id: cache-build
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ runner.os }}-${{ github.sha }}
|
||||
- run: .github/setup-linux.sh oseid
|
||||
- run: .github/test-oseid.sh
|
||||
|
||||
push-artifacts:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build, build-mingw]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/cache@v2
|
||||
id: cache-build
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ runner.os }}-${{ github.sha }}
|
||||
- name: Pull mingw build artifacts
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: opensc-build-mingw
|
||||
- run: git config --global user.email "builds@github.com"
|
||||
- run: git config --global user.name "Github Actions";
|
||||
- run: .github/push_artifacts.sh "Github Actions ${GITHUB_REF}"
|
||||
if: ${{ github.event_name != 'pull_request' && github.repository == 'OpenSC/OpenSC' }}
|
|
@ -0,0 +1,39 @@
|
|||
name: OSX
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.c'
|
||||
- '**.h'
|
||||
push:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: .github/setup-macos.sh
|
||||
- run: .github/build.sh
|
||||
- name: Cache build artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: opensc-build-macos
|
||||
path:
|
||||
OpenSC*.dmg
|
||||
|
||||
push-artifacts:
|
||||
runs-on: macos-latest
|
||||
needs: [build]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Pull build artifacts
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: opensc-build-macos
|
||||
- run: git config --global user.email "builds@github.com"
|
||||
- run: git config --global user.name "Github Actions";
|
||||
- run: .github/push_artifacts.sh "Github Actions ${GITHUB_REF}"
|
||||
if: ${{ github.event_name != 'pull_request' && github.repository == 'OpenSC/OpenSC' }}
|
||||
# TODO this fails probably because the key is not loaded in keychain before with
|
||||
# security: SecKeychainDelete: The specified keychain could not be found.
|
||||
# - run: .github/remove_signing_key.sh; rm -f .github/secrets.tar
|
|
@ -64,6 +64,7 @@ ChangeLog
|
|||
doc/tools/*-tool
|
||||
doc/tools/eidenv
|
||||
doc/tools/opensc-explorer
|
||||
doc/tools/pkcs11-register
|
||||
doc/tools/pkcs15-crypt
|
||||
doc/tools/pkcs15-init
|
||||
doc/tools/opensc-asn1
|
||||
|
@ -79,6 +80,7 @@ src/tools/pkcs15-init
|
|||
src/tools/eidenv
|
||||
src/tools/opensc-explorer
|
||||
src/tools/cardos-info
|
||||
src/tools/gcns
|
||||
src/tools/sceac-example
|
||||
src/tools/opensc-notify
|
||||
src/tools/opensc-notify.plist
|
||||
|
@ -120,5 +122,7 @@ tests/*.trs
|
|||
src/tests/unittests/*.log
|
||||
src/tests/unittests/*.trs
|
||||
src/tests/unittests/asn1
|
||||
src/tests/unittests/compression
|
||||
src/tests/unittests/simpletlv
|
||||
|
||||
version.m4.ci
|
||||
|
|
65
.travis.yml
65
.travis.yml
|
@ -6,9 +6,13 @@ matrix:
|
|||
os: osx
|
||||
osx_image: xcode9.4
|
||||
env: DO_PUSH_ARTIFACT=yes
|
||||
- compiler: clang
|
||||
os: osx
|
||||
osx_image: xcode12.2
|
||||
env: DO_PUSH_ARTIFACT=yes
|
||||
- compiler: clang
|
||||
os: linux
|
||||
dist: bionic
|
||||
dist: focal
|
||||
- compiler: gcc
|
||||
os: linux
|
||||
dist: bionic
|
||||
|
@ -17,7 +21,7 @@ matrix:
|
|||
- ENABLE_DOC=--enable-doc
|
||||
- compiler: gcc
|
||||
os: linux
|
||||
dist: bionic
|
||||
dist: focal
|
||||
env:
|
||||
- DO_SIMULATION=oseid
|
||||
- env:
|
||||
|
@ -47,25 +51,29 @@ env:
|
|||
- COVERITY_SCAN_PROJECT_NAME="$TRAVIS_REPO_SLUG"
|
||||
- SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)
|
||||
|
||||
addons:
|
||||
apt_packages:
|
||||
- binutils-mingw-w64-i686
|
||||
- binutils-mingw-w64-x86-64
|
||||
- docbook-xsl
|
||||
- gcc-mingw-w64-i686
|
||||
- gcc-mingw-w64-x86-64
|
||||
- libpcsclite-dev
|
||||
- mingw-w64
|
||||
- xsltproc
|
||||
- gengetopt
|
||||
- libcmocka-dev
|
||||
- help2man
|
||||
- pcscd
|
||||
- pcsc-tools
|
||||
- check
|
||||
- ant
|
||||
- socat
|
||||
- cmake
|
||||
# Commented out because of a bug in travis images for Focal:
|
||||
# https://travis-ci.community/t/clang-10-was-recently-broken-on-linux-unmet-dependencies-for-clang-10-clang-tidy-10-valgrind/11527
|
||||
#addons:
|
||||
# apt_packages:
|
||||
# - binutils-mingw-w64-i686
|
||||
# - binutils-mingw-w64-x86-64
|
||||
# - docbook-xsl
|
||||
# - gcc-mingw-w64-i686
|
||||
# - gcc-mingw-w64-x86-64
|
||||
# - libpcsclite-dev
|
||||
# - mingw-w64
|
||||
# - xsltproc
|
||||
# - gengetopt
|
||||
# - libcmocka-dev
|
||||
# - help2man
|
||||
# - pcscd
|
||||
# - pcsc-tools
|
||||
# - check
|
||||
# - ant
|
||||
# - socat
|
||||
# - cmake
|
||||
# - clang-tidy
|
||||
# - softhsm2
|
||||
|
||||
before_install:
|
||||
# homebrew is dead slow in older images due to the many updates it would need to download and build.
|
||||
|
@ -85,8 +93,9 @@ before_install:
|
|||
popd;
|
||||
export PATH="/usr/local/opt/ccache/libexec:$PATH";
|
||||
git clone https://github.com/frankmorgner/OpenSCToken.git;
|
||||
sudo rm -rf /Library/Developer/CommandLineTools;
|
||||
fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" -a "$TRAVIS_PULL_REQUEST" = "false" ]; then
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" -a "$TRAVIS_PULL_REQUEST" = "false" -a -n "$encrypted_3b9f0b9d36d1_key" ]; then
|
||||
openssl aes-256-cbc -K $encrypted_3b9f0b9d36d1_key -iv $encrypted_3b9f0b9d36d1_iv -in .github/secrets.tar.enc -out .github/secrets.tar -d;
|
||||
.github/add_signing_key.sh;
|
||||
else
|
||||
|
@ -107,6 +116,12 @@ before_install:
|
|||
- if [ -n "${HOST}" ]; then
|
||||
sudo apt-get install -y wine;
|
||||
fi
|
||||
- if [ "$TRAVIS_DIST" == "focal" ]; then
|
||||
sudo apt-get install -yq --allow-downgrades libc6=2.31-0ubuntu9.2 libc6-dev=2.31-0ubuntu9.2;
|
||||
fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then
|
||||
sudo -E apt-get -yq --no-install-suggests --no-install-recommends --allow-downgrades --allow-remove-essential --allow-change-held-packages install binutils-mingw-w64-i686 binutils-mingw-w64-x86-64 docbook-xsl gcc-mingw-w64-i686 gcc-mingw-w64-x86-64 libpcsclite-dev mingw-w64 xsltproc gengetopt libcmocka-dev help2man pcscd pcsc-tools check ant socat cmake clang-tidy softhsm2;
|
||||
fi
|
||||
|
||||
before_script:
|
||||
- if [ "$TRAVIS_BRANCH" = "master" -a "$TRAVIS_PULL_REQUEST" = "false" ]; then
|
||||
|
@ -245,7 +260,7 @@ script:
|
|||
fi;
|
||||
fi
|
||||
- if [ -z "$HOST" -a "${DO_COVERITY_SCAN}" != "yes" -a -z "$DO_SIMULATION" ]; then
|
||||
make check && make dist;
|
||||
make check && make distcheck || (cat tests/*log src/tests/unittests/*log && exit 1);
|
||||
fi
|
||||
- if [ ! -z "$HOST" -a "${DO_COVERITY_SCAN}" != "yes" ]; then
|
||||
make install;
|
||||
|
@ -318,9 +333,11 @@ script:
|
|||
./OsEID-tool RSA-CREATE-KEYS;
|
||||
./OsEID-tool RSA-UPLOAD-KEYS;
|
||||
./OsEID-tool RSA-DECRYPT-TEST;
|
||||
./OsEID-tool RSA-SIGN-PKCS11-TEST;
|
||||
./OsEID-tool EC-CREATE-KEYS;
|
||||
./OsEID-tool EC-UPLOAD-KEYS;
|
||||
./OsEID-tool EC-SIGN-TEST;
|
||||
./OsEID-tool EC-SIGN-PKCS11-TEST;
|
||||
./OsEID-tool EC-ECDH-TEST;
|
||||
kill -9 $PID;
|
||||
|
||||
|
@ -328,7 +345,7 @@ script:
|
|||
fi
|
||||
- if [ "${DO_SIMULATION}" = "cac" ]; then
|
||||
cd $TRAVIS_BUILD_DIR;
|
||||
make check && sudo make install || (cat tests/*log src/tests/unittests/*log && exit);
|
||||
make check && sudo make install || (cat tests/*log src/tests/unittests/*log && exit 1);
|
||||
export LD_LIBRARY_PATH=/usr/local/lib;
|
||||
cd src/tests/p11test/;
|
||||
./p11test -s 0 -p 12345678 -i &
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<false/>
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
|
@ -13,11 +13,11 @@ set -ex
|
|||
test -x ./configure || ./bootstrap
|
||||
BUILDPATH=${PWD}
|
||||
|
||||
# Locate the latest OSX SDK
|
||||
SDK_PATH=$(xcrun --sdk macosx --show-sdk-path)
|
||||
|
||||
# Set SDK path
|
||||
export CFLAGS="$CFLAGS -isysroot $SDK_PATH -arch x86_64"
|
||||
xcode_ver=$(xcodebuild -version | sed -En 's/Xcode[[:space:]](.*)/\1/p')
|
||||
base_ver="12.2"
|
||||
if [ $(echo -e $base_ver"\n"$xcode_ver | sort -V | head -1) == "$base_ver" ]; then
|
||||
export BUILD_ARM="true"
|
||||
fi
|
||||
|
||||
export SED=/usr/bin/sed
|
||||
PREFIX=/Library/OpenSC
|
||||
|
@ -31,19 +31,39 @@ if ! pkg-config libcrypto --atleast-version=1.0.1; then
|
|||
git clone --depth=1 https://github.com/openssl/openssl.git -b OpenSSL_1_1_1-stable
|
||||
fi
|
||||
cd openssl
|
||||
KERNEL_BITS=64 ./config no-shared --prefix=$PREFIX
|
||||
MACHINE=x86_64 ./config no-shared --prefix=$PREFIX
|
||||
make clean
|
||||
make -j 4
|
||||
make DESTDIR=$BUILDPATH/openssl_bin install_sw
|
||||
if test -n "${BUILD_ARM}"; then
|
||||
make clean
|
||||
MACHINE=arm64 KERNEL_BITS=64 ./config no-shared --prefix=$PREFIX
|
||||
make -j 4
|
||||
make DESTDIR=$BUILDPATH/openssl_arm64 install_sw
|
||||
lipo -create $BUILDPATH/openssl_arm64/$PREFIX/lib/libcrypto.a $BUILDPATH/openssl_bin/$PREFIX/lib/libcrypto.a -output libcrypto.a
|
||||
lipo -create $BUILDPATH/openssl_arm64/$PREFIX/lib/libssl.a $BUILDPATH/openssl_bin/$PREFIX/lib/libssl.a -output libssl.a
|
||||
mv libcrypto.a $BUILDPATH/openssl_bin/$PREFIX/lib/libcrypto.a
|
||||
mv libssl.a $BUILDPATH/openssl_bin/$PREFIX/lib/libssl.a
|
||||
fi
|
||||
cd ..
|
||||
fi
|
||||
export OPENSSL_CFLAGS="`env PKG_CONFIG_PATH=$BUILDPATH/openssl_bin/$PREFIX/lib/pkgconfig PKG_CONFIG_SYSROOT_DIR=$BUILDPATH/openssl_bin pkg-config --static --cflags libcrypto`"
|
||||
export OPENSSL_LIBS="` env PKG_CONFIG_PATH=$BUILDPATH/openssl_bin/$PREFIX/lib/pkgconfig PKG_CONFIG_SYSROOT_DIR=$BUILDPATH/openssl_bin pkg-config --static --libs libcrypto`"
|
||||
fi
|
||||
|
||||
# Locate the latest OSX SDK
|
||||
SDK_PATH=$(xcrun --sdk macosx --show-sdk-path)
|
||||
export CFLAGS="$CFLAGS -isysroot $SDK_PATH"
|
||||
|
||||
if test -n "${BUILD_ARM}"; then
|
||||
export CFLAGS="$CFLAGS -arch x86_64 -arch arm64"
|
||||
export LDFLAGS="$LDFLAGS -arch x86_64 -arch arm64"
|
||||
fi
|
||||
export OBJCFLAGS=$CFLAGS
|
||||
|
||||
if ! test -e $BUILDPATH/openpace_bin/$PREFIX/lib/pkgconfig; then
|
||||
if ! test -e openpace; then
|
||||
git clone --depth=1 https://github.com/frankmorgner/openpace.git -b 1.1.0
|
||||
git clone --depth=1 https://github.com/frankmorgner/openpace.git -b 1.1.1
|
||||
fi
|
||||
cd openpace
|
||||
autoreconf -vis
|
||||
|
@ -99,7 +119,7 @@ fi
|
|||
mkdir -p "$BUILDPATH/target/Applications/Utilities"
|
||||
osacompile -o "$BUILDPATH/target/Applications/Utilities/OpenSC Notify.app" "MacOSX/OpenSC_Notify.applescript"
|
||||
if test -n "${CODE_SIGN_IDENTITY}"; then
|
||||
codesign --force --sign "${CODE_SIGN_IDENTITY}" --entitlements MacOSX/OpenSC_Uninstaller.entitlements --deep --timestamp --options runtime "$BUILDPATH/target/Applications/Utilities/OpenSC Notify.app"
|
||||
codesign --force --sign "${CODE_SIGN_IDENTITY}" --entitlements MacOSX/OpenSC_applescripts.entitlements --deep --timestamp --options runtime "$BUILDPATH/target/Applications/Utilities/OpenSC Notify.app"
|
||||
fi
|
||||
|
||||
|
||||
|
@ -120,9 +140,12 @@ if (( $(xcodebuild -version | sed -En 's/Xcode[[:space:]]+([0-9]+)(\.[0-9]*)*/\1
|
|||
else
|
||||
xcodebuild -target OpenSC -configuration Deployment -project OpenSC.tokend/Tokend.xcodeproj install DSTROOT=${BUILDPATH}/target_tokend
|
||||
fi
|
||||
|
||||
TOKEND="-tokend"
|
||||
else
|
||||
# https://github.com/OpenSC/OpenSC.tokend/issues/33
|
||||
mkdir -p ${BUILDPATH}/target_tokend
|
||||
TOKEND=""
|
||||
fi
|
||||
|
||||
#if ! test -e $BUILDPATH/target/Library/Security/tokend/OpenSC.tokend/Contents/Resources/Applications/terminal-notifier.app; then
|
||||
|
@ -173,6 +196,8 @@ if test -e OpenSCToken -a -n "${CODE_SIGN_IDENTITY}" -a -n "${DEVELOPMENT_TEAM}"
|
|||
xcodebuild -target OpenSCTokenApp -configuration Debug -project OpenSCTokenApp.xcodeproj install DSTROOT=${BUILDPATH}/target_token \
|
||||
CODE_SIGN_IDENTITY="${CODE_SIGN_IDENTITY}" DEVELOPMENT_TEAM="${DEVELOPMENT_TEAM}" OTHER_CODE_SIGN_FLAGS="--timestamp --options=runtime" CODE_SIGN_INJECT_BASE_ENTITLEMENTS=NO CODE_SIGN_STYLE=Manual
|
||||
cd ..
|
||||
|
||||
COMPONENT_TOKEN="--component-plist MacOSX/target_token.plist"
|
||||
else
|
||||
# if no OpenSCToken is checked out, then we create a dummy package
|
||||
mkdir -p ${BUILDPATH}/target_token
|
||||
|
@ -183,7 +208,7 @@ if test -n "${CODE_SIGN_IDENTITY}"; then
|
|||
do
|
||||
# find executable files and run codesign on them
|
||||
find ${d} -type f -perm +111 -print -exec \
|
||||
codesign --force --sign "${CODE_SIGN_IDENTITY}" --entitlements MacOSX/OpenSC_Uninstaller.entitlements --deep --timestamp --options runtime {} \;
|
||||
codesign --force --sign "${CODE_SIGN_IDENTITY}" --entitlements MacOSX/OpenSC_binaries.entitlements --deep --timestamp --options runtime {} \;
|
||||
done
|
||||
fi
|
||||
|
||||
|
@ -191,7 +216,7 @@ fi
|
|||
# Build package
|
||||
pkgbuild --root ${BUILDPATH}/target --component-plist MacOSX/target.plist --scripts MacOSX/scripts --identifier org.opensc-project.mac --version @PACKAGE_VERSION@ --install-location / OpenSC.pkg
|
||||
pkgbuild --root ${BUILDPATH}/target_tokend --component-plist MacOSX/target_tokend.plist --identifier org.opensc-project.tokend --version @PACKAGE_VERSION@ --install-location / OpenSC-tokend.pkg
|
||||
pkgbuild --root ${BUILDPATH}/target_token --component-plist MacOSX/target_token.plist --identifier org.opensc-project.mac.opensctoken --version @PACKAGE_VERSION@ --install-location / OpenSCToken.pkg
|
||||
pkgbuild --root ${BUILDPATH}/target_token $COMPONENT_TOKEN --identifier org.opensc-project.mac.opensctoken --version @PACKAGE_VERSION@ --install-location / OpenSCToken.pkg
|
||||
pkgbuild --root ${BUILDPATH}/target_startup --component-plist MacOSX/target_startup.plist --identifier org.opensc-project.startup --version @PACKAGE_VERSION@ --install-location / OpenSC-startup.pkg
|
||||
|
||||
# Build product
|
||||
|
@ -206,13 +231,13 @@ fi
|
|||
# Build "Uninstaller"
|
||||
osacompile -o "${imagedir}/OpenSC Uninstaller.app" "MacOSX/OpenSC_Uninstaller.applescript"
|
||||
if test -n "${CODE_SIGN_IDENTITY}"; then
|
||||
codesign --force --sign "${CODE_SIGN_IDENTITY}" --entitlements MacOSX/OpenSC_Uninstaller.entitlements --deep --timestamp --options runtime "${imagedir}/OpenSC Uninstaller.app"
|
||||
codesign --force --sign "${CODE_SIGN_IDENTITY}" --entitlements MacOSX/OpenSC_applescripts.entitlements --deep --timestamp --options runtime "${imagedir}/OpenSC Uninstaller.app"
|
||||
fi
|
||||
|
||||
# Create .dmg
|
||||
rm -f OpenSC-@PACKAGE_VERSION@.dmg
|
||||
rm -f OpenSC-@PACKAGE_VERSION@$TOKEND.dmg
|
||||
i=0
|
||||
while ! hdiutil create -srcfolder "${imagedir}" -volname "@PACKAGE_NAME@" -fs JHFS+ OpenSC-@PACKAGE_VERSION@.dmg
|
||||
while ! hdiutil create -srcfolder "${imagedir}" -volname "@PACKAGE_NAME@" -fs JHFS+ OpenSC-@PACKAGE_VERSION@$TOKEND.dmg
|
||||
do
|
||||
i=$[$i+1]
|
||||
if [ $i -gt 2 ]
|
||||
|
|
38
NEWS
38
NEWS
|
@ -1,5 +1,43 @@
|
|||
NEWS for OpenSC -- History of user visible changes
|
||||
|
||||
# New in 0.22.0; 2021-08-10
|
||||
## General improvements
|
||||
* Use standard paths for file cache on Linux (#2148) and OSX (#2214)
|
||||
* Various issues of memory/buffer handling in legacy drivers mostly reported by oss-fuzz and coverity (tcos, oberthur, isoapplet, iasecc, westcos, gpk, flex, dnie, mcrd, authentic, belpic)
|
||||
* Add threading test to `pkcs11-tool` (#2067)
|
||||
* Add support to generate generic secret keys (#2140)
|
||||
* `opensc-explorer`: Print information about LCS (Life cycle status byte) (#2195)
|
||||
* Add support for Apple's arm64 (M1) binaries, removed TokenD. A seperate installer with TokenD (and without arm64 binaries) will be available (#2179).
|
||||
* Support for gcc11 and its new strict aliasing rules (#2241, #2260)
|
||||
* Initial support for building with OpenSSL 3.0 (#2343)
|
||||
* pkcs15-tool: Write data objects in binary mode (#2324)
|
||||
* Avoid limited size of log messages (#2352)
|
||||
## PKCS#11
|
||||
* Support for ECDSA verification (#2211)
|
||||
* Support for ECDSA with different SHA hashes (#2190)
|
||||
* Prevent issues in p11-kit by not returning unexpected return codes (#2207)
|
||||
* Add support for PKCS#11 3.0: The new interfaces, profile objects and functions (#2096, #2293)
|
||||
* Standardize the version 2 on 2.20 in the code (#2096)
|
||||
* Fix CKA_MODIFIABLE and CKA_EXTRACTABLE (#2176)
|
||||
* Copy arguments of C_Initialize (#2350)
|
||||
## Minidriver
|
||||
* Fix RSA-PSS signing (#2234)
|
||||
## OpenPGP
|
||||
* Fix DO deletion (#2215)
|
||||
* Add support for (X)EdDSA keys (#1960)
|
||||
## IDPrime
|
||||
* Add support for applet version 3 and fix RSA-PSS mechanisms (#2205)
|
||||
* Add support for applet version 4 (#2332)
|
||||
## MyEID
|
||||
* New configuration option for opensc.conf to disable pkcs1_padding (#2193)
|
||||
* Add support for ECDSA with different hashes (#2190)
|
||||
* Enable more mechanisms (#2178)
|
||||
* Fixed asking for a user pin when formatting a card (#1737)
|
||||
## IAS/ECC
|
||||
* Added support for French CPx Healthcare cards (#2217)
|
||||
## CardOS
|
||||
* Added ATR for new CardOS 5.4 version (#2296)
|
||||
|
||||
# New in 0.21.0; 2020-11-24
|
||||
## General Improvements
|
||||
* fixed security problems
|
||||
|
|
17
README.md
17
README.md
|
@ -4,7 +4,8 @@ Wiki is [available online](https://github.com/OpenSC/OpenSC/wiki)
|
|||
|
||||
Please take a look at the documentation before trying to use OpenSC.
|
||||
|
||||
[![Travis CI Build Status](https://travis-ci.org/OpenSC/OpenSC.svg)](https://travis-ci.org/OpenSC/OpenSC/branches)
|
||||
[![Linux build](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml/badge.svg)](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml)
|
||||
[![OSX build](https://github.com/OpenSC/OpenSC/actions/workflows/macos.yml/badge.svg)](https://github.com/OpenSC/OpenSC/actions/workflows/macos.yml)
|
||||
[![AppVeyor CI Build Status](https://ci.appveyor.com/api/projects/status/github/OpenSC/OpenSC?branch=master&svg=true)](https://ci.appveyor.com/project/LudovicRousseau/OpenSC/branch/master)
|
||||
[![Coverity Scan Status](https://scan.coverity.com/projects/4026/badge.svg)](https://scan.coverity.com/projects/4026)
|
||||
[![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/OpenSC/OpenSC.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/OpenSC/OpenSC/context:cpp)
|
||||
|
@ -15,11 +16,11 @@ Build and test status of specific cards:
|
|||
|
||||
| Cards | Status |
|
||||
|---------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|
|
||||
| CAC | [![CAC](https://gitlab.com/redhat-crypto/OpenSC/badges/cac/pipeline.svg)](https://gitlab.com/redhat-crypto/OpenSC/pipelines) |
|
||||
| [virt_CACard](https://github.com/PL4typus/virt_cacard) | [![virt_CACard](https://travis-ci.org/OpenSC/OpenSC.svg)](https://travis-ci.org/OpenSC/OpenSC/branches) |
|
||||
| CAC | [![CAC](https://gitlab.com/redhat-crypto/OpenSC/badges/cac/pipeline.svg)](https://gitlab.com/redhat-crypto/OpenSC/pipelines) |
|
||||
| [virt_CACard](https://github.com/Jakuje/virt_cacard) | [![virt_CACard](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml/badge.svg)](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml) |
|
||||
| [Coolkey](https://github.com/dogtagpki/coolkey/tree/master/applet) | [![Coolkey](https://gitlab.com/redhat-crypto/OpenSC/badges/coolkey/pipeline.svg)](https://gitlab.com/redhat-crypto/OpenSC/pipelines) |
|
||||
| [PivApplet](https://github.com/arekinath/PivApplet) | [![PIV](https://travis-ci.org/OpenSC/OpenSC.svg)](https://travis-ci.org/OpenSC/OpenSC/branches) |
|
||||
| [OpenPGP Applet](https://github.com/Yubico/ykneo-openpgp/) | [![OpenPGP](https://travis-ci.org/OpenSC/OpenSC.svg)](https://travis-ci.org/OpenSC/OpenSC/branches) |
|
||||
| [GidsApplet](https://github.com/vletoux/GidsApplet/) | [![GIDS](https://travis-ci.org/OpenSC/OpenSC.svg)](https://travis-ci.org/OpenSC/OpenSC/branches) |
|
||||
| [IsoApplet](https://github.com/philipWendland/IsoApplet/) | [![IsoApplet](https://travis-ci.org/OpenSC/OpenSC.svg)](https://travis-ci.org/OpenSC/OpenSC/branches) |
|
||||
| [OsEID (MyEID)](https://sourceforge.net/projects/oseid/) | [![OsEID (MyEID)](https://travis-ci.org/OpenSC/OpenSC.svg)](https://travis-ci.org/OpenSC/OpenSC/branches) |
|
||||
| [PivApplet](https://github.com/arekinath/PivApplet) | [![PIV](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml/badge.svg)](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml) |
|
||||
| [OpenPGP Applet](https://github.com/Yubico/ykneo-openpgp/) | [![OpenPGP](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml/badge.svg)](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml) |
|
||||
| [GidsApplet](https://github.com/vletoux/GidsApplet/) | [![GIDS](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml/badge.svg)](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml) |
|
||||
| [IsoApplet](https://github.com/philipWendland/IsoApplet/) | [![IsoApplet](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml/badge.svg)](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml) |
|
||||
| [OsEID (MyEID)](https://sourceforge.net/projects/oseid/) | [![OsEID (MyEID)](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml/badge.svg)](https://github.com/OpenSC/OpenSC/actions/workflows/linux.yml) |
|
||||
|
|
12
appveyor.yml
12
appveyor.yml
|
@ -1,4 +1,4 @@
|
|||
version: 0.21.0.{build}
|
||||
version: 0.22.0.{build}
|
||||
|
||||
platform:
|
||||
- x86
|
||||
|
@ -12,7 +12,7 @@ environment:
|
|||
GH_TOKEN:
|
||||
secure: aLu3tFc7lRJbotnmnHLx/QruIHc5rLaGm1RttoEdy4QILlPXzVkCZ6loYMz0sfrY
|
||||
PATH: C:\cygwin\bin;%PATH%
|
||||
OPENPACE_VER: 1.1.0
|
||||
OPENPACE_VER: 1.1.1
|
||||
ZLIB_VER_DOT: 1.2.11
|
||||
matrix:
|
||||
# not compatible with OpenSSL 1.1.1:
|
||||
|
@ -59,12 +59,12 @@ install:
|
|||
Rename-Item -path "c:\openpace-${env:OPENPACE_VER}" -newName "openpace"
|
||||
}
|
||||
}
|
||||
If (!(Test-Path cngsdk.msi )) {
|
||||
appveyor DownloadFile "http://download.microsoft.com/download/2/C/9/2C93059C-0532-42DF-8C24-9AEAFF00768E/cngsdk.msi"
|
||||
If (!(Test-Path cpdksetup.exe )) {
|
||||
appveyor DownloadFile "https://download.microsoft.com/download/1/7/6/176909B0-50F2-4DF3-B29B-830A17EA7E38/CPDK_RELEASE_UPDATE/cpdksetup.exe"
|
||||
}
|
||||
- echo "Using %APPVEYOR_BUILD_WORKER_IMAGE% with %VCVARSALL%"
|
||||
- call "%VCVARSALL%" %Platform%
|
||||
- cngsdk.msi /quiet
|
||||
- cpdksetup.exe /quiet
|
||||
- uname -a
|
||||
- set
|
||||
|
||||
|
@ -126,4 +126,4 @@ cache:
|
|||
- C:\openpace -> appveyor.yml
|
||||
- C:\openpace-Win32 -> appveyor.yml
|
||||
- C:\openpace-Win64 -> appveyor.yml
|
||||
- cngsdk.msi -> appveyor.yml
|
||||
- cpdksetup.exe -> appveyor.yml
|
||||
|
|
22
configure.ac
22
configure.ac
|
@ -1,13 +1,13 @@
|
|||
dnl -*- mode: m4; -*-
|
||||
|
||||
AC_PREREQ(2.60)
|
||||
AC_PREREQ(2.68)
|
||||
|
||||
define([PRODUCT_NAME], [OpenSC])
|
||||
define([PRODUCT_TARNAME], [opensc])
|
||||
define([PRODUCT_BUGREPORT], [https://github.com/OpenSC/OpenSC/issues])
|
||||
define([PRODUCT_URL], [https://github.com/OpenSC/OpenSC])
|
||||
define([PACKAGE_VERSION_MAJOR], [0])
|
||||
define([PACKAGE_VERSION_MINOR], [21])
|
||||
define([PACKAGE_VERSION_MINOR], [22])
|
||||
define([PACKAGE_VERSION_FIX], [0])
|
||||
define([PACKAGE_SUFFIX], [])
|
||||
|
||||
|
@ -45,8 +45,8 @@ OPENSC_VS_FF_PRODUCT_URL="VS_FF_PRODUCT_URL"
|
|||
# (Code changed: REVISION++)
|
||||
# (Oldest interface changed/removed: OLDEST++)
|
||||
# (Interfaces added: CURRENT++, REVISION=0)
|
||||
OPENSC_LT_CURRENT="7"
|
||||
OPENSC_LT_OLDEST="7"
|
||||
OPENSC_LT_CURRENT="8"
|
||||
OPENSC_LT_OLDEST="8"
|
||||
OPENSC_LT_REVISION="0"
|
||||
OPENSC_LT_AGE="0"
|
||||
OPENSC_LT_AGE="$((${OPENSC_LT_CURRENT}-${OPENSC_LT_OLDEST}))"
|
||||
|
@ -133,7 +133,7 @@ esac
|
|||
|
||||
AX_CODE_COVERAGE()
|
||||
|
||||
AX_CHECK_COMPILE_FLAG([-Wunknown-warning-option], [have_unknown_warning_option="yes"], [have_unknown_warning_option="no"], [-Werror])
|
||||
AX_CHECK_COMPILE_FLAG([-Wunknown-warning-option], [have_unknown_warning_option="yes"], [have_unknown_warning_option="no"])
|
||||
AM_CONDITIONAL([HAVE_UNKNOWN_WARNING_OPTION], [test "${have_unknown_warning_option}" = "yes"])
|
||||
|
||||
AC_ARG_ENABLE(
|
||||
|
@ -188,7 +188,7 @@ AC_ARG_ENABLE(
|
|||
)
|
||||
|
||||
AC_ARG_ENABLE([openssl-secure-malloc],
|
||||
[AC_HELP_STRING([--openssl-secure-malloc=<SIZE_IN_BYTES>],
|
||||
[AS_HELP_STRING([--openssl-secure-malloc=<SIZE_IN_BYTES>],
|
||||
[Enable OpenSSL secure memory by specifying its size in bytes, must be a power of 2 @<:@disabled@:>@])],
|
||||
[], [enable_openssl_secure_malloc=no])
|
||||
AS_IF([test $enable_openssl_secure_malloc != no],
|
||||
|
@ -394,7 +394,6 @@ dnl C Compiler features
|
|||
AC_C_INLINE
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
AC_HEADER_SYS_WAIT
|
||||
AC_HEADER_ASSERT
|
||||
AC_CHECK_HEADERS([ \
|
||||
|
@ -408,7 +407,6 @@ dnl Checks for typedefs, structures, and compiler characteristics.
|
|||
AC_C_CONST
|
||||
AC_TYPE_UID_T
|
||||
AC_TYPE_SIZE_T
|
||||
AC_HEADER_TIME
|
||||
|
||||
dnl Checks for library functions.
|
||||
AC_FUNC_ERROR_AT_LINE
|
||||
|
@ -729,7 +727,7 @@ LIBS="$saved_LIBS"
|
|||
|
||||
|
||||
AC_ARG_ENABLE(cvcdir,
|
||||
AC_HELP_STRING([--enable-cvcdir=DIR],
|
||||
AS_HELP_STRING([--enable-cvcdir=DIR],
|
||||
[directory containing CV certificates (default is determined by libeac)]),
|
||||
[cvcdir="${enableval}"],
|
||||
[cvcdir=false])
|
||||
|
@ -751,7 +749,7 @@ AC_SUBST(CVCDIR)
|
|||
AC_DEFINE_UNQUOTED([CVCDIR], ["${CVCDIR}"], [CVC directory])
|
||||
|
||||
AC_ARG_ENABLE(x509dir,
|
||||
AC_HELP_STRING([--enable-x509dir=DIR],
|
||||
AS_HELP_STRING([--enable-x509dir=DIR],
|
||||
[directory containing X.509 certificates (default is determined by libeac)]),
|
||||
[x509dir="${enableval}"],
|
||||
[x509dir=false])
|
||||
|
@ -953,6 +951,7 @@ AC_PATH_PROG(GENGETOPT, gengetopt, not found)
|
|||
AC_ARG_VAR([CLANGTIDY],
|
||||
[absolute path to clang-tidy used for static code analysis])
|
||||
AC_PATH_PROG(CLANGTIDY, clang-tidy, not found)
|
||||
TIDY_CHECKS="-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling"
|
||||
|
||||
AX_FUNC_GETOPT_LONG
|
||||
#AH_BOTTOM([#include "common/compat_getopt.h"])
|
||||
|
@ -1060,6 +1059,7 @@ AC_SUBST([PROFILE_DIR])
|
|||
AC_SUBST([PROFILE_DIR_DEFAULT])
|
||||
AC_SUBST([OPTIONAL_NOTIFY_CFLAGS])
|
||||
AC_SUBST([OPTIONAL_NOTIFY_LIBS])
|
||||
AC_SUBST([TIDY_CHECKS])
|
||||
|
||||
AM_CONDITIONAL([ENABLE_MAN], [test "${enable_man}" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_THREAD_LOCKING], [test "${enable_thread_locking}" = "yes"])
|
||||
|
@ -1089,7 +1089,7 @@ if test "${enable_pedantic}" = "yes"; then
|
|||
CFLAGS="-pedantic ${CFLAGS}"
|
||||
fi
|
||||
if test "${enable_strict}" = "yes"; then
|
||||
CFLAGS="-Wall -Wextra -Wno-unused-parameter -Werror ${CFLAGS}"
|
||||
CFLAGS="-Wall -Wextra -Wno-unused-parameter -Werror -Wstrict-aliasing=2 ${CFLAGS}"
|
||||
fi
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
|
|
|
@ -10,7 +10,7 @@ man5_MANS = pkcs15-profile.5 opensc.conf.5
|
|||
endif
|
||||
|
||||
opensc.conf.5.xml opensc.conf.5: $(srcdir)/opensc.conf.5.xml.in
|
||||
sed \
|
||||
@sed \
|
||||
-e 's|@sysconfdir[@]|$(sysconfdir)|g' \
|
||||
-e 's|@docdir[@]|$(docdir)|g' \
|
||||
-e 's|@libdir[@]|$(libdir)|g' \
|
||||
|
@ -19,14 +19,14 @@ opensc.conf.5.xml opensc.conf.5: $(srcdir)/opensc.conf.5.xml.in
|
|||
-e 's|@PROFILE_DIR_DEFAULT[@]|$(PROFILE_DIR_DEFAULT)|g' \
|
||||
-e 's|@DEFAULT_SM_MODULE[@]|$(DEFAULT_SM_MODULE)|g' \
|
||||
< $< > opensc.conf.5.xml
|
||||
$(XSLTPROC) --nonet --path "$(srcdir)/..:$(xslstylesheetsdir)/manpages" --xinclude -o $@ man.xsl opensc.conf.5.xml
|
||||
$(AM_V_GEN)$(XSLTPROC) --nonet --path "$(srcdir)/..:$(xslstylesheetsdir)/manpages" --xinclude -o $@ man.xsl opensc.conf.5.xml 2>/dev/null
|
||||
|
||||
files.html: $(srcdir)/files.xml $(wildcard $(srcdir)/*.5.xml) opensc.conf.5.xml
|
||||
$(XSLTPROC) --nonet --path "$(builddir):$(srcdir)/..:$(xslstylesheetsdir)/html" --xinclude -o $@ html.xsl $<
|
||||
$(AM_V_GEN)$(XSLTPROC) --nonet --path "$(builddir):$(srcdir)/..:$(xslstylesheetsdir)/html" --xinclude -o $@ html.xsl $< 2>/dev/null
|
||||
|
||||
%.5: $(srcdir)/%.5.xml
|
||||
sed -e 's|@pkgdatadir[@]|$(pkgdatadir)|g' < $< \
|
||||
| $(XSLTPROC) --nonet --path "$(srcdir)/..:$(xslstylesheetsdir)/manpages" --xinclude -o $@ man.xsl $<
|
||||
$(AM_V_GEN)sed -e 's|@pkgdatadir[@]|$(pkgdatadir)|g' < $< \
|
||||
| $(XSLTPROC) --nonet --path "$(srcdir)/..:$(xslstylesheetsdir)/manpages" --xinclude -o $@ man.xsl $< 2>/dev/null
|
||||
|
||||
clean-local:
|
||||
-rm -rf $(html_DATA) $(man5_MANS) opensc.conf.5.xml
|
||||
|
|
|
@ -43,7 +43,7 @@ span.errortext {
|
|||
font-style: italic;
|
||||
}
|
||||
|
||||
--></style></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="book"><div class="titlepage"><div><div><h1 class="title"><a name="idm1"></a>OpenSC Manual Pages: Section 5</h1></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="refentrytitle"><a href="#opensc.conf">opensc.conf</a></span><span class="refpurpose"> — configuration file for OpenSC</span></dt><dt><span class="refentrytitle"><a href="#pkcs15-profile">pkcs15-profile</a></span><span class="refpurpose"> — format of profile for <span class="command"><strong>pkcs15-init</strong></span></span></dt></dl></div><div class="refentry"><a name="opensc.conf"></a><div class="titlepage"></div><div class="refnamediv"><h2>Name</h2><p>opensc.conf — configuration file for OpenSC</p></div><div class="refsect1"><a name="idm13"></a><h2>Description</h2><p>
|
||||
--></style></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="book"><div class="titlepage"><div><div><h1 class="title"><a name="id-1"></a>OpenSC Manual Pages: Section 5</h1></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="refentrytitle"><a href="#opensc.conf">opensc.conf</a></span><span class="refpurpose"> — configuration file for OpenSC</span></dt><dt><span class="refentrytitle"><a href="#pkcs15-profile">pkcs15-profile</a></span><span class="refpurpose"> — format of profile for <span class="command"><strong>pkcs15-init</strong></span></span></dt></dl></div><div class="refentry"><a name="opensc.conf"></a><div class="titlepage"></div><div class="refnamediv"><h2>Name</h2><p>opensc.conf — configuration file for OpenSC</p></div><div class="refsect1"><a name="id-1.2.3"></a><h2>Description</h2><p>
|
||||
OpenSC obtains configuration data from the following sources in the following order
|
||||
</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p>
|
||||
command-line options
|
||||
|
@ -122,7 +122,7 @@ app <em class="replaceable"><code>application</code></em> {
|
|||
<code class="literal">westcos-tool</code>:
|
||||
Configuration block for OpenSC tools
|
||||
</p></li></ul></div><p>
|
||||
</p></div><div class="refsect1"><a name="idm103"></a><h2>Configuration Options</h2><div class="variablelist"><dl class="variablelist"><dt><a name="debug"></a><span class="term">
|
||||
</p></div><div class="refsect1"><a name="id-1.2.4"></a><h2>Configuration Options</h2><div class="variablelist"><dl class="variablelist"><dt><a name="debug"></a><span class="term">
|
||||
<code class="option">debug = <em class="replaceable"><code>num</code></em>;</code>
|
||||
</span></dt><dd><p>
|
||||
Amount of debug info to print (Default:
|
||||
|
@ -153,6 +153,12 @@ app <em class="replaceable"><code>application</code></em> {
|
|||
<code class="filename">Software\OpenSC
|
||||
Project\OpenSC\ProfileDir</code> is
|
||||
checked.
|
||||
</p></dd><dt><span class="term">
|
||||
<code class="option">disable_colors = <em class="replaceable"><code>bool</code></em>;</code>
|
||||
</span></dt><dd><p>
|
||||
Disable colors of log messages (Default:
|
||||
<code class="literal">false</code> if attached to a console,
|
||||
<code class="literal">true</code> otherwise).
|
||||
</p></dd><dt><span class="term">
|
||||
<code class="option">disable_popups = <em class="replaceable"><code>bool</code></em>;</code>
|
||||
</span></dt><dd><p>
|
||||
|
@ -176,7 +182,7 @@ app <em class="replaceable"><code>application</code></em> {
|
|||
default) will load all statically linked drivers.
|
||||
</p><p>
|
||||
If an unknown (i.e. not internal or old) driver is
|
||||
supplied, a separate configuration configuration
|
||||
supplied, a separate configuration
|
||||
block has to be written for the driver. A special
|
||||
value <code class="literal">old</code> will load all
|
||||
statically linked drivers that may be removed in
|
||||
|
@ -227,6 +233,10 @@ app <em class="replaceable"><code>application</code></em> {
|
|||
<code class="literal">npa</code>: See <a class="xref" href="#npa" title="Configuration Options for German ID Card">the section called “Configuration Options for German ID Card”</a>
|
||||
</p></li><li class="listitem"><p>
|
||||
<code class="literal">dnie</code>: See <a class="xref" href="#dnie" title="Configuration Options for DNIe">the section called “Configuration Options for DNIe”</a>
|
||||
</p></li><li class="listitem"><p>
|
||||
<code class="literal">edo</code>: See <a class="xref" href="#edo" title="Configuration Options for Polish eID Card">the section called “Configuration Options for Polish eID Card”</a>
|
||||
</p></li><li class="listitem"><p>
|
||||
<code class="literal">myeid</code>: See <a class="xref" href="#myeid" title="Configuration Options for MyEID Card">the section called “Configuration Options for MyEID Card”</a>
|
||||
</p></li><li class="listitem"><p>
|
||||
Any other value: Configuration block for an externally loaded card driver
|
||||
</p></li></ul></div><p>
|
||||
|
@ -332,7 +342,7 @@ app <em class="replaceable"><code>application</code></em> {
|
|||
Parameters for the OpenSC PKCS11 module.
|
||||
</p><p>
|
||||
For details see <a class="xref" href="#pkcs11" title="Configuration of PKCS#11">the section called “Configuration of PKCS#11”</a>.
|
||||
</p></dd></dl></div><div class="refsect2"><a name="reader_driver"></a><h3>Configuration of Smart Card Reader Driver</h3><div class="refsect3"><a name="idm330"></a><h4>Configuration Options for all Reader Drivers</h4><div class="variablelist"><dl class="variablelist"><dt><span class="term">
|
||||
</p></dd></dl></div><div class="refsect2"><a name="reader_driver"></a><h3>Configuration of Smart Card Reader Driver</h3><div class="refsect3"><a name="id-1.2.4.3.2"></a><h4>Configuration Options for all Reader Drivers</h4><div class="variablelist"><dl class="variablelist"><dt><span class="term">
|
||||
<code class="option">max_send_size = <em class="replaceable"><code>num</code></em>;</code>
|
||||
<code class="option">max_recv_size = <em class="replaceable"><code>num</code></em>;</code>
|
||||
</span></dt><dd><p>
|
||||
|
@ -429,7 +439,27 @@ app <em class="replaceable"><code>application</code></em> {
|
|||
<code class="option">readers = <em class="replaceable"><code>num</code></em>;</code>
|
||||
</span></dt><dd><p>
|
||||
Virtual readers to allocate (Default: <code class="literal">2</code>).
|
||||
</p></dd></dl></div></div></div><div class="refsect2"><a name="npa"></a><h3>Configuration Options for German ID Card</h3><div class="variablelist"><dl class="variablelist"><dt><span class="term">
|
||||
</p></dd></dl></div></div></div><div class="refsect2"><a name="myeid"></a><h3>Configuration Options for MyEID Card</h3><div class="variablelist"><dl class="variablelist"><dt><span class="term">
|
||||
<code class="option">disable_hw_pkcs1_padding = <em class="replaceable"><code>bool</code></em>;</code>
|
||||
</span></dt><dd><p>
|
||||
The MyEID card can internally
|
||||
encapsulate the data (hash code)
|
||||
into a DigestInfo ASN.1 structure
|
||||
according to the selected hash
|
||||
algorithm (currently only for SHA1).
|
||||
DigestInfo is padded to RSA key
|
||||
modulus length according to PKCS#1
|
||||
v1.5, block type 01h. Size of the
|
||||
DigestInfo must not exceed 40%
|
||||
of the RSA key modulus length. If
|
||||
this limit is unsatisfactory (for
|
||||
example someone needs RSA 1024
|
||||
with SHA512), the user can disable
|
||||
this feature. In this case, the
|
||||
card driver will do everything
|
||||
necessary before sending the data
|
||||
(hash code) to the card.
|
||||
</p></dd></dl></div></div><div class="refsect2"><a name="npa"></a><h3>Configuration Options for German ID Card</h3><div class="variablelist"><dl class="variablelist"><dt><span class="term">
|
||||
<code class="option">can = <em class="replaceable"><code>value</code></em>;</code>
|
||||
</span></dt><dd><p>
|
||||
German ID card requires the CAN to
|
||||
|
@ -478,6 +508,16 @@ app <em class="replaceable"><code>application</code></em> {
|
|||
<code class="literal">/usr/bin/pinentry</code>).
|
||||
Only used if compiled with
|
||||
<code class="option">--enable-dnie-ui</code>
|
||||
</p></dd></dl></div></div><div class="refsect2"><a name="edo"></a><h3>Configuration Options for Polish eID Card</h3><div class="variablelist"><dl class="variablelist"><dt><span class="term">
|
||||
<code class="option">can = <em class="replaceable"><code>value</code></em>;</code>
|
||||
</span></dt><dd><p>
|
||||
CAN (Card Access Number – 6 digit number
|
||||
printed on the right bottom corner of the
|
||||
front side of the document) is required
|
||||
to establish connection with the card.
|
||||
It might be overwritten by <code class="literal">EDO_CAN</code>
|
||||
environment variable. Currently, it is not
|
||||
possible to set it in any other way.
|
||||
</p></dd></dl></div></div><div class="refsect2"><a name="card_atr"></a><h3>Configuration based on ATR</h3><p>
|
||||
</p><div class="variablelist"><dl class="variablelist"><dt><span class="term">
|
||||
<code class="option">atrmask = <em class="replaceable"><code>hexstring</code></em>;</code>
|
||||
|
@ -554,10 +594,10 @@ app <em class="replaceable"><code>application</code></em> {
|
|||
<code class="literal">raw</code>
|
||||
</p></li></ul></div><p>
|
||||
</p></dd><dt><span class="term">
|
||||
<code class="option">md_read_only = <em class="replaceable"><code>bool</code></em>;</code>
|
||||
<code class="option">read_only = <em class="replaceable"><code>bool</code></em>;</code>
|
||||
</span></dt><dd><p>
|
||||
Mark card as read/only card in
|
||||
Minidriver/BaseCSP interface
|
||||
PKCS#11/Minidriver/BaseCSP interface
|
||||
(Default: <code class="literal">false</code>).
|
||||
</p></dd><dt><span class="term">
|
||||
<code class="option">md_supports_X509_enrollment = <em class="replaceable"><code>bool</code></em>;</code>
|
||||
|
@ -724,9 +764,11 @@ app <em class="replaceable"><code>application</code></em> {
|
|||
</span></dt><dd><p>
|
||||
Where to cache the card's files. The default values are:
|
||||
</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
|
||||
<code class="filename"><code class="envar">HOME</code>/.eid/cache/</code> (Unix)
|
||||
<code class="filename"><code class="envar">$XDG_CACHE_HOME</code>/opensc/</code> (If <code class="envar">$XDG_CACHE_HOME</code> is defined)
|
||||
</p></li><li class="listitem"><p>
|
||||
<code class="filename"><code class="envar">USERPROFILE</code>\.eid-cache\</code> (Windows)
|
||||
<code class="filename"><code class="envar">$HOME</code>/.cache/opensc/</code> (Unix)
|
||||
</p></li><li class="listitem"><p>
|
||||
<code class="filename"><code class="envar">$USERPROFILE</code>\.eid-cache\</code> (Windows)
|
||||
</p></li></ul></div><p>
|
||||
</p><p>
|
||||
If caching is done by a system process, the
|
||||
|
@ -753,6 +795,26 @@ app <em class="replaceable"><code>application</code></em> {
|
|||
<code class="literal">CKA_ALWAYS_AUTHENTICATE</code> may
|
||||
need to set this to get signatures to work with
|
||||
some cards (Default: <code class="literal">false</code>).
|
||||
</p><p>
|
||||
It is recommended to enable also PIN caching using
|
||||
<code class="literal">use_pin_caching</code> option for OpenSC
|
||||
to be able to provide PIN for the card when needed.
|
||||
</p></dd><dt><span class="term">
|
||||
<code class="option">private_certificate = <em class="replaceable"><code>value</code></em>;</code>
|
||||
</span></dt><dd><p>
|
||||
How to handle a PIN-protected certificate. Known
|
||||
parameters:
|
||||
</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
|
||||
<code class="literal">protect</code>: The certificate stays PIN-protected.
|
||||
</p></li><li class="listitem"><p>
|
||||
<code class="literal">declassify</code>: Allow
|
||||
reading the certificate without
|
||||
enforcing verification of the PIN.
|
||||
</p></li><li class="listitem"><p>
|
||||
<code class="literal">ignore</code>: Ignore PIN-protected certificates.
|
||||
</p></li></ul></div><p>
|
||||
(Default: <code class="literal">ignore</code> in Tokend,
|
||||
<code class="literal">protect</code> otherwise).
|
||||
</p></dd><dt><span class="term">
|
||||
<code class="option">enable_pkcs15_emulation = <em class="replaceable"><code>bool</code></em>;</code>
|
||||
</span></dt><dd><p>
|
||||
|
@ -775,7 +837,7 @@ app <em class="replaceable"><code>application</code></em> {
|
|||
<code class="option">builtin_emulators = <em class="replaceable"><code>emulators</code></em>;</code>
|
||||
</span></dt><dd><p>
|
||||
List of the builtin pkcs15 emulators to test
|
||||
(Default: <code class="literal">westcos, openpgp,
|
||||
(Default: <code class="literal">westcos, openpgp,
|
||||
starcert, tcos, esteid, itacns,
|
||||
PIV-II, cac, gemsafeGPK, gemsafeV1, actalis,
|
||||
atrust-acos, tccardos, entersafe, pteid,
|
||||
|
@ -854,13 +916,6 @@ app <em class="replaceable"><code>application</code></em> {
|
|||
Score for <span class="application">OpenSC.tokend</span>
|
||||
(Default: <code class="literal">300</code>). The tokend with
|
||||
the highest score shall be used.
|
||||
</p></dd><dt><span class="term">
|
||||
<code class="option">ignore_private_certificate = <em class="replaceable"><code>bool</code></em>;</code>
|
||||
</span></dt><dd><p>
|
||||
Tokend ignore to read PIN protected certificate
|
||||
that is set
|
||||
<code class="literal">SC_PKCS15_CO_FLAG_PRIVATE</code> flag
|
||||
(Default: <code class="literal">true</code>).
|
||||
</p></dd></dl></div></div><div class="refsect2"><a name="pkcs11"></a><h3>Configuration of PKCS#11</h3><div class="variablelist"><dl class="variablelist"><dt><span class="term">
|
||||
<code class="option">max_virtual_slots = <em class="replaceable"><code>num</code></em>;</code>
|
||||
</span></dt><dd><p>
|
||||
|
@ -1020,7 +1075,7 @@ app <em class="replaceable"><code>application</code></em> {
|
|||
For the module to simulate the opensc-onepin module
|
||||
behavior the following option
|
||||
<code class="option">create_slots_for_pins = "user";</code>
|
||||
</p></dd></dl></div></div></div><div class="refsect1"><a name="idm971"></a><h2>Environment</h2><div class="variablelist"><dl class="variablelist"><dt><span class="term">
|
||||
</p></dd></dl></div></div></div><div class="refsect1"><a name="id-1.2.5"></a><h2>Environment</h2><div class="variablelist"><dl class="variablelist"><dt><span class="term">
|
||||
<code class="envar">OPENSC_CONF</code>
|
||||
</span></dt><dd><p>
|
||||
Filename for a user defined configuration file
|
||||
|
@ -1063,7 +1118,7 @@ app <em class="replaceable"><code>application</code></em> {
|
|||
</span></dt><dd><p>
|
||||
PIV configuration during initialization with
|
||||
<span class="application">piv-tool</span>.
|
||||
</p></dd></dl></div></div><div class="refsect1"><a name="idm1012"></a><h2>Files</h2><div class="variablelist"><dl class="variablelist"><dt><span class="term">
|
||||
</p></dd></dl></div></div><div class="refsect1"><a name="id-1.2.6"></a><h2>Files</h2><div class="variablelist"><dl class="variablelist"><dt><span class="term">
|
||||
<code class="filename">/usr/etc/opensc.conf</code>
|
||||
</span></dt><dd><p>
|
||||
System-wide configuration file
|
||||
|
@ -1071,7 +1126,7 @@ app <em class="replaceable"><code>application</code></em> {
|
|||
<code class="filename">/usr/share/doc/opensc/opensc.conf</code>
|
||||
</span></dt><dd><p>
|
||||
Extended example configuration file
|
||||
</p></dd></dl></div></div></div><div class="refentry"><div class="refentry.separator"><hr></div><a name="pkcs15-profile"></a><div class="titlepage"></div><div class="refnamediv"><h2>Name</h2><p>pkcs15-profile — format of profile for <span class="command"><strong>pkcs15-init</strong></span></p></div><div class="refsect1"><a name="idm1036"></a><h2>Description</h2><p>
|
||||
</p></dd></dl></div></div></div><div class="refentry"><div class="refentry.separator"><hr></div><a name="pkcs15-profile"></a><div class="titlepage"></div><div class="refnamediv"><h2>Name</h2><p>pkcs15-profile — format of profile for <span class="command"><strong>pkcs15-init</strong></span></p></div><div class="refsect1"><a name="id-1.3.3"></a><h2>Description</h2><p>
|
||||
The <span class="command"><strong>pkcs15-init</strong></span> utility for PKCS #15 smart card
|
||||
personalization is controlled via profiles. When starting, it will read two
|
||||
such profiles at the moment, a generic application profile, and a card
|
||||
|
@ -1087,10 +1142,10 @@ app <em class="replaceable"><code>application</code></em> {
|
|||
The card specific profile contains additional information required during
|
||||
card initialization, such as location of PIN files, key references etc.
|
||||
Profiles currently reside in <code class="filename">@pkgdatadir@</code>
|
||||
</p></div><div class="refsect1"><a name="idm1044"></a><h2>Syntax</h2><p>
|
||||
</p></div><div class="refsect1"><a name="id-1.3.4"></a><h2>Syntax</h2><p>
|
||||
This section should contain information about the profile syntax. Will add
|
||||
this soonishly.
|
||||
</p></div><div class="refsect1"><a name="idm1047"></a><h2>See also</h2><p>
|
||||
</p></div><div class="refsect1"><a name="id-1.3.5"></a><h2>See also</h2><p>
|
||||
<span class="citerefentry"><span class="refentrytitle">pkcs15-init</span>(1)</span>,
|
||||
<span class="citerefentry"><span class="refentrytitle">pkcs15-crypt</span>(1)</span>
|
||||
</p></div></div></div></body></html>
|
||||
|
|
|
@ -296,6 +296,9 @@ app <replaceable>application</replaceable> {
|
|||
<listitem><para>
|
||||
<literal>edo</literal>: See <xref linkend="edo"/>
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
<literal>myeid</literal>: See <xref linkend="myeid"/>
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
Any other value: Configuration block for an externally loaded card driver
|
||||
</para></listitem>
|
||||
|
@ -639,6 +642,37 @@ app <replaceable>application</replaceable> {
|
|||
|
||||
</refsect2>
|
||||
|
||||
<refsect2 id="myeid">
|
||||
<title>Configuration Options for MyEID Card</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>disable_hw_pkcs1_padding = <replaceable>bool</replaceable>;</option>
|
||||
</term>
|
||||
<listitem><para>
|
||||
The MyEID card can internally
|
||||
encapsulate the data (hash code)
|
||||
into a DigestInfo ASN.1 structure
|
||||
according to the selected hash
|
||||
algorithm (currently only for SHA1).
|
||||
DigestInfo is padded to RSA key
|
||||
modulus length according to PKCS#1
|
||||
v1.5, block type 01h. Size of the
|
||||
DigestInfo must not exceed 40%
|
||||
of the RSA key modulus length. If
|
||||
this limit is unsatisfactory (for
|
||||
example someone needs RSA 1024
|
||||
with SHA512), the user can disable
|
||||
this feature. In this case, the
|
||||
card driver will do everything
|
||||
necessary before sending the data
|
||||
(hash code) to the card.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</refsect2>
|
||||
|
||||
<refsect2 id="npa">
|
||||
<title>Configuration Options for German ID Card</title>
|
||||
<variablelist>
|
||||
|
@ -1116,12 +1150,17 @@ app <replaceable>application</replaceable> {
|
|||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<filename><envar>HOME</envar>/.eid/cache/</filename> (Unix)
|
||||
<filename><envar>$XDG_CACHE_HOME</envar>/opensc/</filename> (If <envar>$XDG_CACHE_HOME</envar> is defined)
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<filename><envar>USERPROFILE</envar>\.eid-cache\</filename> (Windows)
|
||||
<filename><envar>$HOME</envar>/.cache/opensc/</filename> (Unix)
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<filename><envar>$USERPROFILE</envar>\.eid-cache\</filename> (Windows)
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
|
|
@ -14,15 +14,14 @@ endif
|
|||
completion_DATA = $(patsubst $(srcdir)/%.1.xml, %, $(wildcard $(srcdir)/*.1.xml))
|
||||
|
||||
tools.html: $(srcdir)/tools.xml $(wildcard $(srcdir)/*.1.xml)
|
||||
$(XSLTPROC) --nonet --path "$(srcdir)/..:$(xslstylesheetsdir)/html" --xinclude -o $@ html.xsl $<
|
||||
$(AM_V_GEN)$(XSLTPROC) --nonet --path "$(srcdir)/..:$(xslstylesheetsdir)/html" --xinclude -o $@ html.xsl $< 2>/dev/null
|
||||
|
||||
%.1: $(srcdir)/%.1.xml
|
||||
sed -e 's|@pkgdatadir[@]|$(pkgdatadir)|g' < $< \
|
||||
| $(XSLTPROC) --nonet --path "$(srcdir)/..:$(xslstylesheetsdir)/manpages" --xinclude -o $@ man.xsl $<
|
||||
$(AM_V_GEN)sed -e 's|@pkgdatadir[@]|$(pkgdatadir)|g' < $< \
|
||||
| $(XSLTPROC) --nonet --path "$(srcdir)/..:$(xslstylesheetsdir)/manpages" --xinclude -o $@ man.xsl $< 2>/dev/null
|
||||
|
||||
%: $(srcdir)/%.1.xml
|
||||
@echo $< $@
|
||||
@cat $(srcdir)/completion-template \
|
||||
$(AM_V_GEN)cat $(srcdir)/completion-template \
|
||||
| sed "s,ALLOPTS,\
|
||||
$(shell sed -n 's,.*<option>\([^<]*\)</option>.*,\1,pg' $< \
|
||||
| sort -u | grep -- '^\-' | tr '\n' ' ')," \
|
||||
|
|
|
@ -53,15 +53,18 @@
|
|||
<option>--admin</option> <replaceable>argument</replaceable>,
|
||||
<option>-A</option> <replaceable>argument</replaceable>
|
||||
</term>
|
||||
<listitem><para>Authenticate to the card using a 2DES or 3DES key.
|
||||
<listitem><para>Authenticate to the card using a 2DES, 3DES or AES key.
|
||||
The <replaceable>argument</replaceable> of the form
|
||||
<synopsis> {<literal>A</literal>|<literal>M</literal>}<literal>:</literal><replaceable>ref</replaceable><literal>:</literal><replaceable>alg</replaceable></synopsis>
|
||||
is required, were <literal>A</literal> uses "EXTERNAL AUTHENTICATION"
|
||||
and <literal>M</literal> uses "MUTUAL AUTHENTICATION".
|
||||
<replaceable>ref</replaceable> is normally <literal>9B</literal>,
|
||||
and <replaceable>alg</replaceable> is <literal>03</literal> for 3DES.
|
||||
The key is provided by the card vendor, and the environment variable
|
||||
<varname>PIV_EXT_AUTH_KEY</varname> must point to a text file containing
|
||||
and <replaceable>alg</replaceable> is <literal>03</literal> for 3DES,
|
||||
<literal>01</literal> for 2DES, <literal>08</literal> for AES-128,
|
||||
<literal>0A</literal> for AES-192 or <literal>0C</literal> for AES-256.
|
||||
The key is provided by the card vendor. The environment variable
|
||||
<varname>PIV_EXT_AUTH_KEY</varname> must point to either a binary file
|
||||
matching the length of the key or a text file containing
|
||||
the key in the format:
|
||||
<code>XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX</code>
|
||||
</para></listitem>
|
||||
|
|
|
@ -146,7 +146,9 @@
|
|||
<term>
|
||||
<option>--key-type</option> <replaceable>specification</replaceable>
|
||||
</term>
|
||||
<listitem><para>Specify the type and length of the key to create, for example rsa:1024 or EC:prime256v1.</para></listitem>
|
||||
<listitem><para>Specify the type and length (bytes if symmetric) of the key to create,
|
||||
for example RSA:1024, EC:prime256v1, GOSTR3410-2012-256:B,
|
||||
DES:8, DES3:24, AES:16 or GENERIC:64.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -219,6 +221,13 @@
|
|||
<listitem><para>List slots with tokens.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--list-interfaces</option>
|
||||
</term>
|
||||
<listitem><para>List interfaces of PKCS #11 3.0 library.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--login</option>,
|
||||
|
@ -417,6 +426,22 @@
|
|||
<listitem><para>Specify the index of the object to use.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--use-locking</option>
|
||||
</term>
|
||||
<listitem><para>Tell pkcs11 module it should use OS thread locking.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--test-threads</option> <replaceable>options</replaceable>
|
||||
</term>
|
||||
<listitem><para>Test a pkcs11 module's thread implication. (See source code).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<option>--token-label</option> <replaceable>label</replaceable>
|
||||
|
|
|
@ -136,11 +136,12 @@
|
|||
<command>pkcs15-init --generate-key " keyspec " --auth-id " nn</command>
|
||||
</para>
|
||||
<para>
|
||||
where <replaceable>keyspec</replaceable> describes the algorithm and length of the
|
||||
key to be created, such as <literal>rsa/512</literal>. This will create a 512 bit
|
||||
RSA key. Currently, only RSA key generation is supported. Note that cards
|
||||
usually support just a few different key lengths. Almost all cards will support
|
||||
512 and 1024 bit keys, some will support 768 or 2048 as well.
|
||||
where <replaceable>keyspec</replaceable> describes the algorithm and the parameters
|
||||
of the key to be created. For example, <literal>rsa:2048</literal> generates a RSA key
|
||||
with 2048-bit modulus. If you are generating an EC key, the curve designation must
|
||||
be specified, for example <literal>ec:prime256v1</literal>. For symmetric key,
|
||||
the length of key is specified in bytes, for example <literal>AES:32</literal>
|
||||
or <literal>DES3:24</literal>.
|
||||
</para>
|
||||
<para>
|
||||
<replaceable>nn</replaceable> is the ID of a user PIN installed previously,
|
||||
|
@ -242,7 +243,7 @@
|
|||
you would use
|
||||
</para>
|
||||
<para>
|
||||
<command>pkcs15-init --store-secret-key /dev/urandom --secret-key-algorithm aes/256 --auth-id 01</command>
|
||||
<command>pkcs15-init --store-secret-key /dev/urandom --secret-key-algorithm aes:256 --auth-id 01</command>
|
||||
</para>
|
||||
<para>
|
||||
By default a random ID is generated for the secret key. You may specify an ID
|
||||
|
@ -332,9 +333,9 @@
|
|||
<listitem>
|
||||
<para>
|
||||
Tells the card to generate new key and store it on the card.
|
||||
<replaceable>keyspec</replaceable> consists of an algorithm name
|
||||
(currently, the only supported name is <option>RSA</option>),
|
||||
optionally followed by a slash and the length of the key in bits.
|
||||
<replaceable>keyspec</replaceable> consists of an algorithm name,
|
||||
optionally followed by a colon ":", slash "/" or hyphen "-" and
|
||||
the parameters of the key to be created.
|
||||
It is a good idea to specify the key ID along with this command,
|
||||
using the <option>id</option> option, otherwise an intrinsic ID
|
||||
will be calculated from the key material. Look the description of
|
||||
|
@ -417,7 +418,7 @@
|
|||
<listitem>
|
||||
<para>
|
||||
<replaceable>keyspec</replaceable> describes the algorithm and length of the
|
||||
key to be created or downloaded, such as <literal>aes/256</literal>.
|
||||
key to be created or downloaded, such as <literal>aes:256</literal>.
|
||||
This will create a 256 bit AES key.
|
||||
</para>
|
||||
</listitem>
|
||||
|
|
1032
doc/tools/tools.html
1032
doc/tools/tools.html
File diff suppressed because it is too large
Load Diff
|
@ -17,7 +17,7 @@ force:
|
|||
opensc.conf.example: opensc.conf.example.in force
|
||||
|
||||
.in:
|
||||
@sed \
|
||||
$(AM_V_GEN)sed \
|
||||
-e 's|@pkgdatadir[@]|$(pkgdatadir)|g' \
|
||||
-e 's|@DEBUG_FILE[@]|$(DEBUG_FILE)|g' \
|
||||
-e 's|@DEFAULT_PCSC_PROVIDER[@]|$(DEFAULT_PCSC_PROVIDER)|g' \
|
||||
|
|
|
@ -43,4 +43,4 @@ TIDY_FILES = \
|
|||
libpkcs11.c libscdl.c
|
||||
|
||||
check-local:
|
||||
if [ -x "$(CLANGTIDY)" ]; then clang-tidy -config='' -header-filter=.* $(TIDY_FILES) -- $(TIDY_FLAGS); fi
|
||||
if [ -x "$(CLANGTIDY)" ]; then clang-tidy -config='' --checks='$(TIDY_CHECKS)' -header-filter=.* $(addprefix $(srcdir)/,$(TIDY_FILES)) -- $(TIDY_FLAGS); fi
|
||||
|
|
|
@ -49,6 +49,7 @@ C_LoadModule(const char *mspec, CK_FUNCTION_LIST_PTR_PTR funcs)
|
|||
{
|
||||
sc_pkcs11_module_t *mod;
|
||||
CK_RV rv, (*c_get_function_list)(CK_FUNCTION_LIST_PTR_PTR);
|
||||
CK_RV (*c_get_interface)(CK_UTF8CHAR_PTR, CK_VERSION_PTR, CK_INTERFACE_PTR_PTR, CK_FLAGS);
|
||||
mod = calloc(1, sizeof(*mod));
|
||||
if (mod == NULL) {
|
||||
return NULL;
|
||||
|
@ -65,6 +66,24 @@ C_LoadModule(const char *mspec, CK_FUNCTION_LIST_PTR_PTR funcs)
|
|||
goto failed;
|
||||
}
|
||||
|
||||
c_get_interface = (CK_RV (*)(CK_UTF8CHAR_PTR, CK_VERSION_PTR, CK_INTERFACE_PTR_PTR, CK_FLAGS))
|
||||
sc_dlsym(mod->handle, "C_GetInterface");
|
||||
if (c_get_interface) {
|
||||
CK_INTERFACE *interface = NULL;
|
||||
|
||||
/* Get default PKCS #11 interface */
|
||||
rv = c_get_interface((CK_UTF8CHAR_PTR) "PKCS 11", NULL, &interface, 0);
|
||||
if (rv == CKR_OK) {
|
||||
/* this is actually 3.0 function list, but it starts
|
||||
* with the same fields. Only for new functions, it
|
||||
* needs to be casted to new structure */
|
||||
*funcs = interface->pFunctionList;
|
||||
return (void *) mod;
|
||||
} else {
|
||||
fprintf(stderr, "C_GetInterface failed %lx, retry 2.x way", rv);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the list of function pointers */
|
||||
c_get_function_list = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR))
|
||||
sc_dlsym(mod->handle, "C_GetFunctionList");
|
||||
|
|
|
@ -28,7 +28,9 @@
|
|||
#if !defined(_WIN32)
|
||||
#include <arpa/inet.h> /* for htons() */
|
||||
#include <unistd.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h> /* for gettimeofday() */
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
/build/
|
|
@ -0,0 +1,12 @@
|
|||
cmake_minimum_required(VERSION 3.18)
|
||||
|
||||
project(gcns VERSION 1.0 DESCRIPTION "Italian healthcare smart card parsing utility")
|
||||
|
||||
add_library(gcns SHARED gcns.c gcns.cpp)
|
||||
target_include_directories(gcns PUBLIC ../.. .. .)
|
||||
install(TARGETS gcns LIBRARY)
|
||||
install(FILES gcns.h gcns.hpp DESTINATION include)
|
||||
|
||||
add_executable(main main.c ../tools/util.c)
|
||||
target_link_libraries(main gcns opensc bsd)
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
# Maintainer: Giovan Battista Rolandi <giomba@linux.it>
|
||||
|
||||
pkgname=gcns
|
||||
pkgver=1.0
|
||||
pkgrel=1
|
||||
pkgdesc='Tools for Italian healthcare smart card'
|
||||
arch=('x86_64')
|
||||
url='https://git.golem.linux.it/giomba/opensc'
|
||||
license=('LGPL')
|
||||
depends=('opensc')
|
||||
source=('git+https://git.golem.linux.it/giomba/opensc#branch=golem/tessera-sanitaria')
|
||||
sha256sums=('SKIP')
|
||||
|
||||
build() {
|
||||
cd opensc
|
||||
|
||||
./bootstrap
|
||||
./configure
|
||||
make -j$(nproc)
|
||||
cd src/gcns
|
||||
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake ..
|
||||
make -j$(nproc)
|
||||
|
||||
}
|
||||
|
||||
package() {
|
||||
cd opensc/src/gcns/build
|
||||
make DESTDIR=$pkgdir install
|
||||
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* gcns.c: A reader of Italian healtcare smartcards with libopensc
|
||||
*
|
||||
* Copyright (C) 2022 Giovan Battista Rolandi <giomba@linux.it>
|
||||
* based on previous work by
|
||||
* Copyright (C) 2001 Juha Yrjölä <juha.yrjola@iki.fi>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "gcns.h"
|
||||
|
||||
#include "libopensc/asn1.h"
|
||||
#include "tools/util.h"
|
||||
|
||||
static int opt_wait = 0;
|
||||
static const char *opt_reader = NULL;
|
||||
static sc_context_t *ctx = NULL;
|
||||
static sc_card_t *card = NULL;
|
||||
sc_context_param_t ctx_param;
|
||||
|
||||
int gcns_init() {
|
||||
int r, err = 0;
|
||||
int lcycle = SC_CARDCTRL_LIFECYCLE_ADMIN;
|
||||
|
||||
memset(&ctx_param, 0, sizeof(ctx_param));
|
||||
ctx_param.ver = 0;
|
||||
|
||||
r = sc_context_create(&ctx, &ctx_param);
|
||||
if (r) {
|
||||
fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r));
|
||||
return GCNS_INIT;
|
||||
}
|
||||
|
||||
ctx->flags |= SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER;
|
||||
|
||||
err = util_connect_card_ex(ctx, &card, opt_reader, opt_wait, 0, 0);
|
||||
if (err) {
|
||||
return GCNS_INIT;
|
||||
}
|
||||
|
||||
r = sc_lock(card);
|
||||
if (r == SC_SUCCESS)
|
||||
r = sc_card_ctl(card, SC_CARDCTL_LIFECYCLE_SET, &lcycle);
|
||||
sc_unlock(card);
|
||||
if (r && r != SC_ERROR_NOT_SUPPORTED) {
|
||||
fprintf(stderr, "unable to change lifecycle: %s\n", sc_strerror(r));
|
||||
return GCNS_INIT;
|
||||
}
|
||||
|
||||
return GCNS_SUCCESS;
|
||||
}
|
||||
|
||||
int gcns_close() {
|
||||
if (card) {
|
||||
sc_disconnect_card(card);
|
||||
}
|
||||
if (ctx) sc_release_context(ctx);
|
||||
return GCNS_SUCCESS;
|
||||
}
|
||||
|
||||
int gcns_read_personal_data(u8 *buffer, size_t len) {
|
||||
sc_path_t path;
|
||||
int r;
|
||||
|
||||
sc_format_path("3F0011001102", &path);
|
||||
r = sc_select_file(card, &path, NULL);
|
||||
if (r) {
|
||||
fprintf(stderr, "no select file: 3F0011001102\n");
|
||||
return GCNS_READ_PERSONAL_DATA;
|
||||
}
|
||||
r = sc_read_binary(card, 0, buffer, 0x180, 0);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "no read binary: %d\n", r);
|
||||
return GCNS_READ_PERSONAL_DATA;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
#include "gcns.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
using namespace gcns;
|
||||
|
||||
PersonalData::PersonalData(const uint8_t* buffer, size_t len) {
|
||||
std::vector<std::string> field;
|
||||
|
||||
// TODO check length at the beginning?
|
||||
for (int i = 12; i < len;) {
|
||||
if (buffer[i] == '\0') break;
|
||||
|
||||
std::string hexstring((const char*)&buffer[i], 2);
|
||||
int len = std::stoi(hexstring, nullptr, 16);
|
||||
i += 2;
|
||||
std::string fieldData((const char*)&buffer[i], len);
|
||||
i += len;
|
||||
|
||||
field.push_back(fieldData);
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)field.size(); ++i) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
this->issue_date.year =
|
||||
std::stoi(field[i].substr(4, 4), nullptr);
|
||||
this->issue_date.month =
|
||||
std::stoi(field[i].substr(2, 2), nullptr);
|
||||
this->issue_date.day =
|
||||
std::stoi(field[i].substr(0, 2), nullptr);
|
||||
break;
|
||||
case 1:
|
||||
this->expiration_date.year =
|
||||
std::stoi(field[i].substr(4, 4), nullptr);
|
||||
this->expiration_date.month =
|
||||
std::stoi(field[i].substr(2, 2), nullptr);
|
||||
this->expiration_date.day =
|
||||
std::stoi(field[i].substr(0, 2), nullptr);
|
||||
break;
|
||||
case 2:
|
||||
this->family_name = field[i];
|
||||
break;
|
||||
case 3:
|
||||
this->first_name = field[i];
|
||||
break;
|
||||
case 4:
|
||||
this->birth_date.year =
|
||||
std::stoi(field[i].substr(4, 4), nullptr);
|
||||
this->birth_date.month =
|
||||
std::stoi(field[i].substr(2, 2), nullptr);
|
||||
this->birth_date.day =
|
||||
std::stoi(field[i].substr(0, 2), nullptr);
|
||||
break;
|
||||
case 5:
|
||||
this->gender = field[i] == "F" ? GENDER_FEMALE : GENDER_MALE;
|
||||
break;
|
||||
case 7:
|
||||
this->fiscal_code = field[i];
|
||||
break;
|
||||
case 9:
|
||||
this->birth_place = field[i];
|
||||
break;
|
||||
case 12:
|
||||
this->residence_place = field[i];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef GCNS_H
|
||||
#define GCNS_H
|
||||
|
||||
#define GCNS_SUCCESS 0
|
||||
#define GCNS_INIT -1001
|
||||
#define GCNS_READ_PERSONAL_DATA -1002
|
||||
#define GCNS_CLOSE -1003
|
||||
|
||||
int gcns_init();
|
||||
int gcns_read_personal_data(u8 *buffer, size_t len);
|
||||
int gcns_close();
|
||||
|
||||
#endif
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef GCNS_CPP
|
||||
#define GCNS_CPP
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace gcns {
|
||||
|
||||
enum Gender { GENDER_MALE, GENDER_FEMALE };
|
||||
|
||||
struct Date {
|
||||
uint16_t year;
|
||||
uint8_t month;
|
||||
uint8_t day;
|
||||
};
|
||||
|
||||
class PersonalData {
|
||||
private:
|
||||
std::string first_name;
|
||||
std::string family_name;
|
||||
std::string fiscal_code;
|
||||
std::string birth_place;
|
||||
Date birth_date;
|
||||
std::string residence_place;
|
||||
Gender gender;
|
||||
Date issue_date;
|
||||
Date expiration_date;
|
||||
|
||||
public:
|
||||
PersonalData(const uint8_t* personal_data, size_t len);
|
||||
};
|
||||
|
||||
} // namespace gcns
|
||||
|
||||
#endif
|
|
@ -0,0 +1,56 @@
|
|||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#ifdef ENABLE_READLINE
|
||||
#include <readline/history.h>
|
||||
#include <readline/readline.h>
|
||||
#endif
|
||||
#if !defined(_WIN32)
|
||||
#include <arpa/inet.h> /* for htons() */
|
||||
#endif
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
#include "common/compat_strlcpy.h"
|
||||
#include "gcns.h"
|
||||
#include "libopensc/asn1.h"
|
||||
#include "libopensc/cardctl.h"
|
||||
#include "libopensc/cards.h"
|
||||
#include "libopensc/internal.h"
|
||||
#include "libopensc/iso7816.h"
|
||||
#include "libopensc/log.h"
|
||||
#include "libopensc/opensc.h"
|
||||
#include "tools/util.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int r;
|
||||
|
||||
printf("OpenSC version: %s\n", sc_get_version());
|
||||
|
||||
r = gcns_init();
|
||||
if (r != GCNS_SUCCESS) {
|
||||
fprintf(stderr, "Init Error\n");
|
||||
return GCNS_INIT;
|
||||
}
|
||||
|
||||
u8 buffer[2048];
|
||||
r = gcns_read_personal_data(buffer, 2048);
|
||||
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "Read personal data error\n");
|
||||
return GCNS_READ_PERSONAL_DATA;
|
||||
}
|
||||
|
||||
util_hex_dump_asc(stdout, buffer, r, 0);
|
||||
|
||||
r = gcns_close();
|
||||
if (r != GCNS_SUCCESS) {
|
||||
return GCNS_CLOSE;
|
||||
}
|
||||
|
||||
return GCNS_SUCCESS;
|
||||
}
|
|
@ -147,4 +147,4 @@ TIDY_FILES = \
|
|||
#$(SOURCES)
|
||||
|
||||
check-local:
|
||||
if [ -x "$(CLANGTIDY)" ]; then clang-tidy -config='' -header-filter=.* $(TIDY_FILES) -- $(TIDY_FLAGS); fi
|
||||
if [ -x "$(CLANGTIDY)" ]; then clang-tidy -config='' --checks='$(TIDY_CHECKS)' -header-filter=.* $(addprefix $(srcdir)/,$(TIDY_FILES)) -- $(TIDY_FLAGS); fi
|
||||
|
|
|
@ -401,11 +401,13 @@ sc_set_le_and_transmit(struct sc_card *card, struct sc_apdu *apdu, size_t olen)
|
|||
/* set the new expected length */
|
||||
apdu->resplen = olen;
|
||||
apdu->le = nlen;
|
||||
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
/* Belpic V1 applets have a problem: if the card sends a 6C XX (only XX bytes available),
|
||||
* and we resend the command too soon (i.e. the reader is too fast), the card doesn't respond.
|
||||
* So we build in a delay. */
|
||||
if (card->type == SC_CARD_TYPE_BELPIC_EID)
|
||||
msleep(40);
|
||||
#endif
|
||||
|
||||
/* re-transmit the APDU with new Le length */
|
||||
rv = sc_single_transmit(card, apdu);
|
||||
|
|
|
@ -253,10 +253,15 @@ static void sc_asn1_print_bit_string(const u8 * buf, size_t buflen, size_t depth
|
|||
if (buflen > sizeof(a) + 1) {
|
||||
print_hex(buf, buflen, depth);
|
||||
} else {
|
||||
r = sc_asn1_decode_bit_string(buf, buflen, &a, sizeof(a));
|
||||
r = sc_asn1_decode_bit_string(buf, buflen, &a, sizeof(a), 1);
|
||||
if (r < 0) {
|
||||
printf("decode error");
|
||||
return;
|
||||
printf("decode error, ");
|
||||
/* try again without the strict mode */
|
||||
r = sc_asn1_decode_bit_string(buf, buflen, &a, sizeof(a), 0);
|
||||
if (r < 0) {
|
||||
printf("even for lax decoding");
|
||||
return ;
|
||||
}
|
||||
}
|
||||
for (i = r - 1; i >= 0; i--) {
|
||||
printf("%c", ((a >> i) & 1) ? '1' : '0');
|
||||
|
@ -567,7 +572,7 @@ const u8 *sc_asn1_verify_tag(sc_context_t *ctx, const u8 * buf, size_t buflen,
|
|||
}
|
||||
|
||||
static int decode_bit_string(const u8 * inbuf, size_t inlen, void *outbuf,
|
||||
size_t outlen, int invert)
|
||||
size_t outlen, int invert, const int strict)
|
||||
{
|
||||
const u8 *in = inbuf;
|
||||
u8 *out = (u8 *) outbuf;
|
||||
|
@ -577,13 +582,19 @@ static int decode_bit_string(const u8 * inbuf, size_t inlen, void *outbuf,
|
|||
|
||||
if (inlen < 1)
|
||||
return SC_ERROR_INVALID_ASN1_OBJECT;
|
||||
/* 8.6.2.3 If the bitstring is empty, there shall be no subsequent octets,
|
||||
* and the initial octet shall be zero. */
|
||||
if (inlen == 1 && *in != 0)
|
||||
return SC_ERROR_INVALID_ASN1_OBJECT;
|
||||
/* ITU-T Rec. X.690 8.6.2.2: The number shall be in the range zero to seven. */
|
||||
if ((*in & ~0x07) != 0)
|
||||
return SC_ERROR_INVALID_ASN1_OBJECT;
|
||||
|
||||
/* The formatting is only enforced by SHALL keyword so we should accept
|
||||
* by default also non-strict values. */
|
||||
if (strict) {
|
||||
/* 8.6.2.3 If the bitstring is empty, there shall be no
|
||||
* subsequent octets,and the initial octet shall be zero. */
|
||||
if (inlen == 1 && *in != 0)
|
||||
return SC_ERROR_INVALID_ASN1_OBJECT;
|
||||
/* ITU-T Rec. X.690 8.6.2.2: The number shall be in the range zero to seven. */
|
||||
if ((*in & ~0x07) != 0)
|
||||
return SC_ERROR_INVALID_ASN1_OBJECT;
|
||||
}
|
||||
|
||||
memset(outbuf, 0, outlen);
|
||||
zero_bits = *in & 0x07;
|
||||
in++;
|
||||
|
@ -622,15 +633,15 @@ static int decode_bit_string(const u8 * inbuf, size_t inlen, void *outbuf,
|
|||
}
|
||||
|
||||
int sc_asn1_decode_bit_string(const u8 * inbuf, size_t inlen,
|
||||
void *outbuf, size_t outlen)
|
||||
void *outbuf, size_t outlen, const int strict)
|
||||
{
|
||||
return decode_bit_string(inbuf, inlen, outbuf, outlen, 1);
|
||||
return decode_bit_string(inbuf, inlen, outbuf, outlen, 1, strict);
|
||||
}
|
||||
|
||||
int sc_asn1_decode_bit_string_ni(const u8 * inbuf, size_t inlen,
|
||||
void *outbuf, size_t outlen)
|
||||
void *outbuf, size_t outlen, const int strict)
|
||||
{
|
||||
return decode_bit_string(inbuf, inlen, outbuf, outlen, 0);
|
||||
return decode_bit_string(inbuf, inlen, outbuf, outlen, 0, strict);
|
||||
}
|
||||
|
||||
static int encode_bit_string(const u8 * inbuf, size_t bits_left, u8 **outbuf,
|
||||
|
@ -675,7 +686,7 @@ static int encode_bit_string(const u8 * inbuf, size_t bits_left, u8 **outbuf,
|
|||
* Bitfields are just bit strings, stored in an unsigned int
|
||||
* (taking endianness into account)
|
||||
*/
|
||||
static int decode_bit_field(const u8 * inbuf, size_t inlen, void *outbuf, size_t outlen)
|
||||
static int decode_bit_field(const u8 * inbuf, size_t inlen, void *outbuf, size_t outlen, const int strict)
|
||||
{
|
||||
u8 data[sizeof(unsigned int)];
|
||||
unsigned int field = 0;
|
||||
|
@ -684,7 +695,7 @@ static int decode_bit_field(const u8 * inbuf, size_t inlen, void *outbuf, size_t
|
|||
if (outlen != sizeof(data))
|
||||
return SC_ERROR_BUFFER_TOO_SMALL;
|
||||
|
||||
n = decode_bit_string(inbuf, inlen, data, sizeof(data), 1);
|
||||
n = decode_bit_string(inbuf, inlen, data, sizeof(data), 1, strict);
|
||||
if (n < 0)
|
||||
return n;
|
||||
|
||||
|
@ -1235,9 +1246,12 @@ static int asn1_decode_se_info(sc_context_t *ctx, const u8 *obj, size_t objlen,
|
|||
size_t idx, ptrlen = objlen;
|
||||
int ret;
|
||||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
|
||||
ses = calloc(SC_MAX_SE_NUM, sizeof(sc_pkcs15_sec_env_info_t *));
|
||||
if (ses == NULL)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
if (ses == NULL) {
|
||||
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_ASN1, SC_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
for (idx=0; idx < SC_MAX_SE_NUM && ptrlen; ) {
|
||||
struct sc_asn1_entry asn1_se[2];
|
||||
|
@ -1281,7 +1295,7 @@ err:
|
|||
free(ses);
|
||||
}
|
||||
|
||||
return ret;
|
||||
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_ASN1, ret);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1535,7 +1549,7 @@ static int asn1_decode_entry(sc_context_t *ctx,struct sc_asn1_entry *entry,
|
|||
*len = objlen-1;
|
||||
parm = *buf;
|
||||
}
|
||||
r = decode_bit_string(obj, objlen, (u8 *) parm, *len, invert);
|
||||
r = decode_bit_string(obj, objlen, (u8 *) parm, *len, invert, 0);
|
||||
if (r >= 0) {
|
||||
*len = r;
|
||||
r = 0;
|
||||
|
@ -1544,7 +1558,7 @@ static int asn1_decode_entry(sc_context_t *ctx,struct sc_asn1_entry *entry,
|
|||
break;
|
||||
case SC_ASN1_BIT_FIELD:
|
||||
if (parm != NULL)
|
||||
r = decode_bit_field(obj, objlen, (u8 *) parm, *len);
|
||||
r = decode_bit_field(obj, objlen, (u8 *) parm, *len, 0);
|
||||
break;
|
||||
case SC_ASN1_OCTET_STRING:
|
||||
if (parm != NULL) {
|
||||
|
@ -1988,6 +2002,10 @@ static int asn1_encode(sc_context_t *ctx, const struct sc_asn1_entry *asn1,
|
|||
u8 *obj = NULL, *buf = NULL, *tmp;
|
||||
size_t total = 0, objsize;
|
||||
|
||||
if (asn1 == NULL) {
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
for (idx = 0; asn1[idx].name != NULL; idx++) {
|
||||
r = asn1_encode_entry(ctx, &asn1[idx], &obj, &objsize, depth);
|
||||
if (r) {
|
||||
|
|
|
@ -96,10 +96,10 @@ void sc_asn1_print_tags(const u8 * buf, size_t buflen);
|
|||
int sc_asn1_utf8string_to_ascii(const u8 * buf, size_t buflen,
|
||||
u8 * outbuf, size_t outlen);
|
||||
int sc_asn1_decode_bit_string(const u8 * inbuf, size_t inlen,
|
||||
void *outbuf, size_t outlen);
|
||||
void *outbuf, size_t outlen, const int strict);
|
||||
/* non-inverting version */
|
||||
int sc_asn1_decode_bit_string_ni(const u8 * inbuf, size_t inlen,
|
||||
void *outbuf, size_t outlen);
|
||||
void *outbuf, size_t outlen, const int strict);
|
||||
int sc_asn1_decode_integer(const u8 * inbuf, size_t inlen, int *out, int strict);
|
||||
int sc_asn1_decode_object_id(const u8 * inbuf, size_t inlen,
|
||||
struct sc_object_id *id);
|
||||
|
@ -127,13 +127,16 @@ int sc_asn1_sig_value_sequence_to_rs(struct sc_context *ctx,
|
|||
const unsigned char *in, size_t inlen,
|
||||
unsigned char *buf, size_t buflen);
|
||||
|
||||
#define SC_ASN1_CLASS_MASK 0x30000000
|
||||
/* long form tags use these */
|
||||
/* Same as SC_ASN1_TAG_* shifted left by 24 bits */
|
||||
#define SC_ASN1_CLASS_MASK 0xC0000000
|
||||
#define SC_ASN1_UNI 0x00000000 /* Universal */
|
||||
#define SC_ASN1_APP 0x10000000 /* Application */
|
||||
#define SC_ASN1_CTX 0x20000000 /* Context */
|
||||
#define SC_ASN1_PRV 0x30000000 /* Private */
|
||||
#define SC_ASN1_CONS 0x01000000
|
||||
#define SC_ASN1_APP 0x40000000 /* Application */
|
||||
#define SC_ASN1_CTX 0x80000000 /* Context */
|
||||
#define SC_ASN1_PRV 0xC0000000 /* Private */
|
||||
#define SC_ASN1_CONS 0x20000000
|
||||
|
||||
#define SC_ASN1_CLASS_CONS 0xE0000000 /* CLASS and CONS */
|
||||
#define SC_ASN1_TAG_MASK 0x00FFFFFF
|
||||
#define SC_ASN1_TAGNUM_SIZE 3
|
||||
|
||||
|
@ -173,6 +176,7 @@ int sc_asn1_sig_value_sequence_to_rs(struct sc_context *ctx,
|
|||
/* use callback function */
|
||||
#define SC_ASN1_CALLBACK 384
|
||||
|
||||
/* use with short one byte tags */
|
||||
#define SC_ASN1_TAG_CLASS 0xC0
|
||||
#define SC_ASN1_TAG_UNIVERSAL 0x00
|
||||
#define SC_ASN1_TAG_APPLICATION 0x40
|
||||
|
@ -181,6 +185,7 @@ int sc_asn1_sig_value_sequence_to_rs(struct sc_context *ctx,
|
|||
|
||||
#define SC_ASN1_TAG_CONSTRUCTED 0x20
|
||||
#define SC_ASN1_TAG_PRIMITIVE 0x1F
|
||||
#define SC_ASN1_TAG_CLASS_CONS 0xE0
|
||||
|
||||
#define SC_ASN1_TAG_EOC 0
|
||||
#define SC_ASN1_TAG_BOOLEAN 1
|
||||
|
|
|
@ -1558,6 +1558,7 @@ authentic_pin_reset(struct sc_card *card, struct sc_pin_cmd_data *data, int *tri
|
|||
pin_cmd.pin_type = data->pin_type;
|
||||
pin_cmd.pin1.tries_left = -1;
|
||||
|
||||
memset(&acls, 0, sizeof(acls));
|
||||
rv = authentic_pin_get_policy(card, &pin_cmd, acls);
|
||||
LOG_TEST_RET(ctx, rv, "Get 'PIN policy' error");
|
||||
|
||||
|
|
|
@ -215,7 +215,6 @@ static int belpic_match_card(sc_card_t *card)
|
|||
static int belpic_init(sc_card_t *card)
|
||||
{
|
||||
int key_size = 1024;
|
||||
int r;
|
||||
|
||||
sc_log(card->ctx, "Belpic V%s\n", BELPIC_VERSION);
|
||||
|
||||
|
@ -227,7 +226,7 @@ static int belpic_init(sc_card_t *card)
|
|||
u8 carddata[BELPIC_CARDDATA_RESP_LEN];
|
||||
memset(carddata, 0, sizeof(carddata));
|
||||
|
||||
if((r = get_carddata(card, carddata, sizeof(carddata))) < 0) {
|
||||
if(get_carddata(card, carddata, sizeof(carddata)) < 0) {
|
||||
return SC_ERROR_INVALID_CARD;
|
||||
}
|
||||
if (carddata[BELPIC_CARDDATA_OFF_APPLETVERS] >= 0x17) {
|
||||
|
|
|
@ -1872,6 +1872,7 @@ static int cac_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries
|
|||
sc_apdu_t apdu;
|
||||
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
|
||||
int rv;
|
||||
|
||||
if (data->cmd == SC_PIN_CMD_CHANGE) {
|
||||
int i = 0;
|
||||
|
@ -1897,7 +1898,10 @@ static int cac_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries
|
|||
}
|
||||
}
|
||||
|
||||
return iso_drv->ops->pin_cmd(card, data, tries_left);
|
||||
rv = iso_drv->ops->pin_cmd(card, data, tries_left);
|
||||
|
||||
data->apdu = NULL;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static struct sc_card_operations cac_ops;
|
||||
|
|
|
@ -55,6 +55,8 @@ static const struct sc_atr_table cardos_atrs[] = {
|
|||
/* CardOS v5.3 */
|
||||
{ "3b:d2:18:00:81:31:fe:58:c9:02:17", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_3, 0, NULL},
|
||||
{ "3b:d2:18:00:81:31:fe:58:c9:03:16", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_3, 0, NULL},
|
||||
/* CardOS v5.4 */
|
||||
{ "3b:d2:18:00:81:31:fe:58:c9:04:11", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_3, 0, NULL},
|
||||
{ NULL, NULL, NULL, 0, 0, NULL }
|
||||
};
|
||||
|
||||
|
@ -159,7 +161,7 @@ static int cardos_have_2048bit_package(sc_card_t *card)
|
|||
sc_apdu_t apdu;
|
||||
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||
int r;
|
||||
const u8 *p = rbuf, *q;
|
||||
const u8 *p = rbuf, *q, *pp;
|
||||
size_t len, tlen = 0, ilen = 0;
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0x88);
|
||||
|
@ -175,10 +177,10 @@ static int cardos_have_2048bit_package(sc_card_t *card)
|
|||
return 0;
|
||||
|
||||
while (len != 0) {
|
||||
p = sc_asn1_find_tag(card->ctx, p, len, 0xe1, &tlen);
|
||||
if (p == NULL)
|
||||
pp = sc_asn1_find_tag(card->ctx, p, len, 0xe1, &tlen);
|
||||
if (pp == NULL)
|
||||
return 0;
|
||||
q = sc_asn1_find_tag(card->ctx, p, tlen, 0x01, &ilen);
|
||||
q = sc_asn1_find_tag(card->ctx, pp, tlen, 0x01, &ilen);
|
||||
if (q == NULL || ilen != 4)
|
||||
return 0;
|
||||
if (q[0] == 0x1c)
|
||||
|
|
|
@ -2143,7 +2143,6 @@ static int dnie_pin_verify(struct sc_card *card,
|
|||
res = cwa_create_secure_channel(card, GET_DNIE_PRIV_DATA(card)->cwa_provider, CWA_SM_ON);
|
||||
LOG_TEST_RET(card->ctx, res, "Establish SM failed");
|
||||
|
||||
data->apdu = &apdu; /* prepare apdu struct */
|
||||
/* compose pin data to be inserted in apdu */
|
||||
if (data->flags & SC_PIN_CMD_NEED_PADDING)
|
||||
padding = 1;
|
||||
|
|
|
@ -948,7 +948,7 @@ decrypt_response(struct sc_card *card, unsigned char *in, size_t inlen, unsigned
|
|||
des3_decrypt_cbc(exdata->sk_enc, 16, iv, &in[i], cipher_len - 1, plaintext);
|
||||
|
||||
/* unpadding */
|
||||
while (0x80 != plaintext[cipher_len - 2] && (cipher_len - 2 > 0))
|
||||
while (0x80 != plaintext[cipher_len - 2] && (cipher_len > 2))
|
||||
cipher_len--;
|
||||
|
||||
if (2 == cipher_len || *out_len < cipher_len - 2)
|
||||
|
|
|
@ -815,7 +815,7 @@ cryptoflex_construct_file_attrs(sc_card_t *card, const sc_file_t *file,
|
|||
r = acl_to_keynum_nibble(entry);
|
||||
p[13 + i/2] |= (r & 0x0F) << (((i+1) % 2) * 4);
|
||||
}
|
||||
p[11] = (file->status & SC_FILE_STATUS_INVALIDATED) ? 0x00 : 0x01;
|
||||
p[11] = (file->status == SC_FILE_STATUS_INVALIDATED) ? 0x00 : 0x01;
|
||||
if (file->type != SC_FILE_TYPE_DF &&
|
||||
(file->ef_structure == SC_FILE_EF_LINEAR_FIXED ||
|
||||
file->ef_structure == SC_FILE_EF_CYCLIC))
|
||||
|
@ -1284,6 +1284,7 @@ static int flex_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
|
|||
r = iso_ops->pin_cmd(card, data, NULL);
|
||||
if (old_cla != -1)
|
||||
card->cla = old_cla;
|
||||
data->apdu = NULL;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -552,7 +552,9 @@ gpk_select_id(sc_card_t *card, int kind, unsigned int fid,
|
|||
cp->len = 0;
|
||||
/* fallthru */
|
||||
case GPK_SEL_DF:
|
||||
assert(cp->len + 1 <= SC_MAX_PATH_SIZE / 2);
|
||||
if (cp->len + 1 > SC_MAX_PATH_SIZE / 2) {
|
||||
return SC_ERROR_INTERNAL;
|
||||
}
|
||||
path = (unsigned short int *) cp->value;
|
||||
path[cp->len++] = fid;
|
||||
}
|
||||
|
@ -1795,7 +1797,10 @@ gpk_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left)
|
|||
|
||||
data->apdu = &apdu;
|
||||
|
||||
return iso_ops->pin_cmd(card, data, tries_left);
|
||||
r = iso_ops->pin_cmd(card, data, tries_left);
|
||||
|
||||
data->apdu = NULL;
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -95,6 +95,18 @@ static const struct sc_atr_table iasecc_known_atrs[] = {
|
|||
"IAS/ECC v1.0.1 Amos", SC_CARD_TYPE_IASECC_AMOS, 0, NULL },
|
||||
{ "3B:DC:18:FF:81:91:FE:1F:C3:80:73:C8:21:13:66:01:0B:03:52:00:05:38", NULL,
|
||||
"IAS/ECC v1.0.1 Amos", SC_CARD_TYPE_IASECC_AMOS, 0, NULL },
|
||||
{
|
||||
.atr = "3B:AC:00:40:2A:00:12:25:00:64:80:00:03:10:00:90:00",
|
||||
.atrmask = "FF:00:00:00:00:FF:FF:FF:FF:FF:FF:00:00:00:FF:FF:FF",
|
||||
.name = "IAS/ECC CPx",
|
||||
.type = SC_CARD_TYPE_IASECC_CPX,
|
||||
},
|
||||
{
|
||||
.atr = "2B:8F:80:01:00:31:B8:64:04:B0:EC:C1:73:94:01:80:82:90:00:0E",
|
||||
.atrmask = "FF:FF:FF:FF:FF:FF:FF:FF:00:00:FF:C0:FF:FF:FF:FF:FF:FF:FF:FF",
|
||||
.name = "IAS/ECC CPxCL",
|
||||
.type = SC_CARD_TYPE_IASECC_CPXCL,
|
||||
},
|
||||
{ NULL, NULL, NULL, 0, 0, NULL }
|
||||
};
|
||||
|
||||
|
@ -310,12 +322,14 @@ iasecc_select_mf(struct sc_card *card, struct sc_file **file_out)
|
|||
mf_file->type = SC_FILE_TYPE_DF;
|
||||
mf_file->path = path;
|
||||
|
||||
if (card->cache.valid)
|
||||
sc_file_free(card->cache.current_df);
|
||||
if (card->cache.valid) {
|
||||
sc_file_free(card->cache.current_df);
|
||||
}
|
||||
card->cache.current_df = NULL;
|
||||
|
||||
if (card->cache.valid)
|
||||
if (card->cache.valid) {
|
||||
sc_file_free(card->cache.current_ef);
|
||||
}
|
||||
card->cache.current_ef = NULL;
|
||||
|
||||
sc_file_dup(&card->cache.current_df, mf_file);
|
||||
|
@ -337,6 +351,8 @@ iasecc_select_aid(struct sc_card *card, struct sc_aid *aid, unsigned char *out,
|
|||
unsigned char apdu_resp[SC_MAX_APDU_BUFFER_SIZE];
|
||||
int rv;
|
||||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
|
||||
/* Select application (deselect previously selected application) */
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0x04, 0x00);
|
||||
apdu.lc = aid->len;
|
||||
|
@ -354,7 +370,7 @@ iasecc_select_aid(struct sc_card *card, struct sc_aid *aid, unsigned char *out,
|
|||
LOG_TEST_RET(card->ctx, SC_ERROR_BUFFER_TOO_SMALL, "Cannot select AID");
|
||||
memcpy(out, apdu.resp, apdu.resplen);
|
||||
|
||||
return SC_SUCCESS;
|
||||
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
|
@ -405,6 +421,11 @@ static int iasecc_parse_ef_atr(struct sc_card *card)
|
|||
sizes->recv = card->ef_atr->issuer_data[10] * 0x100 + card->ef_atr->issuer_data[11];
|
||||
sizes->recv_sc = card->ef_atr->issuer_data[14] * 0x100 + card->ef_atr->issuer_data[15];
|
||||
|
||||
sc_log(ctx,
|
||||
"EF.ATR: IO Buffer Size send/sc %"SC_FORMAT_LEN_SIZE_T"d/%"SC_FORMAT_LEN_SIZE_T"d "
|
||||
"recv/sc %"SC_FORMAT_LEN_SIZE_T"d/%"SC_FORMAT_LEN_SIZE_T"d",
|
||||
sizes->send, sizes->send_sc, sizes->recv, sizes->recv_sc);
|
||||
|
||||
card->max_send_size = sizes->send;
|
||||
card->max_recv_size = sizes->recv;
|
||||
|
||||
|
@ -591,6 +612,45 @@ iasecc_init_amos_or_sagem(struct sc_card *card)
|
|||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||
}
|
||||
|
||||
inline static int
|
||||
iasecc_is_cpx(const struct sc_card *card)
|
||||
{
|
||||
switch(card->type) {
|
||||
case SC_CARD_TYPE_IASECC_CPX:
|
||||
case SC_CARD_TYPE_IASECC_CPXCL:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
iasecc_init_cpx(struct sc_card *card)
|
||||
{
|
||||
struct sc_context *ctx = card->ctx;
|
||||
unsigned int flags;
|
||||
int rv = 0;
|
||||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
|
||||
card->caps = IASECC_CARD_DEFAULT_CAPS;
|
||||
|
||||
flags = IASECC_CARD_DEFAULT_FLAGS;
|
||||
|
||||
_sc_card_add_rsa_alg(card, 512, flags, 0);
|
||||
_sc_card_add_rsa_alg(card, 1024, flags, 0);
|
||||
_sc_card_add_rsa_alg(card, 2048, flags, 0);
|
||||
|
||||
rv = iasecc_parse_ef_atr(card);
|
||||
if (rv)
|
||||
sc_invalidate_cache(card); /* avoid memory leakage */
|
||||
LOG_TEST_RET(ctx, rv, "Parse EF.ATR");
|
||||
|
||||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
iasecc_init(struct sc_card *card)
|
||||
|
@ -618,6 +678,8 @@ iasecc_init(struct sc_card *card)
|
|||
rv = iasecc_init_amos_or_sagem(card);
|
||||
else if (card->type == SC_CARD_TYPE_IASECC_MI)
|
||||
rv = iasecc_init_amos_or_sagem(card);
|
||||
else if (iasecc_is_cpx(card))
|
||||
rv = iasecc_init_cpx(card);
|
||||
else {
|
||||
LOG_TEST_GOTO_ERR(ctx, SC_ERROR_INVALID_CARD, "");
|
||||
}
|
||||
|
@ -857,9 +919,11 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path,
|
|||
sc_log(ctx, "iasecc_select_file() path:%s", sc_print_path(path));
|
||||
|
||||
sc_print_cache(card);
|
||||
if (path->type != SC_PATH_TYPE_DF_NAME
|
||||
if ((!iasecc_is_cpx(card)) &&
|
||||
(card->type != SC_CARD_TYPE_IASECC_GEMALTO) &&
|
||||
(path->type != SC_PATH_TYPE_DF_NAME
|
||||
&& lpath.len >= 2
|
||||
&& lpath.value[0] == 0x3F && lpath.value[1] == 0x00) {
|
||||
&& lpath.value[0] == 0x3F && lpath.value[1] == 0x00)) {
|
||||
sc_log(ctx, "EF.ATR(aid:'%s')", card->ef_atr ? sc_dump_hex(card->ef_atr->aid.value, card->ef_atr->aid.len) : "");
|
||||
|
||||
rv = iasecc_select_mf(card, file_out);
|
||||
|
@ -940,7 +1004,8 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path,
|
|||
&& card->type != SC_CARD_TYPE_IASECC_SAGEM
|
||||
&& card->type != SC_CARD_TYPE_IASECC_AMOS
|
||||
&& card->type != SC_CARD_TYPE_IASECC_MI
|
||||
&& card->type != SC_CARD_TYPE_IASECC_MI2) {
|
||||
&& card->type != SC_CARD_TYPE_IASECC_MI2
|
||||
&& !iasecc_is_cpx(card)) {
|
||||
rv = SC_ERROR_NOT_SUPPORTED;
|
||||
LOG_TEST_GOTO_ERR(ctx, rv, "Unsupported card");
|
||||
}
|
||||
|
@ -952,7 +1017,10 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path,
|
|||
if (card->type == SC_CARD_TYPE_IASECC_OBERTHUR ||
|
||||
card->type == SC_CARD_TYPE_IASECC_AMOS ||
|
||||
card->type == SC_CARD_TYPE_IASECC_MI ||
|
||||
card->type == SC_CARD_TYPE_IASECC_MI2) {
|
||||
card->type == SC_CARD_TYPE_IASECC_MI2 ||
|
||||
card->type == SC_CARD_TYPE_IASECC_GEMALTO ||
|
||||
iasecc_is_cpx(card)
|
||||
) {
|
||||
apdu.p2 = 0x04;
|
||||
}
|
||||
}
|
||||
|
@ -961,7 +1029,9 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path,
|
|||
if (card->type == SC_CARD_TYPE_IASECC_OBERTHUR ||
|
||||
card->type == SC_CARD_TYPE_IASECC_AMOS ||
|
||||
card->type == SC_CARD_TYPE_IASECC_MI ||
|
||||
card->type == SC_CARD_TYPE_IASECC_MI2) {
|
||||
card->type == SC_CARD_TYPE_IASECC_MI2 ||
|
||||
card->type == SC_CARD_TYPE_IASECC_GEMALTO ||
|
||||
iasecc_is_cpx(card)) {
|
||||
apdu.p2 = 0x04;
|
||||
}
|
||||
}
|
||||
|
@ -974,7 +1044,9 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path,
|
|||
apdu.p1 = 0x04;
|
||||
if (card->type == SC_CARD_TYPE_IASECC_AMOS ||
|
||||
card->type == SC_CARD_TYPE_IASECC_MI2 ||
|
||||
card->type == SC_CARD_TYPE_IASECC_OBERTHUR) {
|
||||
card->type == SC_CARD_TYPE_IASECC_OBERTHUR ||
|
||||
card->type == SC_CARD_TYPE_IASECC_GEMALTO ||
|
||||
iasecc_is_cpx(card)) {
|
||||
apdu.p2 = 0x04;
|
||||
}
|
||||
}
|
||||
|
@ -998,6 +1070,7 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path,
|
|||
rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
if (rv == SC_ERROR_INCORRECT_PARAMETERS &&
|
||||
lpath.type == SC_PATH_TYPE_DF_NAME && apdu.p2 == 0x00) {
|
||||
sc_log(ctx, "Warning: SC_ERROR_INCORRECT_PARAMETERS for SC_PATH_TYPE_DF_NAME, try again with P2=0x0C");
|
||||
apdu.p2 = 0x0C;
|
||||
continue;
|
||||
}
|
||||
|
@ -1069,25 +1142,23 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path,
|
|||
|
||||
sc_log(ctx, "FileType %i", file->type);
|
||||
if (file->type == SC_FILE_TYPE_DF) {
|
||||
if (card->cache.valid)
|
||||
if (card->cache.valid) {
|
||||
sc_file_free(card->cache.current_df);
|
||||
}
|
||||
card->cache.current_df = NULL;
|
||||
|
||||
|
||||
if (card->cache.valid)
|
||||
sc_file_free(card->cache.current_ef);
|
||||
card->cache.current_ef = NULL;
|
||||
|
||||
sc_file_dup(&card->cache.current_df, file);
|
||||
card->cache.valid = 1;
|
||||
}
|
||||
else {
|
||||
if (card->cache.valid)
|
||||
if (card->cache.valid) {
|
||||
sc_file_free(card->cache.current_ef);
|
||||
}
|
||||
|
||||
card->cache.current_ef = NULL;
|
||||
|
||||
sc_file_dup(&card->cache.current_ef, file);
|
||||
card->cache.valid = 1;
|
||||
}
|
||||
|
||||
if (file_out) {
|
||||
|
@ -1125,8 +1196,8 @@ iasecc_process_fci(struct sc_card *card, struct sc_file *file,
|
|||
const unsigned char *buf, size_t buflen)
|
||||
{
|
||||
struct sc_context *ctx = card->ctx;
|
||||
size_t taglen;
|
||||
int rv, ii, offs;
|
||||
size_t taglen, offs, ii;
|
||||
int rv;
|
||||
const unsigned char *acls = NULL, *tag = NULL;
|
||||
unsigned char mask;
|
||||
unsigned char ops_DF[7] = {
|
||||
|
@ -1182,10 +1253,15 @@ iasecc_process_fci(struct sc_card *card, struct sc_file *file,
|
|||
for (ii = 0; ii < 7; ii++, mask /= 2) {
|
||||
unsigned char op = file->type == SC_FILE_TYPE_DF ? ops_DF[ii] : ops_EF[ii];
|
||||
|
||||
/* avoid any access to acls[offs] beyond the taglen */
|
||||
if (offs >= taglen) {
|
||||
sc_log(ctx, "Warning: Invalid offset reached during ACL parsing");
|
||||
break;
|
||||
}
|
||||
if (!(mask & acls[0]))
|
||||
continue;
|
||||
|
||||
sc_log(ctx, "ACLs mask 0x%X, offs %i, op 0x%X, acls[offs] 0x%X", mask, offs, op, acls[offs]);
|
||||
sc_log(ctx, "ACLs mask 0x%X, offs %"SC_FORMAT_LEN_SIZE_T"u, op 0x%X, acls[offs] 0x%X", mask, offs, op, acls[offs]);
|
||||
if (op == 0xFF) {
|
||||
;
|
||||
}
|
||||
|
@ -1493,8 +1569,9 @@ iasecc_delete_file(struct sc_card *card, const struct sc_path *path)
|
|||
rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
LOG_TEST_RET(ctx, rv, "Delete file failed");
|
||||
|
||||
if (card->cache.valid)
|
||||
if (card->cache.valid) {
|
||||
sc_file_free(card->cache.current_ef);
|
||||
}
|
||||
card->cache.current_ef = NULL;
|
||||
}
|
||||
|
||||
|
@ -1641,6 +1718,11 @@ iasecc_se_get_info(struct sc_card *card, struct iasecc_se_info *se)
|
|||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
|
||||
if (iasecc_is_cpx(card)) {
|
||||
rv = iasecc_select_mf(card, NULL);
|
||||
LOG_TEST_RET(ctx, rv, "MF invalid");
|
||||
}
|
||||
|
||||
if (se->reference > IASECC_SE_REF_MAX)
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
|
||||
|
||||
|
@ -2797,6 +2879,34 @@ iasecc_sdo_get_tagged_data(struct sc_card *card, int sdo_tag, struct iasecc_sdo
|
|||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
|
||||
sc_log(ctx, "sdo_tag=0x%x sdo_ref=0x%x sdo_class=0x%x", sdo_tag,
|
||||
sdo->sdo_ref, sdo->sdo_class);
|
||||
|
||||
/* XXX: for the CPx, the SDO are available from some specific path */
|
||||
if (iasecc_is_cpx(card)) {
|
||||
struct sc_path path;
|
||||
char *path_str = NULL;
|
||||
switch(sdo_tag) {
|
||||
case IASECC_SDO_PRVKEY_TAG:
|
||||
/* APDU 00 CB 3F FF 0B 4D 09 70 07 BF 90 02 03 7F 48 80 */
|
||||
path_str = "3F00:0001";
|
||||
break;
|
||||
case IASECC_SDO_CHV_TAG:
|
||||
/* APDU 00 CB 3F FF 0B 4D 09 70 07 BF 81 01 03 7F 41 80 */
|
||||
path_str = "3F00";
|
||||
break;
|
||||
default:
|
||||
path_str = NULL;
|
||||
break;
|
||||
}
|
||||
if (path_str) {
|
||||
sc_log(ctx, "Warning: Enforce the path=%s", path_str);
|
||||
sc_format_path(path_str, &path);
|
||||
rv = iasecc_select_file(card, &path, NULL);
|
||||
LOG_TEST_RET(ctx, rv, "path error");
|
||||
}
|
||||
}
|
||||
|
||||
sbuf[offs--] = 0x80;
|
||||
sbuf[offs--] = sdo_tag & 0xFF;
|
||||
if ((sdo_tag >> 8) & 0xFF)
|
||||
|
|
|
@ -195,16 +195,25 @@ static int idprime_process_index(sc_card_t *card, idprime_private_data_t *priv,
|
|||
if (((memcmp(&start[4], "ksc", 3) == 0) || memcmp(&start[4], "kxc", 3) == 0)
|
||||
&& (memcmp(&start[12], "mscp", 5) == 0)) {
|
||||
new_object.fd++;
|
||||
if (card->type == SC_CARD_TYPE_IDPRIME_V2) {
|
||||
/* The key reference starts from 0x11 and increments by the key id (ASCII) */
|
||||
if (card->type == SC_CARD_TYPE_IDPRIME_V1) {
|
||||
/* The key reference is one bigger than the value found here for some reason */
|
||||
new_object.key_reference = start[8] + 1;
|
||||
} else {
|
||||
int key_id = 0;
|
||||
if (start[8] >= '0' && start[8] <= '9') {
|
||||
key_id = start[8] - '0';
|
||||
}
|
||||
new_object.key_reference = 0x11 + key_id;
|
||||
} else {
|
||||
/* The key reference is one bigger than the value found here for some reason */
|
||||
new_object.key_reference = start[8] + 1;
|
||||
switch (card->type) {
|
||||
case SC_CARD_TYPE_IDPRIME_V2:
|
||||
new_object.key_reference = 0x11 + key_id;
|
||||
break;
|
||||
case SC_CARD_TYPE_IDPRIME_V3:
|
||||
new_object.key_reference = 0xF7 + key_id;
|
||||
break;
|
||||
case SC_CARD_TYPE_IDPRIME_V4:
|
||||
new_object.key_reference = 0x56 + key_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Found certificate with fd=%d, key_ref=%d",
|
||||
new_object.fd, new_object.key_reference);
|
||||
|
@ -252,6 +261,14 @@ static int idprime_init(sc_card_t *card)
|
|||
card->type = SC_CARD_TYPE_IDPRIME_V2;
|
||||
sc_log(card->ctx, "Detected IDPrime applet version 2");
|
||||
break;
|
||||
case 0x03:
|
||||
card->type = SC_CARD_TYPE_IDPRIME_V3;
|
||||
sc_log(card->ctx, "Detected IDPrime applet version 3");
|
||||
break;
|
||||
case 0x04:
|
||||
card->type = SC_CARD_TYPE_IDPRIME_V4;
|
||||
sc_log(card->ctx, "Detected IDPrime applet version 4");
|
||||
break;
|
||||
default:
|
||||
sc_log(card->ctx, "Unknown OS version received: %d", rbuf[11]);
|
||||
break;
|
||||
|
@ -290,6 +307,12 @@ static int idprime_init(sc_card_t *card)
|
|||
case SC_CARD_TYPE_IDPRIME_V2:
|
||||
card->name = "Gemalto IDPrime (OSv2)";
|
||||
break;
|
||||
case SC_CARD_TYPE_IDPRIME_V3:
|
||||
card->name = "Gemalto IDPrime (OSv3)";
|
||||
break;
|
||||
case SC_CARD_TYPE_IDPRIME_V4:
|
||||
card->name = "Gemalto IDPrime (OSv4)";
|
||||
break;
|
||||
case SC_CARD_TYPE_IDPRIME_GENERIC:
|
||||
default:
|
||||
card->name = "Gemalto IDPrime (generic)";
|
||||
|
@ -418,6 +441,7 @@ static int idprime_get_token_name(sc_card_t* card, char** tname)
|
|||
sc_path_t tinfo_path = {"\x00\x00", 2, 0, 0, SC_PATH_TYPE_PATH, {"", 0}};
|
||||
sc_file_t *file = NULL;
|
||||
u8 buf[2];
|
||||
char *name;
|
||||
int r;
|
||||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
|
@ -445,20 +469,22 @@ static int idprime_get_token_name(sc_card_t* card, char** tname)
|
|||
}
|
||||
sc_file_free(file);
|
||||
|
||||
*tname = malloc(buf[1]);
|
||||
if (*tname == NULL) {
|
||||
name = malloc(buf[1]);
|
||||
if (name == NULL) {
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
r = iso_ops->read_binary(card, 2, (unsigned char *)*tname, buf[1], 0);
|
||||
r = iso_ops->read_binary(card, 2, (unsigned char *)name, buf[1], 0);
|
||||
if (r < 1) {
|
||||
free(*tname);
|
||||
free(name);
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
|
||||
if ((*tname)[r-1] != '\0') {
|
||||
(*tname)[r-1] = '\0';
|
||||
if (name[r-1] != '\0') {
|
||||
name[r-1] = '\0';
|
||||
}
|
||||
*tname = name;
|
||||
|
||||
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
|
||||
}
|
||||
|
||||
|
@ -615,13 +641,13 @@ idprime_set_security_env(struct sc_card *card,
|
|||
switch (env->operation) {
|
||||
case SC_SEC_OPERATION_DECIPHER:
|
||||
if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_OAEP) {
|
||||
if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1) {
|
||||
if (env->algorithm_flags & SC_ALGORITHM_MGF1_SHA1) {
|
||||
new_env.algorithm_ref = 0x1D;
|
||||
} else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA256) {
|
||||
} else if (env->algorithm_flags & SC_ALGORITHM_MGF1_SHA256) {
|
||||
new_env.algorithm_ref = 0x4D;
|
||||
} else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA384) {
|
||||
} else if (env->algorithm_flags & SC_ALGORITHM_MGF1_SHA384) {
|
||||
new_env.algorithm_ref = 0x5D;
|
||||
} else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA512) {
|
||||
} else if (env->algorithm_flags & SC_ALGORITHM_MGF1_SHA512) {
|
||||
new_env.algorithm_ref = 0x6D;
|
||||
}
|
||||
} else { /* RSA-PKCS without hashing */
|
||||
|
@ -630,11 +656,11 @@ idprime_set_security_env(struct sc_card *card,
|
|||
break;
|
||||
case SC_SEC_OPERATION_SIGN:
|
||||
if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PSS) {
|
||||
if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA256) {
|
||||
if (env->algorithm_flags & SC_ALGORITHM_MGF1_SHA256) {
|
||||
new_env.algorithm_ref = 0x45;
|
||||
} else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA384) {
|
||||
} else if (env->algorithm_flags & SC_ALGORITHM_MGF1_SHA384) {
|
||||
new_env.algorithm_ref = 0x55;
|
||||
} else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA512) {
|
||||
} else if (env->algorithm_flags & SC_ALGORITHM_MGF1_SHA512) {
|
||||
new_env.algorithm_ref = 0x65;
|
||||
}
|
||||
} else { /* RSA-PKCS */
|
||||
|
|
|
@ -503,6 +503,7 @@ static int itacns_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
|
|||
return SC_ERROR_WRONG_CARD;
|
||||
}
|
||||
len = file->size;
|
||||
sc_file_free(file);
|
||||
|
||||
//Returned file->size should be 16.
|
||||
//We choose to not consider it as critical, because some cards
|
||||
|
|
|
@ -882,6 +882,11 @@ select_file_by_fid(sc_card_t * card, unsigned short *pathptr,
|
|||
priv->curpathlen--;
|
||||
priv->is_ef = 0;
|
||||
}
|
||||
/* Free the previously allocated file so we do not leak memory here */
|
||||
if (file) {
|
||||
sc_file_free(*file);
|
||||
*file = NULL;
|
||||
}
|
||||
r = select_down(card, pathptr, 1, 0, file);
|
||||
}
|
||||
|
||||
|
|
|
@ -187,7 +187,7 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file,
|
|||
*p++ = file->record_length;
|
||||
else
|
||||
*p++ = 0;
|
||||
if (file->status & SC_FILE_STATUS_INVALIDATED)
|
||||
if (file->status == SC_FILE_STATUS_INVALIDATED)
|
||||
*p++ = 0;
|
||||
else
|
||||
*p++ = 0x01;
|
||||
|
|
|
@ -43,9 +43,6 @@
|
|||
#define LOAD_KEY_EC_PRIVATE 0x1087
|
||||
#define LOAD_KEY_SYMMETRIC 0x20a0
|
||||
|
||||
#define MYEID_STATE_CREATION 0x01
|
||||
#define MYEID_STATE_ACTIVATED 0x07
|
||||
|
||||
#define MYEID_CARD_NAME_MAX_LEN 100
|
||||
|
||||
/* The following flags define the features supported by the card currently in use.
|
||||
|
@ -86,6 +83,7 @@ typedef struct myeid_private_data {
|
|||
ECDH key agreement. Note that this pointer is usually not valid
|
||||
after this pair of calls and must not be used elsewhere. */
|
||||
const struct sc_security_env* sec_env;
|
||||
int disable_hw_pkcs1_padding;
|
||||
} myeid_private_data_t;
|
||||
|
||||
typedef struct myeid_card_caps {
|
||||
|
@ -166,6 +164,34 @@ myeid_select_aid(struct sc_card *card, struct sc_aid *aid, unsigned char *out, s
|
|||
return SC_SUCCESS;
|
||||
}
|
||||
|
||||
static int myeid_load_options(sc_context_t *ctx, myeid_private_data_t *priv)
|
||||
{
|
||||
int r;
|
||||
size_t i, j;
|
||||
scconf_block **found_blocks, *block;
|
||||
|
||||
if (!ctx || !priv) {
|
||||
r = SC_ERROR_INTERNAL;
|
||||
goto err;
|
||||
}
|
||||
priv->disable_hw_pkcs1_padding = 0;
|
||||
for (i = 0; ctx->conf_blocks[i]; i++) {
|
||||
found_blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i],
|
||||
"card_driver", "myeid");
|
||||
if (!found_blocks)
|
||||
continue;
|
||||
for (j = 0, block = found_blocks[j]; block; j++, block = found_blocks[j]) {
|
||||
priv->disable_hw_pkcs1_padding = scconf_get_int(block, "disable_hw_pkcs1_padding", 0);
|
||||
sc_log(ctx,"Found config option: disable_hw_pkcs1_padding = %d\n", priv->disable_hw_pkcs1_padding);
|
||||
}
|
||||
free(found_blocks);
|
||||
}
|
||||
r = SC_SUCCESS;
|
||||
|
||||
err:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int myeid_init(struct sc_card *card)
|
||||
{
|
||||
unsigned long flags = 0, ext_flags = 0;
|
||||
|
@ -196,6 +222,9 @@ static int myeid_init(struct sc_card *card)
|
|||
if (!priv)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
rv = myeid_load_options (card->ctx, priv);
|
||||
LOG_TEST_GOTO_ERR(card->ctx, rv, "Unable to read options from opensc.conf");
|
||||
|
||||
priv->card_state = SC_FILE_STATUS_CREATION;
|
||||
card->drv_data = priv;
|
||||
|
||||
|
@ -224,8 +253,10 @@ static int myeid_init(struct sc_card *card)
|
|||
}
|
||||
}
|
||||
|
||||
flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_ONBOARD_KEY_GEN;
|
||||
flags |= SC_ALGORITHM_RSA_HASH_NONE | SC_ALGORITHM_RSA_HASH_SHA1;
|
||||
flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_ONBOARD_KEY_GEN;
|
||||
if (priv->disable_hw_pkcs1_padding == 0)
|
||||
flags |= SC_ALGORITHM_RSA_PAD_PKCS1;
|
||||
flags |= SC_ALGORITHM_RSA_HASH_NONE;
|
||||
|
||||
_sc_card_add_rsa_alg(card, 512, flags, 0);
|
||||
_sc_card_add_rsa_alg(card, 768, flags, 0);
|
||||
|
@ -245,7 +276,7 @@ static int myeid_init(struct sc_card *card)
|
|||
int i;
|
||||
|
||||
flags = SC_ALGORITHM_ECDSA_RAW | SC_ALGORITHM_ECDH_CDH_RAW | SC_ALGORITHM_ONBOARD_KEY_GEN;
|
||||
flags |= SC_ALGORITHM_ECDSA_HASH_NONE | SC_ALGORITHM_ECDSA_HASH_SHA1;
|
||||
flags |= SC_ALGORITHM_ECDSA_HASH_NONE;
|
||||
ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES;
|
||||
|
||||
for (i=0; ec_curves[i].curve_name != NULL; i++) {
|
||||
|
@ -441,20 +472,18 @@ static int myeid_process_fci(struct sc_card *card, struct sc_file *file,
|
|||
sc_log(card->ctx, "id (%X) sec_attr (%X %X %X)", file->id,
|
||||
file->sec_attr[0],file->sec_attr[1],file->sec_attr[2]);
|
||||
}
|
||||
tag = sc_asn1_find_tag(NULL, buf, buflen, 0x8A, &taglen);
|
||||
if (tag != NULL && taglen > 0)
|
||||
{
|
||||
if(tag[0] == MYEID_STATE_CREATION) {
|
||||
file->status = SC_FILE_STATUS_CREATION;
|
||||
sc_log(card->ctx, "File id (%X) status SC_FILE_STATUS_CREATION (0x%X)",
|
||||
file->id, tag[0]);
|
||||
}
|
||||
else if(tag[0] == MYEID_STATE_ACTIVATED) {
|
||||
file->status = SC_FILE_STATUS_ACTIVATED;
|
||||
sc_log(card->ctx, "File id (%X) status SC_FILE_STATUS_ACTIVATED (0x%X)",
|
||||
file->id, tag[0]);
|
||||
}
|
||||
priv->card_state = file->status;
|
||||
|
||||
priv->card_state = file->status;
|
||||
switch (file->status) {
|
||||
case SC_FILE_STATUS_CREATION:
|
||||
file->acl_inactive = 1;
|
||||
sc_log(card->ctx, "File id (%X) status SC_FILE_STATUS_CREATION", file->id);
|
||||
break;
|
||||
case SC_FILE_STATUS_ACTIVATED:
|
||||
sc_log(card->ctx, "File id (%X) status SC_FILE_STATUS_ACTIVATED", file->id);
|
||||
break;
|
||||
default:
|
||||
sc_log(card->ctx, "File id (%X) unusual status (0x%X)", file->id, file->status);
|
||||
}
|
||||
|
||||
LOG_FUNC_RETURN(card->ctx, 0);
|
||||
|
|
|
@ -539,7 +539,7 @@ auth_select_file(struct sc_card *card, const struct sc_path *in_path,
|
|||
}
|
||||
}
|
||||
|
||||
if (path.len - offs > 0) {
|
||||
if (path.len > offs) {
|
||||
struct sc_path tmp_path;
|
||||
|
||||
memset(&tmp_path, 0, sizeof(struct sc_path));
|
||||
|
@ -2206,6 +2206,9 @@ auth_read_record(struct sc_card *card, unsigned int nr_rec,
|
|||
"auth_read_record(): nr_rec %i; count %"SC_FORMAT_LEN_SIZE_T"u",
|
||||
nr_rec, count);
|
||||
|
||||
if (nr_rec > 0xFF)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xB2, nr_rec, 0);
|
||||
apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
|
||||
if (flags & SC_RECORD_BY_REC_NR)
|
||||
|
|
|
@ -87,7 +87,11 @@ static struct sc_card_driver pgp_drv = {
|
|||
};
|
||||
|
||||
|
||||
static pgp_ec_curves_t ec_curves[] = {
|
||||
static pgp_ec_curves_t ec_curves_openpgp34[] = {
|
||||
/* OpenPGP 3.4+ Ed25519 and Curve25519 */
|
||||
{{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 256}, /* curve25519 for encryption => CKK_EC_MONTGOMERY */
|
||||
{{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 256}, /* ed25519 for signatures => CKK_EC_EDWARDS */
|
||||
/* v3.0+ supports: [RFC 4880 & 6637] 0x12 = ECDH, 0x13 = ECDSA */
|
||||
{{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256}, /* ansiX9p256r1 */
|
||||
{{{1, 3, 132, 0, 34, -1}}, 384}, /* ansiX9p384r1 */
|
||||
{{{1, 3, 132, 0, 35, -1}}, 521}, /* ansiX9p521r1 */
|
||||
|
@ -97,11 +101,16 @@ static pgp_ec_curves_t ec_curves[] = {
|
|||
{{{-1}}, 0} /* This entry must not be touched. */
|
||||
};
|
||||
|
||||
static pgp_ec_curves_t *ec_curves_openpgp = ec_curves_openpgp34 + 2;
|
||||
|
||||
struct sc_object_id curve25519_oid = {{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}};
|
||||
|
||||
/* Gnuk supports NIST, SECG and Curve25519 since version 1.2 */
|
||||
static pgp_ec_curves_t ec_curves_gnuk[] = {
|
||||
{{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256}, /* ansiX9p256r1 */
|
||||
{{{1, 3, 132, 0, 10, -1}}, 256}, /* secp256k1 */
|
||||
/*{{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 256}, //cv25519
|
||||
{{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 256}, // ed25519 */
|
||||
{{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 256}, /* curve25519 for encryption => CKK_EC_MONTGOMERY */
|
||||
{{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 256}, /* ed25519 for signatures => CKK_EC_EDWARDS */
|
||||
{{{-1}}, 0} /* This entry must not be touched. */
|
||||
};
|
||||
|
||||
|
@ -448,6 +457,15 @@ pgp_init(sc_card_t *card)
|
|||
: (priv->bcd_version < OPENPGP_CARD_3_4) ? pgp33_objects
|
||||
: pgp34_objects;
|
||||
|
||||
/* With gnuk, we use different curves */
|
||||
if (card->type == SC_CARD_TYPE_OPENPGP_GNUK) {
|
||||
priv->ec_curves = ec_curves_gnuk;
|
||||
} else if (priv->bcd_version >= OPENPGP_CARD_3_4) {
|
||||
priv->ec_curves = ec_curves_openpgp34;
|
||||
} else {
|
||||
priv->ec_curves = ec_curves_openpgp;
|
||||
}
|
||||
|
||||
/* change file path to MF for re-use in MF */
|
||||
sc_format_path("3f00", &file->path);
|
||||
|
||||
|
@ -500,22 +518,15 @@ pgp_init(sc_card_t *card)
|
|||
switch (card->type) {
|
||||
case SC_CARD_TYPE_OPENPGP_V3:
|
||||
/* RSA 1024 was removed for v3+ */
|
||||
_sc_card_add_rsa_alg(card, 2048, flags_rsa, 0);
|
||||
_sc_card_add_rsa_alg(card, 3072, flags_rsa, 0);
|
||||
_sc_card_add_rsa_alg(card, 4096, flags_rsa, 0);
|
||||
/* v3.0+ supports: [RFC 4880 & 6637] 0x12 = ECDH, 0x13 = ECDSA */
|
||||
for (i=0; ec_curves[i].oid.value[0] >= 0; i++)
|
||||
{
|
||||
_sc_card_add_ec_alg(card, ec_curves[i].size, flags_ecc, ext_flags, &ec_curves[i].oid);
|
||||
}
|
||||
break;
|
||||
_sc_card_add_rsa_alg(card, 3072, flags_rsa, 0);
|
||||
/* fallthrough */
|
||||
case SC_CARD_TYPE_OPENPGP_GNUK:
|
||||
_sc_card_add_rsa_alg(card, 2048, flags_rsa, 0);
|
||||
/* Gnuk supports NIST, SECG and Curve25519 since version 1.2 */
|
||||
for (i=0; ec_curves_gnuk[i].oid.value[0] >= 0; i++)
|
||||
for (i=0; priv->ec_curves[i].oid.value[0] >= 0; i++)
|
||||
{
|
||||
_sc_card_add_ec_alg(card, ec_curves_gnuk[i].size,
|
||||
flags_ecc, ext_flags, &ec_curves_gnuk[i].oid);
|
||||
_sc_card_add_ec_alg(card, priv->ec_curves[i].size,
|
||||
flags_ecc, ext_flags, &priv->ec_curves[i].oid);
|
||||
}
|
||||
break;
|
||||
case SC_CARD_TYPE_OPENPGP_V2:
|
||||
|
@ -565,21 +576,27 @@ pgp_parse_hist_bytes(sc_card_t *card, u8 *ctlv, size_t ctlv_len)
|
|||
* Internal: parse an algorithm attributes DO
|
||||
**/
|
||||
static int
|
||||
pgp_parse_algo_attr_blob(const pgp_blob_t *blob, sc_cardctl_openpgp_keygen_info_t *key_info)
|
||||
pgp_parse_algo_attr_blob(sc_card_t *card, const pgp_blob_t *blob,
|
||||
sc_cardctl_openpgp_keygen_info_t *key_info)
|
||||
{
|
||||
struct pgp_priv_data *priv = DRVDATA(card);
|
||||
struct sc_object_id oid;
|
||||
unsigned int j, r;
|
||||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
|
||||
if (blob == NULL || blob->data == NULL || blob->len == 0 ||
|
||||
blob->id < 0x00c1 || blob->id > 0x00c3 || key_info == NULL)
|
||||
return SC_ERROR_INCORRECT_PARAMETERS;
|
||||
blob->id < 0x00c1 || blob->id > 0x00c3 || key_info == NULL) {
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INCORRECT_PARAMETERS);
|
||||
}
|
||||
|
||||
key_info->key_id = blob->id - 0x00c0; /* attribute algorithm blobs are C1 - C3 */
|
||||
|
||||
switch (blob->data[0]) {
|
||||
case SC_OPENPGP_KEYALGO_RSA:
|
||||
if (blob->len < 5)
|
||||
return SC_ERROR_INCORRECT_PARAMETERS;
|
||||
if (blob->len < 5) {
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INCORRECT_PARAMETERS);
|
||||
}
|
||||
|
||||
key_info->algorithm = SC_OPENPGP_KEYALGO_RSA;
|
||||
key_info->u.rsa.modulus_len = bebytes2ushort(blob->data + 1);
|
||||
|
@ -591,11 +608,12 @@ pgp_parse_algo_attr_blob(const pgp_blob_t *blob, sc_cardctl_openpgp_keygen_info_
|
|||
break;
|
||||
case SC_OPENPGP_KEYALGO_ECDH:
|
||||
case SC_OPENPGP_KEYALGO_ECDSA:
|
||||
case SC_OPENPGP_KEYALGO_EDDSA:
|
||||
|
||||
/* SC_OPENPGP_KEYALGO_ECDH || SC_OPENPGP_KEYALGO_ECDSA */
|
||||
/* SC_OPENPGP_KEYALGO_ECDH || SC_OPENPGP_KEYALGO_ECDSA || SC_OPENPGP_KEYALGO_EDDSA */
|
||||
key_info->algorithm = blob->data[0];
|
||||
|
||||
/* last byte is only set if pubkey import is supported, empty otherwise*/
|
||||
/* last byte is set to 0xFF if pubkey import is supported */
|
||||
if (blob->data[blob->len-1] == SC_OPENPGP_KEYFORMAT_EC_STDPUB){
|
||||
if (blob->len < 3)
|
||||
return SC_ERROR_INCORRECT_PARAMETERS;
|
||||
|
@ -603,9 +621,14 @@ pgp_parse_algo_attr_blob(const pgp_blob_t *blob, sc_cardctl_openpgp_keygen_info_
|
|||
key_info->u.ec.keyformat = SC_OPENPGP_KEYFORMAT_EC_STDPUB;
|
||||
}
|
||||
else {
|
||||
/* otherwise, last byte could be 00, so let's ignore it, as
|
||||
* it is not part of OID */
|
||||
if (blob->len < 2)
|
||||
return SC_ERROR_INCORRECT_PARAMETERS;
|
||||
key_info->u.ec.oid_len = blob->len - 1;
|
||||
if (blob->data[blob->len-1] == SC_OPENPGP_KEYFORMAT_EC_STD)
|
||||
key_info->u.ec.oid_len = blob->len - 2;
|
||||
else
|
||||
key_info->u.ec.oid_len = blob->len - 1;
|
||||
key_info->u.ec.keyformat = SC_OPENPGP_KEYFORMAT_EC_STD;
|
||||
}
|
||||
|
||||
|
@ -618,20 +641,25 @@ pgp_parse_algo_attr_blob(const pgp_blob_t *blob, sc_cardctl_openpgp_keygen_info_
|
|||
return r;
|
||||
}
|
||||
/* compare with list of supported ec_curves */
|
||||
for (j=0; ec_curves[j].oid.value[0] >= 0; j++){
|
||||
if (sc_compare_oid(&ec_curves[j].oid, &oid)){
|
||||
key_info->u.ec.oid = ec_curves[j].oid;
|
||||
key_info->u.ec.key_length = ec_curves[j].size;
|
||||
for (j = 0; priv->ec_curves[j].oid.value[0] >= 0; j++) {
|
||||
if (sc_compare_oid(&priv->ec_curves[j].oid, &oid)) {
|
||||
sc_log(card->ctx, "Matched EC oid %s (%d)",
|
||||
sc_dump_oid(&oid), j);
|
||||
key_info->u.ec.oid = priv->ec_curves[j].oid;
|
||||
key_info->u.ec.key_length = priv->ec_curves[j].size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* We did not match the OID */
|
||||
if (priv->ec_curves[j].oid.value[0] < 0) {
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return SC_ERROR_NOT_IMPLEMENTED;
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
return SC_SUCCESS;
|
||||
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
|
@ -647,6 +675,8 @@ pgp_get_card_features(sc_card_t *card)
|
|||
size_t i;
|
||||
pgp_blob_t *blob, *blob6e, *blob73;
|
||||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
|
||||
/* parse card capabilities from historical bytes in ATR */
|
||||
if (hist_bytes_len > 0) {
|
||||
/* category indicator 0x00, 0x10 or 0x80 => compact TLV (ISO) */
|
||||
|
@ -776,24 +806,46 @@ pgp_get_card_features(sc_card_t *card)
|
|||
for (i = 0x00c1; i <= 0x00c3; i++) {
|
||||
sc_cardctl_openpgp_keygen_info_t key_info;
|
||||
|
||||
sc_log(card->ctx, "Parsing algorithm attribues DO %zX" , i);
|
||||
|
||||
/* OpenPGP card spec 1.1 & 2.x section 4.3.3.6 / v3.x section 4.4.3.7 */
|
||||
if ((pgp_get_blob(card, blob73, i, &blob) >= 0) &&
|
||||
(pgp_parse_algo_attr_blob(blob, &key_info) >= 0)) {
|
||||
(pgp_parse_algo_attr_blob(card, blob, &key_info) >= 0)) {
|
||||
unsigned long flags = 0, ext_flags = 0;
|
||||
|
||||
/* RSA [RFC 4880] */
|
||||
if (key_info.algorithm == SC_OPENPGP_KEYALGO_RSA){
|
||||
switch (key_info.algorithm) {
|
||||
case SC_OPENPGP_KEYALGO_RSA:
|
||||
/* OpenPGP card spec 1.1 & 2.x, section 7.2.9 & 7.2.10 /
|
||||
* v3.x section 7.2.11 & 7.2.12 */
|
||||
unsigned long flags = SC_ALGORITHM_RSA_PAD_PKCS1 |
|
||||
SC_ALGORITHM_RSA_HASH_NONE |
|
||||
SC_ALGORITHM_ONBOARD_KEY_GEN; /* key gen on card */
|
||||
_sc_card_add_rsa_alg(card, key_info.u.rsa.modulus_len, flags, 0);
|
||||
}
|
||||
/* v3.0+: ECC [RFC 4880 & 6637] */
|
||||
else if (key_info.algorithm == SC_OPENPGP_KEYALGO_ECDH
|
||||
|| key_info.algorithm == SC_OPENPGP_KEYALGO_ECDSA) {
|
||||
flags = SC_ALGORITHM_RSA_PAD_PKCS1 |
|
||||
SC_ALGORITHM_RSA_HASH_NONE |
|
||||
SC_ALGORITHM_ONBOARD_KEY_GEN; /* key gen on card */
|
||||
|
||||
unsigned long flags, ext_flags;
|
||||
_sc_card_add_rsa_alg(card, key_info.u.rsa.modulus_len, flags, 0);
|
||||
sc_log(card->ctx, "DO %zX: Added RSA algorithm, mod_len = %"
|
||||
SC_FORMAT_LEN_SIZE_T"u",
|
||||
i, key_info.u.rsa.modulus_len);
|
||||
break;
|
||||
case SC_OPENPGP_KEYALGO_ECDH:
|
||||
/* The montgomery curve (curve25519) needs to go through
|
||||
* different paths, otherwise we handle it as a normal EC key */
|
||||
if (sc_compare_oid(&key_info.u.ec.oid, &curve25519_oid)) {
|
||||
/* CKM_XEDDSA supports both Sign and Derive, but
|
||||
* OpenPGP card supports only derivation using these
|
||||
* keys as far as I know */
|
||||
_sc_card_add_xeddsa_alg(card, key_info.u.ec.key_length,
|
||||
SC_ALGORITHM_ECDH_CDH_RAW, 0, &key_info.u.ec.oid);
|
||||
|
||||
sc_log(card->ctx, "DO %zX: Added XEDDSA algorithm (%d), mod_len = %d" ,
|
||||
i, key_info.algorithm, key_info.u.ec.key_length);
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
case SC_OPENPGP_KEYALGO_ECDSA:
|
||||
/* v3.0+: ECC [RFC 4880 & 6637] */
|
||||
/* EdDSA from draft-ietf-openpgp-rfc4880bis-08 */
|
||||
flags = 0, ext_flags = 0;
|
||||
|
||||
if (key_info.algorithm == SC_OPENPGP_KEYALGO_ECDH)
|
||||
flags = SC_ALGORITHM_ECDH_CDH_RAW;
|
||||
|
@ -804,7 +856,21 @@ pgp_get_card_features(sc_card_t *card)
|
|||
ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE;
|
||||
|
||||
_sc_card_add_ec_alg(card, key_info.u.ec.key_length, flags, ext_flags,
|
||||
&key_info.u.ec.oid);
|
||||
&key_info.u.ec.oid);
|
||||
sc_log(card->ctx, "DO %zX: Added EC algorithm (%d), mod_len = %d" ,
|
||||
i, key_info.algorithm, key_info.u.ec.key_length);
|
||||
break;
|
||||
case SC_OPENPGP_KEYALGO_EDDSA:
|
||||
_sc_card_add_eddsa_alg(card, key_info.u.ec.key_length,
|
||||
SC_ALGORITHM_EDDSA_RAW, 0, &key_info.u.ec.oid);
|
||||
|
||||
sc_log(card->ctx, "DO %zX: Added EDDSA algorithm (%d), mod_len = %d" ,
|
||||
i, key_info.algorithm, key_info.u.ec.key_length);
|
||||
break;
|
||||
default:
|
||||
sc_log(card->ctx, "DO %zX: Unknown algorithm ID (%d)" ,
|
||||
i, key_info.algorithm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1551,10 +1617,6 @@ pgp_get_pubkey_pem(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len)
|
|||
else if ((r = pgp_get_blob(card, blob, 0x0086, &pubkey_blob)) >= 0
|
||||
&& (r = pgp_read_blob(card, pubkey_blob)) >= 0) {
|
||||
|
||||
p15pubkey.algorithm = SC_ALGORITHM_EC;
|
||||
p15pubkey.u.ec.ecpointQ.value = pubkey_blob->data;
|
||||
p15pubkey.u.ec.ecpointQ.len = pubkey_blob->len;
|
||||
|
||||
switch(tag & 0xFFFE) {
|
||||
case DO_SIGN: aa_tag = 0x00C1; break;
|
||||
case DO_ENCR: aa_tag = 0x00C2; break;
|
||||
|
@ -1567,31 +1629,73 @@ pgp_get_pubkey_pem(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len)
|
|||
if (aa_tag && ((r = pgp_get_blob(card, priv->mf, 0x006e, &blob6e)) >= 0) &&
|
||||
((r = pgp_get_blob(card, blob6e, 0x0073, &blob73)) >= 0) &&
|
||||
((r = pgp_get_blob(card, blob73, aa_tag, &aa_blob)) >= 0) &&
|
||||
((r = pgp_parse_algo_attr_blob(aa_blob, &key_info)) >= 0)) {
|
||||
|
||||
if ((r = sc_encode_oid(card->ctx, &key_info.u.ec.oid,
|
||||
&p15pubkey.u.ec.params.der.value,
|
||||
&p15pubkey.u.ec.params.der.len)) == 0) {
|
||||
p15pubkey.u.ec.params.type = 1;
|
||||
((r = pgp_parse_algo_attr_blob(card, aa_blob, &key_info)) >= 0)) {
|
||||
switch (key_info.algorithm) {
|
||||
case SC_OPENPGP_KEYALGO_EDDSA:
|
||||
/* In EDDSA key case we do not have to care about OIDs
|
||||
* as we support only one for now */
|
||||
p15pubkey.algorithm = SC_ALGORITHM_EDDSA;
|
||||
p15pubkey.u.eddsa.pubkey.value = pubkey_blob->data;
|
||||
p15pubkey.u.eddsa.pubkey.len = pubkey_blob->len;
|
||||
/* PKCS#11 3.0: 2.3.5 Edwards EC public keys only support the use
|
||||
* of the curveName selection to specify a curve name as defined
|
||||
* in [RFC 8032] */
|
||||
r = sc_pkcs15_encode_pubkey_as_spki(card->ctx, &p15pubkey, &data, &len);
|
||||
break;
|
||||
case SC_OPENPGP_KEYALGO_ECDH:
|
||||
/* This yields either EC(DSA) key or EC_MONTGOMERY (curve25519) key */
|
||||
if (sc_compare_oid(&key_info.u.ec.oid, &curve25519_oid)) {
|
||||
p15pubkey.algorithm = SC_ALGORITHM_XEDDSA;
|
||||
p15pubkey.u.eddsa.pubkey.value = pubkey_blob->data;
|
||||
p15pubkey.u.eddsa.pubkey.len = pubkey_blob->len;
|
||||
/* PKCS#11 3.0 2.3.7 Montgomery EC public keys only support
|
||||
* the use of the curveName selection to specify a curve
|
||||
* name as defined in [RFC7748] */
|
||||
/* XXX only curve25519 supported now. Theoretically could be
|
||||
* also curve448 or OIDs */
|
||||
|
||||
r = sc_pkcs15_encode_pubkey_as_spki(card->ctx, &p15pubkey, &data, &len);
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
case SC_OPENPGP_KEYALGO_ECDSA:
|
||||
if ((r = sc_encode_oid(card->ctx, &key_info.u.ec.oid,
|
||||
&p15pubkey.u.ec.params.der.value,
|
||||
&p15pubkey.u.ec.params.der.len)) == 0) {
|
||||
p15pubkey.algorithm = SC_ALGORITHM_EC;
|
||||
p15pubkey.u.ec.ecpointQ.value = pubkey_blob->data;
|
||||
p15pubkey.u.ec.ecpointQ.len = pubkey_blob->len;
|
||||
p15pubkey.u.ec.params.type = 1;
|
||||
r = sc_pkcs15_encode_pubkey_as_spki(card->ctx, &p15pubkey, &data, &len);
|
||||
} else {
|
||||
sc_log(card->ctx, "Unable to encode EC curve OID from algorithm info");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sc_log(card->ctx, "Unknown algorithm ID received (%d)", key_info.algorithm);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
sc_log(card->ctx, "Unable to find Algorithm Attribute for EC curve OID");
|
||||
}
|
||||
else
|
||||
}
|
||||
} else {
|
||||
LOG_TEST_RET(card->ctx, r, "error getting elements");
|
||||
}
|
||||
|
||||
/* clean up anything we may have set in p15pubkey that can not be freed */
|
||||
if (p15pubkey.algorithm == SC_ALGORITHM_RSA) {
|
||||
if (p15pubkey.algorithm == SC_ALGORITHM_RSA) {
|
||||
p15pubkey.u.rsa.modulus.data = NULL;
|
||||
p15pubkey.u.rsa.modulus.len = 0;
|
||||
p15pubkey.u.rsa.exponent.data = NULL;
|
||||
p15pubkey.u.rsa.exponent.len = 0;
|
||||
} else
|
||||
if (p15pubkey.algorithm == SC_ALGORITHM_EC) {
|
||||
} else if (p15pubkey.algorithm == SC_ALGORITHM_EC) {
|
||||
p15pubkey.u.ec.ecpointQ.value = NULL;
|
||||
p15pubkey.u.ec.ecpointQ.len = 0;
|
||||
/* p15pubkey.u.ec.params.der and named_curve will be freed by sc_pkcs15_erase_pubkey */
|
||||
} else if (p15pubkey.algorithm == SC_ALGORITHM_EDDSA
|
||||
|| p15pubkey.algorithm == SC_ALGORITHM_XEDDSA) {
|
||||
p15pubkey.u.eddsa.pubkey.value = NULL;
|
||||
p15pubkey.u.eddsa.pubkey.len = 0;
|
||||
}
|
||||
sc_pkcs15_erase_pubkey(&p15pubkey);
|
||||
|
||||
|
@ -1769,9 +1873,8 @@ pgp_put_data(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len)
|
|||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
|
||||
/* check if the tag is writable */
|
||||
if (priv->current->id != tag)
|
||||
affected_blob = pgp_find_blob(card, tag);
|
||||
/* Check if there is a blob for the given tag */
|
||||
affected_blob = pgp_find_blob(card, tag);
|
||||
|
||||
/* Non-readable DOs have no represented blob, we have to check from pgp_get_info_by_tag */
|
||||
if (affected_blob == NULL)
|
||||
|
@ -1779,6 +1882,7 @@ pgp_put_data(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len)
|
|||
else
|
||||
dinfo = affected_blob->info;
|
||||
|
||||
/* Make sure the DO exists and is writeable */
|
||||
if (dinfo == NULL) {
|
||||
sc_log(card->ctx, "The DO %04X does not exist.", tag);
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
|
||||
|
@ -1843,7 +1947,7 @@ pgp_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left)
|
|||
|
||||
/* In general, the PIN Reference is extracted from the key-id,
|
||||
* for example, CHV0 -> Ref=0, CHV1 -> Ref=1.
|
||||
* However, in the case of OpenGPG, the PIN Ref to compose APDU
|
||||
* However, in the case of OpenPGP, the PIN Ref to compose APDU
|
||||
* must be 81, 82, 83.
|
||||
* So, if we receive Ref=1, Ref=2, we must convert to 81, 82...
|
||||
* In OpenPGP v1, the PINs are named CHV1, CHV2, CHV3.
|
||||
|
@ -1964,6 +2068,7 @@ int pgp_logout(struct sc_card *card)
|
|||
|
||||
/**
|
||||
* ABI: ISO 7816-8 SET SECURITY ENVIRONMENT.
|
||||
* This is optional in the OpenPGP Card 3.4 specs
|
||||
*/
|
||||
static int
|
||||
pgp_set_security_env(sc_card_t *card,
|
||||
|
@ -1973,9 +2078,11 @@ pgp_set_security_env(sc_card_t *card,
|
|||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
|
||||
/* The SC_SEC_ENV_ALG_PRESENT is set always so let it pass for GNUK */
|
||||
if ((env->flags & SC_SEC_ENV_ALG_PRESENT)
|
||||
&& (env->algorithm != SC_ALGORITHM_RSA)
|
||||
&& (priv->bcd_version < OPENPGP_CARD_3_0))
|
||||
&& (priv->bcd_version < OPENPGP_CARD_3_0)
|
||||
&& (card->type != SC_CARD_TYPE_OPENPGP_GNUK))
|
||||
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
|
||||
"only RSA algorithm supported");
|
||||
|
||||
|
@ -2006,6 +2113,9 @@ pgp_set_security_env(sc_card_t *card,
|
|||
"requested usage");
|
||||
}
|
||||
break;
|
||||
case SC_SEC_OPERATION_DERIVE:
|
||||
sc_log(card->ctx, "Operation: Derive: No particular action needed");
|
||||
break;
|
||||
default:
|
||||
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
|
||||
"invalid operation");
|
||||
|
@ -2093,6 +2203,9 @@ pgp_compute_signature(sc_card_t *card, const u8 *data,
|
|||
break;
|
||||
case 0x01:
|
||||
default:
|
||||
/* From PKCS #11 point of view, we should be able to use
|
||||
* curve25519 to do digital signature, but it is not how it
|
||||
* is used in OpenPGP so we will not allow it here */
|
||||
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
|
||||
"invalid key reference");
|
||||
}
|
||||
|
@ -2129,21 +2242,86 @@ pgp_decipher(sc_card_t *card, const u8 *in, size_t inlen,
|
|||
sc_security_env_t *env = &priv->sec_env;
|
||||
sc_apdu_t apdu;
|
||||
u8 apdu_case = SC_APDU_CASE_4;
|
||||
u8 *temp = NULL;
|
||||
u8 *temp = NULL, *p = NULL;
|
||||
size_t templen, pklen, dolen;
|
||||
int r;
|
||||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
|
||||
/* padding according to OpenPGP card spec 1.1 & 2.x section 7.2.9 / 3.x section 7.2.11 */
|
||||
if (!(temp = malloc(inlen + 1)))
|
||||
/* padding according to OpenPGP card spec 1.1 & 2.x section 7.2.9 / 3.x section 7.2.11
|
||||
* The longest possible prefix is 10 bytes for ECDH */
|
||||
templen = inlen + 10;
|
||||
if (!(temp = malloc(templen)))
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
/* padding byte: 0xa6 = ECC; 0x00 = RSA; 0x02 = AES */
|
||||
(env->algorithm == SC_ALGORITHM_EC) ? (temp[0] = 0xa6) : (temp[0] = 0x00);
|
||||
memcpy(temp + 1, in, inlen);
|
||||
in = temp;
|
||||
inlen += 1;
|
||||
|
||||
if (env->operation != SC_SEC_OPERATION_DECIPHER) {
|
||||
/* padding byte: 0xa6 = ECC; 0x00 = RSA; 0x02 = AES */
|
||||
switch (env->algorithm) {
|
||||
case SC_ALGORITHM_RSA:
|
||||
/* This is just PKCS#1.5 start byte and it should be already
|
||||
* provided by the padding routines. But it lets put it here
|
||||
* to make sure it does not conflict with following indicators */
|
||||
temp[0] = 0x00;
|
||||
memcpy(temp + 1, in, inlen);
|
||||
inlen += 1;
|
||||
break;
|
||||
|
||||
case SC_ALGORITHM_EC:
|
||||
case SC_ALGORITHM_XEDDSA:
|
||||
/* Calculate length of External Public Key (0x86) */
|
||||
r = sc_asn1_put_tag(0x86, NULL, inlen, NULL, 0, NULL);
|
||||
if (r <= 0) {
|
||||
free(temp);
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
pklen = r;
|
||||
|
||||
/* Calculate lenght of Public Key DO (0x7F49) */
|
||||
r = sc_asn1_put_tag(0x7f49, NULL, pklen, NULL, 0, NULL);
|
||||
if (r <= 0) {
|
||||
free(temp);
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
dolen = r;
|
||||
|
||||
p = temp;
|
||||
/* This is 0xA6 Cipher DO with associated length field */
|
||||
r = sc_asn1_put_tag(0xA6, NULL, dolen, p, templen - (p - temp), &p);
|
||||
if (r != SC_SUCCESS) {
|
||||
free(temp);
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
|
||||
/* Public Key DO (0x7F49) with associated length field */
|
||||
r = sc_asn1_put_tag(0x7F49, NULL, pklen, p, templen - (p - temp), &p);
|
||||
if (r != SC_SUCCESS) {
|
||||
free(temp);
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
|
||||
/* External Public Key (0x86) with associated length */
|
||||
r = sc_asn1_put_tag(0x86, in, inlen, p, templen - (p - temp), &p);
|
||||
if (r != SC_SUCCESS) {
|
||||
free(temp);
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
inlen = (p - temp);
|
||||
break;
|
||||
case SC_ALGORITHM_AES:
|
||||
/* not supported yet */
|
||||
/*
|
||||
temp[0] = 0x02;
|
||||
memcpy(temp + 1, in, inlen);
|
||||
inlen += 1;
|
||||
*/
|
||||
/* fall through */
|
||||
default:
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
|
||||
}
|
||||
|
||||
in = temp;
|
||||
|
||||
if (env->operation != SC_SEC_OPERATION_DECIPHER &&
|
||||
env->operation != SC_SEC_OPERATION_DERIVE) {
|
||||
free(temp);
|
||||
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
|
||||
"invalid operation");
|
||||
|
@ -2223,7 +2401,8 @@ pgp_update_new_algo_attr(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_
|
|||
if (priv->ext_caps & EXT_CAP_ALG_ATTR_CHANGEABLE) {
|
||||
/* ECDSA and ECDH */
|
||||
if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH
|
||||
|| key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA){
|
||||
|| key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA
|
||||
|| key_info->algorithm == SC_OPENPGP_KEYALGO_EDDSA){
|
||||
data_len = key_info->u.ec.oid_len+1;
|
||||
data = malloc(data_len);
|
||||
if (!data)
|
||||
|
@ -2270,7 +2449,7 @@ pgp_update_new_algo_attr(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_
|
|||
} else {
|
||||
sc_cardctl_openpgp_keygen_info_t old_key_info;
|
||||
|
||||
if (pgp_parse_algo_attr_blob(algo_blob, &old_key_info) != SC_SUCCESS
|
||||
if (pgp_parse_algo_attr_blob(card, algo_blob, &old_key_info) != SC_SUCCESS
|
||||
|| old_key_info.algorithm != key_info->algorithm)
|
||||
LOG_TEST_RET(card->ctx, SC_ERROR_NO_CARD_SUPPORT,
|
||||
"Requested algorithm not supported");
|
||||
|
@ -2427,7 +2606,8 @@ pgp_calculate_and_store_fingerprint(sc_card_t *card, time_t ctime,
|
|||
}
|
||||
/* ECC */
|
||||
else if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH
|
||||
|| key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA) {
|
||||
|| key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA
|
||||
|| key_info->algorithm == SC_OPENPGP_KEYALGO_EDDSA) {
|
||||
/* Algorithm ID, see https://tools.ietf.org/html/rfc6637#section-5 */
|
||||
*p = key_info->algorithm + 6;
|
||||
p += 1;
|
||||
|
@ -2721,6 +2901,9 @@ pgp_gen_key(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_info)
|
|||
&& card->type < SC_CARD_TYPE_OPENPGP_V3
|
||||
&& card->type != SC_CARD_TYPE_OPENPGP_GNUK)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
if (key_info->algorithm == SC_OPENPGP_KEYALGO_EDDSA
|
||||
&& card->type != SC_CARD_TYPE_OPENPGP_GNUK)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
|
||||
/* set Control Reference Template for key */
|
||||
if (key_info->key_id == SC_OPENPGP_KEY_SIGN)
|
||||
|
|
|
@ -184,6 +184,8 @@ struct pgp_priv_data {
|
|||
size_t max_cert_size;
|
||||
size_t max_specialDO_size;
|
||||
|
||||
pgp_ec_curves_t *ec_curves;
|
||||
|
||||
sc_security_env_t sec_env;
|
||||
};
|
||||
|
||||
|
|
|
@ -305,6 +305,7 @@ struct piv_object {
|
|||
};
|
||||
|
||||
/* Must be in order, and one per enumerated PIV_OBJ */
|
||||
// clang-format off
|
||||
static const struct piv_object piv_objects[] = {
|
||||
{ PIV_OBJ_CCC, "Card Capability Container",
|
||||
"2.16.840.1.101.3.7.1.219.0", 3, "\x5F\xC1\x07", "\xDB\x00", 0},
|
||||
|
@ -455,6 +456,7 @@ static const struct piv_object piv_objects[] = {
|
|||
"2.16.840.1.101.3.7.2.9999.120", 2, "\x95\x06", "\x95\x06", PIV_OBJECT_TYPE_PUBKEY},
|
||||
{ PIV_OBJ_LAST_ENUM, "", "", 0, "", "", 0}
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
static struct sc_card_operations piv_ops;
|
||||
|
||||
|
@ -606,14 +608,12 @@ static int piv_generate_key(sc_card_t *card,
|
|||
const u8 *cp;
|
||||
keydata->exponent = 0;
|
||||
|
||||
/* expected tag is 7f49. */
|
||||
/* we will whatever tag is present */
|
||||
|
||||
cp = rbuf;
|
||||
in_len = r;
|
||||
|
||||
/* expected tag is 0x7f49,returned as cla_out == 0x60 and tag_out = 0x1F49 */
|
||||
r = sc_asn1_read_tag(&cp, in_len, &cla_out, &tag_out, &in_len);
|
||||
if (cp == NULL) {
|
||||
if (cp == NULL || in_len == 0 || cla_out != 0x60 || tag_out != 0x1f49) {
|
||||
r = SC_ERROR_ASN1_OBJECT_NOT_FOUND;
|
||||
}
|
||||
if (r != SC_SUCCESS) {
|
||||
|
@ -1030,7 +1030,7 @@ piv_cache_internal_data(sc_card_t *card, int enumtag)
|
|||
priv->obj_cache[enumtag].obj_len,
|
||||
0x53, &bodylen);
|
||||
|
||||
if (body == NULL)
|
||||
if (body == NULL || priv->obj_cache[enumtag].obj_data[0] != 0x53)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OBJECT_NOT_VALID);
|
||||
|
||||
/* get the certificate out */
|
||||
|
@ -1609,7 +1609,7 @@ static int piv_general_mutual_authenticate(sc_card_t *card,
|
|||
/* Remove the encompassing outer TLV of 0x7C and get the data */
|
||||
body = sc_asn1_find_tag(card->ctx, rbuf,
|
||||
r, 0x7C, &body_len);
|
||||
if (!body) {
|
||||
if (!body || rbuf[0] != 0x7C) {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Invalid Witness Data response of NULL\n");
|
||||
r = SC_ERROR_INVALID_DATA;
|
||||
goto err;
|
||||
|
@ -1751,7 +1751,7 @@ static int piv_general_mutual_authenticate(sc_card_t *card,
|
|||
/* Remove the encompassing outer TLV of 0x7C and get the data */
|
||||
body = sc_asn1_find_tag(card->ctx, rbuf,
|
||||
r, 0x7C, &body_len);
|
||||
if(!body) {
|
||||
if(!body || rbuf[0] != 0x7C) {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not find outer tag 0x7C in response");
|
||||
r = SC_ERROR_INVALID_DATA;
|
||||
goto err;
|
||||
|
@ -1912,7 +1912,7 @@ static int piv_general_external_authenticate(sc_card_t *card,
|
|||
/* Remove the encompassing outer TLV of 0x7C and get the data */
|
||||
body = sc_asn1_find_tag(card->ctx, rbuf,
|
||||
r, 0x7C, &body_len);
|
||||
if (!body) {
|
||||
if (!body || rbuf[0] != 0x7C) {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Invalid Challenge Data response of NULL\n");
|
||||
r = SC_ERROR_INVALID_DATA;
|
||||
goto err;
|
||||
|
@ -2077,7 +2077,7 @@ piv_get_serial_nr_from_CHUI(sc_card_t* card, sc_serial_number_t* serial)
|
|||
r = SC_ERROR_INTERNAL;
|
||||
if (rbuflen != 0) {
|
||||
body = sc_asn1_find_tag(card->ctx, rbuf, rbuflen, 0x53, &bodylen); /* Pass the outer wrapper asn1 */
|
||||
if (body != NULL && bodylen != 0) {
|
||||
if (body != NULL && bodylen != 0 && rbuf[0] == 0x53) {
|
||||
fascn = sc_asn1_find_tag(card->ctx, body, bodylen, 0x30, &fascnlen); /* Find the FASC-N data */
|
||||
guid = sc_asn1_find_tag(card->ctx, body, bodylen, 0x34, &guidlen);
|
||||
|
||||
|
@ -2309,10 +2309,10 @@ static int piv_validate_general_authentication(sc_card_t *card,
|
|||
piv_private_data_t * priv = PIV_DATA(card);
|
||||
int r, tmplen, tmplen2;
|
||||
u8 *p;
|
||||
const u8 *tag;
|
||||
const unsigned char *p2;
|
||||
size_t taglen;
|
||||
const u8 *body;
|
||||
size_t bodylen;
|
||||
unsigned int cla, tag;
|
||||
unsigned int real_alg_id, op_tag;
|
||||
|
||||
u8 sbuf[4096]; /* needs work. for 3072 keys, needs 384+10 or so */
|
||||
|
@ -2365,20 +2365,28 @@ static int piv_validate_general_authentication(sc_card_t *card,
|
|||
|
||||
r = piv_general_io(card, 0x87, real_alg_id, priv->key_ref,
|
||||
sbuf, p - sbuf, rbuf, sizeof rbuf);
|
||||
if (r < 0)
|
||||
goto err;
|
||||
|
||||
if (r >= 0) {
|
||||
body = sc_asn1_find_tag(card->ctx, rbuf, r, 0x7c, &bodylen);
|
||||
if (body) {
|
||||
tag = sc_asn1_find_tag(card->ctx, body, bodylen, 0x82, &taglen);
|
||||
if (tag) {
|
||||
memcpy(out, tag, taglen);
|
||||
r = taglen;
|
||||
} else
|
||||
r = SC_ERROR_INVALID_DATA;
|
||||
} else
|
||||
r = SC_ERROR_INVALID_DATA;
|
||||
p2 = rbuf;
|
||||
r = sc_asn1_read_tag(&p2, r, &cla, &tag, &bodylen);
|
||||
if (p2 == NULL || r < 0 || bodylen == 0 || (cla|tag) != 0x7C) {
|
||||
LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_INVALID_DATA, "Can't find 0x7C");
|
||||
}
|
||||
|
||||
r = sc_asn1_read_tag(&p2, bodylen, &cla, &tag, &taglen);
|
||||
if (p2 == NULL || r < 0 || taglen == 0 || (cla|tag) != 0x82) {
|
||||
LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_INVALID_DATA, "Can't find 0x82");
|
||||
}
|
||||
|
||||
if (taglen > outlen) {
|
||||
LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_INVALID_DATA, "data read longer then buffer");
|
||||
}
|
||||
|
||||
memcpy(out, p2, taglen);
|
||||
r = taglen;
|
||||
|
||||
err:
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
|
||||
|
@ -2392,19 +2400,19 @@ piv_compute_signature(sc_card_t *card, const u8 * data, size_t datalen,
|
|||
int i;
|
||||
size_t nLen;
|
||||
u8 rbuf[128]; /* For EC conversions 384 will fit */
|
||||
const u8 * body;
|
||||
size_t bodylen;
|
||||
const u8 * tag;
|
||||
size_t taglen;
|
||||
const unsigned char *pseq, *pint, *ptemp, *pend;
|
||||
unsigned int cla, tag;
|
||||
size_t seqlen;
|
||||
size_t intlen;
|
||||
size_t templen;
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
|
||||
|
||||
/* The PIV returns a DER SEQUENCE{INTEGER, INTEGER}
|
||||
* Which may have leading 00 to force positive
|
||||
* TODO: -DEE should check if PKCS15 want the same
|
||||
* But PKCS11 just wants 2* filed_length in bytes
|
||||
* Which may have leading 00 to force a positive integer
|
||||
* But PKCS11 just wants 2* field_length in bytes
|
||||
* So we have to strip out the integers
|
||||
* if present and pad on left if too short.
|
||||
* and pad on left if too short.
|
||||
*/
|
||||
|
||||
if (priv->alg_id == 0x11 || priv->alg_id == 0x14 ) {
|
||||
|
@ -2422,32 +2430,32 @@ piv_compute_signature(sc_card_t *card, const u8 * data, size_t datalen,
|
|||
if (r < 0)
|
||||
goto err;
|
||||
|
||||
body = sc_asn1_find_tag(card->ctx, rbuf, r, 0x30, &bodylen);
|
||||
pseq = rbuf;
|
||||
r = sc_asn1_read_tag(&pseq, r, &cla, &tag, &seqlen);
|
||||
if (pseq == NULL || r < 0 || seqlen == 0 || (cla|tag) != 0x30)
|
||||
LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_INVALID_DATA, "Can't find 0x30");
|
||||
|
||||
for (i = 0; i<2; i++) {
|
||||
if (body) {
|
||||
tag = sc_asn1_find_tag(card->ctx, body, bodylen, 0x02, &taglen);
|
||||
if (tag) {
|
||||
bodylen -= taglen - (tag - body);
|
||||
body = tag + taglen;
|
||||
pint = pseq;
|
||||
pend = pseq + seqlen;
|
||||
for (i = 0; i < 2; i++) {
|
||||
r = sc_asn1_read_tag(&pint, (pend - pint), &cla, &tag, &intlen);
|
||||
if (pint == NULL || r < 0 || intlen == 0 || (cla|tag) != 0x02)
|
||||
LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_INVALID_DATA, "Can't find 0x02");
|
||||
if (intlen > nLen + 1)
|
||||
LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_INVALID_DATA,"Signature too long");
|
||||
|
||||
if (taglen > nLen) { /* drop leading 00 if present */
|
||||
if (*tag != 0x00) {
|
||||
r = SC_ERROR_INVALID_DATA;
|
||||
goto err;
|
||||
}
|
||||
tag++;
|
||||
taglen--;
|
||||
}
|
||||
memcpy(out + nLen*i + nLen - taglen , tag, taglen);
|
||||
} else {
|
||||
r = SC_ERROR_INVALID_DATA;
|
||||
goto err;
|
||||
ptemp = pint;
|
||||
templen = intlen;
|
||||
if (intlen > nLen) { /* drop leading 00 if present */
|
||||
if (*ptemp != 0x00) {
|
||||
LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_INVALID_DATA,"Signature too long");
|
||||
}
|
||||
} else {
|
||||
r = SC_ERROR_INVALID_DATA;
|
||||
goto err;
|
||||
ptemp++;
|
||||
templen--;
|
||||
}
|
||||
memcpy(out + nLen*i + nLen - templen, ptemp, templen);
|
||||
pint += intlen; /* next integer */
|
||||
|
||||
}
|
||||
r = 2 * nLen;
|
||||
} else { /* RSA is all set */
|
||||
|
@ -2732,7 +2740,7 @@ static int piv_find_discovery(sc_card_t *card)
|
|||
|
||||
/*
|
||||
* During piv_match or piv_card_reader_lock_obtained,
|
||||
* we use the discovery object to test if card present, and
|
||||
* we use the discovery object to test if card present, and
|
||||
* if PIV AID is active. So we can not use the cache
|
||||
*/
|
||||
|
||||
|
@ -3039,8 +3047,8 @@ static int piv_match_card(sc_card_t *card)
|
|||
return 0; /* can not handle the card */
|
||||
}
|
||||
/* its one we know, or we can test for it in piv_init */
|
||||
/*
|
||||
* We will call piv_match_card_continued here then
|
||||
/*
|
||||
* We will call piv_match_card_continued here then
|
||||
* again in piv_init to avoid any issues with passing
|
||||
* anything from piv_match_card
|
||||
* to piv_init as had been done in the past
|
||||
|
@ -3187,7 +3195,7 @@ static int piv_match_card_continued(sc_card_t *card)
|
|||
* Try to avoid doing a select_aid and losing the login state on some cards.
|
||||
* We may get interference on some cards by other drivers trying SELECT_AID before
|
||||
* we get to see if PIV application is still active
|
||||
* putting PIV driver first might help.
|
||||
* putting PIV driver first might help.
|
||||
* This may fail if the wrong AID is active.
|
||||
* Discovery Object introduced in 800-73-3 so will return 0 if found and PIV applet active.
|
||||
* Will fail with SC_ERROR_FILE_NOT_FOUND if 800-73-3 and no Discovery object.
|
||||
|
@ -3264,10 +3272,10 @@ static int piv_match_card_continued(sc_card_t *card)
|
|||
sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d i:%d CI:%08x r:%d\n", card->type, i, priv->card_issues, r);
|
||||
if (i >= 0 && (priv->card_issues & CI_DISCOVERY_USELESS) == 0) {
|
||||
/*
|
||||
* We now know PIV AID is active, test DISCOVERY object again
|
||||
* Some PIV don't support DISCOVERY and return
|
||||
* SC_ERROR_INCORRECT_PARAMETERS. Any error
|
||||
* including SC_ERROR_FILE_NOT_FOUND means we cannot use discovery
|
||||
* We now know PIV AID is active, test DISCOVERY object again
|
||||
* Some PIV don't support DISCOVERY and return
|
||||
* SC_ERROR_INCORRECT_PARAMETERS. Any error
|
||||
* including SC_ERROR_FILE_NOT_FOUND means we cannot use discovery
|
||||
* to test for active AID.
|
||||
*/
|
||||
int i7e = piv_find_discovery(card);
|
||||
|
@ -3350,18 +3358,18 @@ static int piv_init(sc_card_t *card)
|
|||
}
|
||||
|
||||
/*
|
||||
* Set card_issues flags based card->type and version numbers if available.
|
||||
* Set card_issues flags based card->type and version numbers if available.
|
||||
*
|
||||
* YubiKey NEO, Yubikey 4 and other devices with PIV applets, have compliance
|
||||
* issues with the NIST 800-73-3 specs. The OpenSC developers do not have
|
||||
* access to all the different devices or versions of the devices.
|
||||
* Vendor and user input is welcome on any compliance issues.
|
||||
* access to all the different devices or versions of the devices.
|
||||
* Vendor and user input is welcome on any compliance issues.
|
||||
*
|
||||
* For the Yubico devices The assumption is also made that if a bug is
|
||||
* For the Yubico devices The assumption is also made that if a bug is
|
||||
* fixed in a Yubico version that means it is fixed on both NEO and Yubikey 4.
|
||||
*
|
||||
* The flags CI_CANT_USE_GETDATA_FOR_STATE and CI_DISCOVERY_USELESS
|
||||
* may be set earlier or later then in the following code.
|
||||
* may be set earlier or later then in the following code.
|
||||
*/
|
||||
|
||||
sc_debug(card->ctx,SC_LOG_DEBUG_MATCH, "PIV_MATCH card->type:%d CI:%08x r:%d\n", card->type, priv->card_issues, r);
|
||||
|
@ -3463,7 +3471,7 @@ static int piv_init(sc_card_t *card)
|
|||
* We want to process them now as this has information on what
|
||||
* keys and certs the card has and how the pin might be used.
|
||||
* If they fail, ignore it there are optional and introduced in
|
||||
* NIST 800-73-3 and NIST 800-73-2 so some older cards may
|
||||
* NIST 800-73-3 and NIST 800-73-2 so some older cards may
|
||||
* not handle the request.
|
||||
*/
|
||||
piv_process_history(card);
|
||||
|
@ -3626,7 +3634,7 @@ piv_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left)
|
|||
|
||||
/*
|
||||
* If called to check on the login state for a context specific login
|
||||
* return not logged in. Needed because of logic in e6f7373ef066
|
||||
* return not logged in. Needed because of logic in e6f7373ef066
|
||||
*/
|
||||
if (data->pin_type == SC_AC_CONTEXT_SPECIFIC) {
|
||||
data->pin1.logged_in = 0;
|
||||
|
@ -3648,9 +3656,9 @@ piv_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left)
|
|||
|
||||
/*
|
||||
* If this was for a CKU_CONTEXT_SPECFIC login, lock the card one more time.
|
||||
* to avoid any interference from other applications.
|
||||
* Sc_unlock will be called at a later time after the next card command
|
||||
* that should be a crypto operation. If its not then it is a error by the
|
||||
* to avoid any interference from other applications.
|
||||
* Sc_unlock will be called at a later time after the next card command
|
||||
* that should be a crypto operation. If its not then it is a error by the
|
||||
* calling application.
|
||||
*/
|
||||
if (data->cmd == SC_PIN_CMD_VERIFY && data->pin_type == SC_AC_CONTEXT_SPECIFIC) {
|
||||
|
|
|
@ -366,6 +366,19 @@ static int rtecp_logout(sc_card_t *card)
|
|||
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
|
||||
}
|
||||
|
||||
static int rtecp_set_security_env( struct sc_card *card,
|
||||
const struct sc_security_env *env,
|
||||
int se_num)
|
||||
{
|
||||
struct sc_security_env se_env;
|
||||
if(!env)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
se_env= *env;
|
||||
se_env.flags &= ~SC_SEC_ENV_FILE_REF_PRESENT;
|
||||
return iso_ops->set_security_env(card, &se_env, se_num);
|
||||
}
|
||||
|
||||
static int rtecp_cipher(sc_card_t *card, const u8 *data, size_t data_len,
|
||||
u8 *out, size_t out_len, int sign)
|
||||
{
|
||||
|
@ -824,7 +837,7 @@ struct sc_card_driver * sc_get_rtecp_driver(void)
|
|||
rtecp_ops.verify = rtecp_verify;
|
||||
rtecp_ops.logout = rtecp_logout;
|
||||
/* restore_security_env */
|
||||
/* set_security_env */
|
||||
rtecp_ops.set_security_env = rtecp_set_security_env;
|
||||
rtecp_ops.decipher = rtecp_decipher;
|
||||
rtecp_ops.compute_signature = rtecp_compute_signature;
|
||||
rtecp_ops.change_reference_data = rtecp_change_reference_data;
|
||||
|
|
|
@ -718,6 +718,7 @@ static int sc_hsm_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
|
|||
data->pin2.offset = 5;
|
||||
|
||||
r = (*iso_ops->pin_cmd)(card, data, tries_left);
|
||||
data->apdu = NULL;
|
||||
}
|
||||
LOG_TEST_RET(card->ctx, r, "Verification failed");
|
||||
|
||||
|
|
|
@ -654,16 +654,18 @@ static int tcos_decipher(sc_card_t *card, const u8 * crgram, size_t crgram_len,
|
|||
LOG_TEST_RET(ctx, r, "APDU transmit failed");
|
||||
|
||||
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
|
||||
size_t len = (apdu.resplen>outlen) ? outlen : apdu.resplen;
|
||||
size_t len = (apdu.resplen > outlen) ? outlen : apdu.resplen;
|
||||
unsigned int offset = 0;
|
||||
|
||||
if (tcos3 && (data->pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) && apdu.resp[0] == 0 && apdu.resp[1] == 2) {
|
||||
if (tcos3 && (data->pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1)
|
||||
&& len > 2 && apdu.resp[0] == 0 && apdu.resp[1] == 2) {
|
||||
offset = 2;
|
||||
while (offset < len && apdu.resp[offset] != 0)
|
||||
++offset;
|
||||
offset = (offset < len - 1) ? offset + 1 : 0;
|
||||
}
|
||||
memcpy(out, apdu.resp + offset, len-offset);
|
||||
if (offset < len)
|
||||
memcpy(out, apdu.resp + offset, len - offset);
|
||||
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, len - offset);
|
||||
}
|
||||
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
|
||||
|
|
|
@ -805,6 +805,7 @@ static int westcos_pin_cmd(sc_card_t * card, struct sc_pin_cmd_data *data,
|
|||
} else {
|
||||
r = SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
data->apdu = NULL;
|
||||
}
|
||||
if (r)
|
||||
return (r);
|
||||
|
|
|
@ -163,7 +163,7 @@ static void sc_card_free(sc_card_t *card)
|
|||
int i;
|
||||
for (i=0; i<card->algorithm_count; i++) {
|
||||
struct sc_algorithm_info *info = (card->algorithms + i);
|
||||
if (info->algorithm == SC_ALGORITHM_EC) {
|
||||
if (info->algorithm == SC_ALGORITHM_EC) {
|
||||
struct sc_ec_parameters ep = info->u._ec.params;
|
||||
|
||||
free(ep.named_curve);
|
||||
|
@ -1096,16 +1096,18 @@ int _sc_card_add_symmetric_alg(sc_card_t *card, unsigned int algorithm,
|
|||
return _sc_card_add_algorithm(card, &info);
|
||||
}
|
||||
|
||||
int _sc_card_add_ec_alg(sc_card_t *card, unsigned int key_length,
|
||||
static int
|
||||
_sc_card_add_ec_alg_int(sc_card_t *card, unsigned int key_length,
|
||||
unsigned long flags, unsigned long ext_flags,
|
||||
struct sc_object_id *curve_oid)
|
||||
struct sc_object_id *curve_oid,
|
||||
int algorithm)
|
||||
{
|
||||
sc_algorithm_info_t info;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
sc_init_oid(&info.u._ec.params.id);
|
||||
|
||||
info.algorithm = SC_ALGORITHM_EC;
|
||||
info.algorithm = algorithm;
|
||||
info.key_length = key_length;
|
||||
info.flags = flags;
|
||||
|
||||
|
@ -1116,6 +1118,32 @@ int _sc_card_add_ec_alg(sc_card_t *card, unsigned int key_length,
|
|||
return _sc_card_add_algorithm(card, &info);
|
||||
}
|
||||
|
||||
int _sc_card_add_ec_alg(sc_card_t *card, unsigned int key_length,
|
||||
unsigned long flags, unsigned long ext_flags,
|
||||
struct sc_object_id *curve_oid)
|
||||
{
|
||||
return _sc_card_add_ec_alg_int(card, key_length, flags, ext_flags,
|
||||
curve_oid, SC_ALGORITHM_EC);
|
||||
}
|
||||
|
||||
int _sc_card_add_eddsa_alg(sc_card_t *card, unsigned int key_length,
|
||||
unsigned long flags, unsigned long ext_flags,
|
||||
struct sc_object_id *curve_oid)
|
||||
{
|
||||
/* For simplicity, share the ec union with the curve information */
|
||||
return _sc_card_add_ec_alg_int(card, key_length, flags, ext_flags,
|
||||
curve_oid, SC_ALGORITHM_EDDSA);
|
||||
}
|
||||
|
||||
int _sc_card_add_xeddsa_alg(sc_card_t *card, unsigned int key_length,
|
||||
unsigned long flags, unsigned long ext_flags,
|
||||
struct sc_object_id *curve_oid)
|
||||
{
|
||||
/* For simplicity, share the ec union with the curve information */
|
||||
return _sc_card_add_ec_alg_int(card, key_length, flags, ext_flags,
|
||||
curve_oid, SC_ALGORITHM_XEDDSA);
|
||||
}
|
||||
|
||||
sc_algorithm_info_t * sc_card_find_alg(sc_card_t *card,
|
||||
unsigned int algorithm, unsigned int key_length, void *param)
|
||||
{
|
||||
|
@ -1126,13 +1154,15 @@ sc_algorithm_info_t * sc_card_find_alg(sc_card_t *card,
|
|||
|
||||
if (info->algorithm != algorithm)
|
||||
continue;
|
||||
if (param) {
|
||||
if (info->algorithm == SC_ALGORITHM_EC ||
|
||||
info->algorithm == SC_ALGORITHM_EDDSA ||
|
||||
info->algorithm == SC_ALGORITHM_XEDDSA)
|
||||
if (sc_compare_oid((struct sc_object_id *)param, &info->u._ec.params.id))
|
||||
return info;
|
||||
}
|
||||
if (info->key_length != key_length)
|
||||
continue;
|
||||
if (param) {
|
||||
if (info->algorithm == SC_ALGORITHM_EC)
|
||||
if(!sc_compare_oid((struct sc_object_id *)param, &info->u._ec.params.id))
|
||||
continue;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -1144,6 +1174,18 @@ sc_algorithm_info_t * sc_card_find_ec_alg(sc_card_t *card,
|
|||
return sc_card_find_alg(card, SC_ALGORITHM_EC, key_length, curve_name);
|
||||
}
|
||||
|
||||
sc_algorithm_info_t * sc_card_find_eddsa_alg(sc_card_t *card,
|
||||
unsigned int key_length, struct sc_object_id *curve_name)
|
||||
{
|
||||
return sc_card_find_alg(card, SC_ALGORITHM_EDDSA, key_length, curve_name);
|
||||
}
|
||||
|
||||
sc_algorithm_info_t * sc_card_find_xeddsa_alg(sc_card_t *card,
|
||||
unsigned int key_length, struct sc_object_id *curve_name)
|
||||
{
|
||||
return sc_card_find_alg(card, SC_ALGORITHM_XEDDSA, key_length, curve_name);
|
||||
}
|
||||
|
||||
int _sc_card_add_rsa_alg(sc_card_t *card, unsigned int key_length,
|
||||
unsigned long flags, unsigned long exponent)
|
||||
{
|
||||
|
@ -1367,6 +1409,8 @@ scconf_block *sc_get_conf_block(sc_context_t *ctx, const char *name1, const char
|
|||
void sc_invalidate_cache(struct sc_card *card)
|
||||
{
|
||||
if (card) {
|
||||
sc_file_free(card->cache.current_ef);
|
||||
sc_file_free(card->cache.current_df);
|
||||
memset(&card->cache, 0, sizeof(card->cache));
|
||||
card->cache.valid = 0;
|
||||
}
|
||||
|
|
|
@ -974,6 +974,7 @@ typedef struct sc_cardctl_piv_genkey_info_st {
|
|||
#define SC_OPENPGP_KEYALGO_RSA 0x01
|
||||
#define SC_OPENPGP_KEYALGO_ECDH 0x12
|
||||
#define SC_OPENPGP_KEYALGO_ECDSA 0x13
|
||||
#define SC_OPENPGP_KEYALGO_EDDSA 0x16
|
||||
|
||||
#define SC_OPENPGP_KEYFORMAT_RSA_STD 0 /* See 4.3.3.6 Algorithm Attributes */
|
||||
#define SC_OPENPGP_KEYFORMAT_RSA_STDN 1 /* OpenPGP card spec v2 */
|
||||
|
|
|
@ -205,6 +205,8 @@ enum {
|
|||
SC_CARD_TYPE_IASECC_AMOS,
|
||||
SC_CARD_TYPE_IASECC_MI,
|
||||
SC_CARD_TYPE_IASECC_MI2,
|
||||
SC_CARD_TYPE_IASECC_CPX,
|
||||
SC_CARD_TYPE_IASECC_CPXCL,
|
||||
|
||||
/* SmartCard-HSM */
|
||||
SC_CARD_TYPE_SC_HSM = 26000,
|
||||
|
@ -266,6 +268,8 @@ enum {
|
|||
SC_CARD_TYPE_IDPRIME_BASE = 37000,
|
||||
SC_CARD_TYPE_IDPRIME_V1,
|
||||
SC_CARD_TYPE_IDPRIME_V2,
|
||||
SC_CARD_TYPE_IDPRIME_V3,
|
||||
SC_CARD_TYPE_IDPRIME_V4,
|
||||
SC_CARD_TYPE_IDPRIME_GENERIC,
|
||||
|
||||
/* eDO cards */
|
||||
|
|
|
@ -1008,7 +1008,16 @@ int sc_get_cache_dir(sc_context_t *ctx, char *buf, size_t bufsize)
|
|||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
cache_dir = ".eid/cache";
|
||||
#ifdef __APPLE__
|
||||
cache_dir = getenv("Caches");
|
||||
#else
|
||||
cache_dir = getenv("XDG_CACHE_HOME");
|
||||
#endif
|
||||
if (cache_dir != NULL && cache_dir[0] != '\0') {
|
||||
snprintf(buf, bufsize, "%s/%s", cache_dir, "opensc");
|
||||
return SC_SUCCESS;
|
||||
}
|
||||
cache_dir = ".cache/opensc";
|
||||
homedir = getenv("HOME");
|
||||
#else
|
||||
cache_dir = "eid-cache";
|
||||
|
@ -1020,7 +1029,7 @@ int sc_get_cache_dir(sc_context_t *ctx, char *buf, size_t bufsize)
|
|||
homedir = temp_path;
|
||||
}
|
||||
#endif
|
||||
if (homedir == NULL)
|
||||
if (homedir == NULL || homedir[0] == '\0')
|
||||
return SC_ERROR_INTERNAL;
|
||||
if (snprintf(buf, bufsize, "%s/%s", homedir, cache_dir) < 0)
|
||||
return SC_ERROR_BUFFER_TOO_SMALL;
|
||||
|
|
|
@ -405,6 +405,7 @@ static u8 sn_ifd_pin_1[] = { 0xd0, 0x02, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x04 };
|
|||
#define AC_RAIZ_COMPONENTES_ISSUER "/C=ES/O=DIRECCION GENERAL DE LA POLICIA/OU=DNIE/OU=AC RAIZ COMPONENTES/CN=000000006573524449600006"
|
||||
#define AC_RAIZ_COMPONENTES_2_NEW_IDX 1
|
||||
#define AC_RAIZ_COMPONENTES_2_ISSUER "/C=ES/O=DIRECCION GENERAL DE LA POLICIA/OU=DNIE/organizationIdentifier=VATES-S2816015H/OU=AC RAIZ COMPONENTES 2/CN=000000006573524449620018"
|
||||
#define AC_RAIZ_COMPONENTES_2_ISSUER_OU "/OU=AC RAIZ COMPONENTES 2/"
|
||||
|
||||
/**
|
||||
* The DNIe secure channel uses some static configuration.
|
||||
|
@ -649,7 +650,7 @@ static int dnie_set_channel_data(sc_card_t * card, X509 * icc_intermediate_ca_ce
|
|||
sc_log(card->ctx, "icc_intermediate_ca_cert issuer %s", buf);
|
||||
}
|
||||
|
||||
if (buf && strcmp(buf, AC_RAIZ_COMPONENTES_2_ISSUER) == 0) {
|
||||
if (buf && strstr(buf, AC_RAIZ_COMPONENTES_2_ISSUER_OU)) {
|
||||
sc_log(card->ctx, "assigning new data channel configuration");
|
||||
priv_data->channel_data = &channel_data[AC_RAIZ_COMPONENTES_2_NEW_IDX];
|
||||
} else {
|
||||
|
|
|
@ -519,8 +519,8 @@ static int cwa_internal_auth(sc_card_t * card, u8 * sig, size_t sig_len, u8 * da
|
|||
* @return SC_SUCCESS if ok; else errorcode
|
||||
*/
|
||||
static int cwa_prepare_external_auth(sc_card_t * card,
|
||||
RSA * icc_pubkey,
|
||||
RSA * ifd_privkey,
|
||||
const RSA * icc_pubkey,
|
||||
const RSA * ifd_privkey,
|
||||
u8 * sig,
|
||||
size_t sig_len)
|
||||
{
|
||||
|
@ -594,7 +594,7 @@ static int cwa_prepare_external_auth(sc_card_t * card,
|
|||
buf3[127] = 0xBC; /* iso padding */
|
||||
|
||||
/* encrypt with ifd private key */
|
||||
len2 = RSA_private_decrypt(128, buf3, buf2, ifd_privkey, RSA_NO_PADDING);
|
||||
len2 = RSA_private_decrypt(128, buf3, buf2, (RSA *)ifd_privkey, RSA_NO_PADDING);
|
||||
if (len2 < 0) {
|
||||
msg = "Prepare external auth: ifd_privk encrypt failed";
|
||||
res = SC_ERROR_SM_ENCRYPT_FAILED;
|
||||
|
@ -630,7 +630,7 @@ static int cwa_prepare_external_auth(sc_card_t * card,
|
|||
}
|
||||
|
||||
/* re-encrypt result with icc public key */
|
||||
len1 = RSA_public_encrypt(len3, buf3, buf1, icc_pubkey, RSA_NO_PADDING);
|
||||
len1 = RSA_public_encrypt(len3, buf3, buf1, (RSA *)icc_pubkey, RSA_NO_PADDING);
|
||||
if (len1 <= 0 || (size_t) len1 != sig_len) {
|
||||
msg = "Prepare external auth: icc_pubk encrypt failed";
|
||||
res = SC_ERROR_SM_ENCRYPT_FAILED;
|
||||
|
@ -842,8 +842,8 @@ static int cwa_compare_signature(u8 * data, size_t dlen, u8 * ifd_data)
|
|||
* @return SC_SUCCESS if ok; else error code
|
||||
*/
|
||||
static int cwa_verify_internal_auth(sc_card_t * card,
|
||||
RSA * icc_pubkey,
|
||||
RSA * ifd_privkey,
|
||||
const RSA * icc_pubkey,
|
||||
const RSA * ifd_privkey,
|
||||
u8 * ifdbuf,
|
||||
size_t ifdlen,
|
||||
u8 * sig,
|
||||
|
@ -901,7 +901,7 @@ static int cwa_verify_internal_auth(sc_card_t * card,
|
|||
*/
|
||||
|
||||
/* decrypt data with our ifd priv key */
|
||||
len1 = RSA_private_decrypt(sig_len, sig, buf1, ifd_privkey, RSA_NO_PADDING);
|
||||
len1 = RSA_private_decrypt(sig_len, sig, buf1, (RSA *)ifd_privkey, RSA_NO_PADDING);
|
||||
if (len1 <= 0) {
|
||||
msg = "Verify Signature: decrypt with ifd privk failed";
|
||||
res = SC_ERROR_SM_ENCRYPT_FAILED;
|
||||
|
@ -911,7 +911,7 @@ static int cwa_verify_internal_auth(sc_card_t * card,
|
|||
/* OK: now we have SIGMIN in buf1 */
|
||||
/* check if SIGMIN data matches SIG or N.ICC-SIG */
|
||||
/* evaluate DS[SK.ICC.AUTH](SIG) trying to decrypt with icc pubk */
|
||||
len3 = RSA_public_encrypt(len1, buf1, buf3, icc_pubkey, RSA_NO_PADDING);
|
||||
len3 = RSA_public_encrypt(len1, buf1, buf3, (RSA *) icc_pubkey, RSA_NO_PADDING);
|
||||
if (len3 <= 0)
|
||||
goto verify_nicc_sig; /* evaluate N.ICC-SIG and retry */
|
||||
res = cwa_compare_signature(buf3, len3, ifdbuf);
|
||||
|
@ -945,7 +945,7 @@ static int cwa_verify_internal_auth(sc_card_t * card,
|
|||
}
|
||||
/* ok: check again with new data */
|
||||
/* evaluate DS[SK.ICC.AUTH](I.ICC-SIG) trying to decrypt with icc pubk */
|
||||
len3 = RSA_public_encrypt(len2, buf2, buf3, icc_pubkey, RSA_NO_PADDING);
|
||||
len3 = RSA_public_encrypt(len2, buf2, buf3, (RSA *)icc_pubkey, RSA_NO_PADDING);
|
||||
if (len3 <= 0) {
|
||||
msg = "Verify Signature: cannot get valid SIG data";
|
||||
res = SC_ERROR_INVALID_DATA;
|
||||
|
|
|
@ -39,7 +39,11 @@ static const struct app_entry apps[] = {
|
|||
{ (const u8 *) "\xA0\x00\x00\x00\x63PKCS-15", 12, "PKCS #15" },
|
||||
{ (const u8 *) "\xA0\x00\x00\x01\x77PKCS-15", 12, "Belgian eID" },
|
||||
{ (const u8 *) "\x44\x46\x20\x69\x73\x73\x75\x65\x72", 9, "Portugal eID" },
|
||||
{ (const u8 *) "\xE8\x28\xBD\x08\x0F\xA0\x00\x00\x01\x67\x45\x53\x49\x47\x4E", 15, "ESIGN"}
|
||||
{ (const u8 *) "\xE8\x28\xBD\x08\x0F\xA0\x00\x00\x01\x67\x45\x53\x49\x47\x4E", 15, "ESIGN"},
|
||||
{ (const u8 *) "\xE8\x28\xBD\x08\x0F\x80\x25\x00\x00\x01\xFF\x00\x10", 13, "CPx IAS"},
|
||||
{ (const u8 *) "\xE8\x28\xBD\x08\x0F\x80\x25\x00\x00\x01\xFF\x00\x20", 13, "CPx IAS CL"},
|
||||
{ (const u8 *) "\xE8\x28\xBD\x08\x0F\xD2\x50\x45\x43\x43\x2D\x65\x49\x44", 14, "ECC eID"},
|
||||
{ (const u8 *) "\xE8\x28\xBD\x08\x0F\xD2\x50\x47\x65\x6E\x65\x72\x69\x63", 14, "ECC Generic PKI"},
|
||||
};
|
||||
|
||||
static const struct sc_asn1_entry c_asn1_dirrecord[] = {
|
||||
|
|
|
@ -143,6 +143,7 @@ int sc_parse_ef_atr(struct sc_card *card)
|
|||
int rv;
|
||||
unsigned char *buf = NULL;
|
||||
size_t size;
|
||||
size_t off = 0;
|
||||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
|
||||
|
@ -162,8 +163,16 @@ int sc_parse_ef_atr(struct sc_card *card)
|
|||
}
|
||||
rv = sc_read_binary(card, 0, buf, size, 0);
|
||||
LOG_TEST_GOTO_ERR(ctx, rv, "Cannot read EF(ATR) file");
|
||||
|
||||
rv = sc_parse_ef_atr_content(card, buf, rv);
|
||||
|
||||
/* Workaround: Some cards seem to have a buggy storage of the EF.ATR */
|
||||
if ((card->type == SC_CARD_TYPE_IASECC_CPX) ||
|
||||
(card->type == SC_CARD_TYPE_IASECC_CPXCL)) {
|
||||
/* Let's keep the first byte */
|
||||
if ((rv > 1) &&
|
||||
(buf[0] == ISO7816_II_CATEGORY_TLV))
|
||||
off++;
|
||||
}
|
||||
rv = sc_parse_ef_atr_content(card, buf + off, rv - off);
|
||||
LOG_TEST_GOTO_ERR(ctx, rv, "EF(ATR) parse error");
|
||||
|
||||
rv = SC_SUCCESS;
|
||||
|
|
|
@ -133,4 +133,5 @@ struct iasecc_private_data {
|
|||
|
||||
struct iasecc_se_info *se_info;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -93,6 +93,7 @@ typedef unsigned __int8 uint8_t;
|
|||
#define SCARD_S_SUCCESS 0x00000000 /**< No error was encountered. */
|
||||
#define SCARD_E_CANCELLED 0x80100002 /**< The action was cancelled by an SCardCancel request. */
|
||||
#define SCARD_E_INVALID_HANDLE 0x80100003 /**< The supplied handle was invalid. */
|
||||
#define SCARD_E_UNKNOWN_READER 0x80100009 /**< The specified reader name is not recognized. */
|
||||
#define SCARD_E_TIMEOUT 0x8010000A /**< The user-specified timeout value has expired. */
|
||||
#define SCARD_E_SHARING_VIOLATION 0x8010000B /**< The smart card cannot be accessed because of other connections outstanding. */
|
||||
#define SCARD_E_NO_SMARTCARD 0x8010000C /**< The operation requires a smart card, but no smart card is currently in the device. */
|
||||
|
|
|
@ -153,6 +153,12 @@ int _sc_card_add_rsa_alg(struct sc_card *card, unsigned int key_length,
|
|||
int _sc_card_add_ec_alg(struct sc_card *card, unsigned int key_length,
|
||||
unsigned long flags, unsigned long ext_flags,
|
||||
struct sc_object_id *curve_oid);
|
||||
int _sc_card_add_eddsa_alg(struct sc_card *card, unsigned int key_length,
|
||||
unsigned long flags, unsigned long ext_flags,
|
||||
struct sc_object_id *curve_oid);
|
||||
int _sc_card_add_xeddsa_alg(struct sc_card *card, unsigned int key_length,
|
||||
unsigned long flags, unsigned long ext_flags,
|
||||
struct sc_object_id *curve_oid);
|
||||
|
||||
/********************************************************************/
|
||||
/* pkcs1 padding/encoding functions */
|
||||
|
|
|
@ -172,6 +172,9 @@ iso7816_read_record(struct sc_card *card,
|
|||
struct sc_apdu apdu;
|
||||
int r;
|
||||
|
||||
if (rec_nr > 0xFF)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0xB2, rec_nr, 0);
|
||||
apdu.le = count;
|
||||
apdu.resplen = count;
|
||||
|
@ -328,6 +331,8 @@ iso7816_process_fci(struct sc_card *card, struct sc_file *file,
|
|||
size_t length;
|
||||
int size;
|
||||
|
||||
file->status = SC_FILE_STATUS_UNKNOWN;
|
||||
|
||||
for (p = buf, length = buflen, end = buf + buflen;
|
||||
p < end;
|
||||
p += length, length = end - p) {
|
||||
|
@ -448,12 +453,48 @@ iso7816_process_fci(struct sc_card *card, struct sc_file *file,
|
|||
|
||||
case 0x8A:
|
||||
if (length == 1) {
|
||||
if (p[0] == 0x01)
|
||||
file->status = SC_FILE_STATUS_CREATION;
|
||||
else if (p[0] == 0x07 || p[0] == 0x05)
|
||||
file->status = SC_FILE_STATUS_ACTIVATED;
|
||||
else if (p[0] == 0x06 || p[0] == 0x04)
|
||||
file->status = SC_FILE_STATUS_INVALIDATED;
|
||||
switch (p[0]) {
|
||||
case 0:
|
||||
file->status =SC_FILE_STATUS_NO_INFO;
|
||||
break;
|
||||
case 1:
|
||||
file->status = SC_FILE_STATUS_CREATION;
|
||||
break;
|
||||
case 3:
|
||||
file->status = SC_FILE_STATUS_INITIALISATION;
|
||||
break;
|
||||
case 4:
|
||||
case 6:
|
||||
file->status = SC_FILE_STATUS_INVALIDATED;
|
||||
break;
|
||||
case 5:
|
||||
case 7:
|
||||
file->status = SC_FILE_STATUS_ACTIVATED;
|
||||
break;
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
file->status = SC_FILE_STATUS_TERMINATION;
|
||||
break;
|
||||
case 2:
|
||||
file->status = SC_FILE_STATUS_RFU_2;
|
||||
break;
|
||||
case 8:
|
||||
file->status = SC_FILE_STATUS_RFU_8;
|
||||
break;
|
||||
case 9:
|
||||
file->status = SC_FILE_STATUS_RFU_9;
|
||||
break;
|
||||
case 10:
|
||||
file->status = SC_FILE_STATUS_RFU_10;
|
||||
break;
|
||||
case 11:
|
||||
file->status = SC_FILE_STATUS_RFU_11;
|
||||
break;
|
||||
default:
|
||||
file->status = SC_FILE_STATUS_PROPRIETARY;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -114,7 +114,6 @@ sc_bytes2apdu
|
|||
sc_format_asn1_entry
|
||||
sc_format_oid
|
||||
sc_init_oid
|
||||
sc_compare_oid
|
||||
sc_valid_oid
|
||||
sc_format_path
|
||||
sc_free_apps
|
||||
|
@ -150,8 +149,6 @@ sc_pkcs15_cache_file
|
|||
sc_pkcs15_card_clear
|
||||
sc_pkcs15_card_free
|
||||
sc_pkcs15_card_new
|
||||
sc_pkcs15_tokeninfo_new
|
||||
sc_pkcs15_free_tokeninfo
|
||||
sc_pkcs15_change_pin
|
||||
sc_pkcs15_compare_id
|
||||
sc_pkcs15_compute_signature
|
||||
|
@ -178,6 +175,7 @@ sc_pkcs15_encode_pubkey
|
|||
sc_pkcs15_encode_pubkey_dsa
|
||||
sc_pkcs15_encode_pubkey_rsa
|
||||
sc_pkcs15_encode_pubkey_ec
|
||||
sc_pkcs15_encode_pubkey_eddsa
|
||||
sc_pkcs15_encode_pubkey_gostr3410
|
||||
sc_pkcs15_encode_pubkey_as_spki
|
||||
sc_pkcs15_encode_pukdf_entry
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "internal.h"
|
||||
|
||||
static void sc_do_log_va(sc_context_t *ctx, int level, const char *file, int line, const char *func, int color, const char *format, va_list args);
|
||||
static int sc_color_fprintf_va(int colors, struct sc_context *ctx, FILE * stream, const char *format, va_list args);
|
||||
|
||||
void sc_do_log(sc_context_t *ctx, int level, const char *file, int line, const char *func, const char *format, ...)
|
||||
{
|
||||
|
@ -74,7 +75,6 @@ void sc_do_log_noframe(sc_context_t *ctx, int level, const char *format, va_list
|
|||
|
||||
static void sc_do_log_va(sc_context_t *ctx, int level, const char *file, int line, const char *func, int color, const char *format, va_list args)
|
||||
{
|
||||
char buf[4096];
|
||||
#ifdef _WIN32
|
||||
SYSTEMTIME st;
|
||||
#else
|
||||
|
@ -142,11 +142,9 @@ static void sc_do_log_va(sc_context_t *ctx, int level, const char *file, int lin
|
|||
file, line, func ? func : "");
|
||||
}
|
||||
|
||||
if (vsnprintf(buf, sizeof buf, format, args) >= 0) {
|
||||
sc_color_fprintf(color, ctx, ctx->debug_file, "%s", buf);
|
||||
if (strlen(buf) == 0 || buf[strlen(buf)-1] != '\n')
|
||||
sc_color_fprintf(color, ctx, ctx->debug_file, "\n");
|
||||
}
|
||||
sc_color_fprintf_va(color, ctx, ctx->debug_file, format, args);
|
||||
if (strlen(format) == 0 || format[strlen(format) - 1] != '\n')
|
||||
sc_color_fprintf(color, ctx, ctx->debug_file, "\n");
|
||||
fflush(ctx->debug_file);
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -202,7 +200,18 @@ static int is_a_tty(FILE *fp)
|
|||
|
||||
int sc_color_fprintf(int colors, struct sc_context *ctx, FILE * stream, const char * format, ...)
|
||||
{
|
||||
int r;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
r = sc_color_fprintf_va(colors, ctx, stream, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int sc_color_fprintf_va(int colors, struct sc_context *ctx, FILE * stream, const char *format, va_list args)
|
||||
{
|
||||
int r;
|
||||
#ifdef _WIN32
|
||||
WORD old_attr = 0;
|
||||
|
@ -264,9 +273,7 @@ int sc_color_fprintf(int colors, struct sc_context *ctx, FILE * stream, const ch
|
|||
#endif
|
||||
}
|
||||
|
||||
va_start(ap, format);
|
||||
r = vfprintf(stream, format, ap);
|
||||
va_end(ap);
|
||||
r = vfprintf(stream, format, args);
|
||||
|
||||
if (colors && (!ctx || (!(ctx->flags & SC_CTX_FLAG_DISABLE_COLORS)))) {
|
||||
#ifdef _WIN32
|
||||
|
|
|
@ -78,6 +78,8 @@ extern "C" {
|
|||
#define SC_ALGORITHM_DSA 1
|
||||
#define SC_ALGORITHM_EC 2
|
||||
#define SC_ALGORITHM_GOSTR3410 3
|
||||
#define SC_ALGORITHM_EDDSA 4
|
||||
#define SC_ALGORITHM_XEDDSA 5
|
||||
|
||||
/* Symmetric algorithms */
|
||||
#define SC_ALGORITHM_DES 64
|
||||
|
@ -189,6 +191,10 @@ extern "C" {
|
|||
SC_ALGORITHM_ECDSA_HASH_SHA384 | \
|
||||
SC_ALGORITHM_ECDSA_HASH_SHA512)
|
||||
|
||||
/* EdDSA algorithms */
|
||||
#define SC_ALGORITHM_EDDSA_RAW 0x00400000
|
||||
#define SC_ALGORITHM_XEDDSA_RAW 0x00800000
|
||||
|
||||
/* define mask of all algorithms that can do raw */
|
||||
#define SC_ALGORITHM_RAW_MASK (SC_ALGORITHM_RSA_RAW | \
|
||||
SC_ALGORITHM_GOSTR3410_RAW | \
|
||||
|
@ -1555,6 +1561,10 @@ struct sc_algorithm_info * sc_card_find_rsa_alg(struct sc_card *card,
|
|||
unsigned int key_length);
|
||||
struct sc_algorithm_info * sc_card_find_ec_alg(struct sc_card *card,
|
||||
unsigned int field_length, struct sc_object_id *curve_oid);
|
||||
struct sc_algorithm_info * sc_card_find_eddsa_alg(struct sc_card *card,
|
||||
unsigned int field_length, struct sc_object_id *curve_oid);
|
||||
struct sc_algorithm_info * sc_card_find_xeddsa_alg(struct sc_card *card,
|
||||
unsigned int field_length, struct sc_object_id *curve_oid);
|
||||
struct sc_algorithm_info * sc_card_find_gostr3410_alg(struct sc_card *card,
|
||||
unsigned int key_length);
|
||||
struct sc_algorithm_info * sc_card_find_alg(sc_card_t *card,
|
||||
|
|
|
@ -143,7 +143,7 @@ CERT_HANDLE_FUNCTION(default_cert_handle) {
|
|||
int r;
|
||||
X509 *cert_data = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
RSA * rsa = NULL;
|
||||
const RSA * rsa = NULL;
|
||||
int certtype = 0;
|
||||
int modulus_len = 0;
|
||||
const prdata* key = get_prkey_by_cert(items, cert);
|
||||
|
|
|
@ -491,6 +491,8 @@ int sc_get_encoding_flags(sc_context_t *ctx,
|
|||
} else if ((caps & SC_ALGORITHM_RSA_PAD_PSS) &&
|
||||
(iflags & SC_ALGORITHM_RSA_PAD_PSS)) {
|
||||
*sflags |= SC_ALGORITHM_RSA_PAD_PSS;
|
||||
*sflags |= iflags & SC_ALGORITHM_MGF1_HASHES;
|
||||
*pflags = iflags & ~(iflags & (SC_ALGORITHM_MGF1_HASHES | SC_ALGORITHM_RSA_PAD_PSS));
|
||||
|
||||
} else if ((caps & SC_ALGORITHM_RSA_RAW) &&
|
||||
(iflags & SC_ALGORITHM_RSA_PAD_PKCS1
|
||||
|
|
|
@ -412,7 +412,6 @@ static struct sc_asn1_pkcs15_algorithm_info algorithm_table[] = {
|
|||
asn1_encode_pbes2_params,
|
||||
asn1_free_pbes2_params },
|
||||
#endif
|
||||
|
||||
#ifdef SC_ALGORITHM_EC
|
||||
{ SC_ALGORITHM_EC, {{ 1, 2, 840, 10045, 2, 1, -1}},
|
||||
asn1_decode_ec_params,
|
||||
|
@ -448,6 +447,16 @@ static struct sc_asn1_pkcs15_algorithm_info algorithm_table[] = {
|
|||
asn1_decode_ec_params,
|
||||
asn1_encode_ec_params,
|
||||
asn1_free_ec_params },
|
||||
#endif
|
||||
#ifdef SC_ALGORITHM_EDDSA
|
||||
/* aka Ed25519 */
|
||||
/* RFC 8410, needed to parse/create X509 certs/pubkeys */
|
||||
{ SC_ALGORITHM_EDDSA, {{1, 3, 101, 112, -1}}, NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef SC_ALGORITHM_XEDDSA
|
||||
/* aka curve25519 */
|
||||
/* RFC 8410, needed to parse/create X509 certs/pubkeys */
|
||||
{ SC_ALGORITHM_XEDDSA, {{1, 3, 101, 110, -1}}, NULL, NULL, NULL },
|
||||
#endif
|
||||
{ -1, {{ -1 }}, NULL, NULL, NULL }
|
||||
};
|
||||
|
@ -545,7 +554,11 @@ sc_asn1_encode_algorithm_id(struct sc_context *ctx, u8 **buf, size_t *len,
|
|||
sc_format_asn1_entry(asn1_alg_id + 0, (void *) &id->oid, NULL, 1);
|
||||
|
||||
/* no parameters, write NULL tag */
|
||||
if (!id->params || !alg_info->encode)
|
||||
/* If it's EDDSA/XEDDSA, according to RFC8410, params
|
||||
* MUST be absent */
|
||||
if (id->algorithm != SC_ALGORITHM_EDDSA &&
|
||||
id->algorithm != SC_ALGORITHM_XEDDSA &&
|
||||
(!id->params || !alg_info->encode))
|
||||
asn1_alg_id[1].flags |= SC_ASN1_PRESENT;
|
||||
|
||||
r = _sc_asn1_encode(ctx, asn1_alg_id, buf, len, depth + 1);
|
||||
|
|
|
@ -425,7 +425,8 @@ coolkey_get_public_key_from_certificate(sc_pkcs15_card_t *p15card, sc_cardctl_co
|
|||
sc_pkcs15_pubkey_t *key = NULL;
|
||||
int r;
|
||||
|
||||
cert_info.value.value = NULL;
|
||||
memset(&cert_info, 0, sizeof(cert_info));
|
||||
|
||||
r = coolkey_get_certificate(p15card->card, obj, &cert_info.value);
|
||||
if (r < 0) {
|
||||
goto fail;
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
#include "internal.h"
|
||||
#include "pkcs15.h"
|
||||
#include "../pkcs15init/pkcs15-iasecc.h"
|
||||
#include "iasecc.h"
|
||||
#include "aux-data.h"
|
||||
|
||||
|
@ -103,6 +104,38 @@ _iasecc_md_update_keyinfo(struct sc_pkcs15_card *p15card, struct sc_pkcs15_objec
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* CPx cards have an undocumented issue: they lack of
|
||||
* Algorithm's reference into their PKCS's ASN1 encoding.
|
||||
*/
|
||||
static int
|
||||
_iasecc_cpx_fixup_prkdf(struct sc_pkcs15_card *p15card)
|
||||
{
|
||||
struct sc_context * const ctx = p15card->card->ctx;
|
||||
struct sc_pkcs15_object *pkobjs[32];
|
||||
int ii, count;
|
||||
int rv = SC_SUCCESS;
|
||||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
|
||||
rv = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PRKEY, pkobjs, sizeof(pkobjs)/sizeof(pkobjs[0]));
|
||||
LOG_TEST_RET(ctx, rv, "Cannot get PRKEY objects list");
|
||||
|
||||
count = rv;
|
||||
for(ii=0; ii<count; ii++) {
|
||||
rv = iasecc_pkcs15_encode_supported_algos(p15card, pkobjs[ii]);
|
||||
LOG_TEST_RET(ctx, rv, "Cannot fix suported_algos");
|
||||
}
|
||||
|
||||
LOG_FUNC_RETURN(ctx, rv);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* It is the entry point for 2 models of cards that need some hot patching
|
||||
* - Gemalto cards
|
||||
* - CPx: fixup algo_refs from the prkey
|
||||
*/
|
||||
static int
|
||||
_iasecc_parse_df(struct sc_pkcs15_card *p15card, struct sc_pkcs15_df *df)
|
||||
{
|
||||
|
@ -122,14 +155,29 @@ _iasecc_parse_df(struct sc_pkcs15_card *p15card, struct sc_pkcs15_df *df)
|
|||
rv = sc_pkcs15_parse_df(p15card, df);
|
||||
LOG_TEST_RET(ctx, rv, "DF parse error");
|
||||
|
||||
if (p15card->card->type != SC_CARD_TYPE_IASECC_GEMALTO)
|
||||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||
switch(p15card->card->type) {
|
||||
/* enumerate the IASECC cards that need a fixup of the keyInfo */
|
||||
case SC_CARD_TYPE_IASECC_GEMALTO:
|
||||
case SC_CARD_TYPE_IASECC_CPX:
|
||||
case SC_CARD_TYPE_IASECC_CPXCL:
|
||||
sc_log(ctx, "Warning: the %d card has an invalid DF, hot patch to be applied",
|
||||
p15card->card->type);
|
||||
break;
|
||||
default:
|
||||
sc_log(ctx, "the %d card has a proper DF, no need for a hot patch",
|
||||
p15card->card->type);
|
||||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||
break;
|
||||
}
|
||||
|
||||
if (df->type != SC_PKCS15_PRKDF)
|
||||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||
|
||||
sc_log(ctx, "parse of SC_PKCS15_PRKDF");
|
||||
|
||||
rv = _iasecc_cpx_fixup_prkdf(p15card);
|
||||
LOG_TEST_RET(ctx, rv, "Cannot fixup PrKDF");
|
||||
|
||||
rv = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_DATA_OBJECT, dobjs, sizeof(dobjs)/sizeof(dobjs[0]));
|
||||
LOG_TEST_RET(ctx, rv, "Cannot get DATA objects list");
|
||||
|
||||
|
|
|
@ -98,6 +98,13 @@ static int sc_pkcs15emu_idprime_init(sc_pkcs15_card_t *p15card)
|
|||
pin_info.attrs.pin.max_length = 16;
|
||||
pin_info.tries_left = -1;
|
||||
|
||||
if (card->type == SC_CARD_TYPE_IDPRIME_V3 ||
|
||||
card->type == SC_CARD_TYPE_IDPRIME_V4) {
|
||||
pin_info.attrs.pin.flags |= SC_PKCS15_PIN_FLAG_NEEDS_PADDING;
|
||||
pin_info.attrs.pin.stored_length = 16;
|
||||
pin_info.attrs.pin.pad_char = 0x00;
|
||||
}
|
||||
|
||||
sc_log(card->ctx, "IDPrime Adding pin with label=%s", pin_label);
|
||||
strncpy(pin_obj.label, pin_label, SC_PKCS15_MAX_LABEL_SIZE - 1);
|
||||
pin_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;
|
||||
|
|
|
@ -211,6 +211,7 @@ sc_oberthur_get_certificate_authority(struct sc_pkcs15_der *der, int *out_author
|
|||
|
||||
BIO_set_mem_buf(bio, &buf_mem, BIO_NOCLOSE);
|
||||
x = d2i_X509_bio(bio, 0);
|
||||
free(buf_mem.data);
|
||||
BIO_free(bio);
|
||||
if (!x)
|
||||
return SC_ERROR_INVALID_DATA;
|
||||
|
@ -304,7 +305,7 @@ sc_oberthur_read_file(struct sc_pkcs15_card *p15card, const char *in_path,
|
|||
if (verify_pin && rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) {
|
||||
struct sc_pkcs15_object *objs[0x10], *pin_obj = NULL;
|
||||
const struct sc_acl_entry *acl = sc_file_get_acl_entry(file, SC_AC_OP_READ);
|
||||
int ii;
|
||||
int ii, nobjs;
|
||||
|
||||
if (acl == NULL) {
|
||||
sc_file_free(file);
|
||||
|
@ -313,18 +314,19 @@ sc_oberthur_read_file(struct sc_pkcs15_card *p15card, const char *in_path,
|
|||
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
|
||||
}
|
||||
|
||||
rv = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, 0x10);
|
||||
if (rv != SC_SUCCESS) {
|
||||
nobjs = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, 0x10);
|
||||
if (nobjs < 1) {
|
||||
sc_file_free(file);
|
||||
free(*out);
|
||||
*out = NULL;
|
||||
LOG_TEST_RET(ctx, rv, "Cannot read oberthur file: get AUTH objects error");
|
||||
LOG_TEST_RET(ctx, SC_ERROR_DATA_OBJECT_NOT_FOUND,
|
||||
"Cannot read oberthur file: get AUTH objects error");
|
||||
}
|
||||
|
||||
for (ii=0; ii<rv; ii++) {
|
||||
for (ii = 0; ii < nobjs; ii++) {
|
||||
struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *) objs[ii]->data;
|
||||
sc_log(ctx, "compare PIN/ACL refs:%i/%i, method:%i/%i",
|
||||
auth_info->attrs.pin.reference, acl->key_ref, auth_info->auth_method, acl->method);
|
||||
auth_info->attrs.pin.reference, acl->key_ref, auth_info->auth_method, acl->method);
|
||||
if (auth_info->attrs.pin.reference == (int)acl->key_ref && auth_info->auth_method == (unsigned)acl->method) {
|
||||
pin_obj = objs[ii];
|
||||
break;
|
||||
|
@ -574,7 +576,7 @@ sc_pkcs15emu_oberthur_add_pubkey(struct sc_pkcs15_card *p15card,
|
|||
struct sc_pkcs15_pubkey_info key_info;
|
||||
struct sc_pkcs15_object key_obj;
|
||||
char ch_tmp[0x100];
|
||||
unsigned char *info_blob;
|
||||
unsigned char *info_blob = NULL;
|
||||
size_t len, info_len, offs;
|
||||
unsigned flags;
|
||||
int rv;
|
||||
|
@ -591,8 +593,10 @@ sc_pkcs15emu_oberthur_add_pubkey(struct sc_pkcs15_card *p15card,
|
|||
|
||||
/* Flags */
|
||||
offs = 2;
|
||||
if (offs > info_len)
|
||||
if (offs > info_len) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add public key: no 'tag'");
|
||||
}
|
||||
flags = *(info_blob + 0) * 0x100 + *(info_blob + 1);
|
||||
key_info.usage = sc_oberthur_decode_usage(flags);
|
||||
if (flags & OBERTHUR_ATTR_MODIFIABLE)
|
||||
|
@ -600,10 +604,15 @@ sc_pkcs15emu_oberthur_add_pubkey(struct sc_pkcs15_card *p15card,
|
|||
sc_log(ctx, "Public key key-usage:%04X", key_info.usage);
|
||||
|
||||
/* Label */
|
||||
if (offs + 2 > info_len)
|
||||
if (offs + 2 > info_len) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add public key: no 'Label'");
|
||||
}
|
||||
len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
|
||||
if (len) {
|
||||
if (offs + 2 + len > info_len) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Failed to add public key: invalid 'Label' length");
|
||||
} else if (len) {
|
||||
if (len > sizeof(key_obj.label) - 1)
|
||||
len = sizeof(key_obj.label) - 1;
|
||||
memcpy(key_obj.label, info_blob + offs + 2, len);
|
||||
|
@ -611,14 +620,22 @@ sc_pkcs15emu_oberthur_add_pubkey(struct sc_pkcs15_card *p15card,
|
|||
offs += 2 + len;
|
||||
|
||||
/* ID */
|
||||
if (offs > info_len)
|
||||
if (offs + 2 > info_len) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add public key: no 'ID'");
|
||||
}
|
||||
len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
|
||||
if (!len || len > sizeof(key_info.id.value))
|
||||
if (len == 0
|
||||
|| len > sizeof(key_info.id.value)
|
||||
|| offs + 2 + len > info_len) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Failed to add public key: invalid 'ID' length");
|
||||
}
|
||||
memcpy(key_info.id.value, info_blob + offs + 2, len);
|
||||
key_info.id.len = len;
|
||||
|
||||
free(info_blob);
|
||||
|
||||
/* Ignore Start/End dates */
|
||||
|
||||
snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PUB, file_id);
|
||||
|
@ -648,7 +665,7 @@ sc_pkcs15emu_oberthur_add_cert(struct sc_pkcs15_card *p15card, unsigned int file
|
|||
struct sc_context *ctx = p15card->card->ctx;
|
||||
struct sc_pkcs15_cert_info cinfo;
|
||||
struct sc_pkcs15_object cobj;
|
||||
unsigned char *info_blob, *cert_blob;
|
||||
unsigned char *info_blob = NULL, *cert_blob = NULL;
|
||||
size_t info_len, cert_len, len, offs;
|
||||
unsigned flags;
|
||||
int rv;
|
||||
|
@ -664,16 +681,23 @@ sc_pkcs15emu_oberthur_add_cert(struct sc_pkcs15_card *p15card, unsigned int file
|
|||
rv = sc_oberthur_read_file(p15card, ch_tmp, &info_blob, &info_len, 1);
|
||||
LOG_TEST_RET(ctx, rv, "Failed to add certificate: read oberthur file error");
|
||||
|
||||
if (info_len < 2)
|
||||
if (info_len < 2) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add certificate: no 'tag'");
|
||||
}
|
||||
flags = *(info_blob + 0) * 0x100 + *(info_blob + 1);
|
||||
offs = 2;
|
||||
|
||||
/* Label */
|
||||
if (offs + 2 > info_len)
|
||||
if (offs + 2 > info_len) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add certificate: no 'CN'");
|
||||
}
|
||||
len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
|
||||
if (len) {
|
||||
if (len + offs + 2 > info_len) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid 'CN' length");
|
||||
} else if (len) {
|
||||
if (len > sizeof(cobj.label) - 1)
|
||||
len = sizeof(cobj.label) - 1;
|
||||
memcpy(cobj.label, info_blob + offs + 2, len);
|
||||
|
@ -681,14 +705,23 @@ sc_pkcs15emu_oberthur_add_cert(struct sc_pkcs15_card *p15card, unsigned int file
|
|||
offs += 2 + len;
|
||||
|
||||
/* ID */
|
||||
if (offs > info_len)
|
||||
if (offs + 2 > info_len) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add certificate: no 'ID'");
|
||||
}
|
||||
len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
|
||||
if (len > sizeof(cinfo.id.value))
|
||||
if (len + offs + 2 > info_len) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid 'ID' length");
|
||||
} else if (len > sizeof(cinfo.id.value)) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Failed to add certificate: invalid 'ID' length");
|
||||
}
|
||||
memcpy(cinfo.id.value, info_blob + offs + 2, len);
|
||||
cinfo.id.len = len;
|
||||
|
||||
free(info_blob);
|
||||
|
||||
/* Ignore subject, issuer and serial */
|
||||
|
||||
snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PUB, file_id);
|
||||
|
@ -700,7 +733,10 @@ sc_pkcs15emu_oberthur_add_cert(struct sc_pkcs15_card *p15card, unsigned int file
|
|||
cinfo.value.len = cert_len;
|
||||
|
||||
rv = sc_oberthur_get_certificate_authority(&cinfo.value, &cinfo.authority);
|
||||
LOG_TEST_RET(ctx, rv, "Failed to add certificate: get certificate attributes error");
|
||||
if (rv != SC_SUCCESS) {
|
||||
free(cinfo.value.value);
|
||||
LOG_TEST_RET(ctx, rv, "Failed to add certificate: get certificate attributes error");
|
||||
}
|
||||
|
||||
if (flags & OBERTHUR_ATTR_MODIFIABLE)
|
||||
cobj.flags |= SC_PKCS15_CO_FLAG_MODIFIABLE;
|
||||
|
@ -773,15 +809,23 @@ sc_pkcs15emu_oberthur_add_prvkey(struct sc_pkcs15_card *p15card,
|
|||
rv = sc_oberthur_read_file(p15card, ch_tmp, &info_blob, &info_len, 1);
|
||||
LOG_TEST_RET(ctx, rv, "Failed to add private key: read oberthur file error");
|
||||
|
||||
if (info_len < 2)
|
||||
if (info_len < 2) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: no 'tag'");
|
||||
}
|
||||
flags = *(info_blob + 0) * 0x100 + *(info_blob + 1);
|
||||
offs = 2;
|
||||
|
||||
/* CN */
|
||||
if (offs > info_len)
|
||||
if (offs + 2 > info_len) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: no 'CN'");
|
||||
}
|
||||
len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
|
||||
if (len + offs + 2 > info_len) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid 'CN' length");
|
||||
}
|
||||
if (len && !strlen(kobj.label)) {
|
||||
if (len > sizeof(kobj.label) - 1)
|
||||
len = sizeof(kobj.label) - 1;
|
||||
|
@ -790,13 +834,21 @@ sc_pkcs15emu_oberthur_add_prvkey(struct sc_pkcs15_card *p15card,
|
|||
offs += 2 + len;
|
||||
|
||||
/* ID */
|
||||
if (offs > info_len)
|
||||
if (offs + 2 > info_len) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: no 'ID'");
|
||||
}
|
||||
len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
|
||||
if (!len)
|
||||
if (!len) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: zero length ID");
|
||||
else if (len > sizeof(kinfo.id.value))
|
||||
} else if (len + offs + 2 > info_len) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid 'ID' length");
|
||||
} else if (len > sizeof(kinfo.id.value)) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Failed to add private key: invalid ID length");
|
||||
}
|
||||
memcpy(kinfo.id.value, info_blob + offs + 2, len);
|
||||
kinfo.id.len = len;
|
||||
offs += 2 + len;
|
||||
|
@ -805,19 +857,28 @@ sc_pkcs15emu_oberthur_add_prvkey(struct sc_pkcs15_card *p15card,
|
|||
offs += 16;
|
||||
|
||||
/* Subject encoded in ASN1 */
|
||||
if (offs > info_len)
|
||||
return SC_ERROR_UNKNOWN_DATA_RECEIVED;
|
||||
if (offs + 2 > info_len) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: no 'subject'");
|
||||
}
|
||||
len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
|
||||
if (len) {
|
||||
if (len + offs + 2 > info_len) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid 'subject' length");
|
||||
} else if (len) {
|
||||
kinfo.subject.value = malloc(len);
|
||||
if (!kinfo.subject.value)
|
||||
if (!kinfo.subject.value) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Failed to add private key: memory allocation error");
|
||||
}
|
||||
kinfo.subject.len = len;
|
||||
memcpy(kinfo.subject.value, info_blob + offs + 2, len);
|
||||
}
|
||||
|
||||
/* Modulus and exponent are ignored */
|
||||
|
||||
free(info_blob);
|
||||
|
||||
snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PRV, file_id);
|
||||
sc_format_path(ch_tmp, &kinfo.path);
|
||||
sc_log(ctx, "Private key info path %s", ch_tmp);
|
||||
|
@ -865,37 +926,59 @@ sc_pkcs15emu_oberthur_add_data(struct sc_pkcs15_card *p15card,
|
|||
rv = sc_oberthur_read_file(p15card, ch_tmp, &info_blob, &info_len, 1);
|
||||
LOG_TEST_RET(ctx, rv, "Failed to add data: read oberthur file error");
|
||||
|
||||
if (info_len < 2)
|
||||
if (info_len < 2) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add certificate: no 'tag'");
|
||||
}
|
||||
flags = *(info_blob + 0) * 0x100 + *(info_blob + 1);
|
||||
offs = 2;
|
||||
|
||||
/* Label */
|
||||
if (offs > info_len)
|
||||
if (offs + 2 > info_len) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add data: no 'label'");
|
||||
}
|
||||
label = info_blob + offs + 2;
|
||||
label_len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
|
||||
if (offs + 2 + label_len > info_len) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid length of 'label' received");
|
||||
}
|
||||
if (label_len > sizeof(dobj.label) - 1)
|
||||
label_len = sizeof(dobj.label) - 1;
|
||||
offs += 2 + *(info_blob + offs + 1);
|
||||
|
||||
/* Application */
|
||||
if (offs > info_len)
|
||||
if (offs + 2 > info_len) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add data: no 'application'");
|
||||
}
|
||||
app = info_blob + offs + 2;
|
||||
app_len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
|
||||
if (offs + 2 + app_len > info_len) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid length of 'application' received");
|
||||
}
|
||||
if (app_len > sizeof(dinfo.app_label) - 1)
|
||||
app_len = sizeof(dinfo.app_label) - 1;
|
||||
offs += 2 + app_len;
|
||||
|
||||
/* OID encode like DER(ASN.1(oid)) */
|
||||
if (offs > info_len)
|
||||
if (offs + 2 > info_len) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add data: no 'OID'");
|
||||
}
|
||||
oid_len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
|
||||
if (oid_len) {
|
||||
if (offs + 2 + oid_len > info_len) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid length of 'oid' received");
|
||||
}
|
||||
if (oid_len > 2) {
|
||||
oid = info_blob + offs + 2;
|
||||
if (*oid != 0x06 || (*(oid + 1) != oid_len - 2))
|
||||
if (*oid != 0x06 || (*(oid + 1) != oid_len - 2)) {
|
||||
free(info_blob);
|
||||
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add data: invalid 'OID' format");
|
||||
}
|
||||
oid += 2;
|
||||
oid_len -= 2;
|
||||
}
|
||||
|
@ -922,6 +1005,7 @@ sc_pkcs15emu_oberthur_add_data(struct sc_pkcs15_card *p15card,
|
|||
|
||||
rv = sc_pkcs15emu_add_data_object(p15card, &dobj, &dinfo);
|
||||
|
||||
free(info_blob);
|
||||
LOG_FUNC_RETURN(p15card->card->ctx, rv);
|
||||
}
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@ static const pgp_pin_cfg_t pin_cfg_v2[3] = {
|
|||
{ "Admin PIN", 0x03, PGP_ADMIN_PIN_FLAGS, 8, 2 }
|
||||
};
|
||||
|
||||
static struct sc_object_id curve25519_oid = {{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}};
|
||||
|
||||
#define PGP_SIG_PRKEY_USAGE (SC_PKCS15_PRKEY_USAGE_SIGN \
|
||||
| SC_PKCS15_PRKEY_USAGE_SIGNRECOVER \
|
||||
|
@ -169,6 +170,8 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
|
|||
sc_path_t path;
|
||||
sc_file_t *file = NULL;
|
||||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
|
||||
set_string(&p15card->tokeninfo->label, "OpenPGP card");
|
||||
set_string(&p15card->tokeninfo->manufacturer_id, "OpenPGP project");
|
||||
|
||||
|
@ -203,6 +206,7 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
|
|||
* 01-03: max length of pins 1-3
|
||||
* 04-07: tries left for pins 1-3
|
||||
*/
|
||||
sc_log(ctx, "Reading PW status bytes");
|
||||
if ((r = read_file(card, "006E:0073:00C4", c4data, sizeof(c4data))) < 0)
|
||||
goto failed;
|
||||
if (r != 7) {
|
||||
|
@ -251,19 +255,22 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
|
|||
* 20-39: finger print for ENC key
|
||||
* 40-59: finger print for AUT key
|
||||
*/
|
||||
sc_log(ctx, "Reading Fingerprints");
|
||||
if ((r = read_file(card, "006E:0073:00C5", c5data, sizeof(c5data))) < 0)
|
||||
goto failed;
|
||||
if (r < 60) {
|
||||
sc_log(ctx,
|
||||
sc_log(ctx,
|
||||
"finger print bytes have unexpected length (expected 60, got %d)\n", r);
|
||||
return SC_ERROR_OBJECT_NOT_VALID;
|
||||
}
|
||||
|
||||
sc_log(ctx, "Adding private keys");
|
||||
/* XXX: check if "halfkeys" can be stored with gpg2. If not, add key pairs in one loop */
|
||||
for (i = 0; i < 3; i++) {
|
||||
sc_pkcs15_prkey_info_t prkey_info;
|
||||
sc_pkcs15_object_t prkey_obj;
|
||||
u8 cxdata[12];
|
||||
int cxdata_len = sizeof(cxdata);
|
||||
char path_template[] = "006E:0073:00Cx";
|
||||
int j;
|
||||
|
||||
|
@ -272,7 +279,7 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
|
|||
memset(&cxdata, 0, sizeof(cxdata));
|
||||
|
||||
path_template[13] = '1' + i; /* The needed tags are C1 C2 and C3 */
|
||||
if ((r = read_file(card, path_template, cxdata, sizeof(cxdata))) < 0)
|
||||
if ((cxdata_len = read_file(card, path_template, cxdata, sizeof(cxdata))) < 1)
|
||||
goto failed;
|
||||
|
||||
/* check validity using finger prints */
|
||||
|
@ -283,6 +290,10 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
|
|||
|
||||
/* only add valid keys, i.e. those with a legal algorithm identifier & finger print */
|
||||
if (j >= 0 && cxdata[0] != 0) {
|
||||
struct sc_object_id oid;
|
||||
struct sc_algorithm_info * algorithm_info; /* no need to free */
|
||||
|
||||
algorithm_info = NULL;
|
||||
prkey_info.id.len = 1;
|
||||
prkey_info.id.value[0] = i + 1;
|
||||
prkey_info.usage = key_cfg[i].prkey_usage;
|
||||
|
@ -294,24 +305,101 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
|
|||
prkey_obj.auth_id.len = 1;
|
||||
prkey_obj.auth_id.value[0] = key_cfg[i].prkey_pin;
|
||||
|
||||
if (cxdata[0] == SC_OPENPGP_KEYALGO_RSA && r >= 3) {
|
||||
prkey_info.modulus_length = bebytes2ushort(cxdata + 1);
|
||||
r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);
|
||||
/* need to get size from algorithms using oid */
|
||||
if (cxdata[0] == SC_OPENPGP_KEYALGO_ECDH ||
|
||||
cxdata[0] == SC_OPENPGP_KEYALGO_ECDSA ||
|
||||
cxdata[0] == SC_OPENPGP_KEYALGO_EDDSA) {
|
||||
/* Last byte could be Import-Format of private key, let's ignore it,
|
||||
* as it is not part of OID */
|
||||
if (cxdata[cxdata_len-1] == SC_OPENPGP_KEYFORMAT_EC_STD ||
|
||||
cxdata[cxdata_len-1] == SC_OPENPGP_KEYFORMAT_EC_STDPUB)
|
||||
cxdata_len--;
|
||||
r = sc_asn1_decode_object_id(&cxdata[1], cxdata_len-1, &oid);
|
||||
if (r != SC_SUCCESS) {
|
||||
sc_log(ctx, "Failed to parse OID for elliptic curve algorithm");
|
||||
}
|
||||
}
|
||||
if (cxdata[0] == SC_OPENPGP_KEYALGO_ECDH
|
||||
|| cxdata[0] == SC_OPENPGP_KEYALGO_ECDSA) {
|
||||
|
||||
switch (cxdata[0]) {
|
||||
case SC_OPENPGP_KEYALGO_ECDH:
|
||||
if (sc_compare_oid(&oid, &curve25519_oid)) {
|
||||
if ((algorithm_info = sc_card_find_xeddsa_alg(card, 0, &oid)))
|
||||
prkey_info.field_length = algorithm_info->key_length;
|
||||
else {
|
||||
sc_log(ctx, "algorithm not found");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
case SC_OPENPGP_KEYALGO_ECDSA:
|
||||
if((algorithm_info = sc_card_find_ec_alg(card, 0, &oid)))
|
||||
prkey_info.field_length = algorithm_info->key_length;
|
||||
else {
|
||||
sc_log(ctx, "algorithm not found");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case SC_OPENPGP_KEYALGO_EDDSA:
|
||||
if ((algorithm_info = sc_card_find_eddsa_alg(card, 0, &oid)))
|
||||
prkey_info.field_length = algorithm_info->key_length;
|
||||
else {
|
||||
sc_log(ctx, "algorithm not found");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cxdata[0]) {
|
||||
case SC_OPENPGP_KEYALGO_EDDSA:
|
||||
/* Filter out invalid usage: EdDSA does not support anything but sign */
|
||||
prkey_info.usage &= PGP_SIG_PRKEY_USAGE;
|
||||
r = sc_pkcs15emu_add_eddsa_prkey(p15card, &prkey_obj, &prkey_info);
|
||||
break;
|
||||
|
||||
case SC_OPENPGP_KEYALGO_ECDH:
|
||||
/* This can result in either ECDSA key or EC_MONTGOMERY
|
||||
* so we need to check OID */
|
||||
if (sc_compare_oid(&oid, &curve25519_oid)) {
|
||||
/* This can do only DERIVE */
|
||||
prkey_info.usage = SC_PKCS15_PRKEY_USAGE_DERIVE;
|
||||
r = sc_pkcs15emu_add_xeddsa_prkey(p15card, &prkey_obj, &prkey_info);
|
||||
break;
|
||||
}
|
||||
prkey_info.usage |= SC_PKCS15_PRKEY_USAGE_DERIVE;
|
||||
prkey_info.usage &= ~PGP_ENC_PRKEY_USAGE;
|
||||
r = sc_pkcs15emu_add_ec_prkey(p15card, &prkey_obj, &prkey_info);
|
||||
break;
|
||||
|
||||
case SC_OPENPGP_KEYALGO_ECDSA:
|
||||
prkey_info.usage = SC_PKCS15_PRKEY_USAGE_SIGN;
|
||||
r = sc_pkcs15emu_add_ec_prkey(p15card, &prkey_obj, &prkey_info);
|
||||
break;
|
||||
|
||||
case SC_OPENPGP_KEYALGO_RSA:
|
||||
if (cxdata_len >= 3) {
|
||||
prkey_info.modulus_length = bebytes2ushort(cxdata + 1);
|
||||
r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);
|
||||
break;
|
||||
}
|
||||
/* Fallthrough */
|
||||
default:
|
||||
sc_log(ctx, "Invalid algorithm identifier %x (length = %d)",
|
||||
cxdata[0], r);
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
return SC_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
sc_log(ctx, "Adding public keys");
|
||||
/* Add public keys */
|
||||
for (i = 0; i < 3; i++) {
|
||||
sc_pkcs15_pubkey_info_t pubkey_info;
|
||||
sc_pkcs15_object_t pubkey_obj;
|
||||
u8 cxdata[10];
|
||||
u8 cxdata[12];
|
||||
int cxdata_len = sizeof(cxdata);
|
||||
char path_template[] = "006E:0073:00Cx";
|
||||
int j;
|
||||
|
||||
|
@ -320,7 +408,7 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
|
|||
memset(&cxdata, 0, sizeof(cxdata));
|
||||
|
||||
path_template[13] = '1' + i; /* The needed tags are C1 C2 and C3 */
|
||||
if ((r = read_file(card, path_template, cxdata, sizeof(cxdata))) < 0)
|
||||
if ((cxdata_len = read_file(card, path_template, cxdata, sizeof(cxdata))) < 1)
|
||||
goto failed;
|
||||
|
||||
/* check validity using finger prints */
|
||||
|
@ -331,6 +419,10 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
|
|||
|
||||
/* only add valid keys, i.e. those with a legal algorithm identifier & finger print */
|
||||
if (j >= 0 && cxdata[0] != 0) {
|
||||
struct sc_object_id oid;
|
||||
struct sc_algorithm_info * algorithm_info; /* no need to free */
|
||||
|
||||
algorithm_info = NULL;
|
||||
pubkey_info.id.len = 1;
|
||||
pubkey_info.id.value[0] = i + 1;
|
||||
pubkey_info.usage = key_cfg[i].pubkey_usage;
|
||||
|
@ -339,13 +431,83 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
|
|||
strlcpy(pubkey_obj.label, key_cfg[i].label, sizeof(pubkey_obj.label));
|
||||
pubkey_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE;
|
||||
|
||||
if (cxdata[0] == SC_OPENPGP_KEYALGO_RSA && r >= 3) {
|
||||
pubkey_info.modulus_length = bebytes2ushort(cxdata + 1);
|
||||
r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info);
|
||||
if (cxdata[0] == SC_OPENPGP_KEYALGO_ECDH ||
|
||||
cxdata[0] == SC_OPENPGP_KEYALGO_ECDSA ||
|
||||
cxdata[0] == SC_OPENPGP_KEYALGO_EDDSA) {
|
||||
/* Last byte could be Import-Format of private key, let's ignore it,
|
||||
* as it is not part of OID */
|
||||
if (cxdata[cxdata_len-1] == SC_OPENPGP_KEYFORMAT_EC_STD ||
|
||||
cxdata[cxdata_len-1] == SC_OPENPGP_KEYFORMAT_EC_STDPUB)
|
||||
cxdata_len--;
|
||||
r = sc_asn1_decode_object_id(&cxdata[1], cxdata_len-1, &oid);
|
||||
if (r != SC_SUCCESS) {
|
||||
sc_log(ctx, "Failed to parse OID for elliptic curve algorithm");
|
||||
}
|
||||
}
|
||||
if (cxdata[0] == SC_OPENPGP_KEYALGO_ECDH
|
||||
|| cxdata[0] == SC_OPENPGP_KEYALGO_ECDSA) {
|
||||
|
||||
switch (cxdata[0]) {
|
||||
case SC_OPENPGP_KEYALGO_ECDH:
|
||||
if (sc_compare_oid(&oid, &curve25519_oid)) {
|
||||
if ((algorithm_info = sc_card_find_xeddsa_alg(card, 0, &oid)))
|
||||
pubkey_info.field_length = algorithm_info->key_length;
|
||||
else {
|
||||
sc_log(ctx, "algorithm not found");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
case SC_OPENPGP_KEYALGO_ECDSA:
|
||||
if((algorithm_info = sc_card_find_ec_alg(card, 0, &oid)))
|
||||
pubkey_info.field_length = algorithm_info->key_length;
|
||||
else {
|
||||
sc_log(ctx, "algorithm not found");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case SC_OPENPGP_KEYALGO_EDDSA:
|
||||
if ((algorithm_info = sc_card_find_eddsa_alg(card, 0, &oid)))
|
||||
pubkey_info.field_length = algorithm_info->key_length;
|
||||
else {
|
||||
sc_log(ctx, "algorithm not found");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cxdata[0]) {
|
||||
case SC_OPENPGP_KEYALGO_EDDSA:
|
||||
/* assuming Ed25519 as it is the only supported now */
|
||||
/* Filter out invalid usage: ED does not support anything but sign */
|
||||
pubkey_info.usage &= PGP_SIG_PUBKEY_USAGE;
|
||||
r = sc_pkcs15emu_add_eddsa_pubkey(p15card, &pubkey_obj, &pubkey_info);
|
||||
break;
|
||||
case SC_OPENPGP_KEYALGO_ECDH:
|
||||
/* This can result in either ECDSA key or EC_MONTGOMERY
|
||||
* so we need to check OID */
|
||||
if (sc_compare_oid(&oid, &curve25519_oid)) {
|
||||
/* XXX What can this key do? */
|
||||
pubkey_info.usage = SC_PKCS15_PRKEY_USAGE_DERIVE;
|
||||
r = sc_pkcs15emu_add_xeddsa_pubkey(p15card, &pubkey_obj, &pubkey_info);
|
||||
break;
|
||||
}
|
||||
pubkey_info.usage = SC_PKCS15_PRKEY_USAGE_DERIVE;
|
||||
r = sc_pkcs15emu_add_ec_pubkey(p15card, &pubkey_obj, &pubkey_info);
|
||||
break;
|
||||
case SC_OPENPGP_KEYALGO_ECDSA:
|
||||
pubkey_info.usage = PGP_SIG_PUBKEY_USAGE;
|
||||
r = sc_pkcs15emu_add_ec_pubkey(p15card, &pubkey_obj, &pubkey_info);
|
||||
break;
|
||||
case SC_OPENPGP_KEYALGO_RSA:
|
||||
if (cxdata_len >= 3) {
|
||||
pubkey_info.modulus_length = bebytes2ushort(cxdata + 1);
|
||||
r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info);
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
default:
|
||||
sc_log(ctx, "Invalid algorithm identifier %x (length = %d)",
|
||||
cxdata[0], r);
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
|
@ -388,13 +550,13 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
|
|||
|
||||
failed:
|
||||
if (r < 0) {
|
||||
sc_log(card->ctx,
|
||||
sc_log(card->ctx,
|
||||
"Failed to initialize OpenPGP emulation: %s\n",
|
||||
sc_strerror(r));
|
||||
}
|
||||
sc_file_free(file);
|
||||
|
||||
return r;
|
||||
LOG_FUNC_RETURN(ctx, r);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
* partial PKCS15 emulation for PIV-II cards
|
||||
* only minimal use of the authentication cert and key
|
||||
*
|
||||
* Copyright (C) 2005,2006,2007,2008,2009,2010
|
||||
* Douglas E. Engert <deengert@anl.gov>
|
||||
* Copyright (C) 2005,2006,2007,2008,2009,2010
|
||||
* Douglas E. Engert <deengert@anl.gov>
|
||||
* 2004, Nils Larsch <larsch@trustcenter.de>
|
||||
* Copyright (C) 2006, Identity Alliance,
|
||||
* Copyright (C) 2006, Identity Alliance,
|
||||
* Thomas Harning <thomas.harning@identityalliance.com>
|
||||
* Copyright (C) 2007, EMC, Russell Larner <rlarner@rsa.com>
|
||||
*
|
||||
|
@ -66,11 +66,11 @@ typedef struct pdata_st {
|
|||
unsigned int maxlen;
|
||||
unsigned int minlen;
|
||||
unsigned int storedlen;
|
||||
int flags;
|
||||
int flags;
|
||||
int tries_left;
|
||||
const unsigned char pad_char;
|
||||
int obj_flags;
|
||||
} pindata;
|
||||
} pindata;
|
||||
|
||||
typedef struct pubdata_st {
|
||||
const char *id;
|
||||
|
@ -93,7 +93,7 @@ typedef struct prdata_st {
|
|||
int ref;
|
||||
const char *auth_id;
|
||||
int obj_flags;
|
||||
int user_consent;
|
||||
int user_consent;
|
||||
} prdata;
|
||||
|
||||
typedef struct common_key_info_st {
|
||||
|
@ -116,11 +116,11 @@ typedef struct common_key_info_st {
|
|||
* is used, or the GUID is used as a serial number.
|
||||
* We need to return a GUID like value for each object
|
||||
* But this needs to be some what unique.
|
||||
* So we will use two different methods, depending
|
||||
* So we will use two different methods, depending
|
||||
* on the size of the serial number.
|
||||
* If it is 25 bytes, then it was from a FASCN. If 16 bytes
|
||||
* its from a GUID.
|
||||
* If neither, we will uase the default method.
|
||||
* If neither, we will uase the default method.
|
||||
*/
|
||||
|
||||
static int piv_get_guid(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_object *obj,
|
||||
|
@ -152,13 +152,13 @@ static int piv_get_guid(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_o
|
|||
|
||||
/* It is from a FASCN, and we need to shorten it but keep
|
||||
* as much uniqueness as possible.
|
||||
* FASC-N is stored like a ISO 7811 Magnetic Strip Card
|
||||
* FASC-N is stored like a ISO 7811 Magnetic Strip Card
|
||||
* Using the ANSI/ISO BCD Data Format
|
||||
* 4 data bit + 1 parity bit (odd) least significant bit first.
|
||||
* It starts with the Start Sentinel 0x0b ";"
|
||||
* 4 data bit + 1 parity bit (odd) least significant bit first.
|
||||
* It starts with the Start Sentinel 0x0b ";"
|
||||
* Fields are separated by 0x0d "="
|
||||
* Ends with End Sentinel 0x0f "?"
|
||||
* Its 39 characters + the LRC
|
||||
* Its 39 characters + the LRC
|
||||
* http://www.dataip.co.uk/Reference/MagneticCardBCD.php
|
||||
* 0x0a, 0x0c, 0x0e are some type of control
|
||||
* the FASCN has a lot of extra bits, with only 32 digits.
|
||||
|
@ -194,14 +194,14 @@ static int piv_get_guid(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_o
|
|||
}
|
||||
|
||||
/* overwrite two insignificant digits in middle with id */
|
||||
memcpy(guid_bin + 7, id.value, id.len);
|
||||
memcpy(guid_bin + 7, id.value, id.len);
|
||||
tlen = 16;
|
||||
}
|
||||
else if (id.len == 1 && serialnr.len == 16) {
|
||||
/* its from a GUID, we will overwrite the
|
||||
/* its from a GUID, we will overwrite the
|
||||
* first byte with id.value, as this preserves most
|
||||
* of the uniqueness.
|
||||
*/
|
||||
* of the uniqueness.
|
||||
*/
|
||||
memcpy(guid_bin, id.value, id.len);
|
||||
memcpy(guid_bin + id.len, serialnr.value + 1, serialnr.len - 1);
|
||||
|
||||
|
@ -247,8 +247,9 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
|
|||
/* The cert objects will return all the data */
|
||||
/* Note: pkcs11 objects do not have CK_ID values */
|
||||
|
||||
// clang-format off
|
||||
static const objdata objects[] = {
|
||||
{"01", "Card Capability Container",
|
||||
{"01", "Card Capability Container",
|
||||
"2.16.840.1.101.3.7.1.219.0", NULL, "DB00", 0},
|
||||
{"02", "Card Holder Unique Identifier",
|
||||
"2.16.840.1.101.3.7.2.48.0", NULL, "3000", 0},
|
||||
|
@ -260,11 +261,11 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
|
|||
"2.16.840.1.101.3.7.2.96.16", "01", "6010", SC_PKCS15_CO_FLAG_PRIVATE},
|
||||
{"06", "Printed Information",
|
||||
"2.16.840.1.101.3.7.2.48.1", "01", "3001", SC_PKCS15_CO_FLAG_PRIVATE},
|
||||
{"07", "Cardholder Facial Image",
|
||||
{"07", "Cardholder Facial Image",
|
||||
"2.16.840.1.101.3.7.2.96.48", "01", "6030", SC_PKCS15_CO_FLAG_PRIVATE},
|
||||
{"08", "X.509 Certificate for Digital Signature",
|
||||
"2.16.840.1.101.3.7.2.1.0", NULL, "0100", 0},
|
||||
{"09", "X.509 Certificate for Key Management",
|
||||
{"09", "X.509 Certificate for Key Management",
|
||||
"2.16.840.1.101.3.7.2.1.2", NULL, "0102", 0},
|
||||
{"10","X.509 Certificate for Card Authentication",
|
||||
"2.16.840.1.101.3.7.2.5.0", NULL, "0500", 0},
|
||||
|
@ -277,50 +278,51 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
|
|||
{"14", "Cardholder Iris Image",
|
||||
"2.16.840.1.101.3.7.2.16.21", NULL, "1015", SC_PKCS15_CO_FLAG_PRIVATE},
|
||||
|
||||
{"15", "Retired X.509 Certificate for Key Management 1",
|
||||
{"15", "Retired X.509 Certificate for Key Management 1",
|
||||
"2.16.840.1.101.3.7.2.16.1", NULL, "1001", 0},
|
||||
{"16", "Retired X.509 Certificate for Key Management 2",
|
||||
{"16", "Retired X.509 Certificate for Key Management 2",
|
||||
"2.16.840.1.101.3.7.2.16.2", NULL, "1002", 0},
|
||||
{"17", "Retired X.509 Certificate for Key Management 3",
|
||||
{"17", "Retired X.509 Certificate for Key Management 3",
|
||||
"2.16.840.1.101.3.7.2.16.3", NULL, "1003", 0},
|
||||
{"18", "Retired X.509 Certificate for Key Management 4",
|
||||
{"18", "Retired X.509 Certificate for Key Management 4",
|
||||
"2.16.840.1.101.3.7.2.16.4", NULL, "1004", 0},
|
||||
{"19", "Retired X.509 Certificate for Key Management 5",
|
||||
{"19", "Retired X.509 Certificate for Key Management 5",
|
||||
"2.16.840.1.101.3.7.2.16.5", NULL, "1005", 0},
|
||||
{"20", "Retired X.509 Certificate for Key Management 6",
|
||||
{"20", "Retired X.509 Certificate for Key Management 6",
|
||||
"2.16.840.1.101.3.7.2.16.6", NULL, "1006", 0},
|
||||
{"21", "Retired X.509 Certificate for Key Management 7",
|
||||
{"21", "Retired X.509 Certificate for Key Management 7",
|
||||
"2.16.840.1.101.3.7.2.16.7", NULL, "1007", 0},
|
||||
{"22", "Retired X.509 Certificate for Key Management 8",
|
||||
{"22", "Retired X.509 Certificate for Key Management 8",
|
||||
"2.16.840.1.101.3.7.2.16.8", NULL, "1008", 0},
|
||||
{"23", "Retired X.509 Certificate for Key Management 9",
|
||||
{"23", "Retired X.509 Certificate for Key Management 9",
|
||||
"2.16.840.1.101.3.7.2.16.9", NULL, "1009", 0},
|
||||
{"24", "Retired X.509 Certificate for Key Management 10",
|
||||
{"24", "Retired X.509 Certificate for Key Management 10",
|
||||
"2.16.840.1.101.3.7.2.16.10", NULL, "100A", 0},
|
||||
{"25", "Retired X.509 Certificate for Key Management 11",
|
||||
{"25", "Retired X.509 Certificate for Key Management 11",
|
||||
"2.16.840.1.101.3.7.2.16.11", NULL, "100B", 0},
|
||||
{"26", "Retired X.509 Certificate for Key Management 12",
|
||||
{"26", "Retired X.509 Certificate for Key Management 12",
|
||||
"2.16.840.1.101.3.7.2.16.12", NULL, "100C", 0},
|
||||
{"27", "Retired X.509 Certificate for Key Management 13",
|
||||
{"27", "Retired X.509 Certificate for Key Management 13",
|
||||
"2.16.840.1.101.3.7.2.16.13", NULL, "100D", 0},
|
||||
{"28", "Retired X.509 Certificate for Key Management 14",
|
||||
{"28", "Retired X.509 Certificate for Key Management 14",
|
||||
"2.16.840.1.101.3.7.2.16.14", NULL, "100E", 0},
|
||||
{"29", "Retired X.509 Certificate for Key Management 15",
|
||||
{"29", "Retired X.509 Certificate for Key Management 15",
|
||||
"2.16.840.1.101.3.7.2.16.15", NULL, "100F", 0},
|
||||
{"30", "Retired X.509 Certificate for Key Management 16",
|
||||
{"30", "Retired X.509 Certificate for Key Management 16",
|
||||
"2.16.840.1.101.3.7.2.16.16", NULL, "1010", 0},
|
||||
{"31", "Retired X.509 Certificate for Key Management 17",
|
||||
{"31", "Retired X.509 Certificate for Key Management 17",
|
||||
"2.16.840.1.101.3.7.2.16.17", NULL, "1011", 0},
|
||||
{"32", "Retired X.509 Certificate for Key Management 18",
|
||||
{"32", "Retired X.509 Certificate for Key Management 18",
|
||||
"2.16.840.1.101.3.7.2.16.18", NULL, "1012", 0},
|
||||
{"33", "Retired X.509 Certificate for Key Management 19",
|
||||
{"33", "Retired X.509 Certificate for Key Management 19",
|
||||
"2.16.840.1.101.3.7.2.16.19", NULL, "1013", 0},
|
||||
{"34", "Retired X.509 Certificate for Key Management 20",
|
||||
{"34", "Retired X.509 Certificate for Key Management 20",
|
||||
"2.16.840.1.101.3.7.2.16.20", NULL, "1014", 0},
|
||||
{NULL, NULL, NULL, NULL, NULL, 0}
|
||||
};
|
||||
/*
|
||||
* NIST 800-73-1 lifted the restriction on
|
||||
};
|
||||
// clang-format on
|
||||
/*
|
||||
* NIST 800-73-1 lifted the restriction on
|
||||
* requiring pin protected certs. Thus the default is to
|
||||
* not require this.
|
||||
*/
|
||||
|
@ -329,6 +331,7 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
|
|||
|
||||
#define PIV_NUM_CERTS_AND_KEYS 24
|
||||
|
||||
// clang-format off
|
||||
static const cdata certs[PIV_NUM_CERTS_AND_KEYS] = {
|
||||
{"01", "Certificate for PIV Authentication", "0101cece", 0, 0},
|
||||
{"02", "Certificate for Digital Signature", "0100cece", 0, 0},
|
||||
|
@ -355,47 +358,50 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
|
|||
{"23", "Retired Certificate for Key Management 19", "1013cece", 0, 0},
|
||||
{"24", "Retired Certificate for Key Management 20", "1014cece", 0, 0}
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// clang-format off
|
||||
static const pindata pins[] = {
|
||||
{ "01", "PIN", "", 0x80,
|
||||
/* label, flag and ref will change if using global pin */
|
||||
SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
|
||||
8, 4, 8,
|
||||
8, 4, 8,
|
||||
SC_PKCS15_PIN_FLAG_NEEDS_PADDING |
|
||||
SC_PKCS15_PIN_FLAG_INITIALIZED |
|
||||
SC_PKCS15_PIN_FLAG_LOCAL,
|
||||
SC_PKCS15_PIN_FLAG_LOCAL,
|
||||
-1, 0xFF,
|
||||
SC_PKCS15_CO_FLAG_PRIVATE },
|
||||
{ "02", "PIV PUK", "", 0x81,
|
||||
{ "02", "PIV PUK", "", 0x81,
|
||||
SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
|
||||
8, 4, 8,
|
||||
8, 4, 8,
|
||||
SC_PKCS15_PIN_FLAG_NEEDS_PADDING |
|
||||
SC_PKCS15_PIN_FLAG_INITIALIZED |
|
||||
SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_SO_PIN |
|
||||
SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN,
|
||||
-1, 0xFF,
|
||||
SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN,
|
||||
-1, 0xFF,
|
||||
SC_PKCS15_CO_FLAG_PRIVATE },
|
||||
{ NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
/*
|
||||
* The size of the key or the algid is not really known
|
||||
* but can be derived from the certificates.
|
||||
* the cert, pubkey and privkey are a set.
|
||||
* but can be derived from the certificates.
|
||||
* the cert, pubkey and privkey are a set.
|
||||
* Key usages bits taken from pkcs15v1_1 Table 2
|
||||
* RSA and EC have different sets of usage
|
||||
*/
|
||||
// clang-format off
|
||||
static const pubdata pubkeys[PIV_NUM_CERTS_AND_KEYS] = {
|
||||
|
||||
{ "01", "PIV AUTH pubkey",
|
||||
{ "01", "PIV AUTH pubkey",
|
||||
/*RSA*/SC_PKCS15_PRKEY_USAGE_ENCRYPT |
|
||||
SC_PKCS15_PRKEY_USAGE_WRAP |
|
||||
SC_PKCS15_PRKEY_USAGE_VERIFY |
|
||||
SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER,
|
||||
/*EC*/SC_PKCS15_PRKEY_USAGE_VERIFY,
|
||||
"9A06", 0x9A, NULL, 0, "PIV_9A_KEY"},
|
||||
{ "02", "SIGN pubkey",
|
||||
{ "02", "SIGN pubkey",
|
||||
/*RSA*/SC_PKCS15_PRKEY_USAGE_ENCRYPT |
|
||||
SC_PKCS15_PRKEY_USAGE_VERIFY |
|
||||
SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER |
|
||||
|
@ -403,13 +409,13 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
|
|||
/*EC*/SC_PKCS15_PRKEY_USAGE_VERIFY |
|
||||
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION,
|
||||
"9C06", 0x9C, NULL, 0, "PIV_9C_KEY"},
|
||||
{ "03", "KEY MAN pubkey",
|
||||
{ "03", "KEY MAN pubkey",
|
||||
/*RSA*/SC_PKCS15_PRKEY_USAGE_ENCRYPT| SC_PKCS15_PRKEY_USAGE_WRAP,
|
||||
/*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE,
|
||||
"9D06", 0x9D, NULL, 0, "PIV_9D_KEY"},
|
||||
{ "04", "CARD AUTH pubkey",
|
||||
{ "04", "CARD AUTH pubkey",
|
||||
/*RSA*/SC_PKCS15_PRKEY_USAGE_VERIFY |
|
||||
SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER,
|
||||
SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER,
|
||||
/*EC*/SC_PKCS15_PRKEY_USAGE_VERIFY,
|
||||
"9E06", 0x9E, NULL, 0, "PIV_9E_KEY"}, /* no pin, and avail in contactless */
|
||||
|
||||
|
@ -492,33 +498,36 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
|
|||
{ "24", "Retired KEY MAN 20",
|
||||
/*RSA*/SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_WRAP,
|
||||
/*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE,
|
||||
"9506", 0x95, NULL, 0, NULL} };
|
||||
"9506", 0x95, NULL, 0, NULL}
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
/*
|
||||
* note some of the SC_PKCS15_PRKEY values are dependent
|
||||
* on the key algorithm, and will be reset.
|
||||
* on the key algorithm, and will be reset.
|
||||
*/
|
||||
// clang-format off
|
||||
static const prdata prkeys[PIV_NUM_CERTS_AND_KEYS] = {
|
||||
{ "01", "PIV AUTH key",
|
||||
{ "01", "PIV AUTH key",
|
||||
/*RSA*/SC_PKCS15_PRKEY_USAGE_DECRYPT |
|
||||
SC_PKCS15_PRKEY_USAGE_UNWRAP |
|
||||
SC_PKCS15_PRKEY_USAGE_SIGN |
|
||||
SC_PKCS15_PRKEY_USAGE_SIGNRECOVER,
|
||||
/*EC*/SC_PKCS15_PRKEY_USAGE_SIGN,
|
||||
"", 0x9A, "01", SC_PKCS15_CO_FLAG_PRIVATE, 0},
|
||||
{ "02", "SIGN key",
|
||||
{ "02", "SIGN key",
|
||||
/*RSA*/SC_PKCS15_PRKEY_USAGE_DECRYPT |
|
||||
SC_PKCS15_PRKEY_USAGE_SIGN |
|
||||
SC_PKCS15_PRKEY_USAGE_SIGNRECOVER |
|
||||
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION,
|
||||
/*EC*/SC_PKCS15_PRKEY_USAGE_SIGN |
|
||||
/*EC*/SC_PKCS15_PRKEY_USAGE_SIGN |
|
||||
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION,
|
||||
"", 0x9C, "01", SC_PKCS15_CO_FLAG_PRIVATE, 1},
|
||||
{ "03", "KEY MAN key",
|
||||
{ "03", "KEY MAN key",
|
||||
/*RSA*/SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP,
|
||||
/*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE,
|
||||
"", 0x9D, "01", SC_PKCS15_CO_FLAG_PRIVATE, 0},
|
||||
{ "04", "CARD AUTH key",
|
||||
{ "04", "CARD AUTH key",
|
||||
/*RSA*/SC_PKCS15_PRKEY_USAGE_SIGN |
|
||||
SC_PKCS15_PRKEY_USAGE_SIGNRECOVER,
|
||||
/*EC*/SC_PKCS15_PRKEY_USAGE_SIGN,
|
||||
|
@ -604,6 +613,7 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
|
|||
/*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE,
|
||||
"", 0x95, "01", SC_PKCS15_CO_FLAG_PRIVATE, 0}
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
int r, i;
|
||||
sc_card_t *card = p15card->card;
|
||||
|
@ -624,10 +634,10 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
|
|||
set_string(&p15card->tokeninfo->manufacturer_id, MANU_ID);
|
||||
|
||||
/*
|
||||
* get serial number
|
||||
* get serial number
|
||||
* We will use the FASC-N from the CHUID
|
||||
* Note we are not verifying CHUID, belongs to this card
|
||||
* but need serial number for Mac tokend
|
||||
* but need serial number for Mac tokend
|
||||
*/
|
||||
|
||||
r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial);
|
||||
|
@ -671,36 +681,36 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
|
|||
strncpy(obj_obj.label, objects[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
|
||||
obj_obj.flags = objects[i].obj_flags;
|
||||
|
||||
r = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT,
|
||||
&obj_obj, &obj_info);
|
||||
r = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT,
|
||||
&obj_obj, &obj_info);
|
||||
if (r < 0)
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
/* TODO
|
||||
* PIV key 9C requires the pin verify be done just before any
|
||||
* crypto operation using the key.
|
||||
*
|
||||
* crypto operation using the key.
|
||||
*
|
||||
* Nss 3.12.7 does not check the CKA_ALWAYS_AUTHENTICATE attribute of a key
|
||||
* and will do a C_FindObjects with only CKA_VALUE looking for a certificate
|
||||
* it had found earlier after c_Login. The template does not add CKA_TYPE=cert.
|
||||
* This will cause the card-piv to read all the objects and will reset
|
||||
* the security status for the 9C key.
|
||||
* Mozilla Bug 357025
|
||||
* Mozilla Bug 357025
|
||||
* Mozilla Bug 613507
|
||||
* on 5/16/2012, both scheduled for NSS 3.14
|
||||
*
|
||||
* on 5/16/2012, both scheduled for NSS 3.14
|
||||
*
|
||||
* We can not read all the objects, as some need the PIN!
|
||||
*/
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* certs, pubkeys and priv keys are related and we assume
|
||||
* they are in order
|
||||
* We need to read the cert, get modulus and keylen
|
||||
* We use those for the pubkey, and priv key objects.
|
||||
* they are in order
|
||||
* We need to read the cert, get modulus and keylen
|
||||
* We use those for the pubkey, and priv key objects.
|
||||
* If no cert, then see if pubkey (i.e. we are initializing,
|
||||
* and the pubkey is in a file,) then add pubkey and privkey
|
||||
* If no cert and no pubkey, skip adding them.
|
||||
|
||||
* If no cert and no pubkey, skip adding them.
|
||||
|
||||
*/
|
||||
/* set certs */
|
||||
sc_log(card->ctx, "PIV-II adding certs...");
|
||||
|
@ -789,7 +799,7 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* get keyUsage if present save in ckis[i]
|
||||
* Will only use it if this in a non FED issued card
|
||||
* which has a CHUID with FASC-N not starting with 9999
|
||||
|
@ -973,9 +983,9 @@ sc_log(card->ctx, "DEE Adding pin %d label=%s",i, label);
|
|||
|
||||
/* set public keys */
|
||||
/* We may only need this during initialization when genkey
|
||||
* gets the pubkey, but it can not be read from the card
|
||||
* gets the pubkey, but it can not be read from the card
|
||||
* at a later time. The piv-tool can stash pubkey in file
|
||||
*/
|
||||
*/
|
||||
sc_log(card->ctx, "PIV-II adding pub keys...");
|
||||
for (i = 0; i < PIV_NUM_CERTS_AND_KEYS; i++) {
|
||||
struct sc_pkcs15_pubkey_info pubkey_info;
|
||||
|
@ -1002,7 +1012,7 @@ sc_log(card->ctx, "DEE Adding pin %d label=%s",i, label);
|
|||
|
||||
/* If no cert found, piv-tool may have stashed the pubkey
|
||||
* so we can use it when generating a certificate request
|
||||
* The file is a OpenSSL DER EVP_KEY, which looks like
|
||||
* The file is a OpenSSL DER EVP_KEY, which looks like
|
||||
* a certificate subjectPublicKeyInfo.
|
||||
*
|
||||
*/
|
||||
|
@ -1011,7 +1021,7 @@ sc_log(card->ctx, "DEE Adding pin %d label=%s",i, label);
|
|||
|
||||
sc_log(card->ctx, "No cert for this pub key i=%d",i);
|
||||
|
||||
/*
|
||||
/*
|
||||
* If we used the piv-tool to generate a key,
|
||||
* we would have saved the public key as a file.
|
||||
* This code is only used while signing a request
|
||||
|
@ -1020,15 +1030,15 @@ sc_log(card->ctx, "DEE Adding pin %d label=%s",i, label);
|
|||
*/
|
||||
|
||||
|
||||
sc_log(card->ctx, "DEE look for env %s",
|
||||
sc_log(card->ctx, "DEE look for env %s",
|
||||
pubkeys[i].getenvname?pubkeys[i].getenvname:"NULL");
|
||||
|
||||
if (pubkeys[i].getenvname == NULL)
|
||||
if (pubkeys[i].getenvname == NULL)
|
||||
continue;
|
||||
|
||||
filename = getenv(pubkeys[i].getenvname);
|
||||
filename = getenv(pubkeys[i].getenvname);
|
||||
sc_log(card->ctx, "DEE look for file %s", filename?filename:"NULL");
|
||||
if (filename == NULL)
|
||||
if (filename == NULL)
|
||||
continue;
|
||||
|
||||
sc_log(card->ctx, "Adding pubkey from file %s",filename);
|
||||
|
@ -1044,16 +1054,16 @@ sc_log(card->ctx, "DEE Adding pin %d label=%s",i, label);
|
|||
LOG_TEST_GOTO_ERR(card->ctx, r, "SPKI encode public key error");
|
||||
|
||||
/* Only get here if no cert, and the the above found the
|
||||
* pub key file (actually the SPKI version). This only
|
||||
* happens when trying initializing a card and have set
|
||||
* env PIV_9A_KEY or 9C, 9D, 9E to point at the file.
|
||||
* pub key file (actually the SPKI version). This only
|
||||
* happens when trying initializing a card and have set
|
||||
* env PIV_9A_KEY or 9C, 9D, 9E to point at the file.
|
||||
*
|
||||
* We will cache it using the PKCS15 emulation objects
|
||||
*/
|
||||
|
||||
pubkey_info.path.len = 0;
|
||||
|
||||
ckis[i].key_alg = p15_key->algorithm;
|
||||
ckis[i].key_alg = p15_key->algorithm;
|
||||
switch (p15_key->algorithm) {
|
||||
case SC_ALGORITHM_RSA:
|
||||
/* save pubkey_len in pub and priv */
|
||||
|
@ -1107,7 +1117,7 @@ sc_log(card->ctx, "DEE Adding pin %d label=%s",i, label);
|
|||
pubkey_info.usage = pubkeys[i].usage_ec;
|
||||
}
|
||||
|
||||
pubkey_info.field_length = ckis[i].pubkey_len;
|
||||
pubkey_info.field_length = ckis[i].pubkey_len;
|
||||
strncpy(pubkey_obj.label, pubkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
|
||||
|
||||
/* should not fail */
|
||||
|
@ -1121,7 +1131,7 @@ sc_log(card->ctx, "DEE Adding pin %d label=%s",i, label);
|
|||
continue;
|
||||
}
|
||||
sc_log(card->ctx, "USAGE: cert_keyUsage_present:%d usage:0x%8.8x",
|
||||
ckis[i].cert_keyUsage_present ,pubkey_info.usage);
|
||||
ckis[i].cert_keyUsage_present ,pubkey_info.usage);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1150,10 +1160,10 @@ sc_log(card->ctx, "DEE Adding pin %d label=%s",i, label);
|
|||
sc_pkcs15_format_id(prkeys[i].auth_id, &prkey_obj.auth_id);
|
||||
|
||||
/*
|
||||
* When no cert is present and a pubkey in a file was found,
|
||||
* When no cert is present and a pubkey in a file was found,
|
||||
* means the caller is initializing a card. A sign operation
|
||||
* will be required to sign a certificate request even if
|
||||
* normal usage would not allow it. Set SC_PKCS15_PRKEY_USAGE_SIGN
|
||||
* will be required to sign a certificate request even if
|
||||
* normal usage would not allow it. Set SC_PKCS15_PRKEY_USAGE_SIGN
|
||||
* TODO if code is added to allow key generation and request
|
||||
* sign in the same session, similar code will be needed.
|
||||
*/
|
||||
|
|
|
@ -527,7 +527,9 @@ sc_pkcs15_prkey_attrs_from_cert(struct sc_pkcs15_card *p15card, struct sc_pkcs15
|
|||
|
||||
key_info = (struct sc_pkcs15_prkey_info *) key_object->data;
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
ERR_load_ERR_strings();
|
||||
#endif
|
||||
ERR_load_crypto_strings();
|
||||
|
||||
sc_log(ctx, "CertValue(%"SC_FORMAT_LEN_SIZE_T"u) %p",
|
||||
|
@ -617,6 +619,14 @@ sc_pkcs15_free_prkey(struct sc_pkcs15_prkey *key)
|
|||
if (key->u.ec.ecpointQ.value)
|
||||
free(key->u.ec.ecpointQ.value);
|
||||
break;
|
||||
case SC_ALGORITHM_EDDSA:
|
||||
free(key->u.eddsa.pubkey.value);
|
||||
key->u.eddsa.pubkey.value = NULL;
|
||||
key->u.eddsa.pubkey.len = 0;
|
||||
free(key->u.eddsa.value.value);
|
||||
key->u.eddsa.value.value = NULL;
|
||||
key->u.eddsa.value.len = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -718,13 +728,13 @@ sc_pkcs15_convert_prkey(struct sc_pkcs15_prkey *pkcs15_key, void *evp_key)
|
|||
}
|
||||
case EVP_PKEY_EC: {
|
||||
struct sc_pkcs15_prkey_ec *dst = &pkcs15_key->u.ec;
|
||||
EC_KEY *src = NULL;
|
||||
const EC_KEY *src = NULL;
|
||||
const EC_GROUP *grp = NULL;
|
||||
unsigned char buf[255];
|
||||
size_t buflen = 255;
|
||||
int nid;
|
||||
|
||||
src = EVP_PKEY_get0(pk);
|
||||
src = EVP_PKEY_get0_EC_KEY(pk);
|
||||
assert(src);
|
||||
assert(EC_KEY_get0_private_key(src));
|
||||
assert(EC_KEY_get0_public_key(src));
|
||||
|
@ -783,6 +793,13 @@ sc_pkcs15_convert_prkey(struct sc_pkcs15_prkey *pkcs15_key, void *evp_key)
|
|||
break;
|
||||
}
|
||||
#endif /* !defined(OPENSSL_NO_EC) */
|
||||
#ifdef EVP_PKEY_ED25519
|
||||
case EVP_PKEY_ED25519: {
|
||||
/* TODO */
|
||||
break;
|
||||
}
|
||||
#endif /* EVP_PKEY_ED25519 */
|
||||
|
||||
default:
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
|
|
@ -580,6 +580,12 @@ static struct sc_asn1_entry c_asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE] = {
|
|||
{ NULL, 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
#define C_ASN1_EDDSA_PUBKEY_SIZE 2
|
||||
static struct sc_asn1_entry c_asn1_eddsa_pubkey[C_ASN1_EDDSA_PUBKEY_SIZE] = {
|
||||
{ "pubkey", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_ALLOC, NULL, NULL },
|
||||
{ NULL, 0, 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
sc_pkcs15_decode_pubkey_rsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_rsa *key,
|
||||
|
@ -767,6 +773,47 @@ sc_pkcs15_encode_pubkey_ec(sc_context_t *ctx, struct sc_pkcs15_pubkey_ec *key,
|
|||
sc_asn1_encode(ctx, asn1_ec_pointQ, buf, buflen));
|
||||
}
|
||||
|
||||
/*
|
||||
* EdDSA keys are just byte strings. For now only
|
||||
* for Ed25519 keys 32B length are supported
|
||||
*/
|
||||
int
|
||||
sc_pkcs15_decode_pubkey_eddsa(sc_context_t *ctx,
|
||||
struct sc_pkcs15_pubkey_eddsa *key,
|
||||
const u8 *buf, size_t buflen)
|
||||
{
|
||||
int r;
|
||||
u8 * pubkey = NULL;
|
||||
size_t pubkey_len;
|
||||
struct sc_asn1_entry asn1_eddsa_pubkey[C_ASN1_EDDSA_PUBKEY_SIZE];
|
||||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
sc_copy_asn1_entry(c_asn1_eddsa_pubkey, asn1_eddsa_pubkey);
|
||||
sc_format_asn1_entry(asn1_eddsa_pubkey + 0, &pubkey, &pubkey_len, 1);
|
||||
r = sc_asn1_decode(ctx, asn1_eddsa_pubkey, buf, buflen, NULL, NULL);
|
||||
if (r < 0)
|
||||
LOG_TEST_RET(ctx, r, "ASN.1 decoding failed");
|
||||
|
||||
key->pubkey.len = pubkey_len;
|
||||
key->pubkey.value = pubkey;
|
||||
|
||||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||
}
|
||||
|
||||
int
|
||||
sc_pkcs15_encode_pubkey_eddsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_eddsa *key,
|
||||
u8 **buf, size_t *buflen)
|
||||
{
|
||||
struct sc_asn1_entry asn1_eddsa_pubkey[C_ASN1_EDDSA_PUBKEY_SIZE];
|
||||
|
||||
LOG_FUNC_CALLED(ctx);
|
||||
sc_copy_asn1_entry(c_asn1_eddsa_pubkey, asn1_eddsa_pubkey);
|
||||
sc_format_asn1_entry(asn1_eddsa_pubkey + 0, key->pubkey.value, &key->pubkey.len, 1);
|
||||
|
||||
LOG_FUNC_RETURN(ctx,
|
||||
sc_asn1_encode(ctx, asn1_eddsa_pubkey, buf, buflen));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sc_pkcs15_encode_pubkey(sc_context_t *ctx, struct sc_pkcs15_pubkey *key,
|
||||
|
@ -780,6 +827,9 @@ sc_pkcs15_encode_pubkey(sc_context_t *ctx, struct sc_pkcs15_pubkey *key,
|
|||
return sc_pkcs15_encode_pubkey_gostr3410(ctx, &key->u.gostr3410, buf, len);
|
||||
if (key->algorithm == SC_ALGORITHM_EC)
|
||||
return sc_pkcs15_encode_pubkey_ec(ctx, &key->u.ec, buf, len);
|
||||
if (key->algorithm == SC_ALGORITHM_EDDSA ||
|
||||
key->algorithm == SC_ALGORITHM_XEDDSA) /* XXX encoding is the same here */
|
||||
return sc_pkcs15_encode_pubkey_eddsa(ctx, &key->u.eddsa, buf, len);
|
||||
|
||||
sc_log(ctx, "Encoding of public key type %u not supported", key->algorithm);
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
|
@ -862,6 +912,14 @@ sc_pkcs15_encode_pubkey_as_spki(sc_context_t *ctx, struct sc_pkcs15_pubkey *pubk
|
|||
r = sc_pkcs15_encode_pubkey(ctx, pubkey, &pkey.value, &pkey.len);
|
||||
key_len = pkey.len * 8;
|
||||
break;
|
||||
case SC_ALGORITHM_EDDSA:
|
||||
case SC_ALGORITHM_XEDDSA:
|
||||
/* For a SPKI, the pubkey is placed directly in the BIT STRING */
|
||||
pkey.value = malloc(pubkey->u.eddsa.pubkey.len);
|
||||
memcpy(pkey.value, pubkey->u.eddsa.pubkey.value, pubkey->u.eddsa.pubkey.len);
|
||||
// Should be pkey.len = 0 there?
|
||||
key_len = pubkey->u.eddsa.pubkey.len * 8;
|
||||
break;
|
||||
default:
|
||||
r = sc_pkcs15_encode_pubkey(ctx, pubkey, &pkey.value, &pkey.len);
|
||||
key_len = pkey.len * 8;
|
||||
|
@ -897,6 +955,9 @@ sc_pkcs15_decode_pubkey(sc_context_t *ctx, struct sc_pkcs15_pubkey *key,
|
|||
return sc_pkcs15_decode_pubkey_gostr3410(ctx, &key->u.gostr3410, buf, len);
|
||||
if (key->algorithm == SC_ALGORITHM_EC)
|
||||
return sc_pkcs15_decode_pubkey_ec(ctx, &key->u.ec, buf, len);
|
||||
if (key->algorithm == SC_ALGORITHM_EDDSA ||
|
||||
key->algorithm == SC_ALGORITHM_XEDDSA)
|
||||
return sc_pkcs15_decode_pubkey_eddsa(ctx, &key->u.eddsa, buf, len);
|
||||
|
||||
sc_log(ctx, "Decoding of public key type %u not supported", key->algorithm);
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
|
@ -939,6 +1000,12 @@ sc_pkcs15_read_pubkey(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_obj
|
|||
case SC_PKCS15_TYPE_PUBKEY_EC:
|
||||
algorithm = SC_ALGORITHM_EC;
|
||||
break;
|
||||
case SC_PKCS15_TYPE_PUBKEY_EDDSA:
|
||||
algorithm = SC_ALGORITHM_EDDSA;
|
||||
break;
|
||||
case SC_PKCS15_TYPE_PUBKEY_XEDDSA:
|
||||
algorithm = SC_ALGORITHM_XEDDSA;
|
||||
break;
|
||||
default:
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Unsupported public key type.");
|
||||
}
|
||||
|
@ -984,7 +1051,8 @@ sc_pkcs15_read_pubkey(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_obj
|
|||
r = sc_pkcs15_read_file(p15card, &info->path, &data, &len);
|
||||
LOG_TEST_GOTO_ERR(ctx, r, "Failed to read public key file.");
|
||||
|
||||
if (algorithm == SC_ALGORITHM_EC && *data == (SC_ASN1_TAG_SEQUENCE | SC_ASN1_TAG_CONSTRUCTED))
|
||||
if ((algorithm == SC_ALGORITHM_EC || algorithm == SC_ALGORITHM_EDDSA || algorithm == SC_ALGORITHM_XEDDSA)
|
||||
&& *data == (SC_ASN1_TAG_SEQUENCE | SC_ASN1_TAG_CONSTRUCTED))
|
||||
r = sc_pkcs15_pubkey_from_spki_sequence(ctx, data, len, &pubkey);
|
||||
else
|
||||
r = sc_pkcs15_decode_pubkey(ctx, pubkey, data, len);
|
||||
|
@ -1067,6 +1135,22 @@ sc_pkcs15_pubkey_from_prvkey(struct sc_context *ctx, struct sc_pkcs15_prkey *prv
|
|||
}
|
||||
memcpy(pubkey->u.ec.ecpointQ.value, prvkey->u.ec.ecpointQ.value, prvkey->u.ec.ecpointQ.len);
|
||||
pubkey->u.ec.ecpointQ.len = prvkey->u.ec.ecpointQ.len;
|
||||
break;
|
||||
case SC_ALGORITHM_EDDSA:
|
||||
case SC_ALGORITHM_XEDDSA:
|
||||
/* Copy pubkey */
|
||||
if (prvkey->u.eddsa.pubkey.value == NULL || prvkey->u.eddsa.pubkey.len <= 0) {
|
||||
sc_pkcs15_free_pubkey(pubkey);
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
|
||||
}
|
||||
pubkey->u.eddsa.pubkey.value = malloc(prvkey->u.eddsa.pubkey.len);
|
||||
if (!pubkey->u.eddsa.pubkey.value) {
|
||||
sc_pkcs15_free_pubkey(pubkey);
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
memcpy(pubkey->u.eddsa.pubkey.value, prvkey->u.eddsa.pubkey.value, prvkey->u.eddsa.pubkey.len);
|
||||
pubkey->u.eddsa.pubkey.len = prvkey->u.eddsa.pubkey.len;
|
||||
|
||||
break;
|
||||
default:
|
||||
sc_log(ctx, "Unsupported private key algorithm");
|
||||
|
@ -1160,6 +1244,18 @@ sc_pkcs15_dup_pubkey(struct sc_context *ctx, struct sc_pkcs15_pubkey *key, struc
|
|||
rv = SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
break;
|
||||
case SC_ALGORITHM_EDDSA:
|
||||
case SC_ALGORITHM_XEDDSA:
|
||||
/* Copy pubkey */
|
||||
pubkey->u.eddsa.pubkey.value = malloc(key->u.eddsa.pubkey.len);
|
||||
if (!pubkey->u.eddsa.pubkey.value) {
|
||||
rv = SC_ERROR_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
memcpy(pubkey->u.eddsa.pubkey.value, key->u.eddsa.pubkey.value, key->u.eddsa.pubkey.len);
|
||||
pubkey->u.eddsa.pubkey.len = key->u.eddsa.pubkey.len;
|
||||
|
||||
break;
|
||||
default:
|
||||
sc_log(ctx, "Unsupported private key algorithm");
|
||||
|
@ -1215,6 +1311,12 @@ sc_pkcs15_erase_pubkey(struct sc_pkcs15_pubkey *key)
|
|||
if (key->u.ec.ecpointQ.value)
|
||||
free(key->u.ec.ecpointQ.value);
|
||||
break;
|
||||
case SC_ALGORITHM_EDDSA:
|
||||
case SC_ALGORITHM_XEDDSA:
|
||||
free(key->u.eddsa.pubkey.value);
|
||||
key->u.eddsa.pubkey.value = NULL;
|
||||
key->u.eddsa.pubkey.len = 0;
|
||||
break;
|
||||
}
|
||||
sc_mem_clear(key, sizeof(*key));
|
||||
}
|
||||
|
@ -1413,8 +1515,13 @@ sc_pkcs15_pubkey_from_spki_fields(struct sc_context *ctx, struct sc_pkcs15_pubke
|
|||
}
|
||||
memcpy(pubkey->u.ec.ecpointQ.value, pk.value, pk.len);
|
||||
pubkey->u.ec.ecpointQ.len = pk.len;
|
||||
}
|
||||
else {
|
||||
} else if (pk_alg.algorithm == SC_ALGORITHM_EDDSA ||
|
||||
pk_alg.algorithm == SC_ALGORITHM_XEDDSA) {
|
||||
/* EDDSA/XEDDSA public key is not encapsulated into BIT STRING -- it's a BIT STRING */
|
||||
pubkey->u.eddsa.pubkey.value = malloc(pk.len);
|
||||
memcpy(pubkey->u.eddsa.pubkey.value, pk.value, pk.len);
|
||||
pubkey->u.eddsa.pubkey.len = pk.len;
|
||||
} else {
|
||||
/* Public key is expected to be encapsulated into BIT STRING */
|
||||
r = sc_pkcs15_decode_pubkey(ctx, pubkey, pk.value, pk.len);
|
||||
LOG_TEST_GOTO_ERR(ctx, r, "ASN.1 parsing of subjectPubkeyInfo failed");
|
||||
|
@ -1517,7 +1624,11 @@ static struct ec_curve_info {
|
|||
|
||||
{"secp192k1", "1.3.132.0.31", "06052B8104001F", 192},
|
||||
{"secp256k1", "1.3.132.0.10", "06052B8104000A", 256},
|
||||
{NULL, NULL, NULL, 0},
|
||||
|
||||
{"ed25519", "1.3.6.1.4.1.11591.15.1", "06092B06010401DA470F01", 255},
|
||||
{"curve25519", "1.3.6.1.4.1.3029.1.5.1", "060A2B060104019755010501", 255},
|
||||
|
||||
{NULL, NULL, NULL, 0}, /* Do not touch this */
|
||||
};
|
||||
|
||||
|
||||
|
@ -1672,13 +1783,13 @@ sc_pkcs15_convert_pubkey(struct sc_pkcs15_pubkey *pkcs15_key, void *evp_key)
|
|||
}
|
||||
case EVP_PKEY_EC: {
|
||||
struct sc_pkcs15_pubkey_ec *dst = &pkcs15_key->u.ec;
|
||||
EC_KEY *src = NULL;
|
||||
const EC_KEY *src = NULL;
|
||||
const EC_GROUP *grp = NULL;
|
||||
unsigned char buf[255];
|
||||
size_t buflen = 255;
|
||||
int nid;
|
||||
|
||||
src = EVP_PKEY_get0(pk);
|
||||
src = EVP_PKEY_get0_EC_KEY(pk);
|
||||
assert(src);
|
||||
assert(EC_KEY_get0_public_key(src));
|
||||
|
||||
|
@ -1715,6 +1826,12 @@ sc_pkcs15_convert_pubkey(struct sc_pkcs15_pubkey *pkcs15_key, void *evp_key)
|
|||
break;
|
||||
}
|
||||
#endif /* !defined(OPENSSL_NO_EC) */
|
||||
#ifdef EVP_PKEY_ED25519
|
||||
case EVP_PKEY_ED25519: {
|
||||
/* TODO */
|
||||
break;
|
||||
}
|
||||
#endif /* EVP_PKEY_ED25519 */
|
||||
default:
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
|
|
@ -1026,7 +1026,7 @@ static int sc_pkcs15emu_sc_hsm_init (sc_pkcs15_card_t * p15card)
|
|||
r = sc_pin_cmd(card, &pindata, NULL);
|
||||
}
|
||||
|
||||
if ((r != SC_ERROR_DATA_OBJECT_NOT_FOUND) && (r != SC_ERROR_INCORRECT_PARAMETERS))
|
||||
if ((r != SC_ERROR_DATA_OBJECT_NOT_FOUND) && (r != SC_ERROR_INCORRECT_PARAMETERS) && (r != SC_ERROR_REF_DATA_NOT_USABLE))
|
||||
card->caps |= SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH;
|
||||
|
||||
|
||||
|
|
|
@ -166,7 +166,7 @@ static int use_key(struct sc_pkcs15_card *p15card,
|
|||
|
||||
sc_unlock(p15card->card);
|
||||
|
||||
return r;
|
||||
LOG_FUNC_RETURN(p15card->card->ctx, r);
|
||||
}
|
||||
|
||||
static int format_senv(struct sc_pkcs15_card *p15card,
|
||||
|
@ -213,6 +213,28 @@ static int format_senv(struct sc_pkcs15_card *p15card,
|
|||
senv_out->algorithm = SC_ALGORITHM_GOSTR3410;
|
||||
break;
|
||||
|
||||
case SC_PKCS15_TYPE_PRKEY_EDDSA:
|
||||
*alg_info_out = sc_card_find_eddsa_alg(p15card->card, prkey->field_length, NULL);
|
||||
if (*alg_info_out == NULL) {
|
||||
sc_log(ctx,
|
||||
"Card does not support EDDSA with field_size %"SC_FORMAT_LEN_SIZE_T"u",
|
||||
prkey->field_length);
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
senv_out->algorithm = SC_ALGORITHM_EDDSA;
|
||||
break;
|
||||
|
||||
case SC_PKCS15_TYPE_PRKEY_XEDDSA:
|
||||
*alg_info_out = sc_card_find_xeddsa_alg(p15card->card, prkey->field_length, NULL);
|
||||
if (*alg_info_out == NULL) {
|
||||
sc_log(ctx,
|
||||
"Card does not support XEDDSA with field_size %"SC_FORMAT_LEN_SIZE_T"u",
|
||||
prkey->field_length);
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
senv_out->algorithm = SC_ALGORITHM_XEDDSA;
|
||||
break;
|
||||
|
||||
case SC_PKCS15_TYPE_PRKEY_EC:
|
||||
*alg_info_out = sc_card_find_ec_alg(p15card->card, prkey->field_length, NULL);
|
||||
if (*alg_info_out == NULL) {
|
||||
|
@ -320,6 +342,7 @@ int sc_pkcs15_derive(struct sc_pkcs15_card *p15card,
|
|||
|
||||
switch (obj->type) {
|
||||
case SC_PKCS15_TYPE_PRKEY_EC:
|
||||
case SC_PKCS15_TYPE_PRKEY_XEDDSA:
|
||||
if (out == NULL || *poutlen < (prkey->field_length + 7) / 8) {
|
||||
*poutlen = (prkey->field_length + 7) / 8;
|
||||
r = 0; /* say no data to return */
|
||||
|
@ -580,7 +603,9 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
|
|||
modlen = (prkey->modulus_length + 7) / 8 * 2;
|
||||
break;
|
||||
case SC_PKCS15_TYPE_PRKEY_EC:
|
||||
modlen = ((prkey->field_length +7) / 8) * 2; /* 2*nLen */
|
||||
case SC_PKCS15_TYPE_PRKEY_EDDSA:
|
||||
case SC_PKCS15_TYPE_PRKEY_XEDDSA:
|
||||
modlen = ((prkey->field_length +7) / 8) * 2; /* 2*nLen */
|
||||
break;
|
||||
default:
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Key type not supported");
|
||||
|
@ -608,56 +633,69 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
|
|||
|
||||
/* if the card has SC_ALGORITHM_NEED_USAGE set, and the
|
||||
* key is for signing and decryption, we need to emulate signing */
|
||||
/* TODO: -DEE assume only RSA keys will ever use _NEED_USAGE */
|
||||
|
||||
sc_log(ctx, "supported algorithm flags 0x%X, private key usage 0x%X", alg_info->flags, prkey->usage);
|
||||
if ((alg_info->flags & SC_ALGORITHM_NEED_USAGE) &&
|
||||
((prkey->usage & USAGE_ANY_SIGN) &&
|
||||
(prkey->usage & USAGE_ANY_DECIPHER)) ) {
|
||||
size_t tmplen = sizeof(buf);
|
||||
if (flags & SC_ALGORITHM_RSA_RAW) {
|
||||
r = sc_pkcs15_decipher(p15card, obj, flags, in, inlen, out, outlen);
|
||||
if (obj->type == SC_PKCS15_TYPE_PRKEY_RSA) {
|
||||
if ((alg_info->flags & SC_ALGORITHM_NEED_USAGE) &&
|
||||
((prkey->usage & USAGE_ANY_SIGN) &&
|
||||
(prkey->usage & USAGE_ANY_DECIPHER)) ) {
|
||||
size_t tmplen = sizeof(buf);
|
||||
if (flags & SC_ALGORITHM_RSA_RAW) {
|
||||
r = sc_pkcs15_decipher(p15card, obj, flags, in, inlen, out, outlen);
|
||||
LOG_FUNC_RETURN(ctx, r);
|
||||
}
|
||||
if (modlen > tmplen)
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "Buffer too small, needs recompile!");
|
||||
|
||||
/* XXX Assuming RSA key here */
|
||||
r = sc_pkcs1_encode(ctx, flags, in, inlen, buf, &tmplen, prkey->modulus_length);
|
||||
|
||||
/* no padding needed - already done */
|
||||
flags &= ~SC_ALGORITHM_RSA_PADS;
|
||||
/* instead use raw rsa */
|
||||
flags |= SC_ALGORITHM_RSA_RAW;
|
||||
|
||||
LOG_TEST_RET(ctx, r, "Unable to add padding");
|
||||
|
||||
r = sc_pkcs15_decipher(p15card, obj, flags, buf, modlen, out, outlen);
|
||||
LOG_FUNC_RETURN(ctx, r);
|
||||
}
|
||||
if (modlen > tmplen)
|
||||
LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "Buffer too small, needs recompile!");
|
||||
|
||||
/* XXX Assuming RSA key here */
|
||||
r = sc_pkcs1_encode(ctx, flags, in, inlen, buf, &tmplen, prkey->modulus_length);
|
||||
|
||||
/* no padding needed - already done */
|
||||
flags &= ~SC_ALGORITHM_RSA_PADS;
|
||||
/* instead use raw rsa */
|
||||
flags |= SC_ALGORITHM_RSA_RAW;
|
||||
/* If the card doesn't support the requested algorithm, we normally add the
|
||||
* padding here in software and ask the card to do a raw signature. There's
|
||||
* one exception to that, where we might be able to get the signature to
|
||||
* succeed by stripping padding if the card only offers higher-level
|
||||
* signature operations. The only thing we can strip is the DigestInfo
|
||||
* block from PKCS1 padding. */
|
||||
if ((flags == (SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE)) &&
|
||||
!(alg_info->flags & SC_ALGORITHM_RSA_RAW) &&
|
||||
!(alg_info->flags & SC_ALGORITHM_RSA_HASH_NONE) &&
|
||||
(alg_info->flags & SC_ALGORITHM_RSA_PAD_PKCS1)) {
|
||||
unsigned int algo;
|
||||
size_t tmplen = sizeof(buf);
|
||||
|
||||
LOG_TEST_RET(ctx, r, "Unable to add padding");
|
||||
|
||||
r = sc_pkcs15_decipher(p15card, obj, flags, buf, modlen, out, outlen);
|
||||
LOG_FUNC_RETURN(ctx, r);
|
||||
r = sc_pkcs1_strip_digest_info_prefix(&algo, tmp, inlen, tmp, &tmplen);
|
||||
if (r != SC_SUCCESS || algo == SC_ALGORITHM_RSA_HASH_NONE) {
|
||||
sc_mem_clear(buf, sizeof(buf));
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
|
||||
}
|
||||
flags &= ~SC_ALGORITHM_RSA_HASH_NONE;
|
||||
flags |= algo;
|
||||
inlen = tmplen;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* If the card doesn't support the requested algorithm, we normally add the
|
||||
* padding here in software and ask the card to do a raw signature. There's
|
||||
* one exception to that, where we might be able to get the signature to
|
||||
* succeed by stripping padding if the card only offers higher-level
|
||||
* signature operations. The only thing we can strip is the DigestInfo
|
||||
* block from PKCS1 padding. */
|
||||
if ((flags == (SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE)) &&
|
||||
!(alg_info->flags & SC_ALGORITHM_RSA_RAW) &&
|
||||
!(alg_info->flags & SC_ALGORITHM_RSA_HASH_NONE) &&
|
||||
(alg_info->flags & SC_ALGORITHM_RSA_PAD_PKCS1)) {
|
||||
unsigned int algo;
|
||||
size_t tmplen = sizeof(buf);
|
||||
|
||||
r = sc_pkcs1_strip_digest_info_prefix(&algo, tmp, inlen, tmp, &tmplen);
|
||||
if (r != SC_SUCCESS || algo == SC_ALGORITHM_RSA_HASH_NONE) {
|
||||
sc_mem_clear(buf, sizeof(buf));
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
|
||||
/* ECDSA sofware hash has already been done, or is not needed, or card will do hash */
|
||||
/* if card can not do the hash, will use SC_ALGORITHM_ECDSA_RAW */
|
||||
if (obj->type == SC_PKCS15_TYPE_PRKEY_EC) {
|
||||
if ((alg_info->flags & SC_ALGORITHM_ECDSA_RAW)
|
||||
&& !(flags & SC_ALGORITHM_ECDSA_HASHES & alg_info->flags)) {
|
||||
sc_log(ctx, "ECDSA using SC_ALGORITHM_ECDSA_RAW flags before 0x%8.8lx", flags);
|
||||
flags |= SC_ALGORITHM_ECDSA_RAW;
|
||||
flags &= ~SC_ALGORITHM_ECDSA_HASHES;
|
||||
}
|
||||
flags &= ~SC_ALGORITHM_RSA_HASH_NONE;
|
||||
flags |= algo;
|
||||
inlen = tmplen;
|
||||
}
|
||||
|
||||
r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags);
|
||||
|
@ -665,6 +703,7 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
|
|||
sc_mem_clear(buf, sizeof(buf));
|
||||
LOG_FUNC_RETURN(ctx, r);
|
||||
}
|
||||
/* senv now has flags card or driver will do */
|
||||
senv.algorithm_flags = sec_flags;
|
||||
|
||||
sc_log(ctx, "DEE flags:0x%8.8lx alg_info->flags:0x%8.8x pad:0x%8.8lx sec:0x%8.8lx",
|
||||
|
@ -695,9 +734,10 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
|
|||
* If the length of the hash value is larger than the bit length of n, only
|
||||
* the leftmost bits of the hash up to the length of n will be used. Any
|
||||
* truncation is done by the token.
|
||||
* But if card is going to do the hash, pass in all the data
|
||||
*/
|
||||
else if (senv.algorithm == SC_ALGORITHM_EC &&
|
||||
(flags & SC_ALGORITHM_ECDSA_HASH_NONE) != 0) {
|
||||
(senv.algorithm_flags & SC_ALGORITHM_ECDSA_HASHES) == 0) {
|
||||
inlen = MIN(inlen, (prkey->field_length+7)/8);
|
||||
}
|
||||
|
||||
|
|
|
@ -91,6 +91,8 @@ int sc_pkcs15_is_emulation_only(sc_card_t *card)
|
|||
case SC_CARD_TYPE_DNIE_USER:
|
||||
case SC_CARD_TYPE_DNIE_TERMINATED:
|
||||
case SC_CARD_TYPE_IASECC_GEMALTO:
|
||||
case SC_CARD_TYPE_IASECC_CPX:
|
||||
case SC_CARD_TYPE_IASECC_CPXCL:
|
||||
case SC_CARD_TYPE_PIV_II_GENERIC:
|
||||
case SC_CARD_TYPE_PIV_II_HIST:
|
||||
case SC_CARD_TYPE_PIV_II_NEO:
|
||||
|
@ -364,6 +366,7 @@ int sc_pkcs15emu_add_ec_prkey(sc_pkcs15_card_t *p15card,
|
|||
|
||||
return sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_PRKEY_EC, obj, &key);
|
||||
}
|
||||
|
||||
int sc_pkcs15emu_add_ec_pubkey(sc_pkcs15_card_t *p15card,
|
||||
const sc_pkcs15_object_t *obj, const sc_pkcs15_pubkey_info_t *in_key)
|
||||
{
|
||||
|
@ -375,6 +378,56 @@ int sc_pkcs15emu_add_ec_pubkey(sc_pkcs15_card_t *p15card,
|
|||
return sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_PUBKEY_EC, obj, &key);
|
||||
}
|
||||
|
||||
int sc_pkcs15emu_add_eddsa_prkey(sc_pkcs15_card_t *p15card,
|
||||
const sc_pkcs15_object_t *obj, const sc_pkcs15_prkey_info_t *in_key)
|
||||
{
|
||||
sc_pkcs15_prkey_info_t key = *in_key;
|
||||
|
||||
if (key.access_flags == 0)
|
||||
key.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE
|
||||
| SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE
|
||||
| SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE
|
||||
| SC_PKCS15_PRKEY_ACCESS_LOCAL;
|
||||
|
||||
return sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_PRKEY_EDDSA, obj, &key);
|
||||
}
|
||||
|
||||
int sc_pkcs15emu_add_eddsa_pubkey(sc_pkcs15_card_t *p15card,
|
||||
const sc_pkcs15_object_t *obj, const sc_pkcs15_pubkey_info_t *in_key)
|
||||
{
|
||||
sc_pkcs15_pubkey_info_t key = *in_key;
|
||||
|
||||
if (key.access_flags == 0)
|
||||
key.access_flags = SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE;
|
||||
|
||||
return sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_PUBKEY_EDDSA, obj, &key);
|
||||
}
|
||||
|
||||
int sc_pkcs15emu_add_xeddsa_prkey(sc_pkcs15_card_t *p15card,
|
||||
const sc_pkcs15_object_t *obj, const sc_pkcs15_prkey_info_t *in_key)
|
||||
{
|
||||
sc_pkcs15_prkey_info_t key = *in_key;
|
||||
|
||||
if (key.access_flags == 0)
|
||||
key.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE
|
||||
| SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE
|
||||
| SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE
|
||||
| SC_PKCS15_PRKEY_ACCESS_LOCAL;
|
||||
|
||||
return sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_PRKEY_XEDDSA, obj, &key);
|
||||
}
|
||||
|
||||
int sc_pkcs15emu_add_xeddsa_pubkey(sc_pkcs15_card_t *p15card,
|
||||
const sc_pkcs15_object_t *obj, const sc_pkcs15_pubkey_info_t *in_key)
|
||||
{
|
||||
sc_pkcs15_pubkey_info_t key = *in_key;
|
||||
|
||||
if (key.access_flags == 0)
|
||||
key.access_flags = SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE;
|
||||
|
||||
return sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_PUBKEY_XEDDSA, obj, &key);
|
||||
}
|
||||
|
||||
int sc_pkcs15emu_add_x509_cert(sc_pkcs15_card_t *p15card,
|
||||
const sc_pkcs15_object_t *obj, const sc_pkcs15_cert_info_t *cert)
|
||||
{
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue