From 0b57dac8eaa7fc631088a36df2fa41eb496d4c8c Mon Sep 17 00:00:00 2001 From: Will Martin Date: Tue, 18 Apr 2023 14:12:10 -0400 Subject: [PATCH 01/14] Docker build (#496) # PR Details ## Description These changes are meant to reduce the docker size by introducing multi-stage builds. These changes implement a build stage and a final image stage. The build stage builds everything needed to run V2X Hub. Finally, those required files and directories are copied into the final image, removing unnecessary files from the build. ## Related Issue ## Motivation and Context Reducing the size of the docker image creates a more efficient tool, taking up less storage space and reducing image download time. ## How Has This Been Tested? Built and tested locally, then pushed/pulled to/from docker hub and tested. Ensured plugins maintained functionality and required tools were present in the image. ## Types of changes - [ ] Defect fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that cause existing functionality to change) ## Checklist: - [ ] I have added any new packages to the sonar-scanner.properties file - [ ] My change requires a change to the documentation. - [ ] I have updated the documentation accordingly. - [ ] I have read the **CONTRIBUTING** document. [V2XHUB Contributing Guide](https://github.com/usdot-fhwa-OPS/V2X-Hub/blob/develop/Contributing.md) - [ ] I have added tests to cover my changes. - [ ] All new and existing tests passed. --- Dockerfile | 32 +- container/setup.sh | 3 - ext/pkcs11-proxy/.gitignore | 13 - ext/pkcs11-proxy/CMakeLists.txt | 46 - ext/pkcs11-proxy/CMakeLists.txtbackup | 45 - ext/pkcs11-proxy/Dockerfile.jenkins | 2 - ext/pkcs11-proxy/README.rst | 15 - ext/pkcs11-proxy/THANKS | 2 - ext/pkcs11-proxy/UPSTREAM_REV | 1 - ext/pkcs11-proxy/USAGE | 82 - ext/pkcs11-proxy/cmake_install.cmake | 97 - ext/pkcs11-proxy/config.h | 51 - ext/pkcs11-proxy/debian/.gitignore | 12 - ext/pkcs11-proxy/debian/changelog | 53 - ext/pkcs11-proxy/debian/compat | 1 - ext/pkcs11-proxy/debian/control | 22 - ext/pkcs11-proxy/debian/copyright | 18 - ext/pkcs11-proxy/debian/pkcs11-daemon.install | 1 - ext/pkcs11-proxy/debian/pkcs11-proxy1.install | 1 - ext/pkcs11-proxy/debian/rules | 4 - ext/pkcs11-proxy/debian/source/format | 1 - ext/pkcs11-proxy/egg-buffer.c | 544 ---- ext/pkcs11-proxy/egg-buffer.h | 194 -- ext/pkcs11-proxy/ext/include/dlfcn.h | 45 - ext/pkcs11-proxy/gck-rpc-daemon-standalone.c | 358 --- ext/pkcs11-proxy/gck-rpc-dispatch.c | 2735 ----------------- ext/pkcs11-proxy/gck-rpc-layer.h | 24 - ext/pkcs11-proxy/gck-rpc-message.c | 482 --- ext/pkcs11-proxy/gck-rpc-module.c | 2490 --------------- ext/pkcs11-proxy/gck-rpc-private.h | 327 -- ext/pkcs11-proxy/gck-rpc-tls-psk.c | 410 --- ext/pkcs11-proxy/gck-rpc-tls-psk.h | 36 - ext/pkcs11-proxy/gck-rpc-util.c | 284 -- ext/pkcs11-proxy/install_manifest.txt | 4 - ext/pkcs11-proxy/libpkcs11-proxy.so.0 | 1 - ext/pkcs11-proxy/libpkcs11-proxy.so.0.1 | Bin 144248 -> 0 bytes ext/pkcs11-proxy/mksyscalls.sh | 4 - ext/pkcs11-proxy/p11proxy-mitm | 528 ---- ext/pkcs11-proxy/pkcs11-daemon | Bin 160424 -> 0 bytes ext/pkcs11-proxy/pkcs11/pkcs11.h | 1312 -------- ext/pkcs11-proxy/pkcs11/pkcs11g.h | 100 - ext/pkcs11-proxy/pkcs11/pkcs11i.h | 77 - ext/pkcs11-proxy/pkcs11/pkcs11n.h | 221 -- ext/pkcs11-proxy/seccomp-bpf.h | 83 - ext/pkcs11-proxy/syscall-reporter.c | 80 - ext/pkcs11-proxy/syscall-reporter.h | 28 - scripts/deployment_dependencies.sh | 36 + src/tmx/Security/softhsm/CMakeLists.txt | 0 src/tmx/Security/softhsm/softhsm.cc | 23 - src/tmx/Security/softhsm/softhsm.h | 77 - src/tmx/Security/softhsm/token.h | 20 - src/v2i-hub/SpatPlugin/src/SpatPlugin.cpp | 6 - 52 files changed, 64 insertions(+), 10967 deletions(-) delete mode 100644 ext/pkcs11-proxy/.gitignore delete mode 100644 ext/pkcs11-proxy/CMakeLists.txt delete mode 100644 ext/pkcs11-proxy/CMakeLists.txtbackup delete mode 100644 ext/pkcs11-proxy/Dockerfile.jenkins delete mode 100644 ext/pkcs11-proxy/README.rst delete mode 100644 ext/pkcs11-proxy/THANKS delete mode 100644 ext/pkcs11-proxy/UPSTREAM_REV delete mode 100644 ext/pkcs11-proxy/USAGE delete mode 100644 ext/pkcs11-proxy/cmake_install.cmake delete mode 100644 ext/pkcs11-proxy/config.h delete mode 100644 ext/pkcs11-proxy/debian/.gitignore delete mode 100644 ext/pkcs11-proxy/debian/changelog delete mode 100644 ext/pkcs11-proxy/debian/compat delete mode 100755 ext/pkcs11-proxy/debian/control delete mode 100755 ext/pkcs11-proxy/debian/copyright delete mode 100644 ext/pkcs11-proxy/debian/pkcs11-daemon.install delete mode 100644 ext/pkcs11-proxy/debian/pkcs11-proxy1.install delete mode 100755 ext/pkcs11-proxy/debian/rules delete mode 100644 ext/pkcs11-proxy/debian/source/format delete mode 100644 ext/pkcs11-proxy/egg-buffer.c delete mode 100644 ext/pkcs11-proxy/egg-buffer.h delete mode 100644 ext/pkcs11-proxy/ext/include/dlfcn.h delete mode 100644 ext/pkcs11-proxy/gck-rpc-daemon-standalone.c delete mode 100644 ext/pkcs11-proxy/gck-rpc-dispatch.c delete mode 100644 ext/pkcs11-proxy/gck-rpc-layer.h delete mode 100644 ext/pkcs11-proxy/gck-rpc-message.c delete mode 100644 ext/pkcs11-proxy/gck-rpc-module.c delete mode 100644 ext/pkcs11-proxy/gck-rpc-private.h delete mode 100644 ext/pkcs11-proxy/gck-rpc-tls-psk.c delete mode 100644 ext/pkcs11-proxy/gck-rpc-tls-psk.h delete mode 100644 ext/pkcs11-proxy/gck-rpc-util.c delete mode 100644 ext/pkcs11-proxy/install_manifest.txt delete mode 120000 ext/pkcs11-proxy/libpkcs11-proxy.so.0 delete mode 100755 ext/pkcs11-proxy/libpkcs11-proxy.so.0.1 delete mode 100755 ext/pkcs11-proxy/mksyscalls.sh delete mode 100755 ext/pkcs11-proxy/p11proxy-mitm delete mode 100755 ext/pkcs11-proxy/pkcs11-daemon delete mode 100644 ext/pkcs11-proxy/pkcs11/pkcs11.h delete mode 100644 ext/pkcs11-proxy/pkcs11/pkcs11g.h delete mode 100644 ext/pkcs11-proxy/pkcs11/pkcs11i.h delete mode 100644 ext/pkcs11-proxy/pkcs11/pkcs11n.h delete mode 100644 ext/pkcs11-proxy/seccomp-bpf.h delete mode 100644 ext/pkcs11-proxy/syscall-reporter.c delete mode 100644 ext/pkcs11-proxy/syscall-reporter.h create mode 100755 scripts/deployment_dependencies.sh delete mode 100644 src/tmx/Security/softhsm/CMakeLists.txt delete mode 100644 src/tmx/Security/softhsm/softhsm.cc delete mode 100644 src/tmx/Security/softhsm/softhsm.h delete mode 100644 src/tmx/Security/softhsm/token.h diff --git a/Dockerfile b/Dockerfile index 03cd30559..9bf05373d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,11 @@ ARG UBUNTU_VERSION=jammy-20230126 -FROM ubuntu:$UBUNTU_VERSION +FROM ubuntu:$UBUNTU_VERSION AS dependencies ENV DEBIAN_FRONTEND=noninteractive ADD scripts/install_dependencies.sh /usr/local/bin/ -RUN sed -i 's|http://archive.ubuntu.com|http://us.archive.ubuntu.com|g' /etc/apt/sources.list && \ - /usr/local/bin/install_dependencies.sh +RUN sed -i 's|http://archive.ubuntu.com|http://us.archive.ubuntu.com|g' /etc/apt/sources.list +RUN /usr/local/bin/install_dependencies.sh # build out ext components COPY ./ext /home/V2X-Hub/ext @@ -14,6 +14,7 @@ RUN ./build.sh ADD container/wait-for-it.sh /usr/local/bin/ ADD container/service.sh /usr/local/bin/ + COPY ./container /home/V2X-Hub/container WORKDIR /home/V2X-Hub/container/ RUN ./database.sh @@ -26,8 +27,31 @@ WORKDIR /home/V2X-Hub/src/ RUN ./build.sh release RUN ldconfig -WORKDIR /home/V2X-Hub/ +# run final image +FROM ubuntu:$UBUNTU_VERSION AS v2xhub +ENV DEBIAN_FRONTEND=noninteractive +ADD scripts/deployment_dependencies.sh /usr/local/bin/ +RUN /usr/local/bin/deployment_dependencies.sh + +COPY ./container /home/V2X-Hub/container/ +WORKDIR /home/V2X-Hub/container/ +RUN ./database.sh +RUN ./library.sh +RUN ldconfig + +COPY --from=dependencies /usr/local/plugins/ /usr/local/plugins/ +COPY --from=dependencies /usr/local/lib/ /usr/local/lib/ +COPY --from=dependencies /usr/local/bin/ /usr/local/bin/ +COPY --from=dependencies /usr/local/share/ /usr/local/share/ +COPY --from=dependencies /var/www/plugins/ /var/www/plugins/ +COPY --from=dependencies /var/log/tmx/ /var/log/tmx/ +COPY --from=dependencies /opt/ /opt/ +ADD src/tmx/TmxCore/tmxcore.service /lib/systemd/system/ +ADD src/tmx/TmxCore/tmxcore.service /usr/sbin/ +RUN ldconfig + RUN /home/V2X-Hub/container/setup.sh + WORKDIR /var/log/tmx # Set metadata labels diff --git a/container/setup.sh b/container/setup.sh index 954c7dba5..375eb1a0b 100755 --- a/container/setup.sh +++ b/container/setup.sh @@ -1,9 +1,6 @@ #!/bin/sh set -ex -cp src/tmx/TmxCore/tmxcore.service /lib/systemd/system/ -cp src/tmx/TmxCore/tmxcore.service /usr/sbin/ - mkdir -p /var/www/plugins/MAP /var/www/plugins/.ssl openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout /var/www/plugins/.ssl/tmxcmd.key -out /var/www/plugins/.ssl/tmxcmd.crt -subj "/CN= <127.0.0.1> " -days 3650 chown -R plugin:www-data /var/www/plugins/.ssl diff --git a/ext/pkcs11-proxy/.gitignore b/ext/pkcs11-proxy/.gitignore deleted file mode 100644 index 80eadb770..000000000 --- a/ext/pkcs11-proxy/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -build/ -*.o -moc_*.cpp -ui_*.h -*~ -vb-agent -res/.directory -.\#* -\#*# -Makefile -Trolltech.conf -obj-i686-linux-gnu -syscall-names.h diff --git a/ext/pkcs11-proxy/CMakeLists.txt b/ext/pkcs11-proxy/CMakeLists.txt deleted file mode 100644 index 2929a0aa5..000000000 --- a/ext/pkcs11-proxy/CMakeLists.txt +++ /dev/null @@ -1,46 +0,0 @@ -cmake_minimum_required (VERSION 2.4) - -if(COMMAND cmake_policy) - cmake_policy(SET CMP0003 NEW) -endif(COMMAND cmake_policy) - -set(CMAKE_VERBOSE_MAKEFILE ON) -set(CMAKE_INCLUDE_CURRENT_DIR ON) -set(CMAKE_AUTOMOC ON) - -OPTION(NODEBUG "Deactivate No debugging option" "OFF") - -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -Wall -Wno-unused-variable") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -std=c++14 -Wall -Wno-unused-variable") - -if(${NODEBUG} STREQUAL "OFF") -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pg -g3") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg -g3") -else (${NODEBUG} STREQUAL "OFF") -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s -O3") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s -O3") -endif(${NODEBUG} STREQUAL "OFF") - - -set(PKCS11_PROXY_SRCS gck-rpc-module.c gck-rpc-message.c gck-rpc-util.c egg-buffer.c gck-rpc-tls-psk.c) -set(PKCS11_DAEMON_SRCS egg-buffer.c gck-rpc-daemon-standalone.c gck-rpc-dispatch.c gck-rpc-message.c gck-rpc-util.c syscall-reporter.c syscall-names.h gck-rpc-tls-psk.c) - -add_definitions(-Wall) -add_library(pkcs11-proxy SHARED ${PKCS11_PROXY_SRCS}) - - -#add_executable (pkcs11-daemon ${GUI_TYPE} ${PKCS11_DAEMON_SRCS}) - -set_target_properties(pkcs11-proxy PROPERTIES VERSION 0.1 SOVERSION 0) - - -target_link_libraries (pkcs11-proxy pthread ssl crypto) -target_link_libraries (pkcs11-daemon dl pthread ssl crypto seccomp) - -#install_targets (/lib pkcs11-proxy) -#install_targets (/bin pkcs11-daemon) - -install(EXPORT pkcs11-proxyAPIConfig DESTINATION share/pkcs11proxyAPI/cmake) - -export(TARGETS pkcs11-proxy FILE pkcs11proxyAPIConfig.cmake) - diff --git a/ext/pkcs11-proxy/CMakeLists.txtbackup b/ext/pkcs11-proxy/CMakeLists.txtbackup deleted file mode 100644 index f16862e34..000000000 --- a/ext/pkcs11-proxy/CMakeLists.txtbackup +++ /dev/null @@ -1,45 +0,0 @@ -cmake_minimum_required (VERSION 2.4) - -if(COMMAND cmake_policy) - cmake_policy(SET CMP0003 NEW) -endif(COMMAND cmake_policy) - -project (pkcs11 C) - -set(PKCS11_PROXY_SRCS gck-rpc-module.c gck-rpc-message.c gck-rpc-util.c egg-buffer.c gck-rpc-tls-psk.c) -set(PKCS11_DAEMON_SRCS egg-buffer.c gck-rpc-daemon-standalone.c gck-rpc-dispatch.c gck-rpc-message.c gck-rpc-util.c syscall-reporter.c syscall-names.h gck-rpc-tls-psk.c) - -add_definitions(-Wall) -add_library(pkcs11-proxy SHARED ${PKCS11_PROXY_SRCS}) - -# Disable console when building Win32 binary in release mode -if (WIN32 - if("${CMAKE_BUILD_TYPE}" MATCHES "^Rel.*") - set(GUI_TYPE WIN32) - endif() -endif() - -add_executable (pkcs11-daemon ${GUI_TYPE} ${PKCS11_DAEMON_SRCS}) - -set_target_properties(pkcs11-proxy PROPERTIES VERSION 0.1 SOVERSION 0) - -if (WIN32) - include_directories("ext/include") - - add_library(dl STATIC IMPORTED) - set_property(TARGET dl PROPERTY - IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/ext/lib/libdl.a) - target_link_libraries (pkcs11-daemon ws2_32) - target_link_libraries (pkcs11-proxy ws2_32) -endif (WIN32) - -target_link_libraries (pkcs11-proxy pthread ssl crypto) -target_link_libraries (pkcs11-daemon dl pthread ssl crypto seccomp) - -install_targets (/lib pkcs11-proxy) -install_targets (/bin pkcs11-daemon) - -add_custom_command( - OUTPUT syscall-names.h - COMMAND ${CMAKE_SOURCE_DIR}/mksyscalls.sh - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) diff --git a/ext/pkcs11-proxy/Dockerfile.jenkins b/ext/pkcs11-proxy/Dockerfile.jenkins deleted file mode 100644 index 620f8e21d..000000000 --- a/ext/pkcs11-proxy/Dockerfile.jenkins +++ /dev/null @@ -1,2 +0,0 @@ -FROM docker.sunet.se/jenkins-job -RUN apt-get install -y libssl-dev libseccomp-dev diff --git a/ext/pkcs11-proxy/README.rst b/ext/pkcs11-proxy/README.rst deleted file mode 100644 index fd5bb2ae9..000000000 --- a/ext/pkcs11-proxy/README.rst +++ /dev/null @@ -1,15 +0,0 @@ - -PKCS11 Proxy -============ - -This fork has the following additional features: - -- support for running in "inetd mode", useful for calling directly from stunnel -- seccomp syscall filtering (only tested in inetd-mode) -- getaddrinfo support for IPv6, fallback and DNS resolution -- TLS-PSK support to optionally encrypt communication - -Plus a number of important bug fixes. This version passes the SoftHSM test -suite. - -An ubuntu PPA that tracks this version is ppa:leifj diff --git a/ext/pkcs11-proxy/THANKS b/ext/pkcs11-proxy/THANKS deleted file mode 100644 index dcf22ed79..000000000 --- a/ext/pkcs11-proxy/THANKS +++ /dev/null @@ -1,2 +0,0 @@ -Gnome Project - gnome keyring http://live.gnome.org/GnomeKeyring -Casper Gielen - documentation \ No newline at end of file diff --git a/ext/pkcs11-proxy/UPSTREAM_REV b/ext/pkcs11-proxy/UPSTREAM_REV deleted file mode 100644 index 8686b4f96..000000000 --- a/ext/pkcs11-proxy/UPSTREAM_REV +++ /dev/null @@ -1 +0,0 @@ -r1724 \ No newline at end of file diff --git a/ext/pkcs11-proxy/USAGE b/ext/pkcs11-proxy/USAGE deleted file mode 100644 index f79297522..000000000 --- a/ext/pkcs11-proxy/USAGE +++ /dev/null @@ -1,82 +0,0 @@ -PKCS11-Proxy is a proxy for the PKCS11-library. - -This project is based on a stripped down Gnome Keyring without all gnome -dependencies and other features. - -The proxy tunnels PKCS11-requests over the network. One possible use -is to store cryptograhic information on a seperate server. This way -the crypto can be isolated from the rest of the system. - -Example -======= - -Here is an example of using pkcs11-proxy together with SoftHSM (from the -OpenDNSSEC project). The benefit of this setup is that no extra hardware -is needed at all. This could also be considered the greatest weakeness. -For demonstration purposes, however, security is not a consideration. - -$ sudo adduser cgielen pkcs11 -$ sudo adduser cgielen softhsm - -$ softhsm --init-token --slot 0 --label test -The SO PIN must have a length between 4 and 255 characters. -Enter SO PIN: -The user PIN must have a length between 4 and 255 characters. -Enter user PIN: -The token has been initialized. - -$ PKCS11_DAEMON_SOCKET="tcp://127.0.0.1:2345" pkcs11-daemon /usr/lib/libsofthsm.so -$ PKCS11_PROXY_SOCKET="tcp://127.0.0.1:2345" pkcs11-tool --module=/usr/lib/libpkcs11-proxy.so -L Available -slots: Slot 0 SoftHSM - token label: test token manuf: SoftHSM token model: SoftHSM - token flags: rng, login required, PIN initialized, token initialized, - other flags=0x40 serial num : 1 - - -IPv6 and DNS -============ - -The PKCS11_DAEMON_SOCKET and PKCS11_PROXY_SOCKET environment variables can -have both hostnames and IPv6 addresses in them. getaddrinfo(3) is used to -resolve any DNS name. - -$ PKCS11_DAEMON_SOCKET="tcp://server.example.com:2345" ... - -If `server.example.com' resolves to more than one IP address (such as one -IPv4 and one IPv6 address), these will be tried sequentially. Currently, -no attempt is made to speed up connection establishment using Happy Eyeballs -(RFC 6555) or similar, so timeouts in case of unreachable addresses could -be expected to be quite problematic. - -IPv6 addresses should be enclosed by square brackets. - -$ PKCS11_DAEMON_SOCKET="tcp://[::1]:2345" ... - - -Encryption -========== - -This version supports encrypting the communication between the client and -proxy using OpenSSL TLS-PSK (pre-shared key). The PSK is read from a file -that usees the GnuTLS psktool format. This format includes PSK identity -as well as key. - -Currently, there is no way to specify the identity to use on the client -side (client tells server what identity should be used), and the first -identity found in the PSK file is used. The server side will correctly -look up the identity requested by the client in it's PSK file, so it is -possible to have one unique PSK identity and key per PKCS11 client, and -have all the identitys and keys in the PSK file for the PKCS11 daemon. - -$ cat test.psk -test:e9622c85018998993fcc16f5ce9c15e9 -$ PKCS11_PROXY_TLS_PSK_FILE="test.psk" \ - PKCS11_DAEMON_SOCKET="tls://server.example.com:2345" \ - pkcs11-daemon /usr/lib/libsofthsm.so -$ PKCS11_PROXY_TLS_PSK_FILE="test.psk" \ - PKCS11_PROXY_SOCKET="tls://server.example.com:2345" \ - pkcs11-tool --module=/usr/lib/libpkcs11-proxy.so -L Available -slots: Slot 0 SoftHSM - token label: test token manuf: SoftHSM token model: SoftHSM - token flags: rng, login required, PIN initialized, token initialized, - other flags=0x40 serial num : 1 diff --git a/ext/pkcs11-proxy/cmake_install.cmake b/ext/pkcs11-proxy/cmake_install.cmake deleted file mode 100644 index 563c5d0cd..000000000 --- a/ext/pkcs11-proxy/cmake_install.cmake +++ /dev/null @@ -1,97 +0,0 @@ -# Install script for directory: /home/anjanrayamajhi/Projects/pkcs11-proxy - -# Set the install prefix -if(NOT DEFINED CMAKE_INSTALL_PREFIX) - set(CMAKE_INSTALL_PREFIX "/usr/local") -endif() -string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - if(BUILD_TYPE) - string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - else() - set(CMAKE_INSTALL_CONFIG_NAME "") - endif() - message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -endif() - -# Set the component getting installed. -if(NOT CMAKE_INSTALL_COMPONENT) - if(COMPONENT) - message(STATUS "Install component: \"${COMPONENT}\"") - set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - else() - set(CMAKE_INSTALL_COMPONENT) - endif() -endif() - -# Install shared libraries without execute permission? -if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) - set(CMAKE_INSTALL_SO_NO_EXE "1") -endif() - -# Is this installation the result of a crosscompile? -if(NOT DEFINED CMAKE_CROSSCOMPILING) - set(CMAKE_CROSSCOMPILING "FALSE") -endif() - -if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) - if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pkcs11-daemon" AND - NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pkcs11-daemon") - file(RPATH_CHECK - FILE "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pkcs11-daemon" - RPATH "") - endif() - file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" TYPE EXECUTABLE FILES "/home/anjanrayamajhi/Projects/pkcs11-proxy/pkcs11-daemon") - if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pkcs11-daemon" AND - NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pkcs11-daemon") - if(CMAKE_INSTALL_DO_STRIP) - execute_process(COMMAND "/usr/bin/strip" "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/pkcs11-daemon") - endif() - endif() -endif() - -if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT) - foreach(file - "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/libpkcs11-proxy.so.0.1" - "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/libpkcs11-proxy.so.0" - "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/libpkcs11-proxy.so" - ) - if(EXISTS "${file}" AND - NOT IS_SYMLINK "${file}") - file(RPATH_CHECK - FILE "${file}" - RPATH "") - endif() - endforeach() - file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" TYPE SHARED_LIBRARY FILES - "/home/anjanrayamajhi/Projects/pkcs11-proxy/libpkcs11-proxy.so.0.1" - "/home/anjanrayamajhi/Projects/pkcs11-proxy/libpkcs11-proxy.so.0" - "/home/anjanrayamajhi/Projects/pkcs11-proxy/libpkcs11-proxy.so" - ) - foreach(file - "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/libpkcs11-proxy.so.0.1" - "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/libpkcs11-proxy.so.0" - "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/libpkcs11-proxy.so" - ) - if(EXISTS "${file}" AND - NOT IS_SYMLINK "${file}") - if(CMAKE_INSTALL_DO_STRIP) - execute_process(COMMAND "/usr/bin/strip" "${file}") - endif() - endif() - endforeach() -endif() - -if(CMAKE_INSTALL_COMPONENT) - set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") -else() - set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") -endif() - -string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT - "${CMAKE_INSTALL_MANIFEST_FILES}") -file(WRITE "/home/anjanrayamajhi/Projects/pkcs11-proxy/${CMAKE_INSTALL_MANIFEST}" - "${CMAKE_INSTALL_MANIFEST_CONTENT}") diff --git a/ext/pkcs11-proxy/config.h b/ext/pkcs11-proxy/config.h deleted file mode 100644 index f2e0a88f9..000000000 --- a/ext/pkcs11-proxy/config.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef CONFIG_H -# define CONFIG_H - -# define DEBUG_OUTPUT 0 // change to 1 to enable debugging - -# define PKCS11PROXY_LISTEN_BACKLOG 128 -# define PKCS11PROXY_MAX_SESSION_COUNT 256 - -# define PKCS11PROXY_TLS_PSK_CIPHERS "PSK-AES128-CBC-SHA:PSK-AES256-CBC-SHA"; - -//# define DEBUG_SECCOMP -//# define SECCOMP - -#ifdef __MINGW32__ - -# include -# include -# include -# include - -typedef uint32_t __uid32_t; -typedef uint32_t __gid32_t; -typedef uint32_t uid_t; -typedef int socklen_t; - -struct sockaddr_un { - uint16_t sun_family; - char sun_path[PATH_MAX]; -}; - -enum { - SHUT_RD = 0, /* No more receptions. */ - SHUT_WR, /* No more transmissions. */ - SHUT_RDWR /* No more receptions or transmissions. */ -}; - -#ifdef __MINGW32__ -static inline int inet_aton(const char * cp, struct in_addr *pin) -{ - int rc = inet_addr(cp); - if (rc == -1 && strcmp(cp, "255.255.255.255")) - return 0; - - pin->s_addr = rc; - return 1; -} -#endif - -#endif - -#endif /* CONFIG_H */ diff --git a/ext/pkcs11-proxy/debian/.gitignore b/ext/pkcs11-proxy/debian/.gitignore deleted file mode 100644 index 9a94fb2a5..000000000 --- a/ext/pkcs11-proxy/debian/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -files -pkcs11-daemon.debhelper.log -pkcs11-daemon.substvars -pkcs11-proxy1.debhelper.log -pkcs11-proxy1.postinst.debhelper -pkcs11-proxy1.postrm.debhelper -pkcs11-proxy1.substvars -stamp-makefile-build -stamp-makefile-install -tmp -pkcs11-daemon -pkcs11-proxy1 diff --git a/ext/pkcs11-proxy/debian/changelog b/ext/pkcs11-proxy/debian/changelog deleted file mode 100644 index 1aac0c9a8..000000000 --- a/ext/pkcs11-proxy/debian/changelog +++ /dev/null @@ -1,53 +0,0 @@ -pkcs11-proxy (0.4-1ubuntu4) trusty; urgency=medium - - * debian updates - - -- Leif Johansson Fri, 17 Jul 2015 11:02:03 +0200 - -pkcs11-proxy (0.4-1ubuntu3) trusty; urgency=medium - - [ Klaus Darilion ] - * Update seccomp usage to match Ubuntu 14.04. - - -- Fredrik Thulin Tue, 17 Feb 2015 19:20:13 +0100 - -pkcs11-proxy (0.4-1ubuntu2) precise; urgency=low - - * Support IPv6 and connect-fallback through getaddrinfo() - * Implement TLS-PSK using OpenSSL - * Use libseccomp and reduce number of syscalls allowed in dispatchers - * Several important bug fixes (now passes SoftHSM test suite) - - -- Fredrik Thulin Wed, 30 Jan 2013 09:56:34 +0100 - -pkcs11-proxy (0.4-1ubuntu1) precise; urgency=low - - * disable debugging by default - * use syslog instead of stderr unless DEBUG_OUTPUT is 1 - - -- Leif Johansson Tue, 04 Sep 2012 15:58:45 +0200 - -pkcs11-proxy (0.3-1ubuntu~seccomp1) precise; urgency=low - - [ Corentin Chary ] - * debian: remove commonit specific stuff - - [ Andre Grueneberg ] - * Compile in normal debian environment - * Error in SetPIN - - [ Leif Johansson ] - * basic seccmp filter - - -- Leif Johansson Tue, 04 Sep 2012 13:37:56 +0200 - -pkcs11-proxy (0.2-1ubuntu1) precise; urgency=low - - [ Corentin Chary ] - * Initial release. - - [ Leif Johansson ] - * Make it build without the opt prefix - * support for calling pkcs11-daemon from inetd/stunnel directly - - -- Leif Johansson Tue, 04 Sep 2012 09:02:52 +0200 diff --git a/ext/pkcs11-proxy/debian/compat b/ext/pkcs11-proxy/debian/compat deleted file mode 100644 index 7f8f011eb..000000000 --- a/ext/pkcs11-proxy/debian/compat +++ /dev/null @@ -1 +0,0 @@ -7 diff --git a/ext/pkcs11-proxy/debian/control b/ext/pkcs11-proxy/debian/control deleted file mode 100755 index 5336e0cfd..000000000 --- a/ext/pkcs11-proxy/debian/control +++ /dev/null @@ -1,22 +0,0 @@ -Source: pkcs11-proxy -Priority: extra -Maintainer: Corentin Chary -Uploaders: Leif Johansson -Build-Depends: cdbs, debhelper (>= 6), cmake, libssl-dev (>= 1.0.0), libseccomp-dev (>= 1.0.0) -Standards-Version: 3.8.0 -Section: libs - -Package: pkcs11-proxy1 -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} -Recommends: -Description: pkcs11-proxy - A pkcs11 proxy to use pkcs11 over the network - -Package: pkcs11-daemon -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} -Recommends: -Description: pkcs11-proxy - A pkcs11 daemon to talk with pkcs11-proxy - diff --git a/ext/pkcs11-proxy/debian/copyright b/ext/pkcs11-proxy/debian/copyright deleted file mode 100755 index 4a784223e..000000000 --- a/ext/pkcs11-proxy/debian/copyright +++ /dev/null @@ -1,18 +0,0 @@ -License: - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - MA 02110-1301, USA. - - -On Debian systems, the complete text of the GNU General -Public License can be found in `/usr/share/common-licenses/GPL-2'. diff --git a/ext/pkcs11-proxy/debian/pkcs11-daemon.install b/ext/pkcs11-proxy/debian/pkcs11-daemon.install deleted file mode 100644 index 972c9c1c9..000000000 --- a/ext/pkcs11-proxy/debian/pkcs11-daemon.install +++ /dev/null @@ -1 +0,0 @@ -debian/tmp/usr/bin/pkcs11-daemon /usr/bin diff --git a/ext/pkcs11-proxy/debian/pkcs11-proxy1.install b/ext/pkcs11-proxy/debian/pkcs11-proxy1.install deleted file mode 100644 index cce099314..000000000 --- a/ext/pkcs11-proxy/debian/pkcs11-proxy1.install +++ /dev/null @@ -1 +0,0 @@ -debian/tmp/usr/lib/libpkcs11-proxy*.so* /usr/lib diff --git a/ext/pkcs11-proxy/debian/rules b/ext/pkcs11-proxy/debian/rules deleted file mode 100755 index 6355c4729..000000000 --- a/ext/pkcs11-proxy/debian/rules +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/make -f - -%: - dh $@ --buildsystem=cmake --builddirectory=build --sourcedirectory=. diff --git a/ext/pkcs11-proxy/debian/source/format b/ext/pkcs11-proxy/debian/source/format deleted file mode 100644 index 89ae9db8f..000000000 --- a/ext/pkcs11-proxy/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (native) diff --git a/ext/pkcs11-proxy/egg-buffer.c b/ext/pkcs11-proxy/egg-buffer.c deleted file mode 100644 index 843cec76c..000000000 --- a/ext/pkcs11-proxy/egg-buffer.c +++ /dev/null @@ -1,544 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* egg-buffer.c - Generic data buffer, used by openssh, gnome-keyring - - Copyright (C) 2007 Stefan Walter - - The Gnome Keyring Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The Gnome Keyring 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the Gnome Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Stef Walter -*/ -#include "config.h" - -#include -#include - -#include "egg-buffer.h" - -#define DEFAULT_ALLOCATOR ((EggBufferAllocator)realloc) - -int egg_buffer_init(EggBuffer * buffer, size_t reserve) -{ - return egg_buffer_init_full(buffer, reserve, NULL); -} - -int -egg_buffer_init_full(EggBuffer * buffer, size_t reserve, - EggBufferAllocator allocator) -{ - memset(buffer, 0, sizeof(*buffer)); - - if (!allocator) - allocator = DEFAULT_ALLOCATOR; - if (reserve == 0) - reserve = 64; - - buffer->buf = (allocator) (NULL, reserve); - if (!buffer->buf) { - buffer->failures++; - return 0; - } - - buffer->len = 0; - buffer->allocated_len = reserve; - buffer->failures = 0; - buffer->allocator = allocator; - - return 1; -} - -void egg_buffer_init_static(EggBuffer * buffer, unsigned char *buf, size_t len) -{ - memset(buffer, 0, sizeof(*buffer)); - - buffer->buf = buf; - buffer->len = len; - buffer->allocated_len = len; - buffer->failures = 0; - - /* A null allocator, and the buffer can't change in size */ - buffer->allocator = NULL; -} - -void -egg_buffer_init_allocated(EggBuffer * buffer, unsigned char *buf, size_t len, - EggBufferAllocator allocator) -{ - memset(buffer, 0, sizeof(*buffer)); - - if (!allocator) - allocator = DEFAULT_ALLOCATOR; - - buffer->buf = buf; - buffer->len = len; - buffer->allocated_len = len; - buffer->failures = 0; - buffer->allocator = allocator; -} - -void egg_buffer_reset(EggBuffer * buffer) -{ - memset(buffer->buf, 0, buffer->allocated_len); - buffer->len = 0; - buffer->failures = 0; -} - -void egg_buffer_uninit(EggBuffer * buffer) -{ - if (!buffer) - return; - - /* - * Free the memory block using allocator. If no allocator, - * then this memory is ownerd elsewhere and not to be freed. - */ - if (buffer->buf && buffer->allocator) - (buffer->allocator) (buffer->buf, 0); - - memset(buffer, 0, sizeof(*buffer)); -} - -int egg_buffer_set_allocator(EggBuffer * buffer, EggBufferAllocator allocator) -{ - unsigned char *buf = NULL; - - if (!allocator) - allocator = DEFAULT_ALLOCATOR; - if (buffer->allocator == allocator) - return 1; - - if (buffer->allocated_len) { - /* Reallocate memory block using new allocator */ - buf = (allocator) (NULL, buffer->allocated_len); - if (buf == NULL) - return 0; - - /* Copy stuff into new memory */ - memcpy(buf, buffer->buf, buffer->allocated_len); - } - - /* If old wasn't static, then free it */ - if (buffer->allocator && buffer->buf) - (buffer->allocator) (buffer->buf, 0); - - buffer->buf = buf; - buffer->allocator = allocator; - - return 1; -} - -int egg_buffer_equal(EggBuffer * b1, EggBuffer * b2) -{ - if (b1->len != b2->len) - return 0; - return memcmp(b1->buf, b2->buf, b1->len) == 0; -} - -int egg_buffer_reserve(EggBuffer * buffer, size_t len) -{ - unsigned char *newbuf; - size_t newlen; - - if (len < buffer->allocated_len) - return 1; - - /* Calculate a new length, minimize number of buffer allocations */ - newlen = buffer->allocated_len * 2; - if (len > newlen) - newlen += len; - - /* Memory owned elsewhere can't be reallocated */ - if (!buffer->allocator) { - buffer->failures++; - return 0; - } - - /* Reallocate built in buffer using allocator */ - newbuf = (buffer->allocator) (buffer->buf, newlen); - if (!newbuf) { - buffer->failures++; - return 0; - } - - buffer->buf = newbuf; - buffer->allocated_len = newlen; - - return 1; -} - -int egg_buffer_resize(EggBuffer * buffer, size_t len) -{ - if (!egg_buffer_reserve(buffer, len)) - return 0; - - buffer->len = len; - return 1; -} - -unsigned char *egg_buffer_add_empty(EggBuffer * buffer, size_t len) -{ - size_t pos = buffer->len; - if (!egg_buffer_reserve(buffer, buffer->len + len)) - return NULL; - buffer->len += len; - return buffer->buf + pos; -} - -int egg_buffer_append(EggBuffer * buffer, const unsigned char *val, size_t len) -{ - if (!egg_buffer_reserve(buffer, buffer->len + len)) - return 0; /* failures already incremented */ - memcpy(buffer->buf + buffer->len, val, len); - buffer->len += len; - return 1; -} - -int egg_buffer_add_byte(EggBuffer * buffer, unsigned char val) -{ - if (!egg_buffer_reserve(buffer, buffer->len + 1)) - return 0; /* failures already incremented */ - buffer->buf[buffer->len] = val; - buffer->len++; - return 1; -} - -int -egg_buffer_get_byte(EggBuffer * buffer, size_t offset, - size_t * next_offset, unsigned char *val) -{ - unsigned char *ptr; - if (buffer->len < 1 || offset > buffer->len - 1) { - buffer->failures++; - return 0; - } - ptr = (unsigned char *)buffer->buf + offset; - if (val != NULL) - *val = *ptr; - if (next_offset != NULL) - *next_offset = offset + 1; - return 1; -} - -void egg_buffer_encode_uint16(unsigned char *buf, uint16_t val) -{ - buf[0] = (val >> 8) & 0xff; - buf[1] = (val >> 0) & 0xff; -} - -uint16_t egg_buffer_decode_uint16(unsigned char *buf) -{ - uint16_t val = buf[0] << 8 | buf[1]; - return val; -} - -int egg_buffer_add_uint16(EggBuffer * buffer, uint16_t val) -{ - if (!egg_buffer_reserve(buffer, buffer->len + 2)) - return 0; /* failures already incremented */ - buffer->len += 2; - egg_buffer_set_uint16(buffer, buffer->len - 2, val); - return 1; -} - -int egg_buffer_set_uint16(EggBuffer * buffer, size_t offset, uint16_t val) -{ - unsigned char *ptr; - if (buffer->len < 2 || offset > buffer->len - 2) { - buffer->failures++; - return 0; - } - ptr = (unsigned char *)buffer->buf + offset; - egg_buffer_encode_uint16(ptr, val); - return 1; -} - -int -egg_buffer_get_uint16(EggBuffer * buffer, size_t offset, - size_t * next_offset, uint16_t * val) -{ - unsigned char *ptr; - if (buffer->len < 2 || offset > buffer->len - 2) { - buffer->failures++; - return 0; - } - ptr = (unsigned char *)buffer->buf + offset; - if (val != NULL) - *val = egg_buffer_decode_uint16(ptr); - if (next_offset != NULL) - *next_offset = offset + 2; - return 1; -} - -void egg_buffer_encode_uint32(unsigned char *buf, uint32_t val) -{ - buf[0] = (val >> 24) & 0xff; - buf[1] = (val >> 16) & 0xff; - buf[2] = (val >> 8) & 0xff; - buf[3] = (val >> 0) & 0xff; -} - -uint32_t egg_buffer_decode_uint32(unsigned char *ptr) -{ - uint32_t val = ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3]; - return val; -} - -int egg_buffer_add_uint32(EggBuffer * buffer, uint32_t val) -{ - if (!egg_buffer_reserve(buffer, buffer->len + 4)) - return 0; /* failures already incremented */ - buffer->len += 4; - egg_buffer_set_uint32(buffer, buffer->len - 4, val); - return 1; -} - -int egg_buffer_set_uint32(EggBuffer * buffer, size_t offset, uint32_t val) -{ - unsigned char *ptr; - if (buffer->len < 4 || offset > buffer->len - 4) { - buffer->failures++; - return 0; - } - ptr = (unsigned char *)buffer->buf + offset; - egg_buffer_encode_uint32(ptr, val); - return 1; -} - -int -egg_buffer_get_uint32(EggBuffer * buffer, size_t offset, size_t * next_offset, - uint32_t * val) -{ - unsigned char *ptr; - if (buffer->len < 4 || offset > buffer->len - 4) { - buffer->failures++; - return 0; - } - ptr = (unsigned char *)buffer->buf + offset; - if (val != NULL) - *val = egg_buffer_decode_uint32(ptr); - if (next_offset != NULL) - *next_offset = offset + 4; - return 1; -} - -int egg_buffer_add_uint64(EggBuffer * buffer, uint64_t val) -{ - if (!egg_buffer_add_uint32(buffer, ((val >> 32) & 0xffffffff))) - return 0; - return egg_buffer_add_uint32(buffer, (val & 0xffffffff)); -} - -int -egg_buffer_get_uint64(EggBuffer * buffer, size_t offset, - size_t * next_offset, uint64_t * val) -{ - uint32_t a, b; - if (!egg_buffer_get_uint32(buffer, offset, &offset, &a)) - return 0; - if (!egg_buffer_get_uint32(buffer, offset, &offset, &b)) - return 0; - if (val != NULL) - *val = ((uint64_t) a) << 32 | b; - if (next_offset != NULL) - *next_offset = offset; - return 1; -} - -int -egg_buffer_add_byte_array(EggBuffer * buffer, const unsigned char *val, - size_t len) -{ - if (val == NULL) - return egg_buffer_add_uint32(buffer, 0xffffffff); - if (len >= 0x7fffffff) { - buffer->failures++; - return 0; - } - if (!egg_buffer_add_uint32(buffer, len)) - return 0; - return egg_buffer_append(buffer, val, len); -} - -unsigned char *egg_buffer_add_byte_array_empty(EggBuffer * buffer, size_t vlen) -{ - if (vlen >= 0x7fffffff) { - buffer->failures++; - return NULL; - } - if (!egg_buffer_add_uint32(buffer, vlen)) - return NULL; - return egg_buffer_add_empty(buffer, vlen); -} - -int -egg_buffer_get_byte_array(EggBuffer * buffer, size_t offset, - size_t * next_offset, const unsigned char **val, - size_t * vlen) -{ - uint32_t len; - if (!egg_buffer_get_uint32(buffer, offset, &offset, &len)) - return 0; - if (len == 0xffffffff) { - if (next_offset) - *next_offset = offset; - if (val) - *val = NULL; - if (vlen) - *vlen = 0; - return 1; - } else if (len >= 0x7fffffff) { - buffer->failures++; - return 0; - } - - if (buffer->len < len || offset > buffer->len - len) { - buffer->failures++; - return 0; - } - - if (val) - *val = buffer->buf + offset; - if (vlen) - *vlen = len; - if (next_offset) - *next_offset = offset + len; - - return 1; -} - -int egg_buffer_add_string(EggBuffer * buffer, const char *str) -{ - if (str == NULL) { - return egg_buffer_add_uint32(buffer, 0xffffffff); - } else { - size_t len = strlen(str); - if (len >= 0x7fffffff) - return 0; - if (!egg_buffer_add_uint32(buffer, len)) - return 0; - return egg_buffer_append(buffer, (unsigned char *)str, len); - } -} - -int -egg_buffer_get_string(EggBuffer * buffer, size_t offset, size_t * next_offset, - char **str_ret, EggBufferAllocator allocator) -{ - uint32_t len; - - if (!allocator) - allocator = buffer->allocator; - if (!allocator) - allocator = DEFAULT_ALLOCATOR; - - if (!egg_buffer_get_uint32(buffer, offset, &offset, &len)) { - return 0; - } - if (len == 0xffffffff) { - *next_offset = offset; - *str_ret = NULL; - return 1; - } else if (len >= 0x7fffffff) { - return 0; - } - - if (buffer->len < len || offset > buffer->len - len) { - return 0; - } - - /* Make sure no null characters in string */ - if (memchr(buffer->buf + offset, 0, len) != NULL) - return 0; - - /* The passed allocator may be for non-pageable memory */ - *str_ret = (allocator) (NULL, len + 1); - if (!*str_ret) - return 0; - memcpy(*str_ret, buffer->buf + offset, len); - - /* Always zero terminate */ - (*str_ret)[len] = 0; - *next_offset = offset + len; - - return 1; -} - -int egg_buffer_add_stringv(EggBuffer * buffer, const char **strv) -{ - const char **v; - uint32_t n = 0; - - if (!strv) - return 0; - - /* Add the number of strings coming */ - for (v = strv; *v; ++v) - ++n; - if (!egg_buffer_add_uint32(buffer, n)) - return 0; - - /* Add the individual strings */ - for (v = strv; *v; ++v) { - if (!egg_buffer_add_string(buffer, *v)) - return 0; - } - - return 1; -} - -int -egg_buffer_get_stringv(EggBuffer * buffer, size_t offset, size_t * next_offset, - char ***strv_ret, EggBufferAllocator allocator) -{ - uint32_t n, i, j; - size_t len; - - if (!allocator) - allocator = buffer->allocator; - if (!allocator) - allocator = DEFAULT_ALLOCATOR; - - /* First the number of environment variable lines */ - if (!egg_buffer_get_uint32(buffer, offset, &offset, &n)) - return 0; - - /* Then that number of strings */ - len = (n + 1) * sizeof(char *); - *strv_ret = (char **)(allocator) (NULL, len); - if (!*strv_ret) - return 0; - - /* All null strings */ - memset(*strv_ret, 0, len); - - for (i = 0; i < n; ++i) { - if (!egg_buffer_get_string(buffer, offset, &offset, - &((*strv_ret)[i]), allocator)) { - - /* Free all the strings on failure */ - for (j = 0; j < i; ++j) { - if ((*strv_ret)[j]) - (allocator) ((*strv_ret)[j], 0); - } - - return 0; - } - } - - if (next_offset != NULL) - *next_offset = offset; - - return 1; -} diff --git a/ext/pkcs11-proxy/egg-buffer.h b/ext/pkcs11-proxy/egg-buffer.h deleted file mode 100644 index 23cb40f0b..000000000 --- a/ext/pkcs11-proxy/egg-buffer.h +++ /dev/null @@ -1,194 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* egg-buffer.h - Generic data buffer, used by openssh, gnome-keyring - - Copyright (C) 2007, Stefan Walter - - The Gnome Keyring Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The Gnome Keyring 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the Gnome Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Stef Walter -*/ - -#ifndef EGG_BUFFER_H -#define EGG_BUFFER_H - -#include -#include - -/* ------------------------------------------------------------------- - * EggBuffer - * - * IMPORTANT: This is pure vanila standard C, no glib. We need this - * because certain consumers of this protocol need to be built - * without linking in any special libraries. ie: the PKCS#11 module. - * - * Memory Allocation - * - * Callers can set their own allocator. If NULL is used then standard - * C library heap memory is used and failures will not be fatal. Memory - * failures will instead result in a zero return value or - * egg_buffer_has_error() returning one. - * - * If you use something like g_realloc as the allocator, then memory - * failures become fatal just like in a standard GTK program. - * - * Don't change the allocator manually in the EggBuffer structure. The - * egg_buffer_set_allocator() func will reallocate and handle things - * properly. - * - * Pointers into the Buffer - * - * Any write operation has the posibility of reallocating memory - * and invalidating any direct pointers into the buffer. - */ - -/* The allocator for the EggBuffer. This follows the realloc() syntax and logic */ -typedef void* (*EggBufferAllocator) (void* p, size_t len); - -typedef struct _EggBuffer { - unsigned char *buf; - size_t len; - size_t allocated_len; - int failures; - EggBufferAllocator allocator; -} EggBuffer; - -#define EGG_BUFFER_EMPTY { NULL, 0, 0, 0, NULL } - -int egg_buffer_init (EggBuffer *buffer, size_t reserve); - -int egg_buffer_init_full (EggBuffer *buffer, - size_t reserve, - EggBufferAllocator allocator); - -void egg_buffer_init_static (EggBuffer *buffer, - unsigned char *buf, - size_t len); - -void egg_buffer_init_allocated (EggBuffer *buffer, - unsigned char *buf, - size_t len, - EggBufferAllocator allocator); - -void egg_buffer_uninit (EggBuffer *buffer); - -int egg_buffer_set_allocator (EggBuffer *buffer, - EggBufferAllocator allocator); - -void egg_buffer_reset (EggBuffer *buffer); - -int egg_buffer_equal (EggBuffer *b1, - EggBuffer *b2); - -int egg_buffer_reserve (EggBuffer *buffer, - size_t len); - -int egg_buffer_resize (EggBuffer *buffer, - size_t len); - -int egg_buffer_append (EggBuffer *buffer, - const unsigned char *val, - size_t len); - -unsigned char* egg_buffer_add_empty (EggBuffer *buffer, - size_t len); - -int egg_buffer_add_byte (EggBuffer *buffer, - unsigned char val); - -int egg_buffer_get_byte (EggBuffer *buffer, - size_t offset, - size_t *next_offset, - unsigned char *val); - -void egg_buffer_encode_uint32 (unsigned char* buf, - uint32_t val); - -uint32_t egg_buffer_decode_uint32 (unsigned char* buf); - -int egg_buffer_add_uint32 (EggBuffer *buffer, - uint32_t val); - -int egg_buffer_set_uint32 (EggBuffer *buffer, - size_t offset, - uint32_t val); - -int egg_buffer_get_uint32 (EggBuffer *buffer, - size_t offset, - size_t *next_offset, - uint32_t *val); - -void egg_buffer_encode_uint16 (unsigned char* buf, - uint16_t val); - -uint16_t egg_buffer_decode_uint16 (unsigned char* buf); - -int egg_buffer_add_uint16 (EggBuffer *buffer, - uint16_t val); - -int egg_buffer_set_uint16 (EggBuffer *buffer, - size_t offset, - uint16_t val); - -int egg_buffer_get_uint16 (EggBuffer *buffer, - size_t offset, - size_t *next_offset, - uint16_t *val); - -int egg_buffer_add_byte_array (EggBuffer *buffer, - const unsigned char *val, - size_t len); - -int egg_buffer_get_byte_array (EggBuffer *buffer, - size_t offset, - size_t *next_offset, - const unsigned char **val, - size_t *vlen); - -unsigned char* egg_buffer_add_byte_array_empty (EggBuffer *buffer, - size_t vlen); - -int egg_buffer_add_string (EggBuffer *buffer, - const char *str); - -int egg_buffer_get_string (EggBuffer *buffer, - size_t offset, - size_t *next_offset, - char **str_ret, - EggBufferAllocator allocator); - -int egg_buffer_add_stringv (EggBuffer *buffer, - const char** strv); - -int egg_buffer_get_stringv (EggBuffer *buffer, - size_t offset, - size_t *next_offset, - char ***strv_ret, - EggBufferAllocator allocator); - -int egg_buffer_add_uint64 (EggBuffer *buffer, - uint64_t val); - -int egg_buffer_get_uint64 (EggBuffer *buffer, - size_t offset, - size_t *next_offset, - uint64_t *val); - -#define egg_buffer_length(b) ((b)->len) - -#define egg_buffer_has_error(b) ((b)->failures > 0) - -#endif /* EGG_BUFFER_H */ - diff --git a/ext/pkcs11-proxy/ext/include/dlfcn.h b/ext/pkcs11-proxy/ext/include/dlfcn.h deleted file mode 100644 index dfc255118..000000000 --- a/ext/pkcs11-proxy/ext/include/dlfcn.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * dlfcn-win32 - * Copyright (c) 2007 Ramiro Polla - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef DLFCN_H -#define DLFCN_H - -/* POSIX says these are implementation-defined. - * To simplify use with Windows API, we treat them the same way. - */ - -#define RTLD_LAZY 0 -#define RTLD_NOW 0 - -#define RTLD_GLOBAL (1 << 1) -#define RTLD_LOCAL (1 << 2) - -/* These two were added in The Open Group Base Specifications Issue 6. - * Note: All other RTLD_* flags in any dlfcn.h are not standard compliant. - */ - -#define RTLD_DEFAULT 0 -#define RTLD_NEXT 0 - -void *dlopen ( const char *file, int mode ); -int dlclose( void *handle ); -void *dlsym ( void *handle, const char *name ); -char *dlerror( void ); - -#endif /* DLFCN_H */ diff --git a/ext/pkcs11-proxy/gck-rpc-daemon-standalone.c b/ext/pkcs11-proxy/gck-rpc-daemon-standalone.c deleted file mode 100644 index 3d0564f38..000000000 --- a/ext/pkcs11-proxy/gck-rpc-daemon-standalone.c +++ /dev/null @@ -1,358 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* gck-rpc-daemon-standalone.c - A sample daemon. - - Copyright (C) 2008, Stef Walter - - The Gnome Keyring Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The Gnome Keyring 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the Gnome Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Stef Walter -*/ - -#include "config.h" - -#include "pkcs11/pkcs11.h" - -#include "gck-rpc-layer.h" -#include "gck-rpc-tls-psk.h" - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#ifdef __MINGW32__ -# include -#endif - -#define SOCKET_PATH "tcp://127.0.0.1" - -#ifdef SECCOMP -#include -//#include "seccomp-bpf.h" -#ifdef DEBUG_SECCOMP -# include "syscall-reporter.h" -#endif /* DEBUG_SECCOMP */ -#include /* for seccomp init */ -#endif /* SECCOMP */ - - -static int install_syscall_filter(const int sock, const char *tls_psk_keyfile, const char *path) -{ -#ifdef SECCOMP - int rc = -1; - scmp_filter_ctx ctx; - -#ifdef DEBUG_SECCOMP - ctx = seccomp_init(SCMP_ACT_TRAP); -#else - ctx = seccomp_init(SCMP_ACT_KILL); -#endif /* DEBUG_SECCOMP */ - if (ctx == NULL) - goto failure_scmp; - /* - * These are the basic syscalls needed to be able to use - * the syscall-reporter to figure out the rest - */ - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(write), 0); -#ifdef DEBUG_SECCOMP - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0); -# ifdef __NR_sigreturn - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(sigreturn), 0); -# endif -#endif /* DEBUG_SECCOMP */ - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(exit), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0); - - /* - * Network related syscalls. - */ - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(read), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(select), 0); - if (sock) - /* Allow accept() only for the listening socket */ - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(accept), 1, - SCMP_A0(SCMP_CMP_EQ, sock)); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(sendto), 0); - if (path[0] && - strncmp(path, "tcp://", strlen("tcp://")) == 0) { - /* TCP socket - not needed for TLS */ - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(recvfrom), 0); - } - - /* - * These are probably pthreads-related. - */ - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(munmap), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(clone), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(set_robust_list), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(madvise), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(munlock), 0); - - /* - * Both pthreads (? file is "/sys/devices/system/cpu/online") and TLS-PSK open files. - */ - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(open), 1, - SCMP_A1(SCMP_CMP_EQ, O_RDONLY | O_CLOEXEC)); - - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(close), 0); - - /* - * UNIX domain socket - */ - if (path[0] && - strncmp(path, "tcp://", strlen("tcp://")) != 0 && - strncmp(path, "tls://", strlen("tls://")) != 0) { - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(unlink), 0); - } - - /* - * Allow spawned threads to initialize a new seccomp policy (subset of this). - */ - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(prctl), 0); - - /* - * SoftHSM 1.3.0 required syscalls - */ - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(getcwd), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(stat), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(open), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(lseek), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(access), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(fsync), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(unlink), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(ftruncate), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(select), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(futex), 0); - -#ifdef DEBUG_SECCOMP - /* Dumps the generated BPF rules in sort-of human readable syntax. */ - seccomp_export_pfc(ctx,STDERR_FILENO); - - /* Print the name of syscalls stopped by seccomp. Should not be used in production. */ - if (install_syscall_reporter()) - return 1; -#endif /* DEBUG_SECCOMP */ - - rc = seccomp_load(ctx); - if (rc < 0) - goto failure_scmp; - seccomp_release(ctx); - - return 0; - -failure_scmp: - errno = -rc; - fprintf(stderr, "Seccomp filter initialization failed, errno = %u\n", errno); - return errno; -#else /* SECCOMP */ - return 0; -#endif /* SECCOMP */ -} - - -#if 0 -/* Sample configuration for loading NSS remotely */ -static CK_C_INITIALIZE_ARGS p11_init_args = { - NULL, - NULL, - NULL, - NULL, - CKF_OS_LOCKING_OK, - "init-string = configdir='/tmp' certPrefix='' keyPrefix='' secmod='/tmp/secmod.db' flags=" -}; -#endif - -static int is_running = 1; - -static int usage(void) -{ - fprintf(stderr, "usage: pkcs11-daemon pkcs11-module [|\"-\"]\n\tUsing \"-\" results in a single-thread inetd-type daemon\n"); - exit(2); -} - -void termination_handler (int signum) -{ - is_running = 0; -} - -enum { - /* Used to un-confuse clang checker */ - GCP_RPC_DAEMON_MODE_INETD = 0, - GCP_RPC_DAEMON_MODE_SOCKET -}; - -int main(int argc, char *argv[]) -{ - CK_C_GetFunctionList func_get_list; - CK_FUNCTION_LIST_PTR funcs; - void *module; - const char *path, *tls_psk_keyfile; - fd_set read_fds; - int sock, ret, mode; - CK_RV rv; - CK_C_INITIALIZE_ARGS init_args; - GckRpcTlsPskState *tls; - - /* The module to load is the argument */ - if (argc != 2 && argc != 3) - usage(); - - openlog("pkcs11-proxy",LOG_CONS|LOG_PID,LOG_DAEMON); - - /* Load the library */ - module = dlopen(argv[1], RTLD_NOW); - if (!module) { - fprintf(stderr, "couldn't open library: %s: %s\n", argv[1], - dlerror()); - exit(1); - } - - /* Lookup the appropriate function in library */ - func_get_list = - (CK_C_GetFunctionList) dlsym(module, "C_GetFunctionList"); - if (!func_get_list) { - fprintf(stderr, - "couldn't find C_GetFunctionList in library: %s: %s\n", - argv[1], dlerror()); - exit(1); - } - - /* Get the function list */ - rv = (func_get_list) (&funcs); - if (rv != CKR_OK || !funcs) { - fprintf(stderr, - "couldn't get function list from C_GetFunctionList" - "in libary: %s: 0x%08x\n", - argv[1], (int)rv); - exit(1); - } - - /* RPC layer expects initialized module */ - memset(&init_args, 0, sizeof(init_args)); - init_args.flags = CKF_OS_LOCKING_OK; - - rv = (funcs->C_Initialize) (&init_args); - if (rv != CKR_OK) { - fprintf(stderr, "couldn't initialize module: %s: 0x%08x\n", - argv[1], (int)rv); - exit(1); - } - - path = getenv("PKCS11_DAEMON_SOCKET"); - if (!path && argc == 3) - path = argv[2]; - if (!path) - path = SOCKET_PATH; - - /* Initialize TLS, if appropriate */ - tls = NULL; - tls_psk_keyfile = NULL; - if (! strncmp("tls://", path, 6)) { - tls_psk_keyfile = getenv("PKCS11_PROXY_TLS_PSK_FILE"); - if (! tls_psk_keyfile || ! tls_psk_keyfile[0]) { - fprintf(stderr, "key file must be specified for tls:// socket.\n"); - exit(1); - } - - tls = calloc(1, sizeof(GckRpcTlsPskState)); - if (tls == NULL) { - fprintf(stderr, "can't allocate memory for TLS-PSK"); - exit(1); - } - - if (! gck_rpc_init_tls_psk(tls, tls_psk_keyfile, NULL, GCK_RPC_TLS_PSK_SERVER)) { - fprintf(stderr, "TLS-PSK initialization failed"); - exit(1); - } - } - - if (strcmp(path,"-") == 0) { - /* inetd mode */ - sock = 0; - mode = GCP_RPC_DAEMON_MODE_INETD; - } else { - /* Do some initialization before enabling seccomp. */ - sock = gck_rpc_layer_initialize(path, funcs); - if (sock == -1) - exit(1); - - /* Shut down gracefully on SIGTERM. */ - if (signal (SIGTERM, termination_handler) == SIG_IGN) - signal (SIGTERM, SIG_IGN); - - mode = GCP_RPC_DAEMON_MODE_SOCKET; - } - - /* - * Enable seccomp. This is essentially a whitelist containing all the syscalls - * we expect to call from here on. Anything not whitelisted will cause the - * process to terminate. - */ - if (install_syscall_filter(sock, tls_psk_keyfile, path)) - return 1; - - if (mode == GCP_RPC_DAEMON_MODE_INETD) { - gck_rpc_layer_inetd(funcs); - } else if (mode == GCP_RPC_DAEMON_MODE_SOCKET) { - is_running = 1; - while (is_running) { - FD_ZERO(&read_fds); - FD_SET(sock, &read_fds); - ret = select(sock + 1, &read_fds, NULL, NULL, NULL); - if (ret < 0) { - if (errno == EINTR) - continue; - fprintf(stderr, "error watching socket: %s\n", - strerror(errno)); - exit(1); - } - - if (FD_ISSET(sock, &read_fds)) - gck_rpc_layer_accept(tls); - } - - gck_rpc_layer_uninitialize(); - } else { - /* Not reached */ - exit(-1); - } - - rv = (funcs->C_Finalize) (NULL); - if (rv != CKR_OK) - fprintf(stderr, "couldn't finalize module: %s: 0x%08x\n", - argv[1], (int)rv); - - dlclose(module); - - if (tls) { - gck_rpc_close_tls(tls); - free(tls); - tls = NULL; - } - - return 0; -} diff --git a/ext/pkcs11-proxy/gck-rpc-dispatch.c b/ext/pkcs11-proxy/gck-rpc-dispatch.c deleted file mode 100644 index fd0ef389c..000000000 --- a/ext/pkcs11-proxy/gck-rpc-dispatch.c +++ /dev/null @@ -1,2735 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* gck-rpc-dispatch.h - receiver of our PKCS#11 protocol. - - Copyright (C) 2008, Stef Walter - - The Gnome Keyring Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The Gnome Keyring 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the Gnome Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Stef Walter -*/ - -#include "config.h" - -#include "gck-rpc-layer.h" -#include "gck-rpc-private.h" -#include "gck-rpc-tls-psk.h" - -#include "pkcs11/pkcs11.h" -#include "pkcs11/pkcs11g.h" -#include "pkcs11/pkcs11i.h" - -#include -#include -#ifdef __MINGW32__ -# include -#else -# include -# include -# include -# include -# include -# include -# include -#endif -#include - -#include -#include -#include -#include -#include -#include - -#ifdef SECCOMP -#include -//#include "seccomp-bpf.h" -#ifdef DEBUG_SECCOMP -# include "syscall-reporter.h" -#endif /* DEBUG_SECCOMP */ -#include /* for seccomp init */ -#endif /* SECCOMP */ -#include - -/* Where we dispatch the calls to */ -static CK_FUNCTION_LIST_PTR pkcs11_module = NULL; - -/* The error returned on protocol failures */ -#define PARSE_ERROR CKR_DEVICE_ERROR -#define PREP_ERROR CKR_DEVICE_MEMORY - -typedef struct { - CK_SESSION_HANDLE id; - CK_SLOT_ID slot; -} SessionState; - -typedef struct _CallState { - GckRpcMessage *req; - GckRpcMessage *resp; - void *allocated; - uint64_t appid; - int call; - int sock; - int (*read)(void *cs, unsigned char *,size_t); - int (*write)(void *cs, unsigned char *,size_t); - struct sockaddr_storage addr; - socklen_t addrlen; - /* XXX Maybe sessions should be a linked list instead, to remove the hard - * upper limit and reduce typical memory use. - */ - SessionState sessions[PKCS11PROXY_MAX_SESSION_COUNT]; - GckRpcTlsPskState *tls; -} CallState; - -typedef struct _DispatchState { - struct _DispatchState *next; - pthread_t thread; - CallState cs; -} DispatchState; - -/* A linked list of dispatcher threads */ -static DispatchState *pkcs11_dispatchers = NULL; - -/* A mutex to protect the dispatcher list */ -static pthread_mutex_t pkcs11_dispatchers_mutex = PTHREAD_MUTEX_INITIALIZER; - -/* To be able to call C_Finalize from call_uninit. */ -static CK_RV rpc_C_Finalize(CallState *); - -static int _install_dispatch_syscall_filter(int use_tls); - -/* ----------------------------------------------------------------------------- - * LOGGING and DEBUGGING - */ -#ifndef DEBUG_OUTPUT -#define DEBUG_OUTPUT 1 -#endif -#if DEBUG_OUTPUT -#define debug(x) gck_rpc_debug x -#else -#define debug(x) -#endif - -#define warning(x) gck_rpc_warn x - -#define return_val_if_fail(x, v) \ - if (!(x)) { rpc_warn ("'%s' not true at %s", #x, __func__); return v; } - -void gck_rpc_log(const char *msg, ...) -{ - va_list ap; - - va_start(ap, msg); -#if DEBUG_OUTPUT - vfprintf(stderr, msg, ap); - fprintf(stderr, "\n"); -#else - vsyslog(LOG_INFO,msg,ap); -#endif - va_end(ap); -} - -/* ------------------------------------------------------------------------------- - * CALL STRUCTURES - */ - -static int call_init(CallState * cs) -{ - assert(cs); - - cs->req = gck_rpc_message_new((EggBufferAllocator) realloc); - cs->resp = gck_rpc_message_new((EggBufferAllocator) realloc); - if (!cs->req || !cs->resp) { - gck_rpc_message_free(cs->req); - gck_rpc_message_free(cs->resp); - return 0; - } - - cs->allocated = NULL; - return 1; -} - -static void *call_alloc(CallState * cs, size_t length) -{ - void **data; - - assert(cs); - - if (length > 0x7fffffff) - return NULL; - - data = malloc(sizeof(void *) + length); - if (!data) - return NULL; - - /* Munch up the memory to help catch bugs */ - memset(data, 0xff, sizeof(void *) + length); - - /* Store pointer to next allocated block at beginning */ - *data = cs->allocated; - cs->allocated = data; - - /* Data starts after first pointer */ - return (void *)(data + 1); -} - -static void call_reset(CallState * cs) -{ - void *allocated; - void **data; - - assert(cs); - - allocated = cs->allocated; - while (allocated) { - data = (void **)allocated; - - /* Pointer to the next allocation */ - allocated = *data; - free(data); - } - - cs->allocated = NULL; - gck_rpc_message_reset(cs->req); - gck_rpc_message_reset(cs->resp); -} - -static void call_uninit(CallState * cs) -{ - assert(cs); - - /* Close any open sessions. Without this, the application won't be able - * to reconnect (possibly after a crash). - */ - if (cs->req) - rpc_C_Finalize(cs); - - call_reset(cs); - - gck_rpc_message_free(cs->req); - gck_rpc_message_free(cs->resp); -} - -/* ------------------------------------------------------------------- - * PROTOCOL CODE - */ - -static CK_RV -proto_read_byte_buffer(CallState * cs, CK_BYTE_PTR * buffer, - CK_ULONG_PTR * n_buffer) -{ - GckRpcMessage *msg; - uint8_t flags; - uint32_t length; - - assert(cs); - assert(buffer); - assert(n_buffer); - - msg = cs->req; - - /* Check that we're supposed to be reading this at this point */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "fy")); - - if (!egg_buffer_get_byte - (&msg->buffer, msg->parsed, &msg->parsed, &flags)) - return PARSE_ERROR; - - /* The number of ulongs there's room for on the other end */ - if (!egg_buffer_get_uint32 - (&msg->buffer, msg->parsed, &msg->parsed, &length)) - return PARSE_ERROR; - - - **n_buffer = length; - *buffer = NULL_PTR; - - if ((flags & GCK_RPC_BYTE_BUFFER_NULL_COUNT)) - *n_buffer = NULL_PTR; - - if (! (flags & GCK_RPC_BYTE_BUFFER_NULL_DATA)) { - *buffer = call_alloc(cs, length * sizeof(CK_BYTE)); - if (!*buffer) - return CKR_DEVICE_MEMORY; - } - - return CKR_OK; -} - -static CK_RV -proto_read_byte_array(CallState * cs, CK_BYTE_PTR * array, CK_ULONG * n_array) -{ - GckRpcMessage *msg; - const unsigned char *data; - unsigned char valid; - size_t n_data; - - assert(cs); - - msg = cs->req; - - /* Check that we're supposed to have this at this point */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "ay")); - - /* Read out the byte which says whether data is present or not */ - if (!egg_buffer_get_byte - (&msg->buffer, msg->parsed, &msg->parsed, &valid)) - return PARSE_ERROR; - - if (!valid) { - uint32_t n_size; - /* No array, no data, just length */ - if (!egg_buffer_get_uint32 - (&msg->buffer, msg->parsed, &msg->parsed, &n_size)) - return PARSE_ERROR; - *n_array = (size_t) n_size; - *array = NULL; - return CKR_OK; - } - - /* Point our arguments into the buffer */ - if (!egg_buffer_get_byte_array(&msg->buffer, msg->parsed, &msg->parsed, - &data, &n_data)) - return PARSE_ERROR; - - *array = (CK_BYTE_PTR) data; - *n_array = n_data; - return CKR_OK; -} - -static CK_RV -proto_write_byte_array(CallState * cs, CK_BYTE_PTR array, CK_ULONG_PTR len, - CK_RV ret) -{ - assert(cs); - - /* - * When returning an byte array, in many cases we need to pass - * an invalid array along with a length, which signifies CKR_BUFFER_TOO_SMALL. - */ - - switch (ret) { - case CKR_BUFFER_TOO_SMALL: - array = NULL; - /* fall through */ - case CKR_OK: - break; - - /* Pass all other errors straight through */ - default: - return ret; - }; - - if (!gck_rpc_message_write_byte_array(cs->resp, array, len ? *len : 0)) - return PREP_ERROR; - - return CKR_OK; -} - -static CK_RV -proto_read_ulong_buffer(CallState * cs, CK_ULONG_PTR * buffer, - CK_ULONG * n_buffer) -{ - GckRpcMessage *msg; - uint32_t length; - - assert(cs); - assert(buffer); - assert(n_buffer); - - msg = cs->req; - - /* Check that we're supposed to be reading this at this point */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "fu")); - - /* The number of ulongs there's room for on the other end */ - if (!egg_buffer_get_uint32 - (&msg->buffer, msg->parsed, &msg->parsed, &length)) - return PARSE_ERROR; - - *n_buffer = length; - *buffer = NULL; - - /* If set to zero, then they just want the length */ - if (!length) - return CKR_OK; - - *buffer = call_alloc(cs, length * sizeof(CK_ULONG)); - if (!*buffer) - return CKR_DEVICE_MEMORY; - - return CKR_OK; -} - -static CK_RV -proto_write_ulong_array(CallState * cs, CK_ULONG_PTR array, CK_ULONG len, - CK_RV ret) -{ - assert(cs); - - /* - * When returning an ulong array, in many cases we need to pass - * an invalid array along with a length, which signifies CKR_BUFFER_TOO_SMALL. - */ - - switch (ret) { - case CKR_BUFFER_TOO_SMALL: - array = NULL; - /* fall through */ - case CKR_OK: - break; - - /* Pass all other errors straight through */ - default: - return ret; - }; - - if (!gck_rpc_message_write_ulong_array(cs->resp, array, len)) - return PREP_ERROR; - - return CKR_OK; -} - -static CK_RV -proto_read_attribute_buffer(CallState * cs, CK_ATTRIBUTE_PTR * result, - CK_ULONG * n_result) -{ - CK_ATTRIBUTE_PTR attrs; - GckRpcMessage *msg; - uint32_t n_attrs, i; - uint32_t value; - - assert(cs); - assert(result); - assert(n_result); - - msg = cs->req; - - /* Make sure this is in the rigth order */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "fA")); - - /* Read the number of attributes */ - if (!egg_buffer_get_uint32 - (&msg->buffer, msg->parsed, &msg->parsed, &n_attrs)) - return PARSE_ERROR; - - /* Allocate memory for the attribute structures */ - attrs = call_alloc(cs, n_attrs * sizeof(CK_ATTRIBUTE)); - if (!attrs) - return CKR_DEVICE_MEMORY; - - /* Now go through and fill in each one */ - for (i = 0; i < n_attrs; ++i) { - - /* The attribute type */ - if (!egg_buffer_get_uint32 - (&msg->buffer, msg->parsed, &msg->parsed, &value)) - return PARSE_ERROR; - - attrs[i].type = value; - - /* The number of bytes to allocate */ - if (!egg_buffer_get_uint32 - (&msg->buffer, msg->parsed, &msg->parsed, &value)) - return PARSE_ERROR; - - if (value == 0) { - attrs[i].pValue = NULL; - attrs[i].ulValueLen = 0; - } else { - attrs[i].pValue = call_alloc(cs, value); - if (!attrs[i].pValue) - return CKR_DEVICE_MEMORY; - attrs[i].ulValueLen = value; - } - } - - *result = attrs; - *n_result = n_attrs; - return CKR_OK; -} - -static CK_RV -proto_read_attribute_array(CallState * cs, CK_ATTRIBUTE_PTR * result, - CK_ULONG * n_result) -{ - CK_ATTRIBUTE_PTR attrs; - const unsigned char *data; - unsigned char valid; - GckRpcMessage *msg; - uint32_t n_attrs, i; - uint32_t value; - size_t n_data; - - assert(cs); - assert(result); - assert(n_result); - - msg = cs->req; - - /* Make sure this is in the right order */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "aA")); - - /* Read the number of attributes */ - if (!egg_buffer_get_uint32 - (&msg->buffer, msg->parsed, &msg->parsed, &n_attrs)) - return PARSE_ERROR; - - if (! n_attrs) { - /* If there are no attributes, it makes most sense to make result - * a NULL pointer. What use could one have of a potentially dangling - * pointer anyways? - */ - *result = NULL_PTR; - *n_result = n_attrs; - return CKR_OK; - } - - /* Allocate memory for the attribute structures */ - attrs = call_alloc(cs, n_attrs * sizeof(CK_ATTRIBUTE)); - if (!attrs) - return CKR_DEVICE_MEMORY; - - /* Now go through and fill in each one */ - for (i = 0; i < n_attrs; ++i) { - - /* The attribute type */ - if (!egg_buffer_get_uint32 - (&msg->buffer, msg->parsed, &msg->parsed, &value)) - return PARSE_ERROR; - - attrs[i].type = value; - - /* Whether this one is valid or not */ - if (!egg_buffer_get_byte - (&msg->buffer, msg->parsed, &msg->parsed, &valid)) - return PARSE_ERROR; - - if (valid) { - if (!egg_buffer_get_uint32 - (&msg->buffer, msg->parsed, &msg->parsed, &value)) - return PARSE_ERROR; - if (!egg_buffer_get_byte_array - (&msg->buffer, msg->parsed, &msg->parsed, &data, - &n_data)) - return PARSE_ERROR; - - if (data != NULL && n_data != value) { - gck_rpc_warn - ("attribute length and data do not match"); - return PARSE_ERROR; - } - - CK_ULONG a; - - if (value == sizeof (uint64_t) && - value != sizeof (CK_ULONG) && - gck_rpc_has_ulong_parameter(attrs[i].type)) { - - value = sizeof (CK_ULONG); - a = *(uint64_t *)data; - *(CK_ULONG *)data = a; - } - attrs[i].pValue = (CK_VOID_PTR) data; - attrs[i].ulValueLen = value; - } else { - attrs[i].pValue = NULL; - attrs[i].ulValueLen = -1; - } - } - - *result = attrs; - *n_result = n_attrs; - return CKR_OK; -} - -static CK_RV -proto_write_attribute_array(CallState * cs, CK_ATTRIBUTE_PTR array, - CK_ULONG len, CK_RV ret) -{ - assert(cs); - - /* - * When returning an attribute array, certain errors aren't - * actually real errors, these are passed through to the other - * side along with the attribute array. - */ - - switch (ret) { - case CKR_ATTRIBUTE_SENSITIVE: - case CKR_ATTRIBUTE_TYPE_INVALID: - case CKR_BUFFER_TOO_SMALL: - case CKR_OK: - break; - - /* Pass all other errors straight through */ - default: - return ret; - }; - - if (!gck_rpc_message_write_attribute_array(cs->resp, array, len) || - !gck_rpc_message_write_ulong(cs->resp, ret)) - return PREP_ERROR; - - return CKR_OK; -} - -static CK_RV proto_read_space_string(CallState * cs, CK_UTF8CHAR_PTR * val, CK_ULONG length) -{ - GckRpcMessage *msg; - const unsigned char *data; - size_t n_data; - - assert(cs); - assert(val); - - msg = cs->req; - - /* Check that we're supposed to have this at this point */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "s")); - - if (!egg_buffer_get_byte_array - (&msg->buffer, msg->parsed, &msg->parsed, &data, &n_data)) - return PARSE_ERROR; - - /* Allocate a block of memory for it. */ - *val = call_alloc(cs, n_data); - if (!*val) - return CKR_DEVICE_MEMORY; - - memcpy(*val, data, n_data); - - return CKR_OK; -} - -static CK_RV proto_read_mechanism(CallState * cs, CK_MECHANISM_PTR mech) -{ - GckRpcMessage *msg; - const unsigned char *data; - uint32_t value; - size_t n_data; - - assert(cs); - assert(mech); - - msg = cs->req; - - /* Make sure this is in the right order */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "M")); - - /* The mechanism type */ - if (!egg_buffer_get_uint32 - (&msg->buffer, msg->parsed, &msg->parsed, &value)) - return PARSE_ERROR; - - /* The mechanism data */ - if (!egg_buffer_get_byte_array - (&msg->buffer, msg->parsed, &msg->parsed, &data, &n_data)) - return PARSE_ERROR; - - mech->mechanism = value; - mech->pParameter = (CK_VOID_PTR) data; - mech->ulParameterLen = n_data; - return CKR_OK; -} - -static CK_RV proto_write_info(CallState * cs, CK_INFO_PTR info) -{ - GckRpcMessage *msg; - - assert(cs); - assert(info); - - msg = cs->resp; - - if (!gck_rpc_message_write_version(msg, &info->cryptokiVersion) || - !gck_rpc_message_write_space_string(msg, info->manufacturerID, 32) - || !gck_rpc_message_write_ulong(msg, info->flags) - || !gck_rpc_message_write_space_string(msg, - info->libraryDescription, 32) - || !gck_rpc_message_write_version(msg, &info->libraryVersion)) - return PREP_ERROR; - - return CKR_OK; -} - -static CK_RV proto_write_slot_info(CallState * cs, CK_SLOT_INFO_PTR info) -{ - GckRpcMessage *msg; - - assert(cs); - assert(info); - - msg = cs->resp; - - if (!gck_rpc_message_write_space_string(msg, info->slotDescription, 64) - || !gck_rpc_message_write_space_string(msg, info->manufacturerID, - 32) - || !gck_rpc_message_write_ulong(msg, info->flags) - || !gck_rpc_message_write_version(msg, &info->hardwareVersion) - || !gck_rpc_message_write_version(msg, &info->firmwareVersion)) - return PREP_ERROR; - - return CKR_OK; -} - -static CK_RV proto_write_token_info(CallState * cs, CK_TOKEN_INFO_PTR info) -{ - GckRpcMessage *msg; - - assert(cs); - assert(info); - - msg = cs->resp; - - if (!gck_rpc_message_write_space_string(msg, info->label, 32) || - !gck_rpc_message_write_space_string(msg, info->manufacturerID, 32) - || !gck_rpc_message_write_space_string(msg, info->model, 16) - || !gck_rpc_message_write_space_string(msg, info->serialNumber, 16) - || !gck_rpc_message_write_ulong(msg, info->flags) - || !gck_rpc_message_write_ulong(msg, info->ulMaxSessionCount) - || !gck_rpc_message_write_ulong(msg, info->ulSessionCount) - || !gck_rpc_message_write_ulong(msg, info->ulMaxRwSessionCount) - || !gck_rpc_message_write_ulong(msg, info->ulRwSessionCount) - || !gck_rpc_message_write_ulong(msg, info->ulMaxPinLen) - || !gck_rpc_message_write_ulong(msg, info->ulMinPinLen) - || !gck_rpc_message_write_ulong(msg, info->ulTotalPublicMemory) - || !gck_rpc_message_write_ulong(msg, info->ulFreePublicMemory) - || !gck_rpc_message_write_ulong(msg, info->ulTotalPrivateMemory) - || !gck_rpc_message_write_ulong(msg, info->ulFreePrivateMemory) - || !gck_rpc_message_write_version(msg, &info->hardwareVersion) - || !gck_rpc_message_write_version(msg, &info->firmwareVersion) - || !gck_rpc_message_write_space_string(msg, info->utcTime, 16)) - return PREP_ERROR; - - return CKR_OK; -} - -static CK_RV -proto_write_mechanism_info(CallState * cs, CK_MECHANISM_INFO_PTR info) -{ - GckRpcMessage *msg; - - assert(cs); - assert(info); - - msg = cs->resp; - - if (!gck_rpc_message_write_ulong(msg, info->ulMinKeySize) || - !gck_rpc_message_write_ulong(msg, info->ulMaxKeySize) || - !gck_rpc_message_write_ulong(msg, info->flags)) - return PREP_ERROR; - - return CKR_OK; -} - -static CK_RV proto_write_session_info(CallState * cs, CK_SESSION_INFO_PTR info) -{ - GckRpcMessage *msg; - - assert(cs); - assert(info); - - msg = cs->resp; - - if (!gck_rpc_message_write_ulong(msg, info->slotID) || - !gck_rpc_message_write_ulong(msg, info->state) || - !gck_rpc_message_write_ulong(msg, info->flags) || - !gck_rpc_message_write_ulong(msg, info->ulDeviceError)) - return PREP_ERROR; - - return CKR_OK; -} - -/* ------------------------------------------------------------------- - * CALL MACROS - */ - -#define DECLARE_CK_ULONG_PTR(ck_ulong_ptr_name) \ - CK_ULONG ck_ulong_ptr_name ## _v ; \ - CK_ULONG_PTR ck_ulong_ptr_name ; \ - ck_ulong_ptr_name ## _v = 0; \ - ck_ulong_ptr_name = &ck_ulong_ptr_name ## _v ; - -#define BEGIN_CALL(call_id) \ - debug ((#call_id ": enter")); \ - assert (cs); \ - assert (pkcs11_module); \ - { \ - CK_ ## call_id _func = pkcs11_module-> call_id; \ - CK_RV _ret = CKR_OK; \ - if (!_func) { _ret = CKR_GENERAL_ERROR; goto _cleanup; } - -#define PROCESS_CALL(args)\ - assert (gck_rpc_message_is_verified (cs->req)); \ - _ret = _func args - -#define END_CALL \ - _cleanup: \ - debug (("ret: 0x%x", _ret)); \ - return _ret; \ - } - -#define IN_BYTE(val) \ - if (!gck_rpc_message_read_byte (cs->req, &val)) \ - { _ret = PARSE_ERROR; goto _cleanup; } - -#define IN_ULONG(val) \ - if (!gck_rpc_message_read_ulong (cs->req, &val)) \ - { _ret = PARSE_ERROR; goto _cleanup; } - -#define IN_SPACE_STRING(val, len) \ - _ret = proto_read_space_string (cs, &val, len); \ - if (_ret != CKR_OK) goto _cleanup; - -#define IN_BYTE_BUFFER(buffer, buffer_len_ptr) \ - _ret = proto_read_byte_buffer (cs, &buffer, &buffer_len_ptr); \ - if (_ret != CKR_OK) goto _cleanup; - -#define IN_BYTE_ARRAY(buffer, buffer_len) \ - _ret = proto_read_byte_array (cs, &buffer, &buffer_len); \ - if (_ret != CKR_OK) goto _cleanup; - -#define IN_ULONG_BUFFER(buffer, buffer_len) \ - _ret = proto_read_ulong_buffer (cs, &buffer, &buffer_len); \ - if (_ret != CKR_OK) goto _cleanup; - -#define IN_ATTRIBUTE_BUFFER(buffer, buffer_len) \ - _ret = proto_read_attribute_buffer (cs, &buffer, &buffer_len); \ - if (_ret != CKR_OK) goto _cleanup; - -#define IN_ATTRIBUTE_ARRAY(attrs, n_attrs) \ - _ret = proto_read_attribute_array (cs, &attrs, &n_attrs); \ - if (_ret != CKR_OK) goto _cleanup; - -#define IN_MECHANISM(mech) \ - _ret = proto_read_mechanism (cs, &mech); \ - if (_ret != CKR_OK) goto _cleanup; - -#define OUT_ULONG(val) \ - if (_ret == CKR_OK && !gck_rpc_message_write_ulong (cs->resp, val)) \ - _ret = PREP_ERROR; - -#define OUT_BYTE_ARRAY(array, len_ptr) \ - /* Note how we filter return codes */ \ - _ret = proto_write_byte_array (cs, array, len_ptr, _ret); - -#define OUT_ULONG_ARRAY(array, len) \ - /* Note how we filter return codes */ \ - _ret = proto_write_ulong_array (cs, array, len, _ret); - -#define OUT_ATTRIBUTE_ARRAY(array, len) \ - /* Note how we filter return codes */ \ - _ret = proto_write_attribute_array (cs, array, len, _ret); - -#define OUT_INFO(val) \ - if (_ret == CKR_OK) \ - _ret = proto_write_info (cs, &val); - -#define OUT_SLOT_INFO(val) \ - if (_ret == CKR_OK) \ - _ret = proto_write_slot_info (cs, &val); - -#define OUT_TOKEN_INFO(val) \ - if (_ret == CKR_OK) \ - _ret = proto_write_token_info (cs, &val); - -#define OUT_MECHANISM_INFO(val) \ - if (_ret == CKR_OK) \ - _ret = proto_write_mechanism_info (cs, &val); - -#define OUT_SESSION_INFO(val) \ - if (_ret == CKR_OK) \ - _ret = proto_write_session_info (cs, &val); - -/* --------------------------------------------------------------------------- - * DISPATCH SPECIFIC CALLS - */ - -static CK_RV rpc_C_Initialize(CallState * cs) -{ - CK_BYTE_PTR handshake; - CK_ULONG n_handshake; - CK_RV ret = CKR_OK; - - debug(("C_Initialize: enter")); - - assert(cs); - assert(pkcs11_module); - - ret = proto_read_byte_array(cs, &handshake, &n_handshake); - if (ret == CKR_OK) { - - /* Check to make sure the header matches */ - if (n_handshake != GCK_RPC_HANDSHAKE_LEN || - handshake == NULL_PTR || - memcmp(handshake, GCK_RPC_HANDSHAKE, n_handshake) != 0) { - gck_rpc_warn - ("invalid handshake received from connecting module"); - ret = CKR_GENERAL_ERROR; - } - - assert(gck_rpc_message_is_verified(cs->req)); - } - - /* - * We don't actually C_Initialize lower layers. It's assumed - * that they'll already be initialzied by the code that loaded us. - */ - - debug(("ret: %d", ret)); - return ret; -} - -static CK_RV rpc_C_Finalize(CallState * cs) -{ - CK_ULONG i; - CK_RV ret; - DispatchState *ds, *next; - - - debug(("C_Finalize: enter")); - - assert(cs); - assert(pkcs11_module); - - /* - * We don't actually C_Finalize lower layers, since this would finalize - * for all appartments, client applications. Anyway this is done by - * the code that loaded us. - */ - - ret = CKR_OK; - - /* Close all sessions that have been opened by this thread, regardless of slot */ - for (i = 0; i < PKCS11PROXY_MAX_SESSION_COUNT; i++) { - if (cs->sessions[i].id) { - gck_rpc_log("Closing session %li on position %i", cs->sessions[i].id, i); - - ret = (pkcs11_module->C_CloseSession) (cs->sessions[i].id); - if (ret != CKR_OK) - break; - cs->sessions[i].id = 0; - } - } - - /* Make all C_WaitForSlotEvent calls return */ - pthread_mutex_lock(&pkcs11_dispatchers_mutex); - for (ds = pkcs11_dispatchers; ds; ds = next) { - CallState *c = &ds->cs; - - next = ds->next; - - if (c->appid != cs->appid) - continue ; - if (c->sock == cs->sock) - continue ; - if (c->req && - (c->req->call_id == GCK_RPC_CALL_C_WaitForSlotEvent)) { - gck_rpc_log("Sending interuption signal to %i\n", - c->sock); - if (c->sock != -1) - if (shutdown(c->sock, SHUT_RDWR) == 0) - c->sock = -1; - //pthread_kill(ds->thread, SIGINT); - } - } - pthread_mutex_unlock(&pkcs11_dispatchers_mutex); - - debug(("ret: %d", ret)); - return ret; -} - -static CK_RV rpc_C_GetInfo(CallState * cs) -{ - CK_INFO info; - - BEGIN_CALL(C_GetInfo); - PROCESS_CALL((&info)); - OUT_INFO(info); - END_CALL; -} - -static CK_RV rpc_C_GetSlotList(CallState * cs) -{ - CK_BBOOL token_present; - CK_SLOT_ID_PTR slot_list; - CK_ULONG count; - - BEGIN_CALL(C_GetSlotList); - IN_BYTE(token_present); - IN_ULONG_BUFFER(slot_list, count); - PROCESS_CALL((token_present, slot_list, &count)); - OUT_ULONG_ARRAY(slot_list, count); - END_CALL; -} - -static CK_RV rpc_C_GetSlotInfo(CallState * cs) -{ - CK_SLOT_ID slot_id; - CK_SLOT_INFO info; - - /* Slot id becomes appartment so lower layers can tell clients apart. */ - - BEGIN_CALL(C_GetSlotInfo); - IN_ULONG(slot_id); - PROCESS_CALL((slot_id, &info)); - OUT_SLOT_INFO(info); - END_CALL; -} - -static CK_RV rpc_C_GetTokenInfo(CallState * cs) -{ - CK_SLOT_ID slot_id; - CK_TOKEN_INFO info; - - /* Slot id becomes appartment so lower layers can tell clients apart. */ - - BEGIN_CALL(C_GetTokenInfo); - IN_ULONG(slot_id); - PROCESS_CALL((slot_id, &info)); - OUT_TOKEN_INFO(info); - END_CALL; -} - -static CK_RV rpc_C_GetMechanismList(CallState * cs) -{ - CK_SLOT_ID slot_id; - CK_MECHANISM_TYPE_PTR mechanism_list; - CK_ULONG count; - - /* Slot id becomes appartment so lower layers can tell clients apart. */ - - BEGIN_CALL(C_GetMechanismList); - IN_ULONG(slot_id); - IN_ULONG_BUFFER(mechanism_list, count); - PROCESS_CALL((slot_id, mechanism_list, &count)); - OUT_ULONG_ARRAY(mechanism_list, count); - END_CALL; -} - -static CK_RV rpc_C_GetMechanismInfo(CallState * cs) -{ - CK_SLOT_ID slot_id; - CK_MECHANISM_TYPE type; - CK_MECHANISM_INFO info; - - /* Slot id becomes appartment so lower layers can tell clients apart. */ - - BEGIN_CALL(C_GetMechanismInfo); - IN_ULONG(slot_id); - IN_ULONG(type); - PROCESS_CALL((slot_id, type, &info)); - OUT_MECHANISM_INFO(info); - END_CALL; -} - -static CK_RV rpc_C_InitToken(CallState * cs) -{ - CK_SLOT_ID slot_id; - CK_UTF8CHAR_PTR pin; - CK_ULONG pin_len; - CK_UTF8CHAR_PTR label; - - /* Slot id becomes appartment so lower layers can tell clients apart. */ - - BEGIN_CALL(C_InitToken); - IN_ULONG(slot_id); - IN_BYTE_ARRAY(pin, pin_len); - IN_SPACE_STRING(label, 32); - PROCESS_CALL((slot_id, pin, pin_len, label)); - END_CALL; -} - -static CK_RV rpc_C_WaitForSlotEvent(CallState * cs) -{ - CK_FLAGS flags; - CK_SLOT_ID slot_id; - - /* Get slot id from appartment lower layers use. */ - - BEGIN_CALL(C_WaitForSlotEvent); - IN_ULONG(flags); - PROCESS_CALL((flags, &slot_id, NULL)); - slot_id = CK_GNOME_APPARTMENT_SLOT(slot_id); - OUT_ULONG(slot_id); - END_CALL; -} - -static CK_RV rpc_C_OpenSession(CallState * cs) -{ - CK_SLOT_ID slot_id; - CK_FLAGS flags; - CK_SESSION_HANDLE session; - - /* Slot id becomes appartment so lower layers can tell clients apart. */ - - BEGIN_CALL(C_OpenSession); - IN_ULONG(slot_id); - IN_ULONG(flags); - PROCESS_CALL((slot_id, flags, NULL, NULL, &session)); - if (_ret == CKR_OK) { - int i; - /* Remember this thread opened this session. Needed for C_CloseAllSessions. */ - for (i = 0; i < PKCS11PROXY_MAX_SESSION_COUNT; i++) { - if (! cs->sessions[i].id) { - cs->sessions[i].id = session; - cs->sessions[i].slot = slot_id; - gck_rpc_log("Session %li stored in position %i", session, i); - break; - } - } - if (i == PKCS11PROXY_MAX_SESSION_COUNT) { - _ret = CKR_SESSION_COUNT; goto _cleanup; - } - } - OUT_ULONG(session); - END_CALL; -} - -static CK_RV rpc_C_CloseSession(CallState * cs) -{ - CK_SESSION_HANDLE session; - - BEGIN_CALL(C_CloseSession); - IN_ULONG(session); - PROCESS_CALL((session)); - if (_ret == CKR_OK) { - int i; - /* Remove this session from this threads list */ - for (i = 0; i < PKCS11PROXY_MAX_SESSION_COUNT; i++) { - if (cs->sessions[i].id == session) { - gck_rpc_log("Session %li removed from position %i", session, i); - cs->sessions[i].id = 0; - break; - } - } - if (i == PKCS11PROXY_MAX_SESSION_COUNT) { - /* Ignore errors, like with close() */ - gck_rpc_log("C_CloseSession on unknown session"); - } - } - END_CALL; -} - -static CK_RV rpc_C_CloseAllSessions(CallState * cs) -{ - CK_SLOT_ID slot_id; - CK_SLOT_INFO slotInfo; - int i; - - /* Close all sessions that have been opened by this thread. PKCS#11 (v2.2) says - * C_CloseAllSessions closes all the sessions opened by one application, leaving - * sessions opened by other applications alone even if the sessions share slot. - * - * Each application on the client side of pkcs11-proxy will mean different thread - * on the server side, so we should close all sessions for a slot opened in this - * thread. - */ - - BEGIN_CALL(C_CloseAllSessions); - IN_ULONG(slot_id); - - /* To emulate real C_CloseAllSessions (well, the SoftHSM one) we check if slot_id is valid. */ - _ret = pkcs11_module->C_GetSlotInfo(slot_id, &slotInfo); - if (_ret != CKR_OK) - goto _cleanup; - - for (i = 0; i < PKCS11PROXY_MAX_SESSION_COUNT; i++) { - if (cs->sessions[i].id && (cs->sessions[i].slot == slot_id)) { - gck_rpc_log("Closing session %li on position %i with slot %i", cs->sessions[i].id, i, slot_id); - - _ret = (pkcs11_module->C_CloseSession) (cs->sessions[i].id); - if (_ret == CKR_OK || - _ret == CKR_SESSION_CLOSED || - _ret == CKR_SESSION_HANDLE_INVALID) { - cs->sessions[i].id = 0; - } - if (_ret != CKR_OK) - goto _cleanup; - } - } - END_CALL; -} - -static CK_RV rpc_C_GetFunctionStatus(CallState * cs) -{ - CK_SESSION_HANDLE session; - - BEGIN_CALL(C_GetFunctionStatus); - IN_ULONG(session); - PROCESS_CALL((session)); - END_CALL; -} - -static CK_RV rpc_C_CancelFunction(CallState * cs) -{ - CK_SESSION_HANDLE session; - - BEGIN_CALL(C_CancelFunction); - IN_ULONG(session); - PROCESS_CALL((session)); - END_CALL; -} - -static CK_RV rpc_C_GetSessionInfo(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_SESSION_INFO info; - - /* Get slot id from appartment lower layers use. */ - - BEGIN_CALL(C_GetSessionInfo); - IN_ULONG(session); - PROCESS_CALL((session, &info)); - info.slotID = CK_GNOME_APPARTMENT_SLOT(info.slotID); - OUT_SESSION_INFO(info); - END_CALL; -} - -static CK_RV rpc_C_InitPIN(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_UTF8CHAR_PTR pin; - CK_ULONG pin_len; - - BEGIN_CALL(C_InitPIN); - IN_ULONG(session); - IN_BYTE_ARRAY(pin, pin_len); - PROCESS_CALL((session, pin, pin_len)); - END_CALL; -} - -static CK_RV rpc_C_SetPIN(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_UTF8CHAR_PTR old_pin; - CK_ULONG old_len; - CK_UTF8CHAR_PTR new_pin; - CK_ULONG new_len; - - BEGIN_CALL(C_SetPIN); - IN_ULONG(session); - IN_BYTE_ARRAY(old_pin, old_len); - IN_BYTE_ARRAY(new_pin, new_len); - PROCESS_CALL((session, old_pin, old_len, new_pin, new_len)); - END_CALL; -} - -static CK_RV rpc_C_GetOperationState(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR operation_state; - DECLARE_CK_ULONG_PTR(operation_state_len); - - BEGIN_CALL(C_GetOperationState); - IN_ULONG(session); - IN_BYTE_BUFFER(operation_state, operation_state_len); - PROCESS_CALL((session, operation_state, operation_state_len)); - OUT_BYTE_ARRAY(operation_state, operation_state_len); - END_CALL; -} - -static CK_RV rpc_C_SetOperationState(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR operation_state; - CK_ULONG operation_state_len; - CK_OBJECT_HANDLE encryption_key; - CK_OBJECT_HANDLE authentication_key; - - BEGIN_CALL(C_SetOperationState); - IN_ULONG(session); - IN_BYTE_ARRAY(operation_state, operation_state_len); - IN_ULONG(encryption_key); - IN_ULONG(authentication_key); - PROCESS_CALL((session, operation_state, operation_state_len, - encryption_key, authentication_key)); - END_CALL; -} - -static CK_RV rpc_C_Login(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_USER_TYPE user_type; - CK_UTF8CHAR_PTR pin; - CK_ULONG pin_len; - - BEGIN_CALL(C_Login); - IN_ULONG(session); - IN_ULONG(user_type); - IN_BYTE_ARRAY(pin, pin_len); - PROCESS_CALL((session, user_type, pin, pin_len)); - END_CALL; -} - -static CK_RV rpc_C_Logout(CallState * cs) -{ - CK_SESSION_HANDLE session; - - BEGIN_CALL(C_Logout); - IN_ULONG(session); - PROCESS_CALL((session)); - END_CALL; -} - -/* ----------------------------------------------------------------------------- - * OBJECT OPERATIONS - */ - -static CK_RV rpc_C_CreateObject(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_ATTRIBUTE_PTR template; - CK_ULONG count; - CK_OBJECT_HANDLE new_object; - - BEGIN_CALL(C_CreateObject); - IN_ULONG(session); - IN_ATTRIBUTE_ARRAY(template, count); - PROCESS_CALL((session, template, count, &new_object)); - OUT_ULONG(new_object); - END_CALL; -} - -static CK_RV rpc_C_CopyObject(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_OBJECT_HANDLE object; - CK_ATTRIBUTE_PTR template; - CK_ULONG count; - CK_OBJECT_HANDLE new_object; - - BEGIN_CALL(C_CopyObject); - IN_ULONG(session); - IN_ULONG(object); - IN_ATTRIBUTE_ARRAY(template, count); - PROCESS_CALL((session, object, template, count, &new_object)); - OUT_ULONG(new_object); - END_CALL; -} - -static CK_RV rpc_C_DestroyObject(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_OBJECT_HANDLE object; - - BEGIN_CALL(C_DestroyObject); - IN_ULONG(session); - IN_ULONG(object); - PROCESS_CALL((session, object)); - END_CALL; -} - -static CK_RV rpc_C_GetObjectSize(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_OBJECT_HANDLE object; - CK_ULONG size; - - BEGIN_CALL(C_GetObjectSize); - IN_ULONG(session); - IN_ULONG(object); - PROCESS_CALL((session, object, &size)); - OUT_ULONG(size); - END_CALL; -} - -static CK_RV rpc_C_GetAttributeValue(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_OBJECT_HANDLE object; - CK_ATTRIBUTE_PTR template; - CK_ULONG count; - - BEGIN_CALL(C_GetAttributeValue); - IN_ULONG(session); - IN_ULONG(object); - IN_ATTRIBUTE_BUFFER(template, count); - PROCESS_CALL((session, object, template, count)); - OUT_ATTRIBUTE_ARRAY(template, count); - END_CALL; -} - -static CK_RV rpc_C_SetAttributeValue(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_OBJECT_HANDLE object; - CK_ATTRIBUTE_PTR template; - CK_ULONG count; - - BEGIN_CALL(C_SetAttributeValue); - IN_ULONG(session); - IN_ULONG(object); - IN_ATTRIBUTE_ARRAY(template, count); - PROCESS_CALL((session, object, template, count)); - END_CALL; -} - -static CK_RV rpc_C_FindObjectsInit(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_ATTRIBUTE_PTR template; - CK_ULONG count; - - BEGIN_CALL(C_FindObjectsInit); - IN_ULONG(session); - IN_ATTRIBUTE_ARRAY(template, count); - PROCESS_CALL((session, template, count)); - END_CALL; -} - -static CK_RV rpc_C_FindObjects(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_OBJECT_HANDLE_PTR objects; - CK_ULONG max_object_count; - CK_ULONG object_count; - - BEGIN_CALL(C_FindObjects); - IN_ULONG(session); - IN_ULONG_BUFFER(objects, max_object_count); - PROCESS_CALL((session, objects, max_object_count, &object_count)); - OUT_ULONG_ARRAY(objects, object_count); - END_CALL; -} - -static CK_RV rpc_C_FindObjectsFinal(CallState * cs) -{ - CK_SESSION_HANDLE session; - - BEGIN_CALL(C_FindObjectsFinal); - IN_ULONG(session); - PROCESS_CALL((session)); - END_CALL; -} - -static CK_RV rpc_C_EncryptInit(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_MECHANISM mechanism; - CK_OBJECT_HANDLE key; - - BEGIN_CALL(C_EncryptInit); - IN_ULONG(session); - IN_MECHANISM(mechanism); - IN_ULONG(key); - PROCESS_CALL((session, &mechanism, key)); - END_CALL; - -} - -static CK_RV rpc_C_Encrypt(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR data; - CK_ULONG data_len; - CK_BYTE_PTR encrypted_data; - DECLARE_CK_ULONG_PTR(encrypted_data_len); - - BEGIN_CALL(C_Encrypt); - IN_ULONG(session); - IN_BYTE_ARRAY(data, data_len); - IN_BYTE_BUFFER(encrypted_data, encrypted_data_len); - PROCESS_CALL((session, data, data_len, encrypted_data, - encrypted_data_len)); - OUT_BYTE_ARRAY(encrypted_data, encrypted_data_len); - END_CALL; -} - -static CK_RV rpc_C_EncryptUpdate(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR part; - CK_ULONG part_len; - CK_BYTE_PTR encrypted_part; - DECLARE_CK_ULONG_PTR(encrypted_part_len); - - BEGIN_CALL(C_EncryptUpdate); - IN_ULONG(session); - IN_BYTE_ARRAY(part, part_len); - IN_BYTE_BUFFER(encrypted_part, encrypted_part_len); - PROCESS_CALL((session, part, part_len, encrypted_part, - encrypted_part_len)); - OUT_BYTE_ARRAY(encrypted_part, encrypted_part_len); - END_CALL; -} - -static CK_RV rpc_C_EncryptFinal(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR last_encrypted_part; - DECLARE_CK_ULONG_PTR(last_encrypted_part_len); - - BEGIN_CALL(C_EncryptFinal); - IN_ULONG(session); - IN_BYTE_BUFFER(last_encrypted_part, last_encrypted_part_len); - PROCESS_CALL((session, last_encrypted_part, last_encrypted_part_len)); - OUT_BYTE_ARRAY(last_encrypted_part, last_encrypted_part_len); - END_CALL; -} - -static CK_RV rpc_C_DecryptInit(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_MECHANISM mechanism; - CK_OBJECT_HANDLE key; - - BEGIN_CALL(C_DecryptInit); - IN_ULONG(session); - IN_MECHANISM(mechanism); - IN_ULONG(key); - PROCESS_CALL((session, &mechanism, key)); - END_CALL; -} - -static CK_RV rpc_C_Decrypt(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR encrypted_data; - CK_ULONG encrypted_data_len; - CK_BYTE_PTR data; - DECLARE_CK_ULONG_PTR(data_len); - - BEGIN_CALL(C_Decrypt); - IN_ULONG(session); - IN_BYTE_ARRAY(encrypted_data, encrypted_data_len); - IN_BYTE_BUFFER(data, data_len); - PROCESS_CALL((session, encrypted_data, encrypted_data_len, data, - data_len)); - OUT_BYTE_ARRAY(data, data_len); - END_CALL; -} - -static CK_RV rpc_C_DecryptUpdate(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR encrypted_part; - CK_ULONG encrypted_part_len; - CK_BYTE_PTR part; - DECLARE_CK_ULONG_PTR(part_len); - - BEGIN_CALL(C_DecryptUpdate); - IN_ULONG(session); - IN_BYTE_ARRAY(encrypted_part, encrypted_part_len); - IN_BYTE_BUFFER(part, part_len); - PROCESS_CALL((session, encrypted_part, encrypted_part_len, part, - part_len)); - OUT_BYTE_ARRAY(part, part_len); - END_CALL; -} - -static CK_RV rpc_C_DecryptFinal(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR last_part; - DECLARE_CK_ULONG_PTR(last_part_len); - - BEGIN_CALL(C_DecryptFinal); - IN_ULONG(session); - IN_BYTE_BUFFER(last_part, last_part_len); - PROCESS_CALL((session, last_part, last_part_len)); - OUT_BYTE_ARRAY(last_part, last_part_len); - END_CALL; -} - -static CK_RV rpc_C_DigestInit(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_MECHANISM mechanism; - - BEGIN_CALL(C_DigestInit); - IN_ULONG(session); - IN_MECHANISM(mechanism); - PROCESS_CALL((session, &mechanism)); - END_CALL; -} - -static CK_RV rpc_C_Digest(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR data; - CK_ULONG data_len; - CK_BYTE_PTR digest; - DECLARE_CK_ULONG_PTR(digest_len); - - BEGIN_CALL(C_Digest); - IN_ULONG(session); - IN_BYTE_ARRAY(data, data_len); - IN_BYTE_BUFFER(digest, digest_len); - PROCESS_CALL((session, data, data_len, digest, digest_len)); - OUT_BYTE_ARRAY(digest, digest_len); - END_CALL; -} - -static CK_RV rpc_C_DigestUpdate(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR part; - CK_ULONG part_len; - - BEGIN_CALL(C_DigestUpdate); - IN_ULONG(session); - IN_BYTE_ARRAY(part, part_len); - PROCESS_CALL((session, part, part_len)); - END_CALL; -} - -static CK_RV rpc_C_DigestKey(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_OBJECT_HANDLE key; - - BEGIN_CALL(C_DigestKey); - IN_ULONG(session); - IN_ULONG(key); - PROCESS_CALL((session, key)); - END_CALL; -} - -static CK_RV rpc_C_DigestFinal(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR digest; - DECLARE_CK_ULONG_PTR(digest_len); - - BEGIN_CALL(C_DigestFinal); - IN_ULONG(session); - IN_BYTE_BUFFER(digest, digest_len); - PROCESS_CALL((session, digest, digest_len)); - OUT_BYTE_ARRAY(digest, digest_len); - END_CALL; -} - -static CK_RV rpc_C_SignInit(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_MECHANISM mechanism; - CK_OBJECT_HANDLE key; - - BEGIN_CALL(C_SignInit); - IN_ULONG(session); - IN_MECHANISM(mechanism); - IN_ULONG(key); - PROCESS_CALL((session, &mechanism, key)); - END_CALL; -} - -static CK_RV rpc_C_Sign(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR part; - CK_ULONG part_len; - CK_BYTE_PTR signature; - DECLARE_CK_ULONG_PTR(signature_len); - - BEGIN_CALL(C_Sign); - IN_ULONG(session); - IN_BYTE_ARRAY(part, part_len); - IN_BYTE_BUFFER(signature, signature_len); - PROCESS_CALL((session, part, part_len, signature, signature_len)); - OUT_BYTE_ARRAY(signature, signature_len); - END_CALL; - -} - -static CK_RV rpc_C_SignUpdate(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR part; - CK_ULONG part_len; - - BEGIN_CALL(C_SignUpdate); - IN_ULONG(session); - IN_BYTE_ARRAY(part, part_len); - PROCESS_CALL((session, part, part_len)); - END_CALL; -} - -static CK_RV rpc_C_SignFinal(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR signature; - DECLARE_CK_ULONG_PTR(signature_len); - - BEGIN_CALL(C_SignFinal); - IN_ULONG(session); - IN_BYTE_BUFFER(signature, signature_len); - PROCESS_CALL((session, signature, signature_len)); - OUT_BYTE_ARRAY(signature, signature_len); - END_CALL; -} - -static CK_RV rpc_C_SignRecoverInit(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_MECHANISM mechanism; - CK_OBJECT_HANDLE key; - - BEGIN_CALL(C_SignRecoverInit); - IN_ULONG(session); - IN_MECHANISM(mechanism); - IN_ULONG(key); - PROCESS_CALL((session, &mechanism, key)); - END_CALL; -} - -static CK_RV rpc_C_SignRecover(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR data; - CK_ULONG data_len; - CK_BYTE_PTR signature; - DECLARE_CK_ULONG_PTR(signature_len); - - BEGIN_CALL(C_SignRecover); - IN_ULONG(session); - IN_BYTE_ARRAY(data, data_len); - IN_BYTE_BUFFER(signature, signature_len); - PROCESS_CALL((session, data, data_len, signature, signature_len)); - OUT_BYTE_ARRAY(signature, signature_len); - END_CALL; -} - -static CK_RV rpc_C_VerifyInit(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_MECHANISM mechanism; - CK_OBJECT_HANDLE key; - - BEGIN_CALL(C_VerifyInit); - IN_ULONG(session); - IN_MECHANISM(mechanism); - IN_ULONG(key); - PROCESS_CALL((session, &mechanism, key)); - END_CALL; -} - -static CK_RV rpc_C_Verify(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR data; - CK_ULONG data_len; - CK_BYTE_PTR signature; - CK_ULONG signature_len; - - BEGIN_CALL(C_Verify); - IN_ULONG(session); - IN_BYTE_ARRAY(data, data_len); - IN_BYTE_ARRAY(signature, signature_len); - PROCESS_CALL((session, data, data_len, signature, signature_len)); - END_CALL; -} - -static CK_RV rpc_C_VerifyUpdate(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR part; - CK_ULONG part_len; - - BEGIN_CALL(C_VerifyUpdate); - IN_ULONG(session); - IN_BYTE_ARRAY(part, part_len); - PROCESS_CALL((session, part, part_len)); - END_CALL; -} - -static CK_RV rpc_C_VerifyFinal(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR signature; - CK_ULONG signature_len; - - BEGIN_CALL(C_VerifyFinal); - IN_ULONG(session); - IN_BYTE_ARRAY(signature, signature_len); - PROCESS_CALL((session, signature, signature_len)); - END_CALL; -} - -static CK_RV rpc_C_VerifyRecoverInit(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_MECHANISM mechanism; - CK_OBJECT_HANDLE key; - - BEGIN_CALL(C_VerifyRecoverInit); - IN_ULONG(session); - IN_MECHANISM(mechanism); - IN_ULONG(key); - PROCESS_CALL((session, &mechanism, key)); - END_CALL; -} - -static CK_RV rpc_C_VerifyRecover(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR signature; - CK_ULONG signature_len; - CK_BYTE_PTR data; - DECLARE_CK_ULONG_PTR(data_len); - - BEGIN_CALL(C_VerifyRecover); - IN_ULONG(session); - IN_BYTE_ARRAY(signature, signature_len); - IN_BYTE_BUFFER(data, data_len); - PROCESS_CALL((session, signature, signature_len, data, data_len)); - OUT_BYTE_ARRAY(data, data_len); - END_CALL; -} - -static CK_RV rpc_C_DigestEncryptUpdate(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR part; - CK_ULONG part_len; - CK_BYTE_PTR encrypted_part; - DECLARE_CK_ULONG_PTR(encrypted_part_len); - - BEGIN_CALL(C_DigestEncryptUpdate); - IN_ULONG(session); - IN_BYTE_ARRAY(part, part_len); - IN_BYTE_BUFFER(encrypted_part, encrypted_part_len); - PROCESS_CALL((session, part, part_len, encrypted_part, - encrypted_part_len)); - OUT_BYTE_ARRAY(encrypted_part, encrypted_part_len); - END_CALL; -} - -static CK_RV rpc_C_DecryptDigestUpdate(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR encrypted_part; - CK_ULONG encrypted_part_len; - CK_BYTE_PTR part; - DECLARE_CK_ULONG_PTR(part_len); - - BEGIN_CALL(C_DecryptDigestUpdate); - IN_ULONG(session); - IN_BYTE_ARRAY(encrypted_part, encrypted_part_len); - IN_BYTE_BUFFER(part, part_len); - PROCESS_CALL((session, encrypted_part, encrypted_part_len, part, - part_len)); - OUT_BYTE_ARRAY(part, part_len); - END_CALL; -} - -static CK_RV rpc_C_SignEncryptUpdate(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR part; - CK_ULONG part_len; - CK_BYTE_PTR encrypted_part; - DECLARE_CK_ULONG_PTR(encrypted_part_len); - - BEGIN_CALL(C_SignEncryptUpdate); - IN_ULONG(session); - IN_BYTE_ARRAY(part, part_len); - IN_BYTE_BUFFER(encrypted_part, encrypted_part_len); - PROCESS_CALL((session, part, part_len, encrypted_part, - encrypted_part_len)); - OUT_BYTE_ARRAY(encrypted_part, encrypted_part_len); - END_CALL; -} - -static CK_RV rpc_C_DecryptVerifyUpdate(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR encrypted_part; - CK_ULONG encrypted_part_len; - CK_BYTE_PTR part; - DECLARE_CK_ULONG_PTR(part_len); - - BEGIN_CALL(C_DecryptVerifyUpdate); - IN_ULONG(session); - IN_BYTE_ARRAY(encrypted_part, encrypted_part_len); - IN_BYTE_BUFFER(part, part_len); - PROCESS_CALL((session, encrypted_part, encrypted_part_len, part, - part_len)); - OUT_BYTE_ARRAY(part, part_len); - END_CALL; -} - -/* ----------------------------------------------------------------------------- - * KEY OPERATIONS - */ - -static CK_RV rpc_C_GenerateKey(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_MECHANISM mechanism; - CK_ATTRIBUTE_PTR template; - CK_ULONG count; - CK_OBJECT_HANDLE key; - - BEGIN_CALL(C_GenerateKey); - IN_ULONG(session); - IN_MECHANISM(mechanism); - IN_ATTRIBUTE_ARRAY(template, count); - PROCESS_CALL((session, &mechanism, template, count, &key)); - OUT_ULONG(key); - END_CALL; -} - -static CK_RV rpc_C_GenerateKeyPair(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_MECHANISM mechanism; - CK_ATTRIBUTE_PTR public_key_template; - CK_ULONG public_key_attribute_count; - CK_ATTRIBUTE_PTR private_key_template; - CK_ULONG private_key_attribute_count; - CK_OBJECT_HANDLE public_key; - CK_OBJECT_HANDLE private_key; - - BEGIN_CALL(C_GenerateKeyPair); - IN_ULONG(session); - IN_MECHANISM(mechanism); - IN_ATTRIBUTE_ARRAY(public_key_template, public_key_attribute_count); - IN_ATTRIBUTE_ARRAY(private_key_template, private_key_attribute_count); - PROCESS_CALL((session, &mechanism, public_key_template, - public_key_attribute_count, private_key_template, - private_key_attribute_count, &public_key, &private_key)); - OUT_ULONG(public_key); - OUT_ULONG(private_key); - END_CALL; - -} - -static CK_RV rpc_C_WrapKey(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_MECHANISM mechanism; - CK_OBJECT_HANDLE wrapping_key; - CK_OBJECT_HANDLE key; - CK_BYTE_PTR wrapped_key; - DECLARE_CK_ULONG_PTR(wrapped_key_len); - - BEGIN_CALL(C_WrapKey); - IN_ULONG(session); - IN_MECHANISM(mechanism); - IN_ULONG(wrapping_key); - IN_ULONG(key); - IN_BYTE_BUFFER(wrapped_key, wrapped_key_len); - PROCESS_CALL((session, &mechanism, wrapping_key, key, wrapped_key, - wrapped_key_len)); - OUT_BYTE_ARRAY(wrapped_key, wrapped_key_len); - END_CALL; -} - -static CK_RV rpc_C_UnwrapKey(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_MECHANISM mechanism; - CK_OBJECT_HANDLE unwrapping_key; - CK_BYTE_PTR wrapped_key; - CK_ULONG wrapped_key_len; - CK_ATTRIBUTE_PTR template; - CK_ULONG attribute_count; - CK_OBJECT_HANDLE key; - - BEGIN_CALL(C_UnwrapKey); - IN_ULONG(session); - IN_MECHANISM(mechanism); - IN_ULONG(unwrapping_key); - IN_BYTE_ARRAY(wrapped_key, wrapped_key_len); - IN_ATTRIBUTE_ARRAY(template, attribute_count); - PROCESS_CALL((session, &mechanism, unwrapping_key, wrapped_key, - wrapped_key_len, template, attribute_count, &key)); - OUT_ULONG(key); - END_CALL; -} - -static CK_RV rpc_C_DeriveKey(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_MECHANISM mechanism; - CK_OBJECT_HANDLE base_key; - CK_ATTRIBUTE_PTR template; - CK_ULONG attribute_count; - CK_OBJECT_HANDLE key; - - BEGIN_CALL(C_DeriveKey); - IN_ULONG(session); - IN_MECHANISM(mechanism); - IN_ULONG(base_key); - IN_ATTRIBUTE_ARRAY(template, attribute_count); - PROCESS_CALL((session, &mechanism, base_key, template, attribute_count, - &key)); - OUT_ULONG(key); - END_CALL; -} - -static CK_RV rpc_C_SeedRandom(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR seed; - CK_ULONG seed_len; - - BEGIN_CALL(C_SeedRandom); - IN_ULONG(session); - IN_BYTE_ARRAY(seed, seed_len); - PROCESS_CALL((session, seed, seed_len)); - END_CALL; -} - -static CK_RV rpc_C_GenerateRandom(CallState * cs) -{ - CK_SESSION_HANDLE session; - CK_BYTE_PTR random_data; - DECLARE_CK_ULONG_PTR(random_len); - - BEGIN_CALL(C_GenerateRandom); - IN_ULONG(session); - IN_BYTE_BUFFER(random_data, random_len); - if (random_len == NULL_PTR) { - _ret = PARSE_ERROR; goto _cleanup; - } - PROCESS_CALL((session, random_data, *random_len)); - OUT_BYTE_ARRAY(random_data, random_len); - END_CALL; -} - -/* --------------------------------------------------------------------------- - * DISPATCH THREAD HANDLING - */ - -static int dispatch_call(CallState * cs) -{ - GckRpcMessage *req, *resp; - CK_RV ret = CKR_OK; - - assert(cs); - - req = cs->req; - resp = cs->resp; - - /* This should have been checked by the parsing code */ - assert(req->call_id > GCK_RPC_CALL_ERROR); - assert(req->call_id < GCK_RPC_CALL_MAX); - - /* Prepare a response for the function to fill in */ - if (!gck_rpc_message_prep(resp, req->call_id, GCK_RPC_RESPONSE)) { - gck_rpc_warn("couldn't prepare message"); - return 0; - } - - switch (req->call_id) { - -#define CASE_CALL(name) \ - case GCK_RPC_CALL_##name: \ - ret = rpc_##name (cs); \ - break; - CASE_CALL(C_Initialize) - CASE_CALL(C_Finalize) - CASE_CALL(C_GetInfo) - CASE_CALL(C_GetSlotList) - CASE_CALL(C_GetSlotInfo) - CASE_CALL(C_GetTokenInfo) - CASE_CALL(C_GetMechanismList) - CASE_CALL(C_GetMechanismInfo) - CASE_CALL(C_InitToken) - CASE_CALL(C_WaitForSlotEvent) - CASE_CALL(C_OpenSession) - CASE_CALL(C_CloseSession) - CASE_CALL(C_CloseAllSessions) - CASE_CALL(C_GetFunctionStatus) - CASE_CALL(C_CancelFunction) - CASE_CALL(C_GetSessionInfo) - CASE_CALL(C_InitPIN) - CASE_CALL(C_SetPIN) - CASE_CALL(C_GetOperationState) - CASE_CALL(C_SetOperationState) - CASE_CALL(C_Login) - CASE_CALL(C_Logout) - CASE_CALL(C_CreateObject) - CASE_CALL(C_CopyObject) - CASE_CALL(C_DestroyObject) - CASE_CALL(C_GetObjectSize) - CASE_CALL(C_GetAttributeValue) - CASE_CALL(C_SetAttributeValue) - CASE_CALL(C_FindObjectsInit) - CASE_CALL(C_FindObjects) - CASE_CALL(C_FindObjectsFinal) - CASE_CALL(C_EncryptInit) - CASE_CALL(C_Encrypt) - CASE_CALL(C_EncryptUpdate) - CASE_CALL(C_EncryptFinal) - CASE_CALL(C_DecryptInit) - CASE_CALL(C_Decrypt) - CASE_CALL(C_DecryptUpdate) - CASE_CALL(C_DecryptFinal) - CASE_CALL(C_DigestInit) - CASE_CALL(C_Digest) - CASE_CALL(C_DigestUpdate) - CASE_CALL(C_DigestKey) - CASE_CALL(C_DigestFinal) - CASE_CALL(C_SignInit) - CASE_CALL(C_Sign) - CASE_CALL(C_SignUpdate) - CASE_CALL(C_SignFinal) - CASE_CALL(C_SignRecoverInit) - CASE_CALL(C_SignRecover) - CASE_CALL(C_VerifyInit) - CASE_CALL(C_Verify) - CASE_CALL(C_VerifyUpdate) - CASE_CALL(C_VerifyFinal) - CASE_CALL(C_VerifyRecoverInit) - CASE_CALL(C_VerifyRecover) - CASE_CALL(C_DigestEncryptUpdate) - CASE_CALL(C_DecryptDigestUpdate) - CASE_CALL(C_SignEncryptUpdate) - CASE_CALL(C_DecryptVerifyUpdate) - CASE_CALL(C_GenerateKey) - CASE_CALL(C_GenerateKeyPair) - CASE_CALL(C_WrapKey) - CASE_CALL(C_UnwrapKey) - CASE_CALL(C_DeriveKey) - CASE_CALL(C_SeedRandom) - CASE_CALL(C_GenerateRandom) -#undef CASE_CALL - default: - /* This should have been caught by the parse code */ - assert(0 && "Unchecked call"); - break; - }; - - if (ret == CKR_OK) { - - /* Parsing errors? */ - if (gck_rpc_message_buffer_error(req)) { - gck_rpc_warn - ("invalid request from module, probably too short"); - ret = PARSE_ERROR; - } - - /* Out of memory errors? */ - if (gck_rpc_message_buffer_error(resp)) { - gck_rpc_warn - ("out of memory error putting together message"); - ret = PREP_ERROR; - } - } - - /* A filled in response */ - if (ret == CKR_OK) { - - /* - * Since we're dealing with many many functions above generating - * these messages we want to make sure each of them actually - * does what it's supposed to. - */ - - assert(gck_rpc_message_is_verified(resp)); - assert(resp->call_type == GCK_RPC_RESPONSE); - assert(resp->call_id == req->call_id); - assert(gck_rpc_calls[resp->call_id].response); - assert(strcmp(gck_rpc_calls[resp->call_id].response, - resp->signature) == 0); - - /* Fill in an error respnose */ - } else { - if (!gck_rpc_message_prep - (resp, GCK_RPC_CALL_ERROR, GCK_RPC_RESPONSE) - || !gck_rpc_message_write_ulong(resp, (uint32_t) ret) - || gck_rpc_message_buffer_error(resp)) { - gck_rpc_warn("out of memory responding with error"); - return 0; - } - } - - return 1; -} - -static int read_all(CallState *cs, void *data, size_t len) -{ - int r; - - assert(cs->sock >= 0); - assert(data); - assert(len > 0); - - while (len > 0) { - - if (cs->tls) - r = gck_rpc_tls_read_all(cs->tls, data, len); - else - r = recv(cs->sock, data, len, 0); - - if (r == 0) { - /* Connection was closed on client */ - return 0; - } else if (r == -1) { - if (errno != EAGAIN && errno != EINTR) { - gck_rpc_warn("couldn't receive data: %s", - strerror(errno)); - return 0; - } - } else { - data += r; - len -= r; - } - } - return 1; -} - -static int write_all(CallState *cs, void *data, size_t len) -{ - int r; - - assert(cs->sock >= 0); - assert(data); - assert(len > 0); - - while (len > 0) { - - if (cs->tls) - r = gck_rpc_tls_write_all(cs->tls, (void *) data, len); - else - r = send(cs->sock, data, len, MSG_NOSIGNAL); - - if (r == -1) { - if (errno == EPIPE) { - /* Connection closed from client */ - return 0; - } else if (errno != EAGAIN && errno != EINTR) { - gck_rpc_warn("couldn't send data: %s", - strerror(errno)); - return 0; - } - } else { - data += r; - len -= r; - } - } - - return 1; -} - -static void run_dispatch_loop(CallState *cs) -{ - unsigned char buf[4]; - uint32_t len, res; - char hoststr[NI_MAXHOST], portstr[NI_MAXSERV]; - - assert(cs->sock != -1); - - if ((res = getnameinfo((struct sockaddr *) & cs->addr, cs->addrlen, - hoststr, sizeof(hoststr), portstr, sizeof(portstr), - NI_NUMERICHOST | NI_NUMERICSERV)) != 0) { - gck_rpc_warn("couldn't call getnameinfo on client addr: %.100s", - gai_strerror(res)); - hoststr[0] = portstr[0] = '\0'; - } - - /* Enable TLS for this socket */ - if (cs->tls) { - if (! gck_rpc_start_tls(cs->tls, cs->sock)) { - gck_rpc_warn("Can't enable TLS"); - return ; - } - } - - /* The client application */ - if (! cs->read(cs, (void *)&cs->appid, sizeof (cs->appid))) { - gck_rpc_warn("Can't read appid\n"); - return ; - } - - gck_rpc_log("New session %d-%d (client %s, port %s)\n", (uint32_t) (cs->appid >> 32), - (uint32_t) cs->appid, hoststr, portstr); - - /* Setup our buffers */ - if (!call_init(cs)) { - gck_rpc_warn("out of memory"); - return; - } - - /* The main thread loop */ - while (TRUE) { - - call_reset(cs); - - /* Read the number of bytes ... */ - if (! cs->read(cs, buf, 4)) - break; - - /* Calculate the number of bytes */ - len = egg_buffer_decode_uint32(buf); - if (len >= 0x0FFFFFFF) { - gck_rpc_warn - ("invalid message size from module: %u bytes", len); - break; - } - - /* Allocate memory */ - egg_buffer_reserve(&cs->req->buffer, cs->req->buffer.len + len); - if (egg_buffer_has_error(&cs->req->buffer)) { - gck_rpc_warn("error allocating buffer for message"); - break; - } - - /* ... and read/parse in the actual message */ - if (!cs->read(cs, cs->req->buffer.buf, len)) - break; - - egg_buffer_add_empty(&cs->req->buffer, len); - - if (!gck_rpc_message_parse(cs->req, GCK_RPC_REQUEST)) - break; - - /* ... send for processing ... */ - if (!dispatch_call(cs)) - break; - - /* .. send back response length, and then response data */ - egg_buffer_encode_uint32(buf, cs->resp->buffer.len); - if (!cs->write(cs, buf, 4) || - !cs->write(cs, cs->resp->buffer.buf, cs->resp->buffer.len)) - break; - } - - call_uninit(cs); -} - -static void *run_dispatch_thread(void *arg) -{ - CallState *cs = arg; - assert(cs->sock != -1); - - if (_install_dispatch_syscall_filter((cs->tls != NULL))) - return NULL; - - run_dispatch_loop(cs); - - /* The thread closes the socket and marks as done */ - assert(cs->sock != -1); - close(cs->sock); - cs->sock = -1; - - return NULL; -} - -/* --------------------------------------------------------------------------- - * MAIN THREAD - */ - -/* The main daemon socket that we're listening on */ -static int pkcs11_socket = -1; - -/* The unix socket path, that we listen on */ -static char pkcs11_socket_path[MAXPATHLEN] = { 0, }; - -void gck_rpc_layer_accept(GckRpcTlsPskState *tls) -{ - struct sockaddr_storage addr; - DispatchState *ds, **here; - int error; - socklen_t addrlen; - int new_fd; - - assert(pkcs11_socket != -1); - - /* Cleanup any completed dispatch threads */ - pthread_mutex_lock(&pkcs11_dispatchers_mutex); - for (here = &pkcs11_dispatchers, ds = *here; ds != NULL; ds = *here) { - CallState *c = &ds->cs; - if (c && c->sock == -1) { - pthread_join(ds->thread, NULL); - *here = ds->next; - free(ds); - } else { - here = &ds->next; - } - } - - addrlen = sizeof(addr); - new_fd = accept(pkcs11_socket, (struct sockaddr *)&addr, &addrlen); - if (new_fd < 0) { - gck_rpc_warn("cannot accept pkcs11 connection: %s", - strerror(errno)); - return; - } - - ds = calloc(1, sizeof(DispatchState)); - if (ds == NULL) { - gck_rpc_warn("out of memory"); - close(new_fd); - return; - } - - ds->cs.sock = new_fd; - ds->cs.read = &read_all; - ds->cs.write = &write_all; - ds->cs.addr = addr; - ds->cs.addrlen = addrlen; - ds->cs.tls = tls; - - error = pthread_create(&ds->thread, NULL, - run_dispatch_thread, &(ds->cs)); - if (error) { - gck_rpc_warn("couldn't start thread: %s", strerror(errno)); - close(new_fd); - free(ds); - return; - } - - ds->next = pkcs11_dispatchers; - pkcs11_dispatchers = ds; - pthread_mutex_unlock(&pkcs11_dispatchers_mutex); -} - -static int _inetd_read(CallState *cs, void *data, size_t len) -{ - assert(cs->sock >= 0); - return read(cs->sock, data, len); -} - -static int _inetd_write(CallState *cs, void *data, size_t len) -{ - assert(cs->sock >= 0); - return write(cs->sock, data, len); -} - -void gck_rpc_layer_inetd(CK_FUNCTION_LIST_PTR module) -{ - CallState cs; - - memset(&cs, 0, sizeof(cs)); - cs.sock = STDIN_FILENO; - cs.read = &_inetd_read; - cs.write = &_inetd_write; - - pkcs11_module = module; - - run_dispatch_thread(&cs); -} - -/* - * Try to get a listening socket for host and port (host may be either a name or - * an IP address, as string) and port (a string with a service name or a port - * number). - * - * Returns -1 on failure, and the socket fd otherwise. - */ -static int _get_listening_socket(const char *proto, const char *host, const char *port) -{ - char hoststr[NI_MAXHOST], portstr[NI_MAXSERV]; - struct addrinfo *ai, *first, hints; - int res, sock, one = 1; - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_flags = AI_PASSIVE; /* Want addr for bind() */ - hints.ai_family = AF_UNSPEC; /* Either IPv4 or IPv6 */ - hints.ai_socktype = SOCK_STREAM; /* Only stream oriented sockets */ - - if ((res = getaddrinfo(host, port, &hints, &ai)) < 0) { - gck_rpc_warn("couldn't resolve host '%.100s' or service '%.100s' : %.100s\n", - host, port, gai_strerror(res)); - return -1; - } - - sock = -1; - first = ai; - - /* Loop through the sockets returned and see if we can find one that accepts - * our options and bind() - */ - while (ai) { - sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - - if (sock >= 0) { - if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, - (char *)&one, sizeof (one)) == -1) { - gck_rpc_warn("couldn't set pkcs11 " - "socket protocol options (%.100s %.100s): %.100s", - host, port, strerror (errno)); - goto next; - } - - if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, - (char *)&one, sizeof(one)) == -1) { - gck_rpc_warn - ("couldn't set pkcs11 socket options (%.100s %.100s): %.100s", - host, port, strerror(errno)); - goto next; - } - - if (bind(sock, ai->ai_addr, ai->ai_addrlen) == 0) - break; - - next: - close(sock); - sock = -1; - } - ai = ai->ai_next; - } - - if (sock < 0) { - gck_rpc_warn("couldn't create pkcs11 socket (%.100s %.100s): %.100s\n", - host, port, strerror(errno)); - sock = -1; - goto out; - } - - if (listen(sock, PKCS11PROXY_LISTEN_BACKLOG) < 0) { - gck_rpc_warn("couldn't listen on pkcs11 socket (%.100s %.100s): %.100s", - host, port, strerror(errno)); - sock = -1; - goto out; - } - - /* Format a string describing the socket we're listening on into pkcs11_socket_path */ - if ((res = getnameinfo(ai->ai_addr, ai->ai_addrlen, - hoststr, sizeof(hoststr), portstr, sizeof(portstr), - NI_NUMERICHOST | NI_NUMERICSERV)) != 0) { - gck_rpc_warn("couldn't call getnameinfo on pkcs11 socket (%.100s %.100s): %.100s", - host, port, gai_strerror(res)); - sock = -1; - goto out; - } - - snprintf(pkcs11_socket_path, sizeof(pkcs11_socket_path), - (ai->ai_family == AF_INET6) ? "%s://[%s]:%s" : "%s://%s:%s", proto, hoststr, portstr); - - out: - freeaddrinfo(first); - - return sock; -} - -int gck_rpc_layer_initialize(const char *prefix, CK_FUNCTION_LIST_PTR module) -{ - struct sockaddr_un addr; - int sock; - -#ifdef _DEBUG - GCK_RPC_CHECK_CALLS(); -#endif - - assert(module); - assert(prefix); - - /* cannot be called more than once */ - assert(!pkcs11_module); - assert(pkcs11_socket == -1); - assert(pkcs11_dispatchers == NULL); - - memset(&addr, 0, sizeof(addr)); - -#ifdef __MINGW32__ - { - WSADATA wsaData; - int iResult; - - iResult = WSAStartup(MAKEWORD(2,2), &wsaData); - if (iResult != 0) { - gck_rpc_warn("WSAStartup failed: %d\n", iResult); - return -1; - } - } -#endif - - if (!strncmp("tcp://", prefix, 6) || - !strncmp("tls://", prefix, 6)) { - /* - * TCP socket - */ - char *host, *port; - char proto[4]; /* strlen("tcp") and strlen("tls") */ - - snprintf(proto, sizeof(proto), "%s", prefix); - - if (! gck_rpc_parse_host_port(prefix + 6, &host, &port)) { - free(host); - return -1; - } - - if ((sock = _get_listening_socket(proto, host, port)) == -1) { - free(host); - return -1; - } - - free(host); - } else { - /* - * UNIX domain socket - */ - snprintf(pkcs11_socket_path, sizeof(pkcs11_socket_path), - "%s/socket.pkcs11", prefix); - - sock = socket(AF_UNIX, SOCK_STREAM, 0); - - if (sock < 0) { - gck_rpc_warn("couldn't create pkcs11 socket: %s", - strerror(errno)); - return -1; - } - - addr.sun_family = AF_UNIX; - unlink(pkcs11_socket_path); - strncpy(addr.sun_path, pkcs11_socket_path, - sizeof(addr.sun_path)); - - if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - gck_rpc_warn("couldn't bind to pkcs11 socket: %s: %s", - pkcs11_socket_path, strerror(errno)); - return -1; - } - - if (listen(sock, PKCS11PROXY_LISTEN_BACKLOG) < 0) { - gck_rpc_warn("couldn't listen on pkcs11 socket: %s: %s", - pkcs11_socket_path, strerror(errno)); - return -1; - } - } - - gck_rpc_log("Listening on: %s\n", pkcs11_socket_path); - - pkcs11_module = module; - pkcs11_socket = sock; - pkcs11_dispatchers = NULL; - - return sock; -} - -void gck_rpc_layer_uninitialize(void) -{ - DispatchState *ds, *next; - - if (!pkcs11_module) - return; - - /* Close our main listening socket */ - if (pkcs11_socket != -1) - close(pkcs11_socket); - pkcs11_socket = -1; - - /* Delete our unix socket */ - if (pkcs11_socket_path[0] && - strncmp(pkcs11_socket_path, "tcp://", strlen("tcp://")) != 0 && - strncmp(pkcs11_socket_path, "tls://", strlen("tls://")) != 0) - unlink(pkcs11_socket_path); - pkcs11_socket_path[0] = 0; - - /* Stop all of the dispatch threads */ - pthread_mutex_lock(&pkcs11_dispatchers_mutex); - for (ds = pkcs11_dispatchers; ds; ds = next) { - CallState *c = &ds->cs; - next = ds->next; - - /* Forcibly shutdown the connection */ - if (c && c->sock != -1) - if (shutdown(c->sock, SHUT_RDWR) == 0) - c->sock = -1; - - pthread_join(ds->thread, NULL); - - /* This is always closed by dispatch thread */ - if (c) - assert(c->sock == -1); - free(ds); - } - pthread_mutex_unlock(&pkcs11_dispatchers_mutex); - - pkcs11_module = NULL; -} - -/* - * Reduce the syscalls allowed to a subset of the syscalls allowed for - * the parent thread. - */ -static int _install_dispatch_syscall_filter(int use_tls) -{ -#ifdef SECCOMP - int rc = -1; - scmp_filter_ctx ctx; - -#ifdef DEBUG_SECCOMP - ctx = seccomp_init(SCMP_ACT_TRAP); -#else - ctx = seccomp_init(SCMP_ACT_KILL); -#endif /* DEBUG_SECCOMP */ - if (ctx == NULL) - goto failure_scmp; - /* - * These are the basic syscalls needed to be able to use - * the syscall-reporter to figure out the rest - */ - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(write), 0); -#ifdef DEBUG_SECCOMP - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0); -# ifdef __NR_sigreturn - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(sigreturn), 0); -# endif -#endif /* DEBUG_SECCOMP */ - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(exit), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0); - - /* - * Network related syscalls. - */ - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(read), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(sendto), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(recvfrom), 0); - - /* - * TLS-PSK - */ - if (use_tls) - /* Allow open() of the TLS-PSK keyfile. */ - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(open), 1, - SCMP_A1(SCMP_CMP_EQ, O_RDONLY | O_CLOEXEC)); - - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(close), 0); - - /* - * pthreads? - */ - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(madvise), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 1, - SCMP_A2(SCMP_CMP_EQ, PROT_READ|PROT_WRITE)); - - /* - * SoftHSM 1.3.0 - */ - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(getcwd), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(stat), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(open), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(lseek), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(access), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(fsync), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(unlink), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(ftruncate), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(select), 0); - seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(futex), 0); - - rc = seccomp_load(ctx); - if (rc < 0) - goto failure_scmp; - seccomp_release(ctx); - - return 0; - -failure_scmp: - errno = -rc; - gck_rpc_warn("Seccomp filter initialization failed, errno = %u\n", errno); - return errno; -#else /* SECCOMP */ - return 0; -#endif /* SECCOMP */ -} diff --git a/ext/pkcs11-proxy/gck-rpc-layer.h b/ext/pkcs11-proxy/gck-rpc-layer.h deleted file mode 100644 index 8ea653b55..000000000 --- a/ext/pkcs11-proxy/gck-rpc-layer.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef GCKRPC_LAYER_H_ -#define GCKRPC_LAYER_H_ - -#include "pkcs11/pkcs11.h" - -#include "gck-rpc-tls-psk.h" - -/* ------------------------------------------------------------------ - * DISPATCHER - */ - -/* Call to initialize the module and start listening, returns socket or -1 */ -int gck_rpc_layer_initialize(const char *prefix, CK_FUNCTION_LIST_PTR funcs); - -/* Should be called to cleanup dispatcher */ -void gck_rpc_layer_uninitialize(void); - -/* Accept a new connection. Should be called when above fd has read */ -void gck_rpc_layer_accept(GckRpcTlsPskState *tls); - -/* Run a single connection off of STDIN - call from inetd or stunnel */ -void gck_rpc_layer_inetd(CK_FUNCTION_LIST_PTR funcs); - -#endif /* GCKRPC_LAYER_H_ */ diff --git a/ext/pkcs11-proxy/gck-rpc-message.c b/ext/pkcs11-proxy/gck-rpc-message.c deleted file mode 100644 index 9bb10f186..000000000 --- a/ext/pkcs11-proxy/gck-rpc-message.c +++ /dev/null @@ -1,482 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* p11-rpc-message.c - our marshalled PKCS#11 protocol. - - Copyright (C) 2008, Stef Walter - - The Gnome Keyring Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The Gnome Keyring 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the Gnome Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Stef Walter -*/ - -#include "config.h" - -#include "gck-rpc-layer.h" -#include "gck-rpc-private.h" - -#include - -#ifdef G_DISABLE_ASSERT -#define assert(x) -#else -#include -#endif - -GckRpcMessage *gck_rpc_message_new(EggBufferAllocator allocator) -{ - GckRpcMessage *msg; - - assert(allocator); - - msg = (GckRpcMessage *) (allocator) (NULL, sizeof(GckRpcMessage)); - if (!msg) - return NULL; - memset(msg, 0, sizeof(*msg)); - - if (!egg_buffer_init_full(&msg->buffer, 64, allocator)) { - (allocator) (msg, 0); /* Frees allocation */ - return NULL; - } - - gck_rpc_message_reset(msg); - - return msg; -} - -void gck_rpc_message_free(GckRpcMessage * msg) -{ - EggBufferAllocator allocator; - - if (msg) { - assert(msg->buffer.allocator); - allocator = msg->buffer.allocator; - egg_buffer_uninit(&msg->buffer); - - /* frees data buffer */ - (allocator) (msg, 0); - } -} - -void gck_rpc_message_reset(GckRpcMessage * msg) -{ - assert(msg); - - msg->call_id = 0; - msg->call_type = 0; - msg->signature = NULL; - msg->sigverify = NULL; - msg->parsed = 0; - - egg_buffer_reset(&msg->buffer); -} - -int -gck_rpc_message_prep(GckRpcMessage * msg, int call_id, GckRpcMessageType type) -{ - int len; - - assert(type); - assert(call_id >= GCK_RPC_CALL_ERROR); - assert(call_id < GCK_RPC_CALL_MAX); - - gck_rpc_message_reset(msg); - - if (call_id != GCK_RPC_CALL_ERROR) { - - /* The call id and signature */ - if (type == GCK_RPC_REQUEST) - msg->signature = gck_rpc_calls[call_id].request; - else if (type == GCK_RPC_RESPONSE) - msg->signature = gck_rpc_calls[call_id].response; - else - assert(0 && "invalid message type"); - assert(msg->signature); - msg->sigverify = msg->signature; - } - - msg->call_id = call_id; - msg->call_type = type; - - /* Encode the two of them */ - egg_buffer_add_uint32(&msg->buffer, call_id); - if (msg->signature) { - len = strlen(msg->signature); - egg_buffer_add_byte_array(&msg->buffer, - (unsigned char *)msg->signature, len); - } - - msg->parsed = 0; - return !egg_buffer_has_error(&msg->buffer); -} - -int gck_rpc_message_parse(GckRpcMessage * msg, GckRpcMessageType type) -{ - const unsigned char *val; - size_t len; - uint32_t call_id; - - msg->parsed = 0; - - /* Pull out the call identifier */ - if (!egg_buffer_get_uint32 - (&msg->buffer, msg->parsed, &(msg->parsed), &call_id)) { - gck_rpc_warn("invalid message: couldn't read call identifier"); - return 0; - } - - msg->signature = msg->sigverify = NULL; - - /* If it's an error code then no more processing */ - if (call_id == GCK_RPC_CALL_ERROR) { - if (type == GCK_RPC_REQUEST) { - gck_rpc_warn("invalid message: error code in request"); - return 0; - } - - return 1; - } - - /* The call id and signature */ - if (call_id <= 0 || call_id >= GCK_RPC_CALL_MAX) { - gck_rpc_warn("invalid message: bad call id: %d", call_id); - return 0; - } - if (type == GCK_RPC_REQUEST) - msg->signature = gck_rpc_calls[call_id].request; - else if (type == GCK_RPC_RESPONSE) - msg->signature = gck_rpc_calls[call_id].response; - else - assert(0 && "invalid message type"); - msg->call_id = call_id; - msg->call_type = type; - msg->sigverify = msg->signature; - - /* Verify the incoming signature */ - if (!egg_buffer_get_byte_array - (&msg->buffer, msg->parsed, &(msg->parsed), &val, &len)) { - gck_rpc_warn("invalid message: couldn't read signature"); - return 0; - } - - if ((strlen(msg->signature) != len) - || (memcmp(val, msg->signature, len) != 0)) { - gck_rpc_warn("invalid message: signature doesn't match"); - return 0; - } - - return 1; -} - -int gck_rpc_message_equals(GckRpcMessage * m1, GckRpcMessage * m2) -{ - assert(m1 && m2); - - /* Any errors and messages are never equal */ - if (egg_buffer_has_error(&m1->buffer) || - egg_buffer_has_error(&m2->buffer)) - return 0; - - /* Calls and signatures must be identical */ - if (m1->call_id != m2->call_id) - return 0; - if (m1->call_type != m2->call_type) - return 0; - if (m1->signature && m2->signature) { - if (strcmp(m1->signature, m2->signature) != 0) - return 0; - } else if (m1->signature != m2->signature) { - return 0; - } - - /* Data in buffer must be identical */ - return egg_buffer_equal(&m1->buffer, &m2->buffer); -} - -int gck_rpc_message_verify_part(GckRpcMessage * msg, const char *part) -{ - int len, ok; - - if (!msg->sigverify) - return 1; - - len = strlen(part); - ok = (strncmp(msg->sigverify, part, len) == 0); - if (ok) - msg->sigverify += len; - return ok; -} - -int -gck_rpc_message_write_attribute_buffer(GckRpcMessage * msg, - CK_ATTRIBUTE_PTR arr, CK_ULONG num) -{ - CK_ATTRIBUTE_PTR attr; - CK_ULONG i; - - assert(!num || arr); - assert(msg); - - /* Make sure this is in the rigth order */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "fA")); - - /* Write the number of items */ - egg_buffer_add_uint32(&msg->buffer, num); - - for (i = 0; i < num; ++i) { - attr = &(arr[i]); - - /* The attribute type */ - egg_buffer_add_uint32(&msg->buffer, attr->type); - - /* And the attribute buffer length */ - egg_buffer_add_uint32(&msg->buffer, - attr->pValue ? attr->ulValueLen : 0); - } - - return !egg_buffer_has_error(&msg->buffer); -} - -int -gck_rpc_message_write_attribute_array(GckRpcMessage * msg, - CK_ATTRIBUTE_PTR arr, CK_ULONG num) -{ - CK_ULONG i; - CK_ATTRIBUTE_PTR attr; - unsigned char validity; - - assert(!num || arr); - assert(msg); - - /* Make sure this is in the rigth order */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "aA")); - - /* Write the number of items */ - egg_buffer_add_uint32(&msg->buffer, num); - - for (i = 0; i < num; ++i) { - attr = &(arr[i]); - - /* The attribute type */ - egg_buffer_add_uint32(&msg->buffer, attr->type); - - /* Write out the attribute validity */ - validity = (((CK_LONG) attr->ulValueLen) == -1) ? 0 : 1; - egg_buffer_add_byte(&msg->buffer, validity); - - /* The attribute length and value */ - if (validity) { - egg_buffer_add_uint32(&msg->buffer, attr->ulValueLen); - if (gck_rpc_has_bad_sized_ulong_parameter(attr)) { - uint64_t val = *(CK_ULONG *)attr->pValue; - - egg_buffer_add_byte_array (&msg->buffer, (unsigned char *)&val, sizeof (val)); - } else - egg_buffer_add_byte_array(&msg->buffer, attr->pValue, - attr->ulValueLen); - } - } - - return !egg_buffer_has_error(&msg->buffer); -} - -int gck_rpc_message_read_byte(GckRpcMessage * msg, CK_BYTE * val) -{ - assert(msg); - - /* Make sure this is in the right order */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "y")); - return egg_buffer_get_byte(&msg->buffer, msg->parsed, &msg->parsed, - val); -} - -int gck_rpc_message_write_byte(GckRpcMessage * msg, CK_BYTE val) -{ - assert(msg); - - /* Make sure this is in the right order */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "y")); - return egg_buffer_add_byte(&msg->buffer, val); -} - -int gck_rpc_message_read_ulong(GckRpcMessage * msg, CK_ULONG * val) -{ - uint64_t v; - assert(msg); - - /* Make sure this is in the right order */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "u")); - - if (!egg_buffer_get_uint64(&msg->buffer, msg->parsed, &msg->parsed, &v)) - return 0; - if (val) - *val = (CK_ULONG) v; - return 1; -} - -int gck_rpc_message_write_ulong(GckRpcMessage * msg, CK_ULONG val) -{ - assert(msg); - - /* Make sure this is in the rigth order */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "u")); - return egg_buffer_add_uint64(&msg->buffer, val); -} - -int gck_rpc_message_write_byte_buffer(GckRpcMessage * msg, CK_BYTE_PTR arr, CK_ULONG *count_ptr) -{ - uint8_t flags; - assert(msg); - - /* Make sure this is in the right order */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "fy")); - - flags = 0; - if (! arr) - flags |= GCK_RPC_BYTE_BUFFER_NULL_DATA; - if (! count_ptr) - flags |= GCK_RPC_BYTE_BUFFER_NULL_COUNT; - - egg_buffer_add_byte(&msg->buffer, flags); - - egg_buffer_add_uint32(&msg->buffer, count_ptr ? *count_ptr : 0x0); - - return !egg_buffer_has_error(&msg->buffer); -} - -int -gck_rpc_message_write_byte_array(GckRpcMessage * msg, CK_BYTE_PTR arr, - CK_ULONG num) -{ - assert(msg); - - /* Make sure this is in the right order */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "ay")); - - /* No array, no data, just length */ - if (!arr) { - egg_buffer_add_byte(&msg->buffer, 0); - egg_buffer_add_uint32(&msg->buffer, num); - } else { - egg_buffer_add_byte(&msg->buffer, 1); - egg_buffer_add_byte_array(&msg->buffer, arr, num); - } - - return !egg_buffer_has_error(&msg->buffer); -} - -int gck_rpc_message_write_ulong_buffer(GckRpcMessage * msg, CK_ULONG count) -{ - assert(msg); - - /* Make sure this is in the right order */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "fu")); - return egg_buffer_add_uint32(&msg->buffer, count); -} - -int -gck_rpc_message_write_ulong_array(GckRpcMessage * msg, CK_ULONG_PTR array, - CK_ULONG n_array) -{ - CK_ULONG i; - - assert(msg); - - /* Check that we're supposed to have this at this point */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "au")); - - /* We send a byte which determines whether there's actual data present or not */ - egg_buffer_add_byte(&msg->buffer, array ? 1 : 0); - egg_buffer_add_uint32(&msg->buffer, n_array); - - /* Now send the data if valid */ - if (array) { - for (i = 0; i < n_array; ++i) - egg_buffer_add_uint64(&msg->buffer, array[i]); - } - - return !egg_buffer_has_error(&msg->buffer); -} - -int gck_rpc_message_read_version(GckRpcMessage * msg, CK_VERSION * version) -{ - assert(msg); - assert(version); - - /* Check that we're supposed to have this at this point */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "v")); - - return egg_buffer_get_byte(&msg->buffer, msg->parsed, &msg->parsed, - &version->major) - && egg_buffer_get_byte(&msg->buffer, msg->parsed, &msg->parsed, - &version->minor); -} - -int gck_rpc_message_write_version(GckRpcMessage * msg, CK_VERSION * version) -{ - assert(msg); - assert(version); - - /* Check that we're supposed to have this at this point */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "v")); - - egg_buffer_add_byte(&msg->buffer, version->major); - egg_buffer_add_byte(&msg->buffer, version->minor); - - return !egg_buffer_has_error(&msg->buffer); -} - -int -gck_rpc_message_read_space_string(GckRpcMessage * msg, CK_UTF8CHAR * buffer, - CK_ULONG length) -{ - const unsigned char *data; - size_t n_data; - - assert(msg); - assert(buffer); - assert(length); - - assert(!msg->signature || gck_rpc_message_verify_part(msg, "s")); - - if (!egg_buffer_get_byte_array - (&msg->buffer, msg->parsed, &msg->parsed, &data, &n_data)) - return 0; - - if (n_data != length) { - gck_rpc_warn - ("invalid length space padded string received: %d != %d", - length, n_data); - return 0; - } - - memcpy(buffer, data, length); - return 1; -} - -int -gck_rpc_message_write_space_string(GckRpcMessage * msg, CK_UTF8CHAR * buffer, - CK_ULONG length) -{ - assert(msg); - assert(buffer); - assert(length); - - assert(!msg->signature || gck_rpc_message_verify_part(msg, "s")); - - /* XXX it's not really right to treat UTF-8 input as a byte buffer, - * although CK_UTF8CHAR is currently typedef'd to unsigned char in pkcs11.h. - */ - return egg_buffer_add_byte_array(&msg->buffer, buffer, length); -} diff --git a/ext/pkcs11-proxy/gck-rpc-module.c b/ext/pkcs11-proxy/gck-rpc-module.c deleted file mode 100644 index 9ab564527..000000000 --- a/ext/pkcs11-proxy/gck-rpc-module.c +++ /dev/null @@ -1,2490 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* gkr-pkcs11-rpc-module.c - a PKCS#11 module which communicates with another process - - Copyright (C) 2008, Stefan Walter - - The Gnome Keyring Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The Gnome Keyring 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the Gnome Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Stef Walter -*/ - -#include "config.h" - -#include "gck-rpc-layer.h" -#include "gck-rpc-private.h" -#include "gck-rpc-tls-psk.h" - -#include "pkcs11/pkcs11.h" - -#include -#include -#ifdef __MINGW32__ -# include -#else -# include -# include -#include -#include -#include -# include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* ------------------------------------------------------------------- - * GLOBALS / DEFINES - */ - -/* Various mutexes */ -static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER; - -/* Whether we've been initialized, and on what process id it happened */ -static int pkcs11_initialized = 0; -static pid_t pkcs11_initialized_pid = 0; -static uint64_t pkcs11_app_id = 0; - -/* The socket to connect to */ -static char pkcs11_socket_path[MAXPATHLEN] = { 0, }; -/* The TLS-PSK keyfile name */ -static char tls_psk_key_filename[MAXPATHLEN] = { 0, }; - -/* The error used by us when parsing of rpc message fails */ -#define PARSE_ERROR CKR_DEVICE_ERROR - -/* ----------------------------------------------------------------------------- - * LOGGING and DEBUGGING - */ -#if DEBUG_OUTPUT -#define debug(x) gck_rpc_debug x -#else -#define debug(x) -#endif -#define warning(x) gck_rpc_warn x - -#define return_val_if_fail(x, v) \ - if (!(x)) { gck_rpc_warn ("'%s' not true at %s", #x, __func__); return v; } - -void gck_rpc_log(const char *msg, ...) -{ - va_list ap; - - va_start(ap, msg); - vfprintf(stderr, msg, ap); - fprintf(stderr, "\n"); - va_end(ap); -} - -/* ----------------------------------------------------------------------------- - * MODULE ARGUMENTS - */ - -static void parse_argument(char *arg) -{ - char *value; - - value = arg + strcspn(arg, ":="); - if (!*value) - value = NULL; - else - *(value++) = 0; - - /* Setup the socket path from the arguments */ - if (strcmp(arg, "socket") == 0) - snprintf(pkcs11_socket_path, sizeof(pkcs11_socket_path), "%s", - value); - else if (strcmp(arg, "tls_psk_file") == 0) - snprintf(tls_psk_key_filename, sizeof(tls_psk_key_filename), "%s", - value); - else - warning(("unrecognized argument: %s", arg)); -} - -static void parse_arguments(const char *string) -{ - char quote = '\0'; - char *src, *dup, *at, *arg; - - if (!string) - return; - - src = dup = strdup(string); - if (!dup) { - warning(("couldn't allocate memory for argument string")); - return; - } - - for (arg = at = src; *src; src++) { - - /* Matching quote */ - if (quote == *src) { - quote = '\0'; - - /* Inside of quotes */ - } else if (quote != '\0') { - if (*src == '\\') { - *at++ = *src++; - if (!*src) { - warning(("couldn't parse argument string: %s", string)); - goto done; - } - if (*src != quote) - *at++ = '\\'; - } - *at++ = *src; - - /* Space, not inside of quotes */ - } else if (isspace(*src)) { - *at = 0; - parse_argument(arg); - arg = at; - - /* Other character outside of quotes */ - } else { - switch (*src) { - case '\'': - case '"': - quote = *src; - break; - case '\\': - *at++ = *src++; - if (!*src) { - warning(("couldn't parse argument string: %s", string)); - goto done; - } - /* fall through */ - default: - *at++ = *src; - break; - } - } - } - - if (at != arg) - parse_argument(arg); - -done: - free(dup); -} - -/* ----------------------------------------------------------------------------- - * CALL SESSION - */ - -enum CallStatus { - CALL_INVALID, - CALL_READY, - CALL_PREP, - CALL_TRANSIT, - CALL_PARSE -}; - -typedef struct _CallState { - int socket; /* The connection we're sending on */ - GckRpcMessage *req; /* The current request */ - GckRpcMessage *resp; /* The current response */ - int call_status; - GckRpcTlsPskState *tls; - struct _CallState *next; /* For pooling of completed sockets */ -} CallState; - -/* Maximum number of idle calls */ -#define MAX_CALL_STATE_POOL 8 - -/* All call unused call states are in this list */ -static CallState *call_state_pool = NULL; -static unsigned int n_call_state_pool = 0; - -/* Mutex to protect above call state list */ -static pthread_mutex_t call_state_mutex = PTHREAD_MUTEX_INITIALIZER; - -/* Allocator for call session buffers */ -static void *call_allocator(void *p, size_t sz) -{ - void *res = realloc(p, (size_t) sz); - if (!res && sz) - warning(("memory allocation of %lu bytes failed", sz)); - return res; -} - -static void call_disconnect(CallState * cs) -{ - assert(cs); - - if (cs->socket != -1) { - debug(("disconnected socket")); - close(cs->socket); - cs->socket = -1; - } -} - -/* Write all data to session socket. */ -static CK_RV call_write(CallState * cs, unsigned char *data, size_t len) -{ - int fd, r; - - assert(cs); - assert(data); - assert(len > 0); - - while (len > 0) { - - fd = cs->socket; - if (fd == -1) { - warning(("couldn't send data: socket has been closed")); - return CKR_DEVICE_ERROR; - } - - if (cs->tls) - r = gck_rpc_tls_write_all(cs->tls, (void *) data, len); - else - r = send(fd, (void *) data, len, 0); - - if (r == -1) { - if (errno == EPIPE) { - warning(("couldn't send data: daemon closed connection")); - call_disconnect(cs); - return CKR_DEVICE_ERROR; - } else if (errno != EAGAIN && errno != EINTR) { - warning(("couldn't send data: %s", - strerror(errno))); - return CKR_DEVICE_ERROR; - } - } else { - debug(("wrote %d bytes", r)); - data += r; - len -= r; - } - } - - return CKR_OK; -} - -/* Read a certain amount of data from session socket. */ -static CK_RV call_read(CallState * cs, unsigned char *data, size_t len) -{ - int fd, r; - - assert(cs); - assert(data); - assert(len > 0); - - while (len > 0) { - - fd = cs->socket; - if (fd == -1) { - warning(("couldn't receive data: session socket has been closed")); - return CKR_DEVICE_ERROR; - } - - if (cs->tls) - r = gck_rpc_tls_read_all(cs->tls, (void *) data, len); - else - r = recv(fd, (void *) data, len, 0); - - if (r == 0) { - warning(("couldn't receive data: daemon closed connection")); - call_disconnect(cs); - return CKR_DEVICE_ERROR; - } else if (r == -1) { - if (errno != EAGAIN && errno != EINTR) { - warning(("couldn't receive data: %s", - strerror(errno))); - return CKR_DEVICE_ERROR; - } - } else { - debug(("read %d bytes", r)); - data += r; - len -= r; - } - } - - return CKR_OK; -} - -static int _connect_to_host_port(char *host, char *port) -{ - char hoststr[NI_MAXHOST], portstr[NI_MAXSERV], hostport[NI_MAXHOST + NI_MAXSERV + 1]; - struct addrinfo *ai, *first, hints; - int res, sock, one = 1; - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; /* Either IPv4 or IPv6 */ - hints.ai_socktype = SOCK_STREAM; /* Only stream oriented sockets */ - - if ((res = getaddrinfo(host, port, &hints, &ai)) < 0) { - gck_rpc_warn("couldn't resolve host '%.100s' or service '%.100s' : %.100s\n", - host, port, gai_strerror(res)); - return -1; - } - - sock = -1; - first = ai; - - /* Loop through the sockets returned and see if we can find one that accepts - * our options and connect() - */ - while (ai) { - if ((res = getnameinfo(ai->ai_addr, ai->ai_addrlen, - hoststr, sizeof(hoststr), portstr, sizeof(portstr), - NI_NUMERICHOST | NI_NUMERICSERV)) != 0) { - gck_rpc_warn("couldn't call getnameinfo on pkcs11 socket (%.100s %.100s): %.100s", - host, port, gai_strerror(res)); - sock = -1; - continue; - } - - snprintf(hostport, sizeof(hostport), - (ai->ai_family == AF_INET6) ? "[%s]:%s" : "%s:%s", hoststr, portstr); - - sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - - if (sock >= 0) { - if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, - (char *)&one, sizeof (one)) == -1) { - gck_rpc_warn("couldn't set pkcs11 " - "socket protocol options (%.100s): %.100s", - hostport, strerror (errno)); - goto next; - } - -#ifndef __MINGW32__ - /* close on exec */ - if (fcntl(sock, F_SETFD, 1) == -1) { - gck_rpc_warn("couldn't secure socket (%.100s): %.100s", - hostport, strerror(errno)); - goto next; - } -#endif - - if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) { - close(sock); - warning(("couldn't connect (%.100s): %s", - hostport, strerror(errno))); - goto next; - } - - break; - next: - close(sock); - sock = -1; - } - ai = ai->ai_next; - } - - if (sock < 0) { - gck_rpc_warn("couldn't create pkcs11 socket (%.100s): %.100s\n", - pkcs11_socket_path, strerror(errno)); - sock = -1; - goto out; - } - - out: - freeaddrinfo(first); - - return sock; -} - -static CK_RV call_connect(CallState * cs) -{ - struct sockaddr_un addr; - int sock; - - assert(cs); - assert(cs->socket == -1); - assert(cs->call_status == CALL_INVALID); - assert(pkcs11_socket_path[0]); - - debug(("connecting to: %s", pkcs11_socket_path)); - - memset(&addr, 0, sizeof(addr)); - - if (! strncmp("tcp://", pkcs11_socket_path, 6) || - ! strncmp("tls://", pkcs11_socket_path, 6)) { - char *host, *port; - - if (! gck_rpc_parse_host_port(pkcs11_socket_path + 6, &host, &port)) { - gck_rpc_warn("failed parsing pkcs11 socket : %s", - pkcs11_socket_path); - return CKR_DEVICE_ERROR; - } - - if ((sock = _connect_to_host_port(host, port)) == -1) { - free(host); - return CKR_DEVICE_ERROR; - } - - free(host); - - if (! strncmp("tls://", pkcs11_socket_path, 6)) { - cs->tls = calloc(1, sizeof(GckRpcTlsPskState)); - if (cs->tls == NULL) { - warning(("can't allocate memory for TLS-PSK")); - return CKR_HOST_MEMORY; - } - - if (! gck_rpc_init_tls_psk(cs->tls, tls_psk_key_filename, NULL, GCK_RPC_TLS_PSK_CLIENT)) { - warning(("TLS-PSK initialization failed")); - return CKR_DEVICE_ERROR; - } - - if (! gck_rpc_start_tls(cs->tls, sock)) { - gck_rpc_warn("failed starting TLS"); - return CKR_DEVICE_ERROR; - } - } - } else { - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, pkcs11_socket_path, - sizeof(addr.sun_path)); - - sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) { - warning(("couldn't open socket: %s", strerror(errno))); - return CKR_DEVICE_ERROR; - } - - -#ifndef __MINGW32__ - /* close on exec */ - if (fcntl(sock, F_SETFD, 1) == -1) { - close(sock); - warning(("couldn't secure socket: %s", strerror(errno))); - return CKR_DEVICE_ERROR; - } -#endif - - if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - close(sock); - warning(("couldn't connect to: %s: %s", pkcs11_socket_path, - strerror(errno))); - return CKR_DEVICE_ERROR; - } - } - - cs->socket = sock; - cs->call_status = CALL_READY; - debug(("connected socket")); - - return call_write(cs, (unsigned char*)&pkcs11_app_id, - sizeof(pkcs11_app_id)); -} - -static void call_destroy(void *value) -{ - CallState *cs = value; - - if (value) { - call_disconnect(cs); - assert(cs->socket == -1); - - gck_rpc_message_free(cs->req); - gck_rpc_message_free(cs->resp); - - if (cs->tls) - gck_rpc_close_tls(cs->tls); - - free(cs); - - debug(("destroyed state")); - } -} - -static CK_RV call_lookup(CallState ** ret) -{ - CallState *cs = NULL; - CK_RV rv; - - assert(ret); - - pthread_mutex_lock(&call_state_mutex); - - /* Pop one from the pool if possible */ - if (call_state_pool != NULL) { - cs = call_state_pool; - call_state_pool = cs->next; - cs->next = NULL; - assert(n_call_state_pool > 0); - --n_call_state_pool; - } - - pthread_mutex_unlock(&call_state_mutex); - - if (cs == NULL) { - cs = calloc(1, sizeof(CallState)); - if (cs == NULL) - return CKR_HOST_MEMORY; - cs->socket = -1; - cs->call_status = CALL_INVALID; - - /* Try to connect the call */ - rv = call_connect(cs); - if (rv != CKR_OK) { - free(cs); - return rv; - } - } - - assert(cs->call_status == CALL_READY); - assert(cs->socket != -1); - assert(cs->next == NULL); - *ret = cs; - return CKR_OK; -} - -/* Perform the initial setup for a new call. */ -static CK_RV call_prepare(CallState * cs, int call_id) -{ - assert(cs); - assert(cs->call_status == CALL_READY); - - /* Allocate a new request if we've lost the old one */ - if (!cs->req) { - cs->req = gck_rpc_message_new(call_allocator); - if (!cs->req) { - warning(("cannot allocate request buffer: out of memory")); - return CKR_HOST_MEMORY; - } - } - - /* Put in the Call ID and signature */ - gck_rpc_message_reset(cs->req); - if (!gck_rpc_message_prep(cs->req, call_id, GCK_RPC_REQUEST)) - return CKR_HOST_MEMORY; - - debug(("prepared call: %d", call_id)); - - /* Ready to fill in arguments */ - cs->call_status = CALL_PREP; - return CKR_OK; -} - -/* - * Used by call_session_do_call() to actually send the message to the daemon. - * Note how we unlock and relock the session during the call. - */ -static CK_RV call_send_recv(CallState * cs) -{ - GckRpcMessage *req, *resp; - unsigned char buf[4]; - uint32_t len; - CK_RV ret; - - assert(cs); - assert(cs->req); - assert(cs->call_status == CALL_PREP); - - cs->call_status = CALL_TRANSIT; - - /* Setup the response buffer properly */ - if (!cs->resp) { - /* TODO: Do secrets or passwords ever flow through here? */ - cs->resp = gck_rpc_message_new(call_allocator); - if (!cs->resp) { - warning(("couldn't allocate response buffer: out of memory")); - return CKR_HOST_MEMORY; - } - } - gck_rpc_message_reset(cs->resp); - - /* - * Now as an additional check to make sure nothing nasty will - * happen while we are unlocked, we remove the request and - * response from the session during the action. - */ - req = cs->req; - resp = cs->resp; - cs->req = cs->resp = NULL; - - /* Send the number of bytes, and then the data */ - - egg_buffer_encode_uint32(buf, req->buffer.len); - ret = call_write(cs, buf, 4); - if (ret != CKR_OK) - goto cleanup; - ret = call_write(cs, req->buffer.buf, req->buffer.len); - if (ret != CKR_OK) - goto cleanup; - - /* Now read out the number of bytes, and then the data */ - ret = call_read(cs, buf, 4); - if (ret != CKR_OK) - goto cleanup; - - len = egg_buffer_decode_uint32(buf); - if (!egg_buffer_reserve(&resp->buffer, len + resp->buffer.len)) { - warning(("couldn't allocate %u byte response area: out of memory", len)); - ret = CKR_HOST_MEMORY; - goto cleanup; - } - - ret = call_read(cs, resp->buffer.buf, len); - if (ret != CKR_OK) - goto cleanup; - - egg_buffer_add_empty(&resp->buffer, len); - if (!gck_rpc_message_parse(resp, GCK_RPC_RESPONSE)) - goto cleanup; - - debug(("received response from daemon")); - -cleanup: - /* Make sure nobody else used this thread while unlocked */ - assert(cs->call_status == CALL_TRANSIT); - assert(cs->resp == NULL); - cs->resp = resp; - assert(cs->req == NULL); - cs->req = req; - - return ret; -} - -/* - * At this point the request is ready. So we validate it, and we send it to - * the daemon for a response. - */ -static CK_RV call_run(CallState * cs) -{ - CK_RV ret = CKR_OK; - CK_ULONG ckerr; - - assert(cs); - assert(cs->req); - assert(cs->call_status == CALL_PREP); - assert(cs->socket != -1); - - /* Did building the call fail? */ - if (gck_rpc_message_buffer_error(cs->req)) { - warning(("couldn't allocate request area: out of memory")); - return CKR_HOST_MEMORY; - } - - /* Make sure that the signature is valid */ - assert(gck_rpc_message_is_verified(cs->req)); - - /* Do the dialog with daemon */ - ret = call_send_recv(cs); - - cs->call_status = CALL_PARSE; - - if (ret != CKR_OK) - return ret; - - /* If it's an error code then return it */ - if (cs->resp->call_id == GCK_RPC_CALL_ERROR) { - - if (!gck_rpc_message_read_ulong(cs->resp, &ckerr)) { - warning(("invalid error response from gnome-keyring-daemon: too short")); - return CKR_DEVICE_ERROR; - } - - if (ckerr <= CKR_OK) { - warning(("invalid error response from gnome-keyring-daemon: bad error code")); - return CKR_DEVICE_ERROR; - } - - /* An error code from the daemon */ - return (CK_RV) ckerr; - } - - /* Make sure daemon answered the right call */ - if (cs->req->call_id != cs->resp->call_id) { - warning(("invalid response from gnome-keyring-daemon: call mismatch")); - return CKR_DEVICE_ERROR; - } - - assert(!gck_rpc_message_buffer_error(cs->resp)); - debug(("parsing response values")); - - return CKR_OK; -} - -static CK_RV call_done(CallState * cs, CK_RV ret) -{ - assert(cs); - assert(cs->call_status > CALL_INVALID); - - if (cs->call_status == CALL_PARSE && cs->req && cs->resp) { - - /* Check for parsing errors that were not caught elsewhere */ - if (ret == CKR_OK) { - - if (gck_rpc_message_buffer_error(cs->resp)) { - warning(("invalid response from gnome-keyring-daemon: bad argument data")); - ret = CKR_GENERAL_ERROR; - } else { - /* Double check that the signature matched our decoding */ - assert(gck_rpc_message_is_verified(cs->resp)); - } - } - } - - /* Certain error codes cause us to discard the conenction */ - if (ret != CKR_DEVICE_ERROR && ret != CKR_DEVICE_REMOVED - && cs->socket != -1) { - - /* Try and stash it away for later use */ - pthread_mutex_lock(&call_state_mutex); - - if (n_call_state_pool < MAX_CALL_STATE_POOL) { - cs->call_status = CALL_READY; - assert(cs->next == NULL); - cs->next = call_state_pool; - call_state_pool = cs; - ++n_call_state_pool; - cs = NULL; - } - - pthread_mutex_unlock(&call_state_mutex); - } - - if (cs != NULL) - call_destroy(cs); - - return ret; -} - -/* ----------------------------------------------------------------------------- - * MODULE SPECIFIC PROTOCOL CODE - */ - -static CK_RV -proto_read_attribute_array(GckRpcMessage * msg, CK_ATTRIBUTE_PTR arr, - CK_ULONG len) -{ - uint32_t i, num, value, type; - CK_ATTRIBUTE_PTR attr; - const unsigned char *attrval; - size_t attrlen; - unsigned char validity; - CK_RV ret; - - /* Removed assertion. len == 0 is valid for some ret's, - * see proto_write_attribute_array(). - * assert(len); - */ - assert(msg); - - /* Make sure this is in the right order */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "aA")); - - /* Get the number of items. We need this value to be correct */ - if (!egg_buffer_get_uint32 - (&msg->buffer, msg->parsed, &msg->parsed, &num)) - return PARSE_ERROR; - - if (len != num) { - - /* - * This should never happen in normal operation. It denotes a goof up - * on the other side of our RPC. We should be indicating the exact number - * of attributes to the other side. And it should respond with the same - * number. - */ - - warning(("received an attribute array with wrong number of attributes")); - return PARSE_ERROR; - } - - ret = CKR_OK; - - /* We need to go ahead and read everything in all cases */ - for (i = 0; i < num; ++i) { - - /* The attribute type */ - egg_buffer_get_uint32(&msg->buffer, msg->parsed, - &msg->parsed, &type); - - /* Attribute validity */ - egg_buffer_get_byte(&msg->buffer, msg->parsed, - &msg->parsed, &validity); - - /* And the data itself */ - if (validity) { - if (egg_buffer_get_uint32 - (&msg->buffer, msg->parsed, &msg->parsed, &value) - && egg_buffer_get_byte_array(&msg->buffer, - msg->parsed, - &msg->parsed, &attrval, - &attrlen)) { - if (attrval && value != attrlen) { - warning(("attribute length does not match attribute data")); - return PARSE_ERROR; - } - attrlen = value; - } else { - warning(("failed reading byte array")); - return PARSE_ERROR; - } - } - - /* Don't act on this data unless no errors */ - if (egg_buffer_has_error(&msg->buffer)) - break; - - /* Try and stuff it in the output data */ - if (arr) { - attr = &(arr[i]); - if (attr->type != type) { - warning(("returned attributes in invalid order")); - return PARSE_ERROR; - } - - if (validity) { - /* Just requesting the attribute size */ - if (!attr->pValue) { - attr->ulValueLen = attrlen; - - /* Wants attribute data, but too small */ - } else if (attr->ulValueLen < attrlen) { - attr->ulValueLen = attrlen; - ret = CKR_BUFFER_TOO_SMALL; - - /* Wants attribute data, value is null */ - } else if (attrval == NULL) { - attr->ulValueLen = 0; - - /* Wants attribute data, enough space */ - } else { - CK_ULONG a; - - /* Attribute len is an integer, but - * does not match CK_ULONG size, it's certainly - * a CK_ULONG from a different platform */ - if (attrlen == sizeof(uint64_t) && - sizeof(CK_ULONG) != sizeof(uint64_t) && - gck_rpc_has_ulong_parameter(attr->type)) { - attrlen = sizeof(CK_ULONG); - a = *(uint64_t *) attrval; - attrval = (unsigned char *)&a; - } - attr->ulValueLen = attrlen; - memcpy(attr->pValue, attrval, attrlen); - } - - /* Not a valid attribute */ - } else { - attr->ulValueLen = ((CK_ULONG) - 1); - } - } - } - - if (egg_buffer_has_error(&msg->buffer)) - return PARSE_ERROR; - - /* Read in the code that goes along with these attributes */ - if (!gck_rpc_message_read_ulong(msg, &ret)) - return PARSE_ERROR; - - return ret; -} - -static CK_RV -proto_read_byte_array(GckRpcMessage * msg, CK_BYTE_PTR arr, - CK_ULONG_PTR len, CK_ULONG max) -{ - const unsigned char *val; - unsigned char valid; - size_t vlen; - - assert(len); - assert(msg); - - /* Make sure this is in the right order */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "ay")); - - /* A single byte which determines whether valid or not */ - if (!egg_buffer_get_byte - (&msg->buffer, msg->parsed, &msg->parsed, &valid)) - return PARSE_ERROR; - - /* If not valid, then just the length is encoded, this can signify CKR_BUFFER_TOO_SMALL */ - if (!valid) { - uint32_t t_len; - - if (!egg_buffer_get_uint32 - (&msg->buffer, msg->parsed, &msg->parsed, - & t_len)) - return PARSE_ERROR; - - *len = t_len; - - if (arr) - return CKR_BUFFER_TOO_SMALL; - else - return CKR_OK; - } - - /* Get the actual bytes */ - if (!egg_buffer_get_byte_array - (&msg->buffer, msg->parsed, &msg->parsed, &val, &vlen)) - return PARSE_ERROR; - - *len = vlen; - - /* Just asking us for size */ - if (!arr) - return CKR_OK; - - if (max < vlen) - return CKR_BUFFER_TOO_SMALL; - - /* Enough space, yay */ - memcpy(arr, val, vlen); - return CKR_OK; -} - -static CK_RV -proto_read_ulong_array(GckRpcMessage * msg, CK_ULONG_PTR arr, - CK_ULONG_PTR len, CK_ULONG max) -{ - uint32_t i, num; - uint64_t val; - unsigned char valid; - - assert(len); - assert(msg); - - /* Make sure this is in the right order */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "au")); - - /* A single byte which determines whether valid or not */ - if (!egg_buffer_get_byte - (&msg->buffer, msg->parsed, &msg->parsed, &valid)) - return PARSE_ERROR; - - /* Get the number of items. */ - if (!egg_buffer_get_uint32 - (&msg->buffer, msg->parsed, &msg->parsed, &num)) - return PARSE_ERROR; - - *len = num; - - /* If not valid, then just the length is encoded, this can signify CKR_BUFFER_TOO_SMALL */ - if (!valid) { - if (arr) - return CKR_BUFFER_TOO_SMALL; - else - return CKR_OK; - } - - if (max < num) - return CKR_BUFFER_TOO_SMALL; - - /* We need to go ahead and read everything in all cases */ - for (i = 0; i < num; ++i) { - egg_buffer_get_uint64(&msg->buffer, msg->parsed, &msg->parsed, - &val); - if (arr) - arr[i] = (CK_ULONG) val; - } - - return egg_buffer_has_error(&msg->buffer) ? PARSE_ERROR : CKR_OK; -} - -static CK_RV proto_write_mechanism(GckRpcMessage * msg, CK_MECHANISM_PTR mech) -{ - assert(msg); - assert(mech); - - /* Make sure this is in the right order */ - assert(!msg->signature || gck_rpc_message_verify_part(msg, "M")); - - /* The mechanism type */ - egg_buffer_add_uint32(&msg->buffer, mech->mechanism); - - /* - * PKCS#11 mechanism parameters are not easy to serialize. They're - * completely different for so many mechanisms, they contain - * pointers to arbitrary memory, and many callers don't initialize - * them completely or properly. - * - * We only support certain mechanisms. - * - * Also callers do yucky things like leaving parts of the structure - * pointing to garbage if they don't think it's going to be used. - */ - - if (gck_rpc_mechanism_has_no_parameters(mech->mechanism)) - egg_buffer_add_byte_array(&msg->buffer, NULL, 0); - else if (gck_rpc_mechanism_has_sane_parameters(mech->mechanism)) - egg_buffer_add_byte_array(&msg->buffer, mech->pParameter, - mech->ulParameterLen); - else - return CKR_MECHANISM_INVALID; - - return egg_buffer_has_error(&msg->buffer) ? CKR_HOST_MEMORY : CKR_OK; -} - -static CK_RV proto_read_info(GckRpcMessage * msg, CK_INFO_PTR info) -{ - assert(msg); - assert(info); - - if (!gck_rpc_message_read_version(msg, &info->cryptokiVersion) || - !gck_rpc_message_read_space_string(msg, info->manufacturerID, 32) || - !gck_rpc_message_read_ulong(msg, &info->flags) || - !gck_rpc_message_read_space_string(msg, info->libraryDescription, - 32) - || !gck_rpc_message_read_version(msg, &info->libraryVersion)) - return PARSE_ERROR; - - return CKR_OK; -} - -static CK_RV proto_read_slot_info(GckRpcMessage * msg, CK_SLOT_INFO_PTR info) -{ - assert(msg); - assert(info); - - if (!gck_rpc_message_read_space_string(msg, info->slotDescription, 64) - || !gck_rpc_message_read_space_string(msg, info->manufacturerID, 32) - || !gck_rpc_message_read_ulong(msg, &info->flags) - || !gck_rpc_message_read_version(msg, &info->hardwareVersion) - || !gck_rpc_message_read_version(msg, &info->firmwareVersion)) - return PARSE_ERROR; - - return CKR_OK; -} - -static CK_RV proto_read_token_info(GckRpcMessage * msg, CK_TOKEN_INFO_PTR info) -{ - assert(msg); - assert(info); - - if (!gck_rpc_message_read_space_string(msg, info->label, 32) || - !gck_rpc_message_read_space_string(msg, info->manufacturerID, 32) || - !gck_rpc_message_read_space_string(msg, info->model, 16) || - !gck_rpc_message_read_space_string(msg, info->serialNumber, 16) || - !gck_rpc_message_read_ulong(msg, &info->flags) || - !gck_rpc_message_read_ulong(msg, &info->ulMaxSessionCount) || - !gck_rpc_message_read_ulong(msg, &info->ulSessionCount) || - !gck_rpc_message_read_ulong(msg, &info->ulMaxRwSessionCount) || - !gck_rpc_message_read_ulong(msg, &info->ulRwSessionCount) || - !gck_rpc_message_read_ulong(msg, &info->ulMaxPinLen) || - !gck_rpc_message_read_ulong(msg, &info->ulMinPinLen) || - !gck_rpc_message_read_ulong(msg, &info->ulTotalPublicMemory) || - !gck_rpc_message_read_ulong(msg, &info->ulFreePublicMemory) || - !gck_rpc_message_read_ulong(msg, &info->ulTotalPrivateMemory) || - !gck_rpc_message_read_ulong(msg, &info->ulFreePrivateMemory) || - !gck_rpc_message_read_version(msg, &info->hardwareVersion) || - !gck_rpc_message_read_version(msg, &info->firmwareVersion) || - !gck_rpc_message_read_space_string(msg, info->utcTime, 16)) - return PARSE_ERROR; - - return CKR_OK; -} - -static CK_RV -proto_read_mechanism_info(GckRpcMessage * msg, CK_MECHANISM_INFO_PTR info) -{ - assert(msg); - assert(info); - - if (!gck_rpc_message_read_ulong(msg, &info->ulMinKeySize) || - !gck_rpc_message_read_ulong(msg, &info->ulMaxKeySize) || - !gck_rpc_message_read_ulong(msg, &info->flags)) - return PARSE_ERROR; - - return CKR_OK; -} - -static CK_RV -proto_read_sesssion_info(GckRpcMessage * msg, CK_SESSION_INFO_PTR info) -{ - assert(msg); - assert(info); - - if (!gck_rpc_message_read_ulong(msg, &info->slotID) || - !gck_rpc_message_read_ulong(msg, &info->state) || - !gck_rpc_message_read_ulong(msg, &info->flags) || - !gck_rpc_message_read_ulong(msg, &info->ulDeviceError)) - return PARSE_ERROR; - - return CKR_OK; -} - -/* ------------------------------------------------------------------- - * CALL MACROS - */ - -#define BEGIN_CALL(call_id) \ - debug ((#call_id ": enter")); \ - return_val_if_fail (pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); \ - { \ - CallState *_cs; \ - CK_RV _ret = CKR_OK; \ - _ret = call_lookup (&_cs); \ - if (_ret != CKR_OK) return _ret; \ - _ret = call_prepare (_cs, GCK_RPC_CALL_##call_id); \ - if (_ret != CKR_OK) goto _cleanup; - -#define PROCESS_CALL \ - _ret = call_run (_cs); \ - if (_ret != CKR_OK) goto _cleanup; - -#define RETURN(ret) \ - _ret = ret; \ - goto _cleanup; - -#define END_CALL \ - _cleanup: \ - _ret = call_done (_cs, _ret); \ - debug (("ret: 0x%x", _ret)); \ - return _ret; \ - } - -#define IN_BYTE(val) \ - if (!gck_rpc_message_write_byte (_cs->req, val)) \ - { _ret = CKR_HOST_MEMORY; goto _cleanup; } - -#define IN_ULONG(val) \ - if (!gck_rpc_message_write_ulong (_cs->req, val)) \ - { _ret = CKR_HOST_MEMORY; goto _cleanup; } - -#define IN_SPACE_STRING(val, len) \ - if (!gck_rpc_message_write_space_string (_cs->req, val, len)) \ - { _ret = CKR_HOST_MEMORY; goto _cleanup; } - -#define IN_BYTE_BUFFER(arr, len) \ - if (!gck_rpc_message_write_byte_buffer (_cs->req, arr, len)) \ - { _ret = CKR_HOST_MEMORY; goto _cleanup; } - -#define IN_BYTE_ARRAY(arr, len) \ - if (len != 0 && arr == NULL) \ - { _ret = CKR_ARGUMENTS_BAD; goto _cleanup; } \ - if (!gck_rpc_message_write_byte_array (_cs->req, arr, len)) \ - { _ret = CKR_HOST_MEMORY; goto _cleanup; } - -#define IN_ULONG_BUFFER(arr, len) \ - if (len == NULL) \ - { _ret = CKR_ARGUMENTS_BAD; goto _cleanup; } \ - IN_ULONG_BUFFER2(arr, len); - -#define IN_ULONG_BUFFER2(arr, len) \ - if (!gck_rpc_message_write_ulong_buffer (_cs->req, arr ? *len : 0)) \ - { _ret = CKR_HOST_MEMORY; goto _cleanup; } - -#define IN_ULONG_ARRAY(arr, len) \ - if (len != 0 && arr == NULL) \ - { _ret = CKR_ARGUMENTS_BAD; goto _cleanup; }\ - if (!gck_rpc_message_write_ulong_array (_cs->req, arr, len)) \ - { _ret = CKR_HOST_MEMORY; goto _cleanup; } - -#define IN_ATTRIBUTE_BUFFER(arr, num) \ - if (num != 0 && arr == NULL) \ - { _ret = CKR_ARGUMENTS_BAD; goto _cleanup; } \ - if (!gck_rpc_message_write_attribute_buffer (_cs->req, (arr), (num))) \ - { _ret = CKR_HOST_MEMORY; goto _cleanup; } - -#define IN_ATTRIBUTE_ARRAY(arr, num) \ - if (num != 0 && arr == NULL) \ - { _ret = CKR_ARGUMENTS_BAD; goto _cleanup; } \ - if (!gck_rpc_message_write_attribute_array (_cs->req, (arr), (num))) \ - { _ret = CKR_HOST_MEMORY; goto _cleanup; } - -#define IN_MECHANISM_TYPE(val) \ - if(!gck_rpc_mechanism_is_supported (val)) \ - { _ret = CKR_MECHANISM_INVALID; goto _cleanup; } \ - if (!gck_rpc_message_write_ulong (_cs->req, val)) \ - { _ret = CKR_HOST_MEMORY; goto _cleanup; } - -#define IN_MECHANISM(val) \ - if (val == NULL) \ - { _ret = CKR_ARGUMENTS_BAD; goto _cleanup; } \ - _ret = proto_write_mechanism (_cs->req, val); \ - if (_ret != CKR_OK) goto _cleanup; - -#define OUT_ULONG(val) \ - if (val == NULL) \ - _ret = CKR_ARGUMENTS_BAD; \ - if (_ret == CKR_OK && !gck_rpc_message_read_ulong (_cs->resp, val)) \ - _ret = PARSE_ERROR; - -#define OUT_BYTE_ARRAY(arr, len) \ - if (len == NULL) \ - _ret = CKR_ARGUMENTS_BAD; \ - OUT_BYTE_ARRAY2(arr, len); - -#define OUT_BYTE_ARRAY2(arr, len) \ - if (_ret == CKR_OK) \ - _ret = proto_read_byte_array (_cs->resp, (arr), (len), *(len)); - -#define OUT_ULONG_ARRAY(a, len) \ - if (len == NULL) \ - _ret = CKR_ARGUMENTS_BAD; \ - if (_ret == CKR_OK) \ - _ret = proto_read_ulong_array (_cs->resp, (a), (len), *(len)); - -#define OUT_ATTRIBUTE_ARRAY(arr, num) \ - if (_ret == CKR_OK) \ - _ret = proto_read_attribute_array (_cs->resp, (arr), (num)); - -#define OUT_INFO(info) \ - if (info == NULL) \ - _ret = CKR_ARGUMENTS_BAD; \ - if (_ret == CKR_OK) \ - _ret = proto_read_info (_cs->resp, info); - -#define OUT_SLOT_INFO(info) \ - if (info == NULL) \ - _ret = CKR_ARGUMENTS_BAD; \ - if (_ret == CKR_OK) \ - _ret = proto_read_slot_info (_cs->resp, info); - -#define OUT_TOKEN_INFO(info) \ - if (info == NULL) \ - _ret = CKR_ARGUMENTS_BAD; \ - if (_ret == CKR_OK) \ - _ret = proto_read_token_info (_cs->resp, info); - -#define OUT_SESSION_INFO(info) \ - if (info == NULL) \ - _ret = CKR_ARGUMENTS_BAD; \ - if (_ret == CKR_OK) \ - _ret = proto_read_sesssion_info (_cs->resp, info); - -#define OUT_MECHANISM_TYPE_ARRAY(arr, len) \ - if (len == NULL) \ - _ret = CKR_ARGUMENTS_BAD; \ - if (_ret == CKR_OK) \ - _ret = proto_read_ulong_array (_cs->resp, (arr), (len), *(len)); \ - if (_ret == CKR_OK && arr) \ - gck_rpc_mechanism_list_purge (arr, len); - -#define OUT_MECHANISM_INFO(info) \ - if (info == NULL) \ - _ret = CKR_ARGUMENTS_BAD; \ - if (_ret == CKR_OK) \ - _ret = proto_read_mechanism_info (_cs->resp, info); - -/* ------------------------------------------------------------------- - * INITIALIZATION and 'GLOBAL' CALLS - */ - -static CK_RV rpc_C_Initialize(CK_VOID_PTR init_args) -{ - CK_C_INITIALIZE_ARGS_PTR args = NULL; - CK_RV ret = CKR_OK; - const char *path; - CallState *cs; - pid_t pid; - - debug(("C_Initialize: enter")); - -#ifdef _DEBUG - GCK_RPC_CHECK_CALLS(); -#endif - - pthread_mutex_lock(&init_mutex); - - if (init_args != NULL) { - int supplied_ok; - - /* pReserved must be NULL */ - args = init_args; - - /* XXX since we're never going to call the supplied mutex functions, shouldn't we reject them? */ - /* ALL supplied function pointers need to have the value either NULL or non-NULL. */ - supplied_ok = (args->CreateMutex == NULL - && args->DestroyMutex == NULL - && args->LockMutex == NULL - && args->UnlockMutex == NULL) - || (args->CreateMutex != NULL && args->DestroyMutex != NULL - && args->LockMutex != NULL - && args->UnlockMutex != NULL); - if (!supplied_ok) { - warning(("invalid set of mutex calls supplied")); - ret = CKR_ARGUMENTS_BAD; - goto done; - } - - /* - * When the CKF_OS_LOCKING_OK flag isn't set return an error. - * We must be able to use our pthread functionality. - */ - if (!(args->flags & CKF_OS_LOCKING_OK)) { - warning(("can't do without os locking")); - ret = CKR_CANT_LOCK; - goto done; - } - - /* - * We support setting the socket path and other arguments from from the - * pReserved pointer, similar to how NSS PKCS#11 components are initialized. - */ - if (args->pReserved) - parse_arguments((const char *)args->pReserved); - } - - pid = getpid(); - if (pkcs11_initialized) { - - /* This process has called C_Initialize already */ - if (pid == pkcs11_initialized_pid) { - warning(("C_Initialize called twice for same process")); - ret = CKR_CRYPTOKI_ALREADY_INITIALIZED; - goto done; - } - } - - /* Lookup the socket path, append '.pkcs11' if it is a domain socket. */ - if (pkcs11_socket_path[0] == 0) { - path = getenv("PKCS11_PROXY_SOCKET"); - if (path && path[0]) { - if ((! strncmp("tcp://", path, 6)) || - (! strncmp("tls://", path, 6))) - snprintf(pkcs11_socket_path, - sizeof(pkcs11_socket_path), "%s", - path); - else - snprintf(pkcs11_socket_path, - sizeof(pkcs11_socket_path), - "%s.pkcs11", path); - pkcs11_socket_path[sizeof(pkcs11_socket_path) - 1] = 0; - } else { - ret = CKR_FUNCTION_NOT_SUPPORTED; - goto done; - } - } - - /* If socket path indicates TLS, make sure tls_psk_key_filename is populated. */ - if (! strncmp("tls://", pkcs11_socket_path, 6)) { - if (! tls_psk_key_filename[0]) { - path = getenv("PKCS11_PROXY_TLS_PSK_FILE"); - if (path && path[0]) { - snprintf(tls_psk_key_filename, sizeof(tls_psk_key_filename), - "%s", path); - } - } - - if (! tls_psk_key_filename[0]) { - warning(("can't handle tls:// path without a tls-psk file")); - ret = CKR_FUNCTION_NOT_SUPPORTED; - goto done; - } - } - - srand(time(NULL) ^ pid); - pkcs11_app_id = (uint64_t) rand() << 32 | rand(); - - /* Call through and initialize the daemon */ - ret = call_lookup(&cs); - if (ret == CKR_OK) { - ret = call_prepare(cs, GCK_RPC_CALL_C_Initialize); - if (ret == CKR_OK) - if (!gck_rpc_message_write_byte_array - (cs->req, (unsigned char *)GCK_RPC_HANDSHAKE, - GCK_RPC_HANDSHAKE_LEN)) - ret = CKR_HOST_MEMORY; - if (ret == CKR_OK) - ret = call_run(cs); - call_done(cs, ret); - } - -done: - /* Mark us as officially initialized */ - if (ret == CKR_OK) { - pkcs11_initialized = 1; - pkcs11_initialized_pid = pid; - } else if (ret != CKR_CRYPTOKI_ALREADY_INITIALIZED) { - pkcs11_initialized = 0; - pkcs11_initialized_pid = 0; - pkcs11_socket_path[0] = 0; - } - - pthread_mutex_unlock(&init_mutex); - - debug(("C_Initialize: %d", ret)); - return ret; -} - -static CK_RV rpc_C_Finalize(CK_VOID_PTR reserved) -{ - CallState *cs; - CK_RV ret; - - debug(("C_Finalize: enter")); - return_val_if_fail(! reserved, CKR_ARGUMENTS_BAD); - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - pthread_mutex_lock(&init_mutex); - - ret = call_lookup(&cs); - if (ret == CKR_OK) { - ret = call_prepare(cs, GCK_RPC_CALL_C_Finalize); - if (ret == CKR_OK) { - ret = call_run(cs); - } - call_done(cs, ret); - } - - if (ret != CKR_OK) - warning(("finalizing the daemon returned an error: %d", ret)); - - /* This should stop all other calls in */ - pkcs11_initialized = 0; - pkcs11_initialized_pid = 0; - pkcs11_socket_path[0] = 0; - - pthread_mutex_unlock(&init_mutex); - - debug(("C_Finalize: %d", CKR_OK)); - return CKR_OK; -} - -static CK_RV rpc_C_GetInfo(CK_INFO_PTR info) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - return_val_if_fail(info, CKR_ARGUMENTS_BAD); - - BEGIN_CALL(C_GetInfo); - PROCESS_CALL; - OUT_INFO(info); - END_CALL; -} - -static CK_RV rpc_C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR list) -{ - /* This would be a strange call to receive */ - return C_GetFunctionList(list); -} - -static CK_RV -rpc_C_GetSlotList(CK_BBOOL token_present, CK_SLOT_ID_PTR slot_list, - CK_ULONG_PTR count) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - return_val_if_fail(count, CKR_ARGUMENTS_BAD); - - BEGIN_CALL(C_GetSlotList); - IN_BYTE(token_present); - IN_ULONG_BUFFER(slot_list, count); - PROCESS_CALL; - OUT_ULONG_ARRAY(slot_list, count); - END_CALL; -} - -static CK_RV rpc_C_GetSlotInfo(CK_SLOT_ID id, CK_SLOT_INFO_PTR info) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - return_val_if_fail(info, CKR_ARGUMENTS_BAD); - - BEGIN_CALL(C_GetSlotInfo); - IN_ULONG(id); - PROCESS_CALL; - OUT_SLOT_INFO(info); - END_CALL; -} - -static CK_RV rpc_C_GetTokenInfo(CK_SLOT_ID id, CK_TOKEN_INFO_PTR info) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - return_val_if_fail(info, CKR_ARGUMENTS_BAD); - - BEGIN_CALL(C_GetTokenInfo); - IN_ULONG(id); - PROCESS_CALL; - OUT_TOKEN_INFO(info); - END_CALL; -} - -static CK_RV -rpc_C_GetMechanismList(CK_SLOT_ID id, CK_MECHANISM_TYPE_PTR mechanism_list, - CK_ULONG_PTR count) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - return_val_if_fail(count, CKR_ARGUMENTS_BAD); - - BEGIN_CALL(C_GetMechanismList); - IN_ULONG(id); - IN_ULONG_BUFFER(mechanism_list, count); - PROCESS_CALL; - OUT_MECHANISM_TYPE_ARRAY(mechanism_list, count); - END_CALL; - -} - -static CK_RV -rpc_C_GetMechanismInfo(CK_SLOT_ID id, CK_MECHANISM_TYPE type, - CK_MECHANISM_INFO_PTR info) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - return_val_if_fail(info, CKR_ARGUMENTS_BAD); - - BEGIN_CALL(C_GetMechanismInfo); - IN_ULONG(id); - IN_MECHANISM_TYPE(type); - PROCESS_CALL; - OUT_MECHANISM_INFO(info); - END_CALL; -} - -static CK_RV -rpc_C_InitToken(CK_SLOT_ID id, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len, - CK_UTF8CHAR_PTR label) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_InitToken); - IN_ULONG(id); - IN_BYTE_ARRAY(pin, pin_len); - IN_SPACE_STRING(label, 32); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR slot, - CK_VOID_PTR reserved) -{ - return_val_if_fail(slot, CKR_ARGUMENTS_BAD); - - BEGIN_CALL(C_WaitForSlotEvent); - IN_ULONG(flags); - PROCESS_CALL; - OUT_ULONG(slot); - END_CALL; -} - -static CK_RV -rpc_C_OpenSession(CK_SLOT_ID id, CK_FLAGS flags, CK_VOID_PTR user_data, - CK_NOTIFY callback, CK_SESSION_HANDLE_PTR session) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - /* It is unnecessarily intrusive to check session here. Leave it to the p11 module. - * return_val_if_fail(session, CKR_ARGUMENTS_BAD); - */ - - BEGIN_CALL(C_OpenSession); - IN_ULONG(id); - IN_ULONG(flags); - PROCESS_CALL; - OUT_ULONG(session); - END_CALL; -} - -static CK_RV rpc_C_CloseSession(CK_SESSION_HANDLE session) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_CloseSession); - IN_ULONG(session); - PROCESS_CALL; - END_CALL; -} - -static CK_RV rpc_C_CloseAllSessions(CK_SLOT_ID id) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_CloseAllSessions); - IN_ULONG(id); - PROCESS_CALL; - END_CALL; -} - -static CK_RV rpc_C_GetFunctionStatus(CK_SESSION_HANDLE session) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_GetFunctionStatus); - IN_ULONG(session); - PROCESS_CALL; - END_CALL; -} - -static CK_RV rpc_C_CancelFunction(CK_SESSION_HANDLE session) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_CancelFunction); - IN_ULONG(session); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_GetSessionInfo(CK_SESSION_HANDLE session, CK_SESSION_INFO_PTR info) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - return_val_if_fail(info, CKR_ARGUMENTS_BAD); - - BEGIN_CALL(C_GetSessionInfo); - IN_ULONG(session); - PROCESS_CALL; - OUT_SESSION_INFO(info); - END_CALL; -} - -static CK_RV -rpc_C_InitPIN(CK_SESSION_HANDLE session, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_InitPIN); - IN_ULONG(session); - IN_BYTE_ARRAY(pin, pin_len); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_SetPIN(CK_SESSION_HANDLE session, CK_UTF8CHAR_PTR old_pin, - CK_ULONG old_pin_len, CK_UTF8CHAR_PTR new_pin, - CK_ULONG new_pin_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_SetPIN); - IN_ULONG(session); - IN_BYTE_ARRAY(old_pin, old_pin_len); - IN_BYTE_ARRAY(new_pin, new_pin_len); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_GetOperationState(CK_SESSION_HANDLE session, CK_BYTE_PTR operation_state, - CK_ULONG_PTR operation_state_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_GetOperationState); - IN_ULONG(session); - IN_BYTE_BUFFER(operation_state, operation_state_len); - PROCESS_CALL; - OUT_BYTE_ARRAY(operation_state, operation_state_len); - END_CALL; -} - -static CK_RV -rpc_C_SetOperationState(CK_SESSION_HANDLE session, CK_BYTE_PTR operation_state, - CK_ULONG operation_state_len, - CK_OBJECT_HANDLE encryption_key, - CK_OBJECT_HANDLE authentication_key) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_SetOperationState); - IN_ULONG(session); - IN_BYTE_ARRAY(operation_state, operation_state_len); - IN_ULONG(encryption_key); - IN_ULONG(authentication_key); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_Login(CK_SESSION_HANDLE session, CK_USER_TYPE user_type, - CK_UTF8CHAR_PTR pin, CK_ULONG pin_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_Login); - IN_ULONG(session); - IN_ULONG(user_type); - IN_BYTE_ARRAY(pin, pin_len); - PROCESS_CALL; - END_CALL; -} - -static CK_RV rpc_C_Logout(CK_SESSION_HANDLE session) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_Logout); - IN_ULONG(session); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_CreateObject(CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR template, - CK_ULONG count, CK_OBJECT_HANDLE_PTR new_object) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - return_val_if_fail(session != CK_INVALID_HANDLE, CKR_SESSION_HANDLE_INVALID); - return_val_if_fail(template, CKR_ARGUMENTS_BAD); - return_val_if_fail(new_object, CKR_ARGUMENTS_BAD); - - BEGIN_CALL(C_CreateObject); - IN_ULONG(session); - IN_ATTRIBUTE_ARRAY(template, count); - PROCESS_CALL; - OUT_ULONG(new_object); - END_CALL; -} - -static CK_RV -rpc_C_CopyObject(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, - CK_ATTRIBUTE_PTR template, CK_ULONG count, - CK_OBJECT_HANDLE_PTR new_object) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - return_val_if_fail(new_object, CKR_ARGUMENTS_BAD); - - BEGIN_CALL(C_CopyObject); - IN_ULONG(session); - IN_ULONG(object); - IN_ATTRIBUTE_ARRAY(template, count); - PROCESS_CALL; - OUT_ULONG(new_object); - END_CALL; -} - -static CK_RV -rpc_C_DestroyObject(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_DestroyObject); - IN_ULONG(session); - IN_ULONG(object); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_GetObjectSize(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, - CK_ULONG_PTR size) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - return_val_if_fail(size, CKR_ARGUMENTS_BAD); - - BEGIN_CALL(C_GetObjectSize); - IN_ULONG(session); - IN_ULONG(object); - PROCESS_CALL; - OUT_ULONG(size); - END_CALL; -} - -static CK_RV -rpc_C_GetAttributeValue(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, - CK_ATTRIBUTE_PTR template, CK_ULONG count) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - return_val_if_fail(template, CKR_ARGUMENTS_BAD); - - BEGIN_CALL(C_GetAttributeValue); - IN_ULONG(session); - IN_ULONG(object); - IN_ATTRIBUTE_BUFFER(template, count); - PROCESS_CALL; - OUT_ATTRIBUTE_ARRAY(template, count); - END_CALL; -} - -static CK_RV -rpc_C_SetAttributeValue(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, - CK_ATTRIBUTE_PTR template, CK_ULONG count) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - BEGIN_CALL(C_SetAttributeValue); - IN_ULONG(session); - IN_ULONG(object); - IN_ATTRIBUTE_ARRAY(template, count); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_FindObjectsInit(CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR template, - CK_ULONG count) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_FindObjectsInit); - IN_ULONG(session); - IN_ATTRIBUTE_ARRAY(template, count); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_FindObjects(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE_PTR objects, - CK_ULONG max_count, CK_ULONG_PTR count) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - return_val_if_fail(count, CKR_ARGUMENTS_BAD); - - BEGIN_CALL(C_FindObjects); - IN_ULONG(session); - IN_ULONG_BUFFER2(objects, &max_count); - PROCESS_CALL; - *count = max_count; - OUT_ULONG_ARRAY(objects, count); - END_CALL; -} - -static CK_RV rpc_C_FindObjectsFinal(CK_SESSION_HANDLE session) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - BEGIN_CALL(C_FindObjectsFinal); - IN_ULONG(session); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_EncryptInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE key) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_EncryptInit); - IN_ULONG(session); - IN_MECHANISM(mechanism); - IN_ULONG(key); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_Encrypt(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len, - CK_BYTE_PTR encrypted_data, CK_ULONG_PTR encrypted_data_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - /* From PKCS#11 v2.01 : - * A call to C_Encrypt always terminates the active encryption operation - * unless it returns CKR_BUFFER_TOO_SMALL or is a successful call (i.e., - * one which returns CKR_OK) to determine the length of the buffer - * needed to hold the ciphertext. - * - * Thus, we can't reject for example NULL encrypted_data_len, since then - * the encryption operation won't be terminated in the real PKCS#11 module. - */ - - BEGIN_CALL(C_Encrypt); - IN_ULONG(session); - IN_BYTE_ARRAY(data, data_len); - IN_BYTE_BUFFER(encrypted_data, encrypted_data_len); - PROCESS_CALL; - OUT_BYTE_ARRAY(encrypted_data, encrypted_data_len); - END_CALL; -} - -static CK_RV -rpc_C_EncryptUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, - CK_ULONG part_len, CK_BYTE_PTR encrypted_part, - CK_ULONG_PTR encrypted_part_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_EncryptUpdate); - IN_ULONG(session); - IN_BYTE_ARRAY(part, part_len); - IN_BYTE_BUFFER(encrypted_part, encrypted_part_len); - PROCESS_CALL; - OUT_BYTE_ARRAY(encrypted_part, encrypted_part_len); - END_CALL; -} - -static CK_RV -rpc_C_EncryptFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR last_part, - CK_ULONG_PTR last_part_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_EncryptFinal); - IN_ULONG(session); - IN_BYTE_BUFFER(last_part, last_part_len); - PROCESS_CALL; - OUT_BYTE_ARRAY(last_part, last_part_len); - END_CALL; -} - -static CK_RV -rpc_C_DecryptInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE key) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_DecryptInit); - IN_ULONG(session); - IN_MECHANISM(mechanism); - IN_ULONG(key); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_Decrypt(CK_SESSION_HANDLE session, CK_BYTE_PTR enc_data, - CK_ULONG enc_data_len, CK_BYTE_PTR data, CK_ULONG_PTR data_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_Decrypt); - IN_ULONG(session); - IN_BYTE_ARRAY(enc_data, enc_data_len); - IN_BYTE_BUFFER(data, data_len); - PROCESS_CALL; - OUT_BYTE_ARRAY(data, data_len); - END_CALL; -} - -static CK_RV -rpc_C_DecryptUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR enc_part, - CK_ULONG enc_part_len, CK_BYTE_PTR part, - CK_ULONG_PTR part_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_DecryptUpdate); - IN_ULONG(session); - IN_BYTE_ARRAY(enc_part, enc_part_len); - IN_BYTE_BUFFER(part, part_len); - PROCESS_CALL; - OUT_BYTE_ARRAY(part, part_len); - END_CALL; -} - -static CK_RV -rpc_C_DecryptFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR last_part, - CK_ULONG_PTR last_part_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_DecryptFinal); - IN_ULONG(session); - IN_BYTE_BUFFER(last_part, last_part_len); - PROCESS_CALL; - OUT_BYTE_ARRAY(last_part, last_part_len); - END_CALL; -} - -static CK_RV -rpc_C_DigestInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - BEGIN_CALL(C_DigestInit); - IN_ULONG(session); - IN_MECHANISM(mechanism); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_Digest(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len, - CK_BYTE_PTR digest, CK_ULONG_PTR digest_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_Digest); - IN_ULONG(session); - IN_BYTE_ARRAY(data, data_len); - IN_BYTE_BUFFER(digest, digest_len); - PROCESS_CALL; - OUT_BYTE_ARRAY(digest, digest_len); - END_CALL; -} - -static CK_RV -rpc_C_DigestUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, - CK_ULONG part_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_DigestUpdate); - IN_ULONG(session); - IN_BYTE_ARRAY(part, part_len); - PROCESS_CALL; - END_CALL; -} - -static CK_RV rpc_C_DigestKey(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_DigestKey); - IN_ULONG(session); - IN_ULONG(key); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_DigestFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR digest, - CK_ULONG_PTR digest_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_DigestFinal); - IN_ULONG(session); - IN_BYTE_BUFFER(digest, digest_len); - PROCESS_CALL; - OUT_BYTE_ARRAY(digest, digest_len); - END_CALL; -} - -static CK_RV -rpc_C_SignInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE key) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - BEGIN_CALL(C_SignInit); - IN_ULONG(session); - IN_MECHANISM(mechanism); - IN_ULONG(key); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_Sign(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len, - CK_BYTE_PTR signature, CK_ULONG_PTR signature_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_Sign); - IN_ULONG(session); - IN_BYTE_ARRAY(data, data_len); - IN_BYTE_BUFFER(signature, signature_len); - PROCESS_CALL; - OUT_BYTE_ARRAY(signature, signature_len); - END_CALL; -} - -static CK_RV -rpc_C_SignUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, CK_ULONG part_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - return_val_if_fail(part_len, CKR_ARGUMENTS_BAD); - - BEGIN_CALL(C_SignUpdate); - IN_ULONG(session); - IN_BYTE_ARRAY(part, part_len); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_SignFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR signature, - CK_ULONG_PTR signature_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_SignFinal); - IN_ULONG(session); - IN_BYTE_BUFFER(signature, signature_len); - PROCESS_CALL; - OUT_BYTE_ARRAY(signature, signature_len); - END_CALL; -} - -static CK_RV -rpc_C_SignRecoverInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE key) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_SignRecoverInit); - IN_ULONG(session); - IN_MECHANISM(mechanism); - IN_ULONG(key); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_SignRecover(CK_SESSION_HANDLE session, CK_BYTE_PTR data, - CK_ULONG data_len, CK_BYTE_PTR signature, - CK_ULONG_PTR signature_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_SignRecover); - IN_ULONG(session); - IN_BYTE_ARRAY(data, data_len); - IN_BYTE_BUFFER(signature, signature_len); - PROCESS_CALL; - OUT_BYTE_ARRAY(signature, signature_len); - END_CALL; -} - -static CK_RV -rpc_C_VerifyInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE key) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_VerifyInit); - IN_ULONG(session); - IN_MECHANISM(mechanism); - IN_ULONG(key); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_Verify(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len, - CK_BYTE_PTR signature, CK_ULONG signature_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_Verify); - IN_ULONG(session); - IN_BYTE_ARRAY(data, data_len); - IN_BYTE_ARRAY(signature, signature_len); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_VerifyUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, - CK_ULONG part_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_VerifyUpdate); - IN_ULONG(session); - IN_BYTE_ARRAY(part, part_len); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_VerifyFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR signature, - CK_ULONG signature_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_VerifyFinal); - IN_ULONG(session); - IN_BYTE_ARRAY(signature, signature_len); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_VerifyRecoverInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE key) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_VerifyRecoverInit); - IN_ULONG(session); - IN_MECHANISM(mechanism); - IN_ULONG(key); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_VerifyRecover(CK_SESSION_HANDLE session, CK_BYTE_PTR signature, - CK_ULONG signature_len, CK_BYTE_PTR data, - CK_ULONG_PTR data_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_VerifyRecover); - IN_ULONG(session); - IN_BYTE_ARRAY(signature, signature_len); - IN_BYTE_BUFFER(data, data_len); - PROCESS_CALL; - OUT_BYTE_ARRAY(data, data_len); - END_CALL; -} - -static CK_RV -rpc_C_DigestEncryptUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, - CK_ULONG part_len, CK_BYTE_PTR enc_part, - CK_ULONG_PTR enc_part_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_DigestEncryptUpdate); - IN_ULONG(session); - IN_BYTE_ARRAY(part, part_len); - IN_BYTE_BUFFER(enc_part, enc_part_len); - PROCESS_CALL; - OUT_BYTE_ARRAY(enc_part, enc_part_len); - END_CALL; -} - -static CK_RV -rpc_C_DecryptDigestUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR enc_part, - CK_ULONG enc_part_len, CK_BYTE_PTR part, - CK_ULONG_PTR part_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_DecryptDigestUpdate); - IN_ULONG(session); - IN_BYTE_ARRAY(enc_part, enc_part_len); - IN_BYTE_BUFFER(part, part_len); - PROCESS_CALL; - OUT_BYTE_ARRAY(part, part_len); - END_CALL; -} - -static CK_RV -rpc_C_SignEncryptUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, - CK_ULONG part_len, CK_BYTE_PTR enc_part, - CK_ULONG_PTR enc_part_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_SignEncryptUpdate); - IN_ULONG(session); - IN_BYTE_ARRAY(part, part_len); - IN_BYTE_BUFFER(enc_part, enc_part_len); - PROCESS_CALL; - OUT_BYTE_ARRAY(enc_part, enc_part_len); - END_CALL; -} - -static CK_RV -rpc_C_DecryptVerifyUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR enc_part, - CK_ULONG enc_part_len, CK_BYTE_PTR part, - CK_ULONG_PTR part_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_DecryptVerifyUpdate); - IN_ULONG(session); - IN_BYTE_ARRAY(enc_part, enc_part_len); - IN_BYTE_BUFFER(part, part_len); - PROCESS_CALL; - OUT_BYTE_ARRAY(part, part_len); - END_CALL; -} - -static CK_RV -rpc_C_GenerateKey(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, - CK_ATTRIBUTE_PTR template, CK_ULONG count, - CK_OBJECT_HANDLE_PTR key) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_GenerateKey); - IN_ULONG(session); - IN_MECHANISM(mechanism); - IN_ATTRIBUTE_ARRAY(template, count); - PROCESS_CALL; - OUT_ULONG(key); - END_CALL; -} - -static CK_RV -rpc_C_GenerateKeyPair(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, - CK_ATTRIBUTE_PTR pub_template, CK_ULONG pub_count, - CK_ATTRIBUTE_PTR priv_template, CK_ULONG priv_count, - CK_OBJECT_HANDLE_PTR pub_key, - CK_OBJECT_HANDLE_PTR priv_key) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - return_val_if_fail(session != CK_INVALID_HANDLE, CKR_SESSION_HANDLE_INVALID); - return_val_if_fail(mechanism, CKR_ARGUMENTS_BAD); - return_val_if_fail(pub_template, CKR_ARGUMENTS_BAD); - return_val_if_fail(priv_template, CKR_ARGUMENTS_BAD); - return_val_if_fail(pub_key, CKR_ARGUMENTS_BAD); - return_val_if_fail(priv_key, CKR_ARGUMENTS_BAD); - - BEGIN_CALL(C_GenerateKeyPair); - IN_ULONG(session); - IN_MECHANISM(mechanism); - IN_ATTRIBUTE_ARRAY(pub_template, pub_count); - IN_ATTRIBUTE_ARRAY(priv_template, priv_count); - PROCESS_CALL; - OUT_ULONG(pub_key); - OUT_ULONG(priv_key); - END_CALL; -} - -static CK_RV -rpc_C_WrapKey(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE key, - CK_BYTE_PTR wrapped_key, CK_ULONG_PTR wrapped_key_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_WrapKey); - IN_ULONG(session); - IN_MECHANISM(mechanism); - IN_ULONG(wrapping_key); - IN_ULONG(key); - IN_BYTE_BUFFER(wrapped_key, wrapped_key_len); - PROCESS_CALL; - OUT_BYTE_ARRAY(wrapped_key, wrapped_key_len); - END_CALL; -} - -static CK_RV -rpc_C_UnwrapKey(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE unwrapping_key, CK_BYTE_PTR wrapped_key, - CK_ULONG wrapped_key_len, CK_ATTRIBUTE_PTR template, - CK_ULONG count, CK_OBJECT_HANDLE_PTR key) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_UnwrapKey); - IN_ULONG(session); - IN_MECHANISM(mechanism); - IN_ULONG(unwrapping_key); - IN_BYTE_ARRAY(wrapped_key, wrapped_key_len); - IN_ATTRIBUTE_ARRAY(template, count); - PROCESS_CALL; - OUT_ULONG(key); - END_CALL; -} - -static CK_RV -rpc_C_DeriveKey(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE base_key, CK_ATTRIBUTE_PTR template, - CK_ULONG count, CK_OBJECT_HANDLE_PTR key) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_DeriveKey); - IN_ULONG(session); - IN_MECHANISM(mechanism); - IN_ULONG(base_key); - IN_ATTRIBUTE_ARRAY(template, count); - PROCESS_CALL; - OUT_ULONG(key); - END_CALL; -} - -static CK_RV -rpc_C_SeedRandom(CK_SESSION_HANDLE session, CK_BYTE_PTR seed, CK_ULONG seed_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - BEGIN_CALL(C_SeedRandom); - IN_ULONG(session); - IN_BYTE_ARRAY(seed, seed_len); - PROCESS_CALL; - END_CALL; -} - -static CK_RV -rpc_C_GenerateRandom(CK_SESSION_HANDLE session, CK_BYTE_PTR random_data, - CK_ULONG random_len) -{ - return_val_if_fail(pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - return_val_if_fail(random_data, CKR_ARGUMENTS_BAD); - - BEGIN_CALL(C_GenerateRandom); - IN_ULONG(session); - IN_BYTE_BUFFER(random_data, &random_len); - PROCESS_CALL; - OUT_BYTE_ARRAY2(random_data, &random_len); - END_CALL; -} - -/* -------------------------------------------------------------------- - * MODULE ENTRY POINT - */ - -/* - * PKCS#11 is broken here. It states that Unix compilers automatically byte - * pack structures. This is wrong. GCC on Linux aligns to 4 by default. - * - * This results in incompatibilities. Where this structure's first version - * members take up too much or too little space depending on how this module - * is compiled. - */ - -static CK_FUNCTION_LIST functionList = { - {CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR}, /* version */ - rpc_C_Initialize, - rpc_C_Finalize, - rpc_C_GetInfo, - rpc_C_GetFunctionList, - rpc_C_GetSlotList, - rpc_C_GetSlotInfo, - rpc_C_GetTokenInfo, - rpc_C_GetMechanismList, - rpc_C_GetMechanismInfo, - rpc_C_InitToken, - rpc_C_InitPIN, - rpc_C_SetPIN, - rpc_C_OpenSession, - rpc_C_CloseSession, - rpc_C_CloseAllSessions, - rpc_C_GetSessionInfo, - rpc_C_GetOperationState, - rpc_C_SetOperationState, - rpc_C_Login, - rpc_C_Logout, - rpc_C_CreateObject, - rpc_C_CopyObject, - rpc_C_DestroyObject, - rpc_C_GetObjectSize, - rpc_C_GetAttributeValue, - rpc_C_SetAttributeValue, - rpc_C_FindObjectsInit, - rpc_C_FindObjects, - rpc_C_FindObjectsFinal, - rpc_C_EncryptInit, - rpc_C_Encrypt, - rpc_C_EncryptUpdate, - rpc_C_EncryptFinal, - rpc_C_DecryptInit, - rpc_C_Decrypt, - rpc_C_DecryptUpdate, - rpc_C_DecryptFinal, - rpc_C_DigestInit, - rpc_C_Digest, - rpc_C_DigestUpdate, - rpc_C_DigestKey, - rpc_C_DigestFinal, - rpc_C_SignInit, - rpc_C_Sign, - rpc_C_SignUpdate, - rpc_C_SignFinal, - rpc_C_SignRecoverInit, - rpc_C_SignRecover, - rpc_C_VerifyInit, - rpc_C_Verify, - rpc_C_VerifyUpdate, - rpc_C_VerifyFinal, - rpc_C_VerifyRecoverInit, - rpc_C_VerifyRecover, - rpc_C_DigestEncryptUpdate, - rpc_C_DecryptDigestUpdate, - rpc_C_SignEncryptUpdate, - rpc_C_DecryptVerifyUpdate, - rpc_C_GenerateKey, - rpc_C_GenerateKeyPair, - rpc_C_WrapKey, - rpc_C_UnwrapKey, - rpc_C_DeriveKey, - rpc_C_SeedRandom, - rpc_C_GenerateRandom, - rpc_C_GetFunctionStatus, - rpc_C_CancelFunction, - rpc_C_WaitForSlotEvent -}; - -CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR list) -{ - return_val_if_fail(list, CKR_ARGUMENTS_BAD); - - *list = &functionList; - return CKR_OK; -} diff --git a/ext/pkcs11-proxy/gck-rpc-private.h b/ext/pkcs11-proxy/gck-rpc-private.h deleted file mode 100644 index dd1f49128..000000000 --- a/ext/pkcs11-proxy/gck-rpc-private.h +++ /dev/null @@ -1,327 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* p11-rpc-private.h - various ids and signatures for our protocol - - Copyright (C) 2008, Stef Walter - - The Gnome Keyring Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The Gnome Keyring 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the Gnome Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Stef Walter -*/ - -#ifndef GCK_RPC_CALLS_H -#define GCK_RPC_CALLS_H - -#include "config.h" - -#include -#include - -#include "egg-buffer.h" - -#include "pkcs11/pkcs11.h" - -/* The calls, must be in sync with array below */ -enum { - GCK_RPC_CALL_ERROR = 0, - - GCK_RPC_CALL_C_Initialize, - GCK_RPC_CALL_C_Finalize, - GCK_RPC_CALL_C_GetInfo, - GCK_RPC_CALL_C_GetSlotList, - GCK_RPC_CALL_C_GetSlotInfo, - GCK_RPC_CALL_C_GetTokenInfo, - GCK_RPC_CALL_C_GetMechanismList, - GCK_RPC_CALL_C_GetMechanismInfo, - GCK_RPC_CALL_C_InitToken, - GCK_RPC_CALL_C_WaitForSlotEvent, - - GCK_RPC_CALL_C_OpenSession, - - GCK_RPC_CALL_C_CloseSession, - GCK_RPC_CALL_C_CloseAllSessions, - GCK_RPC_CALL_C_GetFunctionStatus, - GCK_RPC_CALL_C_CancelFunction, - - GCK_RPC_CALL_C_GetSessionInfo, - GCK_RPC_CALL_C_InitPIN, - GCK_RPC_CALL_C_SetPIN, - GCK_RPC_CALL_C_GetOperationState, - GCK_RPC_CALL_C_SetOperationState, - GCK_RPC_CALL_C_Login, - GCK_RPC_CALL_C_Logout, - GCK_RPC_CALL_C_CreateObject, - GCK_RPC_CALL_C_CopyObject, - GCK_RPC_CALL_C_DestroyObject, - GCK_RPC_CALL_C_GetObjectSize, - GCK_RPC_CALL_C_GetAttributeValue, - GCK_RPC_CALL_C_SetAttributeValue, - GCK_RPC_CALL_C_FindObjectsInit, - GCK_RPC_CALL_C_FindObjects, - GCK_RPC_CALL_C_FindObjectsFinal, - GCK_RPC_CALL_C_EncryptInit, - GCK_RPC_CALL_C_Encrypt, - GCK_RPC_CALL_C_EncryptUpdate, - GCK_RPC_CALL_C_EncryptFinal, - GCK_RPC_CALL_C_DecryptInit, - GCK_RPC_CALL_C_Decrypt, - GCK_RPC_CALL_C_DecryptUpdate, - GCK_RPC_CALL_C_DecryptFinal, - GCK_RPC_CALL_C_DigestInit, - GCK_RPC_CALL_C_Digest, - GCK_RPC_CALL_C_DigestUpdate, - GCK_RPC_CALL_C_DigestKey, - GCK_RPC_CALL_C_DigestFinal, - GCK_RPC_CALL_C_SignInit, - GCK_RPC_CALL_C_Sign, - GCK_RPC_CALL_C_SignUpdate, - GCK_RPC_CALL_C_SignFinal, - GCK_RPC_CALL_C_SignRecoverInit, - GCK_RPC_CALL_C_SignRecover, - GCK_RPC_CALL_C_VerifyInit, - GCK_RPC_CALL_C_Verify, - GCK_RPC_CALL_C_VerifyUpdate, - GCK_RPC_CALL_C_VerifyFinal, - GCK_RPC_CALL_C_VerifyRecoverInit, - GCK_RPC_CALL_C_VerifyRecover, - GCK_RPC_CALL_C_DigestEncryptUpdate, - GCK_RPC_CALL_C_DecryptDigestUpdate, - GCK_RPC_CALL_C_SignEncryptUpdate, - GCK_RPC_CALL_C_DecryptVerifyUpdate, - GCK_RPC_CALL_C_GenerateKey, - GCK_RPC_CALL_C_GenerateKeyPair, - GCK_RPC_CALL_C_WrapKey, - GCK_RPC_CALL_C_UnwrapKey, - GCK_RPC_CALL_C_DeriveKey, - GCK_RPC_CALL_C_SeedRandom, - GCK_RPC_CALL_C_GenerateRandom, - - GCK_RPC_CALL_MAX -}; - -typedef struct _GckRpcCall { - int call_id; - const char *name; - const char *request; - const char *response; -} GckRpcCall; - -/* - * a_ = prefix denotes array of _ - * A = CK_ATTRIBUTE - * f_ = prefix denotes buffer for _ - * M = CK_MECHANISM - * u = CK_ULONG - * s = space padded string - * v = CK_VERSION - * y = CK_BYTE - */ - -static const GckRpcCall gck_rpc_calls[] = { - {GCK_RPC_CALL_ERROR, "ERROR", NULL, NULL}, - {GCK_RPC_CALL_C_Initialize, "C_Initialize", "ay", ""}, - {GCK_RPC_CALL_C_Finalize, "C_Finalize", "", ""}, - {GCK_RPC_CALL_C_GetInfo, "C_GetInfo", "", "vsusv"}, - {GCK_RPC_CALL_C_GetSlotList, "C_GetSlotList", "yfu", "au"}, - {GCK_RPC_CALL_C_GetSlotInfo, "C_GetSlotInfo", "u", "ssuvv"}, - {GCK_RPC_CALL_C_GetTokenInfo, "C_GetTokenInfo", "u", - "ssssuuuuuuuuuuuvvs"}, - {GCK_RPC_CALL_C_GetMechanismList, "C_GetMechanismList", "ufu", "au"}, - {GCK_RPC_CALL_C_GetMechanismInfo, "C_GetMechanismInfo", "uu", "uuu"}, - {GCK_RPC_CALL_C_InitToken, "C_InitToken", "uays", ""}, - {GCK_RPC_CALL_C_WaitForSlotEvent, "C_WaitForSlotEvent", "u", "u"}, - {GCK_RPC_CALL_C_OpenSession, "C_OpenSession", "uu", "u"}, - {GCK_RPC_CALL_C_CloseSession, "C_CloseSession", "u", ""}, - {GCK_RPC_CALL_C_CloseAllSessions, "C_CloseAllSessions", "u", ""}, - {GCK_RPC_CALL_C_GetFunctionStatus, "C_GetFunctionStatus", "u", ""}, - {GCK_RPC_CALL_C_CancelFunction, "C_CancelFunction", "u", ""}, - {GCK_RPC_CALL_C_GetSessionInfo, "C_GetSessionInfo", "u", "uuuu"}, - {GCK_RPC_CALL_C_InitPIN, "C_InitPIN", "uay", ""}, - {GCK_RPC_CALL_C_SetPIN, "C_SetPIN", "uayay", ""}, - {GCK_RPC_CALL_C_GetOperationState, "C_GetOperationState", "ufy", "ay"}, - {GCK_RPC_CALL_C_SetOperationState, "C_SetOperationState", "uayuu", ""}, - {GCK_RPC_CALL_C_Login, "C_Login", "uuay", ""}, - {GCK_RPC_CALL_C_Logout, "C_Logout", "u", ""}, - {GCK_RPC_CALL_C_CreateObject, "C_CreateObject", "uaA", "u"}, - {GCK_RPC_CALL_C_CopyObject, "C_CopyObject", "uuaA", "u"}, - {GCK_RPC_CALL_C_DestroyObject, "C_DestroyObject", "uu", ""}, - {GCK_RPC_CALL_C_GetObjectSize, "C_GetObjectSize", "uu", "u"}, - {GCK_RPC_CALL_C_GetAttributeValue, "C_GetAttributeValue", "uufA", - "aAu"}, - {GCK_RPC_CALL_C_SetAttributeValue, "C_SetAttributeValue", "uuaA", ""}, - {GCK_RPC_CALL_C_FindObjectsInit, "C_FindObjectsInit", "uaA", ""}, - {GCK_RPC_CALL_C_FindObjects, "C_FindObjects", "ufu", "au"}, - {GCK_RPC_CALL_C_FindObjectsFinal, "C_FindObjectsFinal", "u", ""}, - {GCK_RPC_CALL_C_EncryptInit, "C_EncryptInit", "uMu", ""}, - {GCK_RPC_CALL_C_Encrypt, "C_Encrypt", "uayfy", "ay"}, - {GCK_RPC_CALL_C_EncryptUpdate, "C_EncryptUpdate", "uayfy", "ay"}, - {GCK_RPC_CALL_C_EncryptFinal, "C_EncryptFinal", "ufy", "ay"}, - {GCK_RPC_CALL_C_DecryptInit, "C_DecryptInit", "uMu", ""}, - {GCK_RPC_CALL_C_Decrypt, "C_Decrypt", "uayfy", "ay"}, - {GCK_RPC_CALL_C_DecryptUpdate, "C_DecryptUpdate", "uayfy", "ay"}, - {GCK_RPC_CALL_C_DecryptFinal, "C_DecryptFinal", "ufy", "ay"}, - {GCK_RPC_CALL_C_DigestInit, "C_DigestInit", "uM", ""}, - {GCK_RPC_CALL_C_Digest, "C_Digest", "uayfy", "ay"}, - {GCK_RPC_CALL_C_DigestUpdate, "C_DigestUpdate", "uay", ""}, - {GCK_RPC_CALL_C_DigestKey, "C_DigestKey", "uu", ""}, - {GCK_RPC_CALL_C_DigestFinal, "C_DigestFinal", "ufy", "ay"}, - {GCK_RPC_CALL_C_SignInit, "C_SignInit", "uMu", ""}, - {GCK_RPC_CALL_C_Sign, "C_Sign", "uayfy", "ay"}, - {GCK_RPC_CALL_C_SignUpdate, "C_SignUpdate", "uay", ""}, - {GCK_RPC_CALL_C_SignFinal, "C_SignFinal", "ufy", "ay"}, - {GCK_RPC_CALL_C_SignRecoverInit, "C_SignRecoverInit", "uMu", ""}, - {GCK_RPC_CALL_C_SignRecover, "C_SignRecover", "uayfy", "ay"}, - {GCK_RPC_CALL_C_VerifyInit, "C_VerifyInit", "uMu", ""}, - {GCK_RPC_CALL_C_Verify, "C_Verify", "uayay", ""}, - {GCK_RPC_CALL_C_VerifyUpdate, "C_VerifyUpdate", "uay", ""}, - {GCK_RPC_CALL_C_VerifyFinal, "C_VerifyFinal", "uay", ""}, - {GCK_RPC_CALL_C_VerifyRecoverInit, "C_VerifyRecoverInit", "uMu", ""}, - {GCK_RPC_CALL_C_VerifyRecover, "C_VerifyRecover", "uayfy", "ay"}, - {GCK_RPC_CALL_C_DigestEncryptUpdate, "C_DigestEncryptUpdate", "uayfy", - "ay"}, - {GCK_RPC_CALL_C_DecryptDigestUpdate, "C_DecryptDigestUpdate", "uayfy", - "ay"}, - {GCK_RPC_CALL_C_SignEncryptUpdate, "C_SignEncryptUpdate", "uayfy", - "ay"}, - {GCK_RPC_CALL_C_DecryptVerifyUpdate, "C_DecryptVerifyUpdate", "uayfy", - "ay"}, - {GCK_RPC_CALL_C_GenerateKey, "C_GenerateKey", "uMaA", "u"}, - {GCK_RPC_CALL_C_GenerateKeyPair, "C_GenerateKeyPair", "uMaAaA", "uu"}, - {GCK_RPC_CALL_C_WrapKey, "C_WrapKey", "uMuufy", "ay"}, - {GCK_RPC_CALL_C_UnwrapKey, "C_UnwrapKey", "uMuayaA", "u"}, - {GCK_RPC_CALL_C_DeriveKey, "C_DeriveKey", "uMuaA", "u"}, - {GCK_RPC_CALL_C_SeedRandom, "C_SeedRandom", "uay", ""}, - {GCK_RPC_CALL_C_GenerateRandom, "C_GenerateRandom", "ufy", "ay"}, -}; - -#ifdef _DEBUG -#define GCK_RPC_CHECK_CALLS() \ - { int i; for (i = 0; i < GCK_RPC_CALL_MAX; ++i) assert (gck_rpc_calls[i].call_id == i); } -#endif - -#define GCK_RPC_HANDSHAKE \ - "PRIVATE-GNOME-KEYRING-PKCS11-PROTOCOL-V-3" -#define GCK_RPC_HANDSHAKE_LEN \ - (sizeof (GCK_RPC_HANDSHAKE) - 1) - -#define GCK_RPC_SOCKET_EXT "pkcs11" - -typedef enum _GckRpcMessageType { - GCK_RPC_REQUEST = 1, - GCK_RPC_RESPONSE -} GckRpcMessageType; - -typedef struct _GckRpcMessage { - int call_id; - GckRpcMessageType call_type; - const char *signature; - EggBuffer buffer; - - size_t parsed; - const char *sigverify; -} GckRpcMessage; - -#define GCK_RPC_BYTE_BUFFER_NULL_DATA 1 -#define GCK_RPC_BYTE_BUFFER_NULL_COUNT 2 - -GckRpcMessage *gck_rpc_message_new(EggBufferAllocator allocator); - -void gck_rpc_message_free(GckRpcMessage * msg); - -void gck_rpc_message_reset(GckRpcMessage * msg); - -int gck_rpc_message_equals(GckRpcMessage * m1, GckRpcMessage * m2); - -#define gck_rpc_message_is_verified(msg) (!(msg)->sigverify || (msg)->sigverify[0] == 0) - -#define gck_rpc_message_buffer_error(msg) (egg_buffer_has_error(&(msg)->buffer)) - -int gck_rpc_message_prep(GckRpcMessage * msg, - int call_id, GckRpcMessageType type); - -int gck_rpc_message_parse(GckRpcMessage * msg, GckRpcMessageType type); - -int gck_rpc_message_verify_part(GckRpcMessage * msg, const char *part); - -int gck_rpc_message_write_byte(GckRpcMessage * msg, CK_BYTE val); - -int gck_rpc_message_write_ulong(GckRpcMessage * msg, CK_ULONG val); - -int gck_rpc_message_write_space_string(GckRpcMessage * msg, - CK_UTF8CHAR * buffer, CK_ULONG length); - -int gck_rpc_message_write_byte_buffer(GckRpcMessage * msg, CK_BYTE_PTR arr, CK_ULONG *count_ptr); - -int gck_rpc_message_write_byte_array(GckRpcMessage * msg, - CK_BYTE_PTR arr, CK_ULONG num); - -int gck_rpc_message_write_ulong_buffer(GckRpcMessage * msg, CK_ULONG count); - -int gck_rpc_message_write_ulong_array(GckRpcMessage * msg, - CK_ULONG_PTR arr, CK_ULONG num); - -int gck_rpc_message_write_attribute_buffer(GckRpcMessage * msg, - CK_ATTRIBUTE_PTR arr, CK_ULONG num); - -int gck_rpc_message_write_attribute_array(GckRpcMessage * msg, - CK_ATTRIBUTE_PTR arr, CK_ULONG num); - -int gck_rpc_message_write_version(GckRpcMessage * msg, CK_VERSION * version); - -int gck_rpc_message_read_byte(GckRpcMessage * msg, CK_BYTE * val); - -int gck_rpc_message_read_ulong(GckRpcMessage * msg, CK_ULONG * val); - -int gck_rpc_message_read_space_string(GckRpcMessage * msg, - CK_UTF8CHAR * buffer, CK_ULONG length); - -int gck_rpc_message_read_version(GckRpcMessage * msg, CK_VERSION * version); - -void gck_rpc_log(const char *msg, ...); - -void gck_rpc_warn(const char *msg, ...); - -void gck_rpc_debug(const char *msg, ...); - -#ifdef G_DISABLE_ASSERT -#define assert(x) -#else -#include -#endif - -/* - * PKCS#11 mechanism parameters are not easy to serialize. They're - * completely different for so many mechanisms, they contain - * pointers to arbitrary memory, and many callers don't initialize - * them completely or properly. - * - * We only support certain mechanisms. - * - * Also callers do yucky things like leaving parts of the structure - * pointing to garbage if they don't think it's going to be used. - */ - -int gck_rpc_mechanism_is_supported(CK_MECHANISM_TYPE mech); -void gck_rpc_mechanism_list_purge(CK_MECHANISM_TYPE_PTR mechs, - CK_ULONG_PTR n_mechs); -int gck_rpc_mechanism_has_sane_parameters(CK_MECHANISM_TYPE type); -int gck_rpc_mechanism_has_no_parameters(CK_MECHANISM_TYPE mech); -int gck_rpc_has_bad_sized_ulong_parameter(CK_ATTRIBUTE_PTR attr); -int gck_rpc_has_ulong_parameter(CK_ATTRIBUTE_TYPE type); - -/* Parses strings (prefix) to host and port components. */ -int gck_rpc_parse_host_port(const char *prefix, char **host, char **port); - -#endif /* GCK_RPC_CALLS_H */ diff --git a/ext/pkcs11-proxy/gck-rpc-tls-psk.c b/ext/pkcs11-proxy/gck-rpc-tls-psk.c deleted file mode 100644 index c19ea860e..000000000 --- a/ext/pkcs11-proxy/gck-rpc-tls-psk.c +++ /dev/null @@ -1,410 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* gck-rpc-tls-psk.c - TLS-PSK functionality to protect communication - - Copyright (C) 2013, NORDUnet A/S - - pkcs11-proxy is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - pkcs11-proxy 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the Gnome Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Fredrik Thulin -*/ - -#include "config.h" - -#include "gck-rpc-private.h" -#include "gck-rpc-tls-psk.h" - -#include -#include - -/* for file I/O */ -#include -#include -#include -#include - -/* TLS pre-shared key */ -static char tls_psk_identity[128] = { 0, }; -static char tls_psk_key_filename[MAXPATHLEN] = { 0, }; - -/* ----------------------------------------------------------------------------- - * LOGGING and DEBUGGING - */ -#ifndef DEBUG_OUTPUT -#define DEBUG_OUTPUT 0 -#endif -#if DEBUG_OUTPUT -#define debug(x) gck_rpc_debug x -#else -#define debug(x) -#endif -#define warning(x) gck_rpc_warn x - - -/* ----------------------------------------------------------------------------- - * TLS-PSK (pre-shared key) functionality - */ - -/* Utility function to decode a single hex char. - * - * Returns value as integer, or -1 on invalid hex char (not 0-9, a-f or A-F). - */ -static int -_tls_psk_to_hex(char val) -{ - if (val >= '0' && val <= '9') - return val - '0'; - if (val >= 'a' && val <= 'f') - return val - 'a' + 10; - if (val >= 'A' && val <= 'F') - return val - 'A' + 10; - return -1; -} - -/* Hex decode the key from an entry in the TLS-PSK key file. Entrys are of the form - * - * identity:hex-key\n - * - * Logging debug/error messages here is a bit problematic since the key is sensitive - * and should not be logged to syslog for example. This code avoids logging the key - * part and only logs identity. - * - * Returns 0 on failure, number of bytes in hex-decoded key on success. - */ -static int -_tls_psk_decode_key(const char *identity, const char *hexkey, unsigned char *psk, unsigned int max_psk_len) -{ - int psk_len, i; - - /* check that length of the key is even */ - if ((strlen(hexkey) % 2) != 0) { - warning(("un-even length TLS-PSK key")); - return 0; - } - - memset(psk, 0, max_psk_len); - psk_len = 0; - - while (*hexkey && (psk_len < max_psk_len)) { - /* decode first half of byte, check for errors */ - if ((i = _tls_psk_to_hex(*hexkey)) < 0) { - warning(("bad TLS-PSK '%.100s' hex char at position %i (%c)", - identity, psk_len + 1, *hexkey)); - return 0; - } - *psk = i << 4; - hexkey++; - - /* decode second half of byte, check for errors */ - if ((i = _tls_psk_to_hex(*hexkey)) < 0) { - warning(("bad TLS-PSK '%.100s' hex char at position %i (%c)", - identity, psk_len + 1, *hexkey)); - return 0; - } - *psk |= i; - hexkey++; - - psk_len++; - psk++; - } - if (*hexkey) { - warning(("too long TLS-PSK '%.100s' key (max %i)", identity, max_psk_len)); - return 0; - } - - return psk_len; -} - -/* - * Read from a file descriptor until a newline is spotted. - * - * Using open() and _fgets() instead of fopen() and fgets() avoids having to - * seccomp-allow the mmap() syscall. - * - * Reading one byte at a time is perhaps not optimal from a performance - * standpoint, but the kernel will surely have pre-buffered the data anyways. - */ -int _fgets(char *buf, unsigned int len, const int fd) -{ - int bytes; - - bytes = 0; - - while (len) { - if (read(fd, buf, 1) != 1) - break; - bytes++; - if (*buf == '\n') { - buf++; - len--; - break; - } - buf++; - len--; - } - - if (! len) - /* ran out of space */ - return -1; - *buf = '\0'; - return bytes; -} - -/* - * Callbacks invoked by OpenSSL PSK initialization. - */ - - -/* Server side TLS-PSK initialization callback. Given an identity (chosen by the client), - * locate a pre-shared key and put it in psk. - * - * Returns the number of bytes put in psk, or 0 on failure. - */ -static unsigned int -_tls_psk_server_cb(SSL *ssl, const char *identity, - unsigned char *psk, unsigned int max_psk_len) -{ - char line[1024], *hexkey; - unsigned int psk_len; - int i, fd; - - debug(("Initializing TLS-PSK with keyfile '%.100s', identity '%.100s'", - tls_psk_key_filename, identity)); - - if ((fd = open(tls_psk_key_filename, O_RDONLY | O_CLOEXEC)) < 0) { - gck_rpc_warn("can't open TLS-PSK keyfile '%.100s' for reading : %s", - tls_psk_key_filename, strerror(errno)); - return 0; - } - - /* Format of PSK file is that of GnuTLS psktool. - * - * identity:hex-key - * other:another-hex-key - */ - psk_len = 0; - - while (_fgets(line, sizeof(line) - 1, fd) > 0) { - /* Find first colon and replace it with NULL */ - hexkey = strchr(line, ':'); - if (! hexkey) - continue; - *hexkey = 0; - hexkey++; - - /* Remove newline(s) at the end */ - for (i = strlen(hexkey) - 1; i && (hexkey[i] == '\n' || hexkey[i] == '\r'); i--) - hexkey[i] = 0; - - if (identity == NULL || ! identity[0] || ! strcmp(line, identity)) { - /* If the line starts with identity: or identity is not provided, parse this line. */ - psk_len = _tls_psk_decode_key(line, hexkey, psk, max_psk_len); - if (psk_len) - debug(("Loaded TLS-PSK '%.100s' from keyfile '%.100s'", - line, tls_psk_key_filename)); - else - warning(("Failed loading TLS-PSK '%.100s' from keyfile '%.100s'", - line, tls_psk_key_filename)); - break; - } - } - close(fd); - - return psk_len; -} - -/* Client side TLS-PSK initialization callback. Indicate to OpenSSL what identity to - * use, and the pre-shared key for that identity. - * - * Returns the number of bytes put in psk, or 0 on failure. - */ -static unsigned int -_tls_psk_client_cb(SSL *ssl, const char *hint, - char *identity, unsigned int max_identity_len, - unsigned char *psk, unsigned int max_psk_len) -{ - /* Client tells server which identity it wants to use in ClientKeyExchange */ - snprintf(identity, max_identity_len, "%s", tls_psk_identity); - - /* We currently just discard the hint sent to us by the server */ - return _tls_psk_server_cb(ssl, identity, psk, max_psk_len); -} - - -/* Initialize OpenSSL and create an SSL CTX. Should be called just once. - * - * Returns 0 on failure and 1 on success. - */ -int -gck_rpc_init_tls_psk(GckRpcTlsPskState *state, const char *key_filename, - const char *identity, enum gck_rpc_tls_psk_caller caller) -{ - char *tls_psk_ciphers = PKCS11PROXY_TLS_PSK_CIPHERS; - - if (state->initialized == 1) { - warning(("TLS state already initialized")); - return 0; - } - - /* Global OpenSSL initialization */ - SSL_load_error_strings(); - SSL_library_init(); - OpenSSL_add_ssl_algorithms(); - - assert(caller == GCK_RPC_TLS_PSK_CLIENT || caller == GCK_RPC_TLS_PSK_SERVER); - - state->ssl_ctx = SSL_CTX_new(TLSv1_2_method()); - - if (state->ssl_ctx == NULL) { - gck_rpc_warn("can't initialize SSL_CTX"); - return 0; - } - - /* Set up callback for TLS-PSK initialization */ - if (caller == GCK_RPC_TLS_PSK_CLIENT) - SSL_CTX_set_psk_client_callback(state->ssl_ctx, _tls_psk_client_cb); - else - SSL_CTX_set_psk_server_callback(state->ssl_ctx, _tls_psk_server_cb); - - /* Disable compression, for security (CRIME Attack). */ - SSL_CTX_set_options(state->ssl_ctx, SSL_OP_NO_COMPRESSION); - - /* Specify ciphers to use */ - SSL_CTX_set_cipher_list(state->ssl_ctx, tls_psk_ciphers); - - snprintf(tls_psk_key_filename, sizeof(tls_psk_key_filename), "%s", key_filename); - snprintf(tls_psk_identity, sizeof(tls_psk_identity), "%s", identity ? identity : ""); - - state->type = caller; - state->initialized = 1; - - debug(("Initialized TLS-PSK %s", caller == GCK_RPC_TLS_PSK_CLIENT ? "client" : "server")); - - return 1; -} - -/* Set up SSL for a new socket. Call this after accept() or connect(). - * - * When a socket has been created, call gck_rpc_start_tls() with the TLS state - * initialized using gck_rpc_init_tls_psk() and the new socket. - * - * Returns 1 on success and 0 on failure. - */ -int -gck_rpc_start_tls(GckRpcTlsPskState *state, int sock) -{ - int res; - char buf[256]; - - state->ssl = SSL_new(state->ssl_ctx); - if (! state->ssl) { - warning(("can't initialize SSL")); - return 0; - } - - state->bio = BIO_new_socket(sock, BIO_NOCLOSE); - if (! state->bio) { - warning(("can't initialize SSL BIO")); - return 0; - } - - SSL_set_bio(state->ssl, state->bio, state->bio); - - /* Set up callback for TLS-PSK initialization */ - if (state->type == GCK_RPC_TLS_PSK_CLIENT) - res = SSL_connect(state->ssl); - else - res = SSL_accept(state->ssl); - - if (res != 1) { - ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); - warning(("can't start TLS : %i/%i (%s perhaps)", - res, SSL_get_error(state->ssl, res), strerror(errno))); - warning(("SSL ERR: %s", buf)); - return 0; - } - - return 1; -} - -/* Un-initialize everything SSL related. Call this on application shut down. - */ -void -gck_rpc_close_tls(GckRpcTlsPskState *state) -{ - if (state->ssl_ctx) { - SSL_CTX_free(state->ssl_ctx); - state->ssl_ctx = NULL; - } - - if (state->ssl) { - SSL_free(state->ssl); - state->ssl = NULL; - } -} - -/* Send data using SSL. - * - * Returns the number of bytes written. - */ -int -gck_rpc_tls_write_all(GckRpcTlsPskState *state, void *data, unsigned int len) -{ - int bytes, error; - char buf[256]; - - assert(state); - assert(data); - assert(len > 0); - - bytes = SSL_write(state->ssl, data, len); - - if (bytes <= 0) { - while ((error = ERR_get_error())) { - ERR_error_string_n(error, buf, sizeof(buf)); - warning(("SSL_write error: %s", buf)); - } - return 0; - } - - return bytes; -} - -/* Read data using SSL. - * - * Returns the number of bytes read. - */ -int -gck_rpc_tls_read_all(GckRpcTlsPskState *state, void *data, unsigned int len) -{ - int bytes, error; - char buf[256]; - - assert(state); - assert(data); - assert(len > 0); - - bytes = SSL_read(state->ssl, data, len); - - if (bytes <= 0) { - while ((error = ERR_get_error())) { - ERR_error_string_n(error, buf, sizeof(buf)); - warning(("SSL_read error: %s", buf)); - } - return 0; - } - - return bytes; -} diff --git a/ext/pkcs11-proxy/gck-rpc-tls-psk.h b/ext/pkcs11-proxy/gck-rpc-tls-psk.h deleted file mode 100644 index b878376ae..000000000 --- a/ext/pkcs11-proxy/gck-rpc-tls-psk.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -#ifndef GCKRPC_TLS_PSK_H_ -#define GCKRPC_TLS_PSK_H_ - -#include "openssl/bio.h" -#include "openssl/ssl.h" -#include "openssl/err.h" - -#if OPENSSL_VERSION_NUMBER < 0x10000000 -# error "OpenSSL version >= 1.0.0 required" -#endif - -enum gck_rpc_tls_psk_caller { - GCK_RPC_TLS_PSK_CLIENT, - GCK_RPC_TLS_PSK_SERVER -}; - -typedef struct { - int initialized; - SSL_CTX *ssl_ctx; - BIO *bio; - SSL *ssl; - enum gck_rpc_tls_psk_caller type; -} GckRpcTlsPskState; - - -int gck_rpc_init_tls_psk(GckRpcTlsPskState *state, const char *key_filename, - const char *identity, enum gck_rpc_tls_psk_caller caller); -int gck_rpc_start_tls(GckRpcTlsPskState *state, int sock); - -int gck_rpc_tls_write_all(GckRpcTlsPskState *state, void *data, unsigned int len); -int gck_rpc_tls_read_all(GckRpcTlsPskState *state, void *data, unsigned int len); - -void gck_rpc_close_tls(GckRpcTlsPskState *state); - -#endif /* GCKRPC_TLS_PSK_H_ */ diff --git a/ext/pkcs11-proxy/gck-rpc-util.c b/ext/pkcs11-proxy/gck-rpc-util.c deleted file mode 100644 index 6095159ea..000000000 --- a/ext/pkcs11-proxy/gck-rpc-util.c +++ /dev/null @@ -1,284 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* p11-rpc-util.c - utilities for module and dispatcher - - Copyright (C) 2008, Stef Walter - - The Gnome Keyring Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The Gnome Keyring 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the Gnome Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Stef Walter -*/ - -#include "config.h" - -#include "gck-rpc-layer.h" -#include "gck-rpc-private.h" - -#include -#include -#include - -static void do_log(const char *pref, const char *msg, va_list va) -{ - char buffer[1024]; - size_t len = 0; - - if (pref) { - snprintf(buffer, sizeof(buffer), "%s: ", pref); - len = strlen(buffer); - } - - vsnprintf(buffer + len, sizeof(buffer) - len, msg, va); - gck_rpc_log(buffer); -} - -void gck_rpc_warn(const char *msg, ...) -{ - va_list va; - va_start(va, msg); - do_log("WARNING", msg, va); - va_end(va); -} - -void gck_rpc_debug(const char *msg, ...) -{ - va_list va; - va_start(va, msg); - do_log("DEBUG", msg, va); - va_end(va); -} - -int gck_rpc_mechanism_is_supported(CK_MECHANISM_TYPE mech) -{ - if (gck_rpc_mechanism_has_no_parameters(mech) || - gck_rpc_mechanism_has_sane_parameters(mech)) - return 1; - return 0; -} - -void -gck_rpc_mechanism_list_purge(CK_MECHANISM_TYPE_PTR mechs, CK_ULONG * n_mechs) -{ - int i; - - assert(mechs); - assert(n_mechs); - - for (i = 0; i < (int)(*n_mechs); ++i) { - if (!gck_rpc_mechanism_has_no_parameters(mechs[i]) && - !gck_rpc_mechanism_has_sane_parameters(mechs[i])) { - - /* Remove the mechanism from the list */ - memmove(&mechs[i], &mechs[i + 1], - (*n_mechs - i) * sizeof(CK_MECHANISM_TYPE)); - - --(*n_mechs); - --i; - } - } -} - -int gck_rpc_mechanism_has_sane_parameters(CK_MECHANISM_TYPE type) -{ - /* This list is incomplete */ - switch (type) { - case CKM_RSA_PKCS_OAEP: - case CKM_RSA_PKCS_PSS: - return 1; - default: - return 0; - } -} - -int gck_rpc_mechanism_has_no_parameters(CK_MECHANISM_TYPE mech) -{ - /* This list is incomplete */ - - switch (mech) { - case CKM_RSA_PKCS_KEY_PAIR_GEN: - case CKM_RSA_X9_31_KEY_PAIR_GEN: - case CKM_RSA_PKCS: - case CKM_RSA_9796: - case CKM_RSA_X_509: - case CKM_RSA_X9_31: - case CKM_MD2_RSA_PKCS: - case CKM_MD5_RSA_PKCS: - case CKM_SHA1_RSA_PKCS: - case CKM_SHA256_RSA_PKCS: - case CKM_SHA384_RSA_PKCS: - case CKM_SHA512_RSA_PKCS: - case CKM_RIPEMD128_RSA_PKCS: - case CKM_RIPEMD160_RSA_PKCS: - case CKM_SHA1_RSA_X9_31: - case CKM_DSA_KEY_PAIR_GEN: - case CKM_DSA_PARAMETER_GEN: - case CKM_DSA: - case CKM_DSA_SHA1: - case CKM_FORTEZZA_TIMESTAMP: - case CKM_EC_KEY_PAIR_GEN: - case CKM_ECDSA: - case CKM_ECDSA_SHA1: - case CKM_DH_PKCS_KEY_PAIR_GEN: - case CKM_DH_PKCS_PARAMETER_GEN: - case CKM_X9_42_DH_KEY_PAIR_GEN: - case CKM_X9_42_DH_PARAMETER_GEN: - case CKM_KEA_KEY_PAIR_GEN: - case CKM_GENERIC_SECRET_KEY_GEN: - case CKM_RC2_KEY_GEN: - case CKM_RC4_KEY_GEN: - case CKM_RC4: - case CKM_RC5_KEY_GEN: - case CKM_AES_KEY_GEN: - case CKM_AES_ECB: - case CKM_AES_MAC: - case CKM_DES_KEY_GEN: - case CKM_DES2_KEY_GEN: - case CKM_DES3_KEY_GEN: - case CKM_CDMF_KEY_GEN: - case CKM_CAST_KEY_GEN: - case CKM_CAST3_KEY_GEN: - case CKM_CAST128_KEY_GEN: - case CKM_IDEA_KEY_GEN: - case CKM_SSL3_PRE_MASTER_KEY_GEN: - case CKM_TLS_PRE_MASTER_KEY_GEN: - case CKM_SKIPJACK_KEY_GEN: - case CKM_BATON_KEY_GEN: - case CKM_JUNIPER_KEY_GEN: - case CKM_RC2_ECB: - case CKM_DES_ECB: - case CKM_DES3_ECB: - case CKM_CDMF_ECB: - case CKM_CAST_ECB: - case CKM_CAST3_ECB: - case CKM_CAST128_ECB: - case CKM_RC5_ECB: - case CKM_IDEA_ECB: - case CKM_RC2_MAC: - case CKM_DES_MAC: - case CKM_DES3_MAC: - case CKM_CDMF_MAC: - case CKM_CAST_MAC: - case CKM_CAST3_MAC: - case CKM_RC5_MAC: - case CKM_IDEA_MAC: - case CKM_SSL3_MD5_MAC: - case CKM_SSL3_SHA1_MAC: - case CKM_SKIPJACK_WRAP: - case CKM_BATON_WRAP: - case CKM_JUNIPER_WRAP: - case CKM_MD2: - case CKM_MD2_HMAC: - case CKM_MD5: - case CKM_MD5_HMAC: - case CKM_SHA_1: - case CKM_SHA_1_HMAC: - case CKM_SHA256: - case CKM_SHA256_HMAC: - case CKM_SHA384: - case CKM_SHA384_HMAC: - case CKM_SHA512: - case CKM_SHA512_HMAC: - case CKM_FASTHASH: - case CKM_RIPEMD128: - case CKM_RIPEMD128_HMAC: - case CKM_RIPEMD160: - case CKM_RIPEMD160_HMAC: - case CKM_KEY_WRAP_LYNKS: - return 1; - default: - return 0; - }; -} - -int -gck_rpc_has_ulong_parameter(CK_ATTRIBUTE_TYPE type) -{ - switch (type) { - case CKA_CLASS: - case CKA_KEY_TYPE: - case CKA_CERTIFICATE_TYPE: - case CKA_HW_FEATURE_TYPE: - case CKA_MODULUS_BITS: - return 1; - default: - return 0; - } -} - -int -gck_rpc_has_bad_sized_ulong_parameter(CK_ATTRIBUTE_PTR attr) -{ - if (!attr->pValue) - return 0; - /* All this parameters are transmited on the network - * as 64bit integers */ - if (sizeof (uint64_t) != attr->ulValueLen) - return 0; - if (sizeof (CK_ULONG) == attr->ulValueLen) - return 0; - return gck_rpc_has_ulong_parameter(attr->type); -} - -/* - * Parses prefix into two strings (host and port). Port may be a NULL pointer - * if none is specified. Since this code does not decode port in any way, a - * service name works too (but requires other code (like - * _get_listening_socket()) able to resolve service names). - * - * This should work for IPv4 and IPv6 inputs : - * - * 0.0.0.0:2345 - * 0.0.0.0 - * [::]:2345 - * [::] - * [::1]:2345 - * localhost:2345 - * localhost - * localhost:p11proxy (if p11proxy is a known service name) - * - * Returns 0 on failure, and 1 on success. - */ -int gck_rpc_parse_host_port(const char *prefix, char **host, char **port) -{ - char *p = NULL; - int is_ipv6; - - is_ipv6 = (prefix[0] == '[') ? 1 : 0; - - *host = strdup(prefix + is_ipv6); - *port = NULL; - - if (*host == NULL) { - gck_rpc_warn("out of memory"); - return 0; - } - - if (is_ipv6 && prefix[0] == '[') - p = strchr(*host, ']'); - else - p = strchr(*host, ':'); - - if (p) { - is_ipv6 = (*p == ']'); /* remember if separator was ']' */ - - *p = '\0'; /* replace separator will NULL to terminate *host */ - *port = p + 1; - - if (is_ipv6 && (**port == ':')) - *port = p + 2; - } - - return 1; -} diff --git a/ext/pkcs11-proxy/install_manifest.txt b/ext/pkcs11-proxy/install_manifest.txt deleted file mode 100644 index e0b24b172..000000000 --- a/ext/pkcs11-proxy/install_manifest.txt +++ /dev/null @@ -1,4 +0,0 @@ -/usr/local/bin/pkcs11-daemon -/usr/local/lib/libpkcs11-proxy.so.0.1 -/usr/local/lib/libpkcs11-proxy.so.0 -/usr/local/lib/libpkcs11-proxy.so \ No newline at end of file diff --git a/ext/pkcs11-proxy/libpkcs11-proxy.so.0 b/ext/pkcs11-proxy/libpkcs11-proxy.so.0 deleted file mode 120000 index c5a87ce85..000000000 --- a/ext/pkcs11-proxy/libpkcs11-proxy.so.0 +++ /dev/null @@ -1 +0,0 @@ -libpkcs11-proxy.so.0.1 \ No newline at end of file diff --git a/ext/pkcs11-proxy/libpkcs11-proxy.so.0.1 b/ext/pkcs11-proxy/libpkcs11-proxy.so.0.1 deleted file mode 100755 index 84348b6e3387efb3267b8f2ec8e0926893eae647..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 144248 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 diff --git a/ext/pkcs11-proxy/mksyscalls.sh b/ext/pkcs11-proxy/mksyscalls.sh deleted file mode 100755 index 47b4a96d5..000000000 --- a/ext/pkcs11-proxy/mksyscalls.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -(echo "static const char *syscall_names[] = {" -echo "#include " | cpp -dM | grep '^#define __NR_' | LC_ALL=C sed -r -n -e 's/^\#define[ \t]+__NR_([a-z0-9_]+)[ \t]+([0-9]+)(.*)/ [\2] = "\1",/p' -echo "};")> syscall-names.h diff --git a/ext/pkcs11-proxy/p11proxy-mitm b/ext/pkcs11-proxy/p11proxy-mitm deleted file mode 100755 index a64015093..000000000 --- a/ext/pkcs11-proxy/p11proxy-mitm +++ /dev/null @@ -1,528 +0,0 @@ -#!/usr/bin/python -# -# Copyright (c) 2012, 2013, NORDUnet A/S -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or -# without modification, are permitted provided that the following -# conditions are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# 3. Neither the name of the NORDUnet nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# -# Author : Fredrik Thulin -# -""" -MITM (man in the middle) proxy of pkcs11-proxy. Written while learning -how the (not very documented) wire format worked, as well as to help -diagnose (and fix) a couple of bugs in the C implementation. - -Usage : - - On console 1 : - - $ PKCS11_DAEMON_SOCKET="tcp://127.0.0.1:2345" pkcs11-daemon /usr/lib/libsofthsm.so - - On console 2 : - - $ ./p11proxy-mitm --debug - - On console 3 : - - $ PKCS11_PROXY_SOCKET="tcp://127.0.0.1:2344" pkcs11-tool --show-info --module libpkcs11-proxy.so - -""" - -import sys -import struct -import socket -import logging -import argparse -import SocketServer -import PyKCS11 # used to get all the PKCS#11 defines - -default_host = "localhost" -default_port_in = 2344 -default_port_out = 2345 -default_timeout = 3 -default_debug = False - -args = None -yhsm = None -logger = None - -# Extracted from gck-rpc-private.h. The last two elements of the tuples describe -# the requests/responses. -# -# /* -# * a_ = prefix denotes array of _ -# * A = CK_ATTRIBUTE -# * f_ = prefix denotes buffer for _ -# * M = CK_MECHANISM -# * u = CK_ULONG -# * s = space padded string -# * v = CK_VERSION -# * y = CK_BYTE -# * z = null terminated string -# */ -request_list = [ - (0, "ERROR", None, None), - (1, "C_Initialize", "ay", ""), - (2, "C_Finalize", "", ""), - (3, "C_GetInfo", "", "vsusv"), - (4, "C_GetSlotList", "yfu", "au"), - (5, "C_GetSlotInfo", "u", "ssuvv"), - (6, "C_GetTokenInfo", "u", "ssssuuuuuuuuuuuvvs"), - (7, "C_GetMechanismList", "ufu", "au"), - (8, "C_GetMechanismInfo", "uu", "uuu"), - (9, "C_InitToken", "uays", ""), - (10, "C_WaitForSlotEvent", "u", "u"), - (11, "C_OpenSession", "uu", "u"), - (12, "C_CloseSession", "u", ""), - (13, "C_CloseAllSessions", "u", ""), - (14, "C_GetFunctionStatus", "u", ""), - (15, "C_CancelFunction", "u", ""), - (16, "C_GetSessionInfo", "u", "uuuu"), - (17, "C_InitPIN", "uay", ""), - (18, "C_SetPIN", "uayay", ""), - (19, "C_GetOperationState", "ufy", "ay"), - (20, "C_SetOperationState", "uayuu", ""), - (21, "C_Login", "uuay", ""), - (22, "C_Logout", "u", ""), - (23, "C_CreateObject", "uaA", "u"), - (24, "C_CopyObject", "uuaA", "u"), - (25, "C_DestroyObject", "uu", ""), - (26, "C_GetObjectSize", "uu", "u"), - (27, "C_GetAttributeValue", "uufA", "aAu"), - (28, "C_SetAttributeValue", "uuaA", ""), - (29, "C_FindObjectsInit", "uaA", ""), - (30, "C_FindObjects", "ufu", "au"), - (31, "C_FindObjectsFinal", "u", ""), - (32, "C_EncryptInit", "uMu", ""), - (33, "C_Encrypt", "uayfy", "ay"), - (34, "C_EncryptUpdate", "uayfy", "ay"), - (35, "C_EncryptFinal", "ufy", "ay"), - (36, "C_DecryptInit", "uMu", ""), - (37, "C_Decrypt", "uayfy", "ay"), - (38, "C_DecryptUpdate", "uayfy", "ay"), - (39, "C_DecryptFinal", "ufy", "ay"), - (40, "C_DigestInit", "uM", ""), - (41, "C_Digest", "uayfy", "ay"), - (42, "C_DigestUpdate", "uay", ""), - (43, "C_DigestKey", "uu", ""), - (44, "C_DigestFinal", "ufy", "ay"), - (45, "C_SignInit", "uMu", ""), - (46, "C_Sign", "uayfy", "ay"), - (47, "C_SignUpdate", "uay", ""), - (48, "C_SignFinal", "ufy", "ay"), - (49, "C_SignRecoverInit", "uMu", ""), - (50, "C_SignRecover", "uayfy", "ay"), - (51, "C_VerifyInit", "uMu", ""), - (52, "C_Verify", "uayay", ""), - (53, "C_VerifyUpdate", "uay", ""), - (54, "C_VerifyFinal", "uay", ""), - (55, "C_VerifyRecoverInit", "uMu", ""), - (56, "C_VerifyRecover", "uayfy", "ay"), - (57, "C_DigestEncryptUpdate", "uayfy", "ay"), - (58, "C_DecryptDigestUpdate", "uayfy", "ay"), - (59, "C_SignEncryptUpdate", "uayfy", "ay"), - (60, "C_DecryptVerifyUpdate", "uayfy", "ay"), - (61, "C_GenerateKey", "uMaA", "u"), - (62, "C_GenerateKeyPair", "uMaAaA", "uu"), - (63, "C_WrapKey", "uMuufy", "ay"), - (64, "C_UnwrapKey", "uMuayaA", "u"), - (65, "C_DeriveKey", "uMuaA", "u"), - (66, "C_SeedRandom", "uay", ""), - (67, "C_GenerateRandom", "ufy", "ay"), - ] - -def parse_args(): - """ - Parse the command line arguments. - """ - parser = argparse.ArgumentParser(description = "pkcs11-proxy man-in-the-middle", - add_help = True, - formatter_class = argparse.ArgumentDefaultsHelpFormatter, - ) - - parser.add_argument('-H', '--host', - dest='listen_host', - default=default_host, - help='Host address to listen on', - metavar='HOST', - ) - - parser.add_argument('--host-out', - dest='connect_to_host', - default=default_host, - help='Host address to connect to', - metavar='HOST', - ) - - parser.add_argument('--port-in', - dest='listen_port', - type=int, - default=default_port_in, - help='Port to listen on', - metavar='PORT', - ) - - parser.add_argument('--port-out', - dest='connect_to_port', - type=int, - default=default_port_out, - help='Port to connect to', - metavar='PORT', - ) - - parser.add_argument('--timeout', - dest='timeout', - type=int, default=default_timeout, - required=False, - help='Request timeout in seconds', - metavar='SECONDS', - ) - - parser.add_argument('--debug', - dest='debug', - action='store_true', default=default_debug, - help='Enable debug operation', - ) - - return parser.parse_args() - -class ProxyHandler(SocketServer.StreamRequestHandler): - """ - The RequestHandler class for our server. - - It is instantiated once per connection to the server, and must - override the handle() method to implement communication to the - client. - """ - - def __init__(self, *other_args, **kwargs): - self.timeout = args.timeout - - # Outgoing connection to the real server (pkcs11-daemon) - self.p11proxy = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.p11proxy.connect((args.connect_to_host, args.connect_to_port)) - - self.logger = logger - SocketServer.BaseRequestHandler.__init__(self, *other_args, **kwargs) - - def handle(self): - """ - Handle an incoming connection. Read requests/responses and decode them after passing - them on to the real pkcs11-proxy client/server. - """ - # self.request is the TCP socket connected to the client - try: - # 64 bits app id. Randomized on the client, and not really used in the server. - self.appid = self.request.recv(8) - self.p11proxy.send(self.appid) - - while True: - # Read request. First 32 bits are length. - length = self.request.recv(4) - if not length: - break - # Pass length to real server. - self.p11proxy.send(length) - self.logger.debug("\n\nRequest length is {}".format(length.encode('hex'))) - self._handle_request(struct.unpack('>L', length)[0]) - - # Read response. Again, first 32 bits are length. - length = self.p11proxy.recv(4) - # Pass length to client. - self.request.sendall(length) - self.logger.debug("\n\nAnswer length is {}".format(length.encode('hex'))) - self._handle_answer(struct.unpack('>L', length)[0]) - except Exception, e: - self.logger.exception("Got exception handling request from {}".format(self.client_address[0])) - return None - - def _handle_request(self, length): - """ - Given expected length, read the rest of a request, pass it on and decode whatever we can. - """ - self.logger.debug("Request({})".format(length)) - data = self.request.recv(length) - self.logger.debug(" R: {}".format(data.encode('hex'))) - self.p11proxy.send(data) - # parse request - (call_id, rest) = self._get_uint32(data) - if call_id > len(request_list): - return None - self.logger.debug(" R: call_id {}".format(call_id)) - rinfo = request_list[call_id] - self.logger.debug(" R: name {}".format(rinfo[1])) - fmt = rinfo[2] - if fmt: - self.logger.debug(" R: fmt {} ({})".format(fmt, fmt.encode('hex'))) - return self._parse_message('R', fmt, rest) - - def _handle_answer(self, length): - """ - Given expected length, read the rest of a response, pass it on and decode whatever we can. - """ - self.logger.debug("Answer({})".format(length)) - data = self.p11proxy.recv(length) - self.logger.debug(" A: {}".format(data.encode('hex'))) - self.request.sendall(data) - (call_id, rest) = self._get_uint32(data) - if call_id > len(request_list): - return None - # parse answer - (call_id, rest) = self._get_uint32(data) - if call_id > len(request_list): - return None - self.logger.debug(" A: call_id {}".format(call_id)) - rinfo = request_list[call_id] - self.logger.debug(" A: name {}".format(rinfo[1])) - if not call_id: - # This is ERROR - (ckr, _) = self._get_uint32(data[-4:]) - self.logger.debug(" A: {}".format(PyKCS11.CKR[ckr])) - fmt = rinfo[3] - if fmt: - self.logger.debug(" A: fmt {} ({})".format(fmt, fmt.encode('hex'))) - self._parse_message('A', fmt, rest) - - def _parse_message(self, msgtype, fmt, data): - """ - Parse the data in the request/response, which share format. - """ - # Check that the data is of the format we expect it to be. The format of every request/answer - # is redundantly included in the data sent over the network, although we already know what - # it should be. I guess this is a way to reduce the likeliness of undetected stream de-sync, - # because it would be wasteful if it was just used to make developers forget to update the - # handshake string when changing the format for a request/response. - (parsed_fmt, rest) = self._get_byte_array(data) - if parsed_fmt != fmt: - self.logger.error(" {}: Format mismatch, mine is {} and received is {}".format(msgtype, fmt, parsed_fmt)) - return None - self.logger.debug(" {}: format match".format(msgtype)) - try: - res = self._value_dump(msgtype, parsed_fmt, rest) - return res - except Exception: - self.logger.exception("Got exception trying to dump all data") - return [] - - def _value_dump(self, msgtype, fmt, data, res = []): - """ - Decode the data in a request/answer according to fmt. - - Will output the decoded data using self.logger.debug(). - """ - if not fmt: - if data: - self.logger.warning("{} bytes left after processing : {}".format(len(data), data.encode('hex'))) - return [] - #self.logger.debug("PARSING {} FROM {}".format(fmt[0], data.encode('hex'))) - if fmt[0] == 'u': - (this, rest) = self._get_uint64(data) - res.append(this) - self.logger.debug(" {}: uint64 {}".format(msgtype, hex(this))) - elif fmt[0] == 'a': - #self.logger.debug("PARSING {} FROM {}".format(fmt[0], data.encode('hex'))) - if fmt[1] == 'A': - valid = 1 - rest = data - else: - (valid, rest) = self._get_uint8(data) - self.logger.debug(" {}: Byte-Array valid : {}".format(msgtype, valid)) - array_num = 0 - (array_num, rest) = self._get_uint32(rest) - self.logger.debug(" {}: Byte-Array length : {}/{}".format(msgtype, array_num, hex(array_num))) - if array_num > 256: - raise Exception("Unreasonable array length : {}".format(hex(array_num))) - if not valid: - # /* If not valid, then just the length is encoded, this can signify CKR_BUFFER_TOO_SMALL */ - self.logger.debug(" {}: Array length {}/{}, not valid - maybe CKR_BUFFER_TOO_SMALL".format(msgtype, array_num, array_num)) - # array is now fully handled, remove next element of fmt - fmt = fmt[1:] - if rest: - self.logger.debug(" {}: CKR_BUFFER_TOO_SMALL leaving data {} ({} bytes) for fmt {}".format(msgtype, rest.encode('hex'), len(rest), fmt[1:])) - else: - if fmt[1] == 'y': - # simple byte array (i.e. string to us) - rest = struct.pack('>L', array_num) + rest # restore length before calling _get_byte_array - (this, rest) = self._get_byte_array(rest) - self.logger.debug(" {}: Byte-Array({}) {}".format(msgtype, len(this), repr(this))) - res.append(this) - fmt = fmt[1:] - else: - if array_num > 0: - # modify fmt to match the array length - placeholder = 'X' - array_elements = fmt[1] * (array_num - 1) - fmt_rest = fmt[1:] - fmt = placeholder + array_elements + fmt_rest - else: - # chomp the next fmt too - fmt = fmt[1:] - self.logger.debug(" {}: Array length {}, new fmt {}".format(msgtype, array_num, fmt)) - elif fmt[0] == 's': - (this, rest) = self._get_byte_array(data) - res.append(this) - self.logger.debug(" {}: string({}/{}) {}".format(msgtype, len(this), hex(len(this)), repr(this))) - elif fmt[0] == 'v': - # version, struct ck_version from pkcs11.h - (major, rest) = self._get_uint8(data) - (minor, rest) = self._get_uint8(rest) - self.logger.debug(" {}: CK_Version {}.{}".format(msgtype, major, minor)) - elif fmt[0] == 'y': - (this, rest) = self._get_uint8(data) - self.logger.debug(" {}: CK_Byte {}".format(msgtype, hex(this))) - elif fmt[0] == 'z': - # NULL-terminated string, len == -1 for empty string - (length, rest) = self._get_uint32(data) - if length == 0xffffffff: - res.append('') - else: - (this, rest) = self._get_byte_array(data) - res.append(this) - self.logger.debug(" {}: NULL-string({}/{}) {}".format(msgtype, len(this), hex(len(this)), repr(this))) - elif fmt[0] == 'M': - # Mechanism - #self.logger.debug("PARSING {} FROM {}".format(fmt[0], data.encode('hex'))) - (mech_type, rest) = self._get_uint32(data) - self.logger.debug(" {}: Mechanism {}/{}".format(msgtype, repr(mech_type), PyKCS11.CKM.get(mech_type))) - (this, rest) = self._get_byte_array(rest) - self.logger.debug(" {}: Mechanism parameter {}".format(msgtype, repr(this))) - res.append((mech_type, this)) - elif fmt[0] == 'A': - # Attribute - (this, rest) = self._get_attribute(data) - res.append(this) - #self.logger.debug(" {}: Attribute {}".format(msgtype, this)) - vl = "None" - if this['uValueLen'] is not None: - vl = hex(this['uValueLen']) - self.logger.debug(" {}: Attribute type {}/{}, valid {}, len {}, data {}".format(\ - msgtype, hex(this['type']), PyKCS11.CKA.get(this['type']), this['valid'], vl, this['data'].encode('hex'))) - elif fmt[0] == 'f': - # array buffer - if fmt[1] == 'y': - (flags, rest) = self._get_uint8(data) - else: - rest = data - (num_items, rest) = self._get_uint32(rest) - if fmt[1] == 'A': - self.logger.debug(" {}: Attribute buffer, {} elements".format(msgtype, hex(num_items))) - while num_items: - (attr_type, rest) = self._get_uint32(rest) - (buffer_len, rest) = self._get_uint32(rest) - self.logger.debug(" {}: type {}/{} len {}".format(msgtype, hex(attr_type), PyKCS11.CKA.get(attr_type), hex(buffer_len))) - res.append(('attribute buffer', attr_type, buffer_len)) - num_items -= 1 - elif fmt[1] == 'y': - self.logger.debug(" {}: Byte buffer, length {} (flags {})".format(msgtype, hex(num_items), flags)) - # just a number of bytes to alloc - pass - elif fmt[1] == 'u': - # ulong buffer, just an uint32 (?) - self.logger.debug("PARSING {} FROM {}".format(fmt[0], data.encode('hex'))) - (this, rest) = self._get_uint32(data) - self.logger.debug(" {}: ulong buffer {}".format(msgtype, hex(this))) - else: - raise Exception("Unknown array buffer fmt '{}'".format(fmt[1])) - # need to munch an extra fmt - fmt = fmt[1:] - else: - self.logger.warn(" {}: STOPPING at fmt {}, data {}".format(msgtype, fmt[0], data.encode('hex'))) - return [] - return self._value_dump(msgtype, fmt[1:], rest, res) - - def _get_uint64(self, data): - (a, rest) = self._get_uint32(data) - (b, rest) = self._get_uint32(rest) - return (a << 32 | b, data[8:]) - - def _get_uint32(self, data): - res = struct.unpack('>L', data[:4])[0] - return (res, data[4:]) - - def _get_uint8(self, data): - res = ord(data[0]) - return (res, data[1:]) - - def _get_byte_array(self, data): - (length, rest) = self._get_uint32(data) - if length == 0xffffffff: - return('', rest) - if length > len(rest): - raise Exception('Parse error, not enough bytes left for byte-array') - res = rest[:length] - return (res, rest[length:]) - - def _get_attribute(self, data): - attr = {} - (attr_type, rest) = self._get_uint32(data) - (attr_valid, rest) = self._get_uint8(rest) - attr_vallen = None - data = '' - if attr_valid: - (attr_vallen, rest) = self._get_uint32(rest) - # length doubly included, in byte array again? - (data, rest) = self._get_byte_array(rest) - # read data here! - attr['type'] = attr_type - attr['valid'] = attr_valid - attr['uValueLen'] = attr_vallen - attr['data'] = data - return (attr, rest) - -def main(): - global args - args = parse_args() - - level = logging.INFO - if args.debug: - level = logging.DEBUG - logging.basicConfig(level=level) - global logger - logger = logging.getLogger('p11proxy-mitm') - - # Create the server - server = SocketServer.TCPServer((args.listen_host, args.listen_port), \ - ProxyHandler, \ - bind_and_activate=False, \ - ) - server.allow_reuse_address = True - server.timeout = args.timeout - server.server_bind() # Manually bind, to support allow_reuse_address - server.server_activate() # (see above comment) - - # Activate the server; this will keep running until you - # interrupt the program with Ctrl-C - server.serve_forever() - -if __name__ == '__main__': - try: - if main(): - sys.exit(0) - sys.exit(1) - except KeyboardInterrupt: - pass diff --git a/ext/pkcs11-proxy/pkcs11-daemon b/ext/pkcs11-proxy/pkcs11-daemon deleted file mode 100755 index 1efabee7e34e289a2b8942a3ceaa1907e8016cb6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 160424 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 O82)3TC^J+pz5fH;4;B9a diff --git a/ext/pkcs11-proxy/pkcs11/pkcs11.h b/ext/pkcs11-proxy/pkcs11/pkcs11.h deleted file mode 100644 index 6899788a4..000000000 --- a/ext/pkcs11-proxy/pkcs11/pkcs11.h +++ /dev/null @@ -1,1312 +0,0 @@ -/* pkcs11.h - Copyright 2006, 2007 g10 Code GmbH - Copyright 2006 Andreas Jellinghaus - - This file is free software; as a special exception the author gives - unlimited permission to copy and/or distribute it, with or without - modifications, as long as this notice is preserved. - - This file is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY, to the extent permitted by law; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. */ - -/* Please submit changes back to the Scute project at - http://www.scute.org/ (or send them to marcus@g10code.com), so that - they can be picked up by other projects from there as well. */ - -/* This file is a modified implementation of the PKCS #11 standard by - RSA Security Inc. It is mostly a drop-in replacement, with the - following change: - - This header file does not require any macro definitions by the user - (like CK_DEFINE_FUNCTION etc). In fact, it defines those macros - for you (if useful, some are missing, let me know if you need - more). - - There is an additional API available that does comply better to the - GNU coding standard. It can be switched on by defining - CRYPTOKI_GNU before including this header file. For this, the - following changes are made to the specification: - - All structure types are changed to a "struct ck_foo" where CK_FOO - is the type name in PKCS #11. - - All non-structure types are changed to ck_foo_t where CK_FOO is the - lowercase version of the type name in PKCS #11. The basic types - (CK_ULONG et al.) are removed without substitute. - - All members of structures are modified in the following way: Type - indication prefixes are removed, and underscore characters are - inserted before words. Then the result is lowercased. - - Note that function names are still in the original case, as they - need for ABI compatibility. - - CK_FALSE, CK_TRUE and NULL_PTR are removed without substitute. Use - . - - If CRYPTOKI_COMPAT is defined before including this header file, - then none of the API changes above take place, and the API is the - one defined by the PKCS #11 standard. */ - -#ifndef PKCS11_H -#define PKCS11_H 1 - -#if defined(__cplusplus) -extern "C" { -#endif - -/* The version of cryptoki we implement. The revision is changed with - each modification of this file. If you do not use the "official" - version of this file, please consider deleting the revision macro - (you may use a macro with a different name to keep track of your - versions). */ -#define CRYPTOKI_VERSION_MAJOR 2 -#define CRYPTOKI_VERSION_MINOR 20 -#define CRYPTOKI_VERSION_REVISION 6 - -/* Compatibility interface is default, unless CRYPTOKI_GNU is - given. */ -#ifndef CRYPTOKI_GNU -#ifndef CRYPTOKI_COMPAT -#define CRYPTOKI_COMPAT 1 -#endif -#endif - -/* System dependencies. */ - -#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32) - -/* There is a matching pop below. */ -#pragma pack(push, cryptoki, 1) - -#ifdef CRYPTOKI_EXPORTS -#define CK_SPEC __declspec(dllexport) -#else -#define CK_SPEC __declspec(dllimport) -#endif - -#else - -#define CK_SPEC - -#endif - -#ifdef CRYPTOKI_COMPAT - /* If we are in compatibility mode, switch all exposed names to the - PKCS #11 variant. There are corresponding #undefs below. */ - -#define ck_flags_t CK_FLAGS -#define ck_version _CK_VERSION - -#define ck_info _CK_INFO -#define cryptoki_version cryptokiVersion -#define manufacturer_id manufacturerID -#define library_description libraryDescription -#define library_version libraryVersion - -#define ck_notification_t CK_NOTIFICATION -#define ck_slot_id_t CK_SLOT_ID - -#define ck_slot_info _CK_SLOT_INFO -#define slot_description slotDescription -#define hardware_version hardwareVersion -#define firmware_version firmwareVersion - -#define ck_token_info _CK_TOKEN_INFO -#define serial_number serialNumber -#define max_session_count ulMaxSessionCount -#define session_count ulSessionCount -#define max_rw_session_count ulMaxRwSessionCount -#define rw_session_count ulRwSessionCount -#define max_pin_len ulMaxPinLen -#define min_pin_len ulMinPinLen -#define total_public_memory ulTotalPublicMemory -#define free_public_memory ulFreePublicMemory -#define total_private_memory ulTotalPrivateMemory -#define free_private_memory ulFreePrivateMemory -#define utc_time utcTime - -#define ck_session_handle_t CK_SESSION_HANDLE -#define ck_user_type_t CK_USER_TYPE -#define ck_state_t CK_STATE - -#define ck_session_info _CK_SESSION_INFO -#define slot_id slotID -#define device_error ulDeviceError - -#define ck_object_handle_t CK_OBJECT_HANDLE -#define ck_object_class_t CK_OBJECT_CLASS -#define ck_hw_feature_type_t CK_HW_FEATURE_TYPE -#define ck_key_type_t CK_KEY_TYPE -#define ck_certificate_type_t CK_CERTIFICATE_TYPE -#define ck_attribute_type_t CK_ATTRIBUTE_TYPE - -#define ck_attribute _CK_ATTRIBUTE -#define value pValue -#define value_len ulValueLen - -#define ck_date _CK_DATE - -#define ck_mechanism_type_t CK_MECHANISM_TYPE - -#define ck_mechanism _CK_MECHANISM -#define parameter pParameter -#define parameter_len ulParameterLen - -#define ck_mechanism_info _CK_MECHANISM_INFO -#define min_key_size ulMinKeySize -#define max_key_size ulMaxKeySize - -#define ck_rv_t CK_RV -#define ck_notify_t CK_NOTIFY - -#define ck_function_list _CK_FUNCTION_LIST - -#define ck_createmutex_t CK_CREATEMUTEX -#define ck_destroymutex_t CK_DESTROYMUTEX -#define ck_lockmutex_t CK_LOCKMUTEX -#define ck_unlockmutex_t CK_UNLOCKMUTEX - -#define ck_c_initialize_args _CK_C_INITIALIZE_ARGS -#define create_mutex CreateMutex -#define destroy_mutex DestroyMutex -#define lock_mutex LockMutex -#define unlock_mutex UnlockMutex -#define reserved pReserved - -#endif /* CRYPTOKI_COMPAT */ - - typedef unsigned long ck_flags_t; - - struct ck_version { - unsigned char major; - unsigned char minor; - }; - - struct ck_info { - struct ck_version cryptoki_version; - unsigned char manufacturer_id[32]; - ck_flags_t flags; - unsigned char library_description[32]; - struct ck_version library_version; - }; - - typedef unsigned long ck_notification_t; - -#define CKN_SURRENDER (0UL) - - typedef unsigned long ck_slot_id_t; - - struct ck_slot_info { - unsigned char slot_description[64]; - unsigned char manufacturer_id[32]; - ck_flags_t flags; - struct ck_version hardware_version; - struct ck_version firmware_version; - }; - -#define CKF_TOKEN_PRESENT (1UL << 0) -#define CKF_REMOVABLE_DEVICE (1UL << 1) -#define CKF_HW_SLOT (1UL << 2) -#define CKF_ARRAY_ATTRIBUTE (1UL << 30) - - struct ck_token_info { - unsigned char label[32]; - unsigned char manufacturer_id[32]; - unsigned char model[16]; - unsigned char serial_number[16]; - ck_flags_t flags; - unsigned long max_session_count; - unsigned long session_count; - unsigned long max_rw_session_count; - unsigned long rw_session_count; - unsigned long max_pin_len; - unsigned long min_pin_len; - unsigned long total_public_memory; - unsigned long free_public_memory; - unsigned long total_private_memory; - unsigned long free_private_memory; - struct ck_version hardware_version; - struct ck_version firmware_version; - unsigned char utc_time[16]; - }; - -#define CKF_RNG (1UL << 0) -#define CKF_WRITE_PROTECTED (1UL << 1) -#define CKF_LOGIN_REQUIRED (1UL << 2) -#define CKF_USER_PIN_INITIALIZED (1UL << 3) -#define CKF_RESTORE_KEY_NOT_NEEDED (1UL << 5) -#define CKF_CLOCK_ON_TOKEN (1UL << 6) -#define CKF_PROTECTED_AUTHENTICATION_PATH (1UL << 8) -#define CKF_DUAL_CRYPTO_OPERATIONS (1UL << 9) -#define CKF_TOKEN_INITIALIZED (1UL << 10) -#define CKF_SECONDARY_AUTHENTICATION (1UL << 11) -#define CKF_USER_PIN_COUNT_LOW (1UL << 16) -#define CKF_USER_PIN_FINAL_TRY (1UL << 17) -#define CKF_USER_PIN_LOCKED (1UL << 18) -#define CKF_USER_PIN_TO_BE_CHANGED (1UL << 19) -#define CKF_SO_PIN_COUNT_LOW (1UL << 20) -#define CKF_SO_PIN_FINAL_TRY (1UL << 21) -#define CKF_SO_PIN_LOCKED (1UL << 22) -#define CKF_SO_PIN_TO_BE_CHANGED (1UL << 23) - -#define CK_UNAVAILABLE_INFORMATION ((unsigned long)-1L) -#define CK_EFFECTIVELY_INFINITE (0UL) - - typedef unsigned long ck_session_handle_t; - -#define CK_INVALID_HANDLE (0UL) - - typedef unsigned long ck_user_type_t; - -#define CKU_SO (0UL) -#define CKU_USER (1UL) -#define CKU_CONTEXT_SPECIFIC (2UL) - - typedef unsigned long ck_state_t; - -#define CKS_RO_PUBLIC_SESSION (0UL) -#define CKS_RO_USER_FUNCTIONS (1UL) -#define CKS_RW_PUBLIC_SESSION (2UL) -#define CKS_RW_USER_FUNCTIONS (3UL) -#define CKS_RW_SO_FUNCTIONS (4UL) - - struct ck_session_info { - ck_slot_id_t slot_id; - ck_state_t state; - ck_flags_t flags; - unsigned long device_error; - }; - -#define CKF_RW_SESSION (1UL << 1) -#define CKF_SERIAL_SESSION (1UL << 2) - - typedef unsigned long ck_object_handle_t; - - typedef unsigned long ck_object_class_t; - -#define CKO_DATA (0UL) -#define CKO_CERTIFICATE (1UL) -#define CKO_PUBLIC_KEY (2UL) -#define CKO_PRIVATE_KEY (3UL) -#define CKO_SECRET_KEY (4UL) -#define CKO_HW_FEATURE (5UL) -#define CKO_DOMAIN_PARAMETERS (6UL) -#define CKO_MECHANISM (7UL) -#define CKO_VENDOR_DEFINED ((unsigned long) (1UL << 31)) - - typedef unsigned long ck_hw_feature_type_t; - -#define CKH_MONOTONIC_COUNTER (1UL) -#define CKH_CLOCK (2UL) -#define CKH_USER_INTERFACE (3UL) -#define CKH_VENDOR_DEFINED ((unsigned long) (1UL << 31)) - - typedef unsigned long ck_key_type_t; - -#define CKK_RSA (0UL) -#define CKK_DSA (1UL) -#define CKK_DH (2UL) -#define CKK_ECDSA (3UL) -#define CKK_EC (3UL) -#define CKK_X9_42_DH (4UL) -#define CKK_KEA (5UL) -#define CKK_GENERIC_SECRET (0x10UL) -#define CKK_RC2 (0x11UL) -#define CKK_RC4 (0x12UL) -#define CKK_DES (0x13UL) -#define CKK_DES2 (0x14UL) -#define CKK_DES3 (0x15UL) -#define CKK_CAST (0x16UL) -#define CKK_CAST3 (0x17UL) -#define CKK_CAST128 (0x18UL) -#define CKK_RC5 (0x19UL) -#define CKK_IDEA (0x1aUL) -#define CKK_SKIPJACK (0x1bUL) -#define CKK_BATON (0x1cUL) -#define CKK_JUNIPER (0x1dUL) -#define CKK_CDMF (0x1eUL) -#define CKK_AES (0x1fUL) -#define CKK_BLOWFISH (0x20UL) -#define CKK_TWOFISH (0x21UL) -#define CKK_VENDOR_DEFINED ((unsigned long) (1UL << 31)) - - typedef unsigned long ck_certificate_type_t; - -#define CKC_X_509 (0UL) -#define CKC_X_509_ATTR_CERT (1UL) -#define CKC_WTLS (2UL) -#define CKC_VENDOR_DEFINED ((unsigned long) (1UL << 31)) - - typedef unsigned long ck_attribute_type_t; - -#define CKA_CLASS (0UL) -#define CKA_TOKEN (1UL) -#define CKA_PRIVATE (2UL) -#define CKA_LABEL (3UL) -#define CKA_APPLICATION (0x10UL) -#define CKA_VALUE (0x11UL) -#define CKA_OBJECT_ID (0x12UL) -#define CKA_CERTIFICATE_TYPE (0x80UL) -#define CKA_ISSUER (0x81UL) -#define CKA_SERIAL_NUMBER (0x82UL) -#define CKA_AC_ISSUER (0x83UL) -#define CKA_OWNER (0x84UL) -#define CKA_ATTR_TYPES (0x85UL) -#define CKA_TRUSTED (0x86UL) -#define CKA_CERTIFICATE_CATEGORY (0x87UL) -#define CKA_JAVA_MIDP_SECURITY_DOMAIN (0x88UL) -#define CKA_URL (0x89UL) -#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY (0x8aUL) -#define CKA_HASH_OF_ISSUER_PUBLIC_KEY (0x8bUL) -#define CKA_CHECK_VALUE (0x90UL) -#define CKA_KEY_TYPE (0x100UL) -#define CKA_SUBJECT (0x101UL) -#define CKA_ID (0x102UL) -#define CKA_SENSITIVE (0x103UL) -#define CKA_ENCRYPT (0x104UL) -#define CKA_DECRYPT (0x105UL) -#define CKA_WRAP (0x106UL) -#define CKA_UNWRAP (0x107UL) -#define CKA_SIGN (0x108UL) -#define CKA_SIGN_RECOVER (0x109UL) -#define CKA_VERIFY (0x10aUL) -#define CKA_VERIFY_RECOVER (0x10bUL) -#define CKA_DERIVE (0x10cUL) -#define CKA_START_DATE (0x110UL) -#define CKA_END_DATE (0x111UL) -#define CKA_MODULUS (0x120UL) -#define CKA_MODULUS_BITS (0x121UL) -#define CKA_PUBLIC_EXPONENT (0x122UL) -#define CKA_PRIVATE_EXPONENT (0x123UL) -#define CKA_PRIME_1 (0x124UL) -#define CKA_PRIME_2 (0x125UL) -#define CKA_EXPONENT_1 (0x126UL) -#define CKA_EXPONENT_2 (0x127UL) -#define CKA_COEFFICIENT (0x128UL) -#define CKA_PRIME (0x130UL) -#define CKA_SUBPRIME (0x131UL) -#define CKA_BASE (0x132UL) -#define CKA_PRIME_BITS (0x133UL) -#define CKA_SUB_PRIME_BITS (0x134UL) -#define CKA_VALUE_BITS (0x160UL) -#define CKA_VALUE_LEN (0x161UL) -#define CKA_EXTRACTABLE (0x162UL) -#define CKA_LOCAL (0x163UL) -#define CKA_NEVER_EXTRACTABLE (0x164UL) -#define CKA_ALWAYS_SENSITIVE (0x165UL) -#define CKA_KEY_GEN_MECHANISM (0x166UL) -#define CKA_MODIFIABLE (0x170UL) -#define CKA_ECDSA_PARAMS (0x180UL) -#define CKA_EC_PARAMS (0x180UL) -#define CKA_EC_POINT (0x181UL) -#define CKA_SECONDARY_AUTH (0x200UL) -#define CKA_AUTH_PIN_FLAGS (0x201UL) -#define CKA_ALWAYS_AUTHENTICATE (0x202UL) -#define CKA_WRAP_WITH_TRUSTED (0x210UL) -#define CKA_HW_FEATURE_TYPE (0x300UL) -#define CKA_RESET_ON_INIT (0x301UL) -#define CKA_HAS_RESET (0x302UL) -#define CKA_PIXEL_X (0x400UL) -#define CKA_PIXEL_Y (0x401UL) -#define CKA_RESOLUTION (0x402UL) -#define CKA_CHAR_ROWS (0x403UL) -#define CKA_CHAR_COLUMNS (0x404UL) -#define CKA_COLOR (0x405UL) -#define CKA_BITS_PER_PIXEL (0x406UL) -#define CKA_CHAR_SETS (0x480UL) -#define CKA_ENCODING_METHODS (0x481UL) -#define CKA_MIME_TYPES (0x482UL) -#define CKA_MECHANISM_TYPE (0x500UL) -#define CKA_REQUIRED_CMS_ATTRIBUTES (0x501UL) -#define CKA_DEFAULT_CMS_ATTRIBUTES (0x502UL) -#define CKA_SUPPORTED_CMS_ATTRIBUTES (0x503UL) -#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x211UL) -#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x212UL) -#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE | 0x600UL) -#define CKA_VENDOR_DEFINED ((unsigned long) (1UL << 31)) - - struct ck_attribute { - ck_attribute_type_t type; - void *value; - unsigned long value_len; - }; - - struct ck_date { - unsigned char year[4]; - unsigned char month[2]; - unsigned char day[2]; - }; - - typedef unsigned long ck_mechanism_type_t; - -#define CKM_RSA_PKCS_KEY_PAIR_GEN (0UL) -#define CKM_RSA_PKCS (1UL) -#define CKM_RSA_9796 (2UL) -#define CKM_RSA_X_509 (3UL) -#define CKM_MD2_RSA_PKCS (4UL) -#define CKM_MD5_RSA_PKCS (5UL) -#define CKM_SHA1_RSA_PKCS (6UL) -#define CKM_RIPEMD128_RSA_PKCS (7UL) -#define CKM_RIPEMD160_RSA_PKCS (8UL) -#define CKM_RSA_PKCS_OAEP (9UL) -#define CKM_RSA_X9_31_KEY_PAIR_GEN (0xaUL) -#define CKM_RSA_X9_31 (0xbUL) -#define CKM_SHA1_RSA_X9_31 (0xcUL) -#define CKM_RSA_PKCS_PSS (0xdUL) -#define CKM_SHA1_RSA_PKCS_PSS (0xeUL) -#define CKM_DSA_KEY_PAIR_GEN (0x10UL) -#define CKM_DSA (0x11UL) -#define CKM_DSA_SHA1 (0x12UL) -#define CKM_DH_PKCS_KEY_PAIR_GEN (0x20UL) -#define CKM_DH_PKCS_DERIVE (0x21UL) -#define CKM_X9_42_DH_KEY_PAIR_GEN (0x30UL) -#define CKM_X9_42_DH_DERIVE (0x31UL) -#define CKM_X9_42_DH_HYBRID_DERIVE (0x32UL) -#define CKM_X9_42_MQV_DERIVE (0x33UL) -#define CKM_SHA256_RSA_PKCS (0x40UL) -#define CKM_SHA384_RSA_PKCS (0x41UL) -#define CKM_SHA512_RSA_PKCS (0x42UL) -#define CKM_SHA256_RSA_PKCS_PSS (0x43UL) -#define CKM_SHA384_RSA_PKCS_PSS (0x44UL) -#define CKM_SHA512_RSA_PKCS_PSS (0x45UL) -#define CKM_RC2_KEY_GEN (0x100UL) -#define CKM_RC2_ECB (0x101UL) -#define CKM_RC2_CBC (0x102UL) -#define CKM_RC2_MAC (0x103UL) -#define CKM_RC2_MAC_GENERAL (0x104UL) -#define CKM_RC2_CBC_PAD (0x105UL) -#define CKM_RC4_KEY_GEN (0x110UL) -#define CKM_RC4 (0x111UL) -#define CKM_DES_KEY_GEN (0x120UL) -#define CKM_DES_ECB (0x121UL) -#define CKM_DES_CBC (0x122UL) -#define CKM_DES_MAC (0x123UL) -#define CKM_DES_MAC_GENERAL (0x124UL) -#define CKM_DES_CBC_PAD (0x125UL) -#define CKM_DES2_KEY_GEN (0x130UL) -#define CKM_DES3_KEY_GEN (0x131UL) -#define CKM_DES3_ECB (0x132UL) -#define CKM_DES3_CBC (0x133UL) -#define CKM_DES3_MAC (0x134UL) -#define CKM_DES3_MAC_GENERAL (0x135UL) -#define CKM_DES3_CBC_PAD (0x136UL) -#define CKM_CDMF_KEY_GEN (0x140UL) -#define CKM_CDMF_ECB (0x141UL) -#define CKM_CDMF_CBC (0x142UL) -#define CKM_CDMF_MAC (0x143UL) -#define CKM_CDMF_MAC_GENERAL (0x144UL) -#define CKM_CDMF_CBC_PAD (0x145UL) -#define CKM_MD2 (0x200UL) -#define CKM_MD2_HMAC (0x201UL) -#define CKM_MD2_HMAC_GENERAL (0x202UL) -#define CKM_MD5 (0x210UL) -#define CKM_MD5_HMAC (0x211UL) -#define CKM_MD5_HMAC_GENERAL (0x212UL) -#define CKM_SHA_1 (0x220UL) -#define CKM_SHA_1_HMAC (0x221UL) -#define CKM_SHA_1_HMAC_GENERAL (0x222UL) -#define CKM_RIPEMD128 (0x230UL) -#define CKM_RIPEMD128_HMAC (0x231UL) -#define CKM_RIPEMD128_HMAC_GENERAL (0x232UL) -#define CKM_RIPEMD160 (0x240UL) -#define CKM_RIPEMD160_HMAC (0x241UL) -#define CKM_RIPEMD160_HMAC_GENERAL (0x242UL) -#define CKM_SHA256 (0x250UL) -#define CKM_SHA256_HMAC (0x251UL) -#define CKM_SHA256_HMAC_GENERAL (0x252UL) -#define CKM_SHA384 (0x260UL) -#define CKM_SHA384_HMAC (0x261UL) -#define CKM_SHA384_HMAC_GENERAL (0x262UL) -#define CKM_SHA512 (0x270UL) -#define CKM_SHA512_HMAC (0x271UL) -#define CKM_SHA512_HMAC_GENERAL (0x272UL) -#define CKM_CAST_KEY_GEN (0x300UL) -#define CKM_CAST_ECB (0x301UL) -#define CKM_CAST_CBC (0x302UL) -#define CKM_CAST_MAC (0x303UL) -#define CKM_CAST_MAC_GENERAL (0x304UL) -#define CKM_CAST_CBC_PAD (0x305UL) -#define CKM_CAST3_KEY_GEN (0x310UL) -#define CKM_CAST3_ECB (0x311UL) -#define CKM_CAST3_CBC (0x312UL) -#define CKM_CAST3_MAC (0x313UL) -#define CKM_CAST3_MAC_GENERAL (0x314UL) -#define CKM_CAST3_CBC_PAD (0x315UL) -#define CKM_CAST5_KEY_GEN (0x320UL) -#define CKM_CAST128_KEY_GEN (0x320UL) -#define CKM_CAST5_ECB (0x321UL) -#define CKM_CAST128_ECB (0x321UL) -#define CKM_CAST5_CBC (0x322UL) -#define CKM_CAST128_CBC (0x322UL) -#define CKM_CAST5_MAC (0x323UL) -#define CKM_CAST128_MAC (0x323UL) -#define CKM_CAST5_MAC_GENERAL (0x324UL) -#define CKM_CAST128_MAC_GENERAL (0x324UL) -#define CKM_CAST5_CBC_PAD (0x325UL) -#define CKM_CAST128_CBC_PAD (0x325UL) -#define CKM_RC5_KEY_GEN (0x330UL) -#define CKM_RC5_ECB (0x331UL) -#define CKM_RC5_CBC (0x332UL) -#define CKM_RC5_MAC (0x333UL) -#define CKM_RC5_MAC_GENERAL (0x334UL) -#define CKM_RC5_CBC_PAD (0x335UL) -#define CKM_IDEA_KEY_GEN (0x340UL) -#define CKM_IDEA_ECB (0x341UL) -#define CKM_IDEA_CBC (0x342UL) -#define CKM_IDEA_MAC (0x343UL) -#define CKM_IDEA_MAC_GENERAL (0x344UL) -#define CKM_IDEA_CBC_PAD (0x345UL) -#define CKM_GENERIC_SECRET_KEY_GEN (0x350UL) -#define CKM_CONCATENATE_BASE_AND_KEY (0x360UL) -#define CKM_CONCATENATE_BASE_AND_DATA (0x362UL) -#define CKM_CONCATENATE_DATA_AND_BASE (0x363UL) -#define CKM_XOR_BASE_AND_DATA (0x364UL) -#define CKM_EXTRACT_KEY_FROM_KEY (0x365UL) -#define CKM_SSL3_PRE_MASTER_KEY_GEN (0x370UL) -#define CKM_SSL3_MASTER_KEY_DERIVE (0x371UL) -#define CKM_SSL3_KEY_AND_MAC_DERIVE (0x372UL) -#define CKM_SSL3_MASTER_KEY_DERIVE_DH (0x373UL) -#define CKM_TLS_PRE_MASTER_KEY_GEN (0x374UL) -#define CKM_TLS_MASTER_KEY_DERIVE (0x375UL) -#define CKM_TLS_KEY_AND_MAC_DERIVE (0x376UL) -#define CKM_TLS_MASTER_KEY_DERIVE_DH (0x377UL) -#define CKM_SSL3_MD5_MAC (0x380UL) -#define CKM_SSL3_SHA1_MAC (0x381UL) -#define CKM_MD5_KEY_DERIVATION (0x390UL) -#define CKM_MD2_KEY_DERIVATION (0x391UL) -#define CKM_SHA1_KEY_DERIVATION (0x392UL) -#define CKM_PBE_MD2_DES_CBC (0x3a0UL) -#define CKM_PBE_MD5_DES_CBC (0x3a1UL) -#define CKM_PBE_MD5_CAST_CBC (0x3a2UL) -#define CKM_PBE_MD5_CAST3_CBC (0x3a3UL) -#define CKM_PBE_MD5_CAST5_CBC (0x3a4UL) -#define CKM_PBE_MD5_CAST128_CBC (0x3a4UL) -#define CKM_PBE_SHA1_CAST5_CBC (0x3a5UL) -#define CKM_PBE_SHA1_CAST128_CBC (0x3a5UL) -#define CKM_PBE_SHA1_RC4_128 (0x3a6UL) -#define CKM_PBE_SHA1_RC4_40 (0x3a7UL) -#define CKM_PBE_SHA1_DES3_EDE_CBC (0x3a8UL) -#define CKM_PBE_SHA1_DES2_EDE_CBC (0x3a9UL) -#define CKM_PBE_SHA1_RC2_128_CBC (0x3aaUL) -#define CKM_PBE_SHA1_RC2_40_CBC (0x3abUL) -#define CKM_PKCS5_PBKD2 (0x3b0UL) -#define CKM_PBA_SHA1_WITH_SHA1_HMAC (0x3c0UL) -#define CKM_KEY_WRAP_LYNKS (0x400UL) -#define CKM_KEY_WRAP_SET_OAEP (0x401UL) -#define CKM_SKIPJACK_KEY_GEN (0x1000UL) -#define CKM_SKIPJACK_ECB64 (0x1001UL) -#define CKM_SKIPJACK_CBC64 (0x1002UL) -#define CKM_SKIPJACK_OFB64 (0x1003UL) -#define CKM_SKIPJACK_CFB64 (0x1004UL) -#define CKM_SKIPJACK_CFB32 (0x1005UL) -#define CKM_SKIPJACK_CFB16 (0x1006UL) -#define CKM_SKIPJACK_CFB8 (0x1007UL) -#define CKM_SKIPJACK_WRAP (0x1008UL) -#define CKM_SKIPJACK_PRIVATE_WRAP (0x1009UL) -#define CKM_SKIPJACK_RELAYX (0x100aUL) -#define CKM_KEA_KEY_PAIR_GEN (0x1010UL) -#define CKM_KEA_KEY_DERIVE (0x1011UL) -#define CKM_FORTEZZA_TIMESTAMP (0x1020UL) -#define CKM_BATON_KEY_GEN (0x1030UL) -#define CKM_BATON_ECB128 (0x1031UL) -#define CKM_BATON_ECB96 (0x1032UL) -#define CKM_BATON_CBC128 (0x1033UL) -#define CKM_BATON_COUNTER (0x1034UL) -#define CKM_BATON_SHUFFLE (0x1035UL) -#define CKM_BATON_WRAP (0x1036UL) -#define CKM_ECDSA_KEY_PAIR_GEN (0x1040UL) -#define CKM_EC_KEY_PAIR_GEN (0x1040UL) -#define CKM_ECDSA (0x1041UL) -#define CKM_ECDSA_SHA1 (0x1042UL) -#define CKM_ECDH1_DERIVE (0x1050UL) -#define CKM_ECDH1_COFACTOR_DERIVE (0x1051UL) -#define CKM_ECMQV_DERIVE (0x1052UL) -#define CKM_JUNIPER_KEY_GEN (0x1060UL) -#define CKM_JUNIPER_ECB128 (0x1061UL) -#define CKM_JUNIPER_CBC128 (0x1062UL) -#define CKM_JUNIPER_COUNTER (0x1063UL) -#define CKM_JUNIPER_SHUFFLE (0x1064UL) -#define CKM_JUNIPER_WRAP (0x1065UL) -#define CKM_FASTHASH (0x1070UL) -#define CKM_AES_KEY_GEN (0x1080UL) -#define CKM_AES_ECB (0x1081UL) -#define CKM_AES_CBC (0x1082UL) -#define CKM_AES_MAC (0x1083UL) -#define CKM_AES_MAC_GENERAL (0x1084UL) -#define CKM_AES_CBC_PAD (0x1085UL) -#define CKM_DSA_PARAMETER_GEN (0x2000UL) -#define CKM_DH_PKCS_PARAMETER_GEN (0x2001UL) -#define CKM_X9_42_DH_PARAMETER_GEN (0x2002UL) -#define CKM_VENDOR_DEFINED ((unsigned long) (1UL << 31)) - - struct ck_mechanism { - ck_mechanism_type_t mechanism; - void *parameter; - unsigned long parameter_len; - }; - - struct ck_mechanism_info { - unsigned long min_key_size; - unsigned long max_key_size; - ck_flags_t flags; - }; - -#define CKF_HW (1UL << 0) -#define CKF_ENCRYPT (1UL << 8) -#define CKF_DECRYPT (1UL << 9) -#define CKF_DIGEST (1UL << 10) -#define CKF_SIGN (1UL << 11) -#define CKF_SIGN_RECOVER (1UL << 12) -#define CKF_VERIFY (1UL << 13) -#define CKF_VERIFY_RECOVER (1UL << 14) -#define CKF_GENERATE (1UL << 15) -#define CKF_GENERATE_KEY_PAIR (1UL << 16) -#define CKF_WRAP (1UL << 17) -#define CKF_UNWRAP (1UL << 18) -#define CKF_DERIVE (1UL << 19) -#define CKF_EXTENSION ((unsigned long) (1UL << 31)) - -/* Flags for C_WaitForSlotEvent. */ -#define CKF_DONT_BLOCK (1UL) - - typedef unsigned long ck_rv_t; - - typedef ck_rv_t(*ck_notify_t) (ck_session_handle_t session, - ck_notification_t event, - void *application); - -/* Forward reference. */ - struct ck_function_list; - -#define _CK_DECLARE_FUNCTION(name, args) \ -typedef ck_rv_t (*CK_ ## name) args; \ -ck_rv_t CK_SPEC name args - - _CK_DECLARE_FUNCTION(C_Initialize, (void *init_args)); - _CK_DECLARE_FUNCTION(C_Finalize, (void *reserved)); - _CK_DECLARE_FUNCTION(C_GetInfo, (struct ck_info * info)); - _CK_DECLARE_FUNCTION(C_GetFunctionList, - (struct ck_function_list ** function_list)); - - _CK_DECLARE_FUNCTION(C_GetSlotList, - (unsigned char token_present, - ck_slot_id_t * slot_list, unsigned long *count)); - _CK_DECLARE_FUNCTION(C_GetSlotInfo, - (ck_slot_id_t slot_id, - struct ck_slot_info * info)); - _CK_DECLARE_FUNCTION(C_GetTokenInfo, - (ck_slot_id_t slot_id, - struct ck_token_info * info)); - _CK_DECLARE_FUNCTION(C_WaitForSlotEvent, - (ck_flags_t flags, ck_slot_id_t * slot, - void *reserved)); - _CK_DECLARE_FUNCTION(C_GetMechanismList, - (ck_slot_id_t slot_id, - ck_mechanism_type_t * mechanism_list, - unsigned long *count)); - _CK_DECLARE_FUNCTION(C_GetMechanismInfo, - (ck_slot_id_t slot_id, ck_mechanism_type_t type, - struct ck_mechanism_info * info)); - _CK_DECLARE_FUNCTION(C_InitToken, - (ck_slot_id_t slot_id, unsigned char *pin, - unsigned long pin_len, unsigned char *label)); - _CK_DECLARE_FUNCTION(C_InitPIN, - (ck_session_handle_t session, unsigned char *pin, - unsigned long pin_len)); - _CK_DECLARE_FUNCTION(C_SetPIN, - (ck_session_handle_t session, - unsigned char *old_pin, unsigned long old_len, - unsigned char *new_pin, unsigned long new_len)); - - _CK_DECLARE_FUNCTION(C_OpenSession, - (ck_slot_id_t slot_id, ck_flags_t flags, - void *application, ck_notify_t notify, - ck_session_handle_t * session)); - _CK_DECLARE_FUNCTION(C_CloseSession, (ck_session_handle_t session)); - _CK_DECLARE_FUNCTION(C_CloseAllSessions, (ck_slot_id_t slot_id)); - _CK_DECLARE_FUNCTION(C_GetSessionInfo, - (ck_session_handle_t session, - struct ck_session_info * info)); - _CK_DECLARE_FUNCTION(C_GetOperationState, - (ck_session_handle_t session, - unsigned char *operation_state, - unsigned long *operation_state_len)); - _CK_DECLARE_FUNCTION(C_SetOperationState, - (ck_session_handle_t session, - unsigned char *operation_state, - unsigned long operation_state_len, - ck_object_handle_t encryption_key, - ck_object_handle_t authentiation_key)); - _CK_DECLARE_FUNCTION(C_Login, - (ck_session_handle_t session, - ck_user_type_t user_type, unsigned char *pin, - unsigned long pin_len)); - _CK_DECLARE_FUNCTION(C_Logout, (ck_session_handle_t session)); - - _CK_DECLARE_FUNCTION(C_CreateObject, - (ck_session_handle_t session, - struct ck_attribute * templ, - unsigned long count, - ck_object_handle_t * object)); - _CK_DECLARE_FUNCTION(C_CopyObject, - (ck_session_handle_t session, - ck_object_handle_t object, - struct ck_attribute * templ, unsigned long count, - ck_object_handle_t * new_object)); - _CK_DECLARE_FUNCTION(C_DestroyObject, - (ck_session_handle_t session, - ck_object_handle_t object)); - _CK_DECLARE_FUNCTION(C_GetObjectSize, - (ck_session_handle_t session, - ck_object_handle_t object, unsigned long *size)); - _CK_DECLARE_FUNCTION(C_GetAttributeValue, - (ck_session_handle_t session, - ck_object_handle_t object, - struct ck_attribute * templ, - unsigned long count)); - _CK_DECLARE_FUNCTION(C_SetAttributeValue, - (ck_session_handle_t session, - ck_object_handle_t object, - struct ck_attribute * templ, - unsigned long count)); - _CK_DECLARE_FUNCTION(C_FindObjectsInit, - (ck_session_handle_t session, - struct ck_attribute * templ, - unsigned long count)); - _CK_DECLARE_FUNCTION(C_FindObjects, - (ck_session_handle_t session, - ck_object_handle_t * object, - unsigned long max_object_count, - unsigned long *object_count)); - _CK_DECLARE_FUNCTION(C_FindObjectsFinal, - (ck_session_handle_t session)); - - _CK_DECLARE_FUNCTION(C_EncryptInit, - (ck_session_handle_t session, - struct ck_mechanism * mechanism, - ck_object_handle_t key)); - _CK_DECLARE_FUNCTION(C_Encrypt, - (ck_session_handle_t session, - unsigned char *data, unsigned long data_len, - unsigned char *encrypted_data, - unsigned long *encrypted_data_len)); - _CK_DECLARE_FUNCTION(C_EncryptUpdate, - (ck_session_handle_t session, - unsigned char *part, unsigned long part_len, - unsigned char *encrypted_part, - unsigned long *encrypted_part_len)); - _CK_DECLARE_FUNCTION(C_EncryptFinal, - (ck_session_handle_t session, - unsigned char *last_encrypted_part, - unsigned long *last_encrypted_part_len)); - - _CK_DECLARE_FUNCTION(C_DecryptInit, - (ck_session_handle_t session, - struct ck_mechanism * mechanism, - ck_object_handle_t key)); - _CK_DECLARE_FUNCTION(C_Decrypt, - (ck_session_handle_t session, - unsigned char *encrypted_data, - unsigned long encrypted_data_len, - unsigned char *data, unsigned long *data_len)); - _CK_DECLARE_FUNCTION(C_DecryptUpdate, - (ck_session_handle_t session, - unsigned char *encrypted_part, - unsigned long encrypted_part_len, - unsigned char *part, unsigned long *part_len)); - _CK_DECLARE_FUNCTION(C_DecryptFinal, - (ck_session_handle_t session, - unsigned char *last_part, - unsigned long *last_part_len)); - - _CK_DECLARE_FUNCTION(C_DigestInit, - (ck_session_handle_t session, - struct ck_mechanism * mechanism)); - _CK_DECLARE_FUNCTION(C_Digest, - (ck_session_handle_t session, - unsigned char *data, unsigned long data_len, - unsigned char *digest, - unsigned long *digest_len)); - _CK_DECLARE_FUNCTION(C_DigestUpdate, - (ck_session_handle_t session, - unsigned char *part, unsigned long part_len)); - _CK_DECLARE_FUNCTION(C_DigestKey, - (ck_session_handle_t session, - ck_object_handle_t key)); - _CK_DECLARE_FUNCTION(C_DigestFinal, - (ck_session_handle_t session, - unsigned char *digest, - unsigned long *digest_len)); - - _CK_DECLARE_FUNCTION(C_SignInit, - (ck_session_handle_t session, - struct ck_mechanism * mechanism, - ck_object_handle_t key)); - _CK_DECLARE_FUNCTION(C_Sign, - (ck_session_handle_t session, - unsigned char *data, unsigned long data_len, - unsigned char *signature, - unsigned long *signature_len)); - _CK_DECLARE_FUNCTION(C_SignUpdate, - (ck_session_handle_t session, - unsigned char *part, unsigned long part_len)); - _CK_DECLARE_FUNCTION(C_SignFinal, - (ck_session_handle_t session, - unsigned char *signature, - unsigned long *signature_len)); - _CK_DECLARE_FUNCTION(C_SignRecoverInit, - (ck_session_handle_t session, - struct ck_mechanism * mechanism, - ck_object_handle_t key)); - _CK_DECLARE_FUNCTION(C_SignRecover, - (ck_session_handle_t session, - unsigned char *data, unsigned long data_len, - unsigned char *signature, - unsigned long *signature_len)); - - _CK_DECLARE_FUNCTION(C_VerifyInit, - (ck_session_handle_t session, - struct ck_mechanism * mechanism, - ck_object_handle_t key)); - _CK_DECLARE_FUNCTION(C_Verify, - (ck_session_handle_t session, - unsigned char *data, unsigned long data_len, - unsigned char *signature, - unsigned long signature_len)); - _CK_DECLARE_FUNCTION(C_VerifyUpdate, - (ck_session_handle_t session, - unsigned char *part, unsigned long part_len)); - _CK_DECLARE_FUNCTION(C_VerifyFinal, - (ck_session_handle_t session, - unsigned char *signature, - unsigned long signature_len)); - _CK_DECLARE_FUNCTION(C_VerifyRecoverInit, - (ck_session_handle_t session, - struct ck_mechanism * mechanism, - ck_object_handle_t key)); - _CK_DECLARE_FUNCTION(C_VerifyRecover, - (ck_session_handle_t session, - unsigned char *signature, - unsigned long signature_len, - unsigned char *data, unsigned long *data_len)); - - _CK_DECLARE_FUNCTION(C_DigestEncryptUpdate, - (ck_session_handle_t session, - unsigned char *part, unsigned long part_len, - unsigned char *encrypted_part, - unsigned long *encrypted_part_len)); - _CK_DECLARE_FUNCTION(C_DecryptDigestUpdate, - (ck_session_handle_t session, - unsigned char *encrypted_part, - unsigned long encrypted_part_len, - unsigned char *part, unsigned long *part_len)); - _CK_DECLARE_FUNCTION(C_SignEncryptUpdate, - (ck_session_handle_t session, - unsigned char *part, unsigned long part_len, - unsigned char *encrypted_part, - unsigned long *encrypted_part_len)); - _CK_DECLARE_FUNCTION(C_DecryptVerifyUpdate, - (ck_session_handle_t session, - unsigned char *encrypted_part, - unsigned long encrypted_part_len, - unsigned char *part, unsigned long *part_len)); - - _CK_DECLARE_FUNCTION(C_GenerateKey, - (ck_session_handle_t session, - struct ck_mechanism * mechanism, - struct ck_attribute * templ, - unsigned long count, ck_object_handle_t * key)); - _CK_DECLARE_FUNCTION(C_GenerateKeyPair, - (ck_session_handle_t session, - struct ck_mechanism * mechanism, - struct ck_attribute * public_key_template, - unsigned long public_key_attribute_count, - struct ck_attribute * private_key_template, - unsigned long private_key_attribute_count, - ck_object_handle_t * public_key, - ck_object_handle_t * private_key)); - _CK_DECLARE_FUNCTION(C_WrapKey, - (ck_session_handle_t session, - struct ck_mechanism * mechanism, - ck_object_handle_t wrapping_key, - ck_object_handle_t key, - unsigned char *wrapped_key, - unsigned long *wrapped_key_len)); - _CK_DECLARE_FUNCTION(C_UnwrapKey, - (ck_session_handle_t session, - struct ck_mechanism * mechanism, - ck_object_handle_t unwrapping_key, - unsigned char *wrapped_key, - unsigned long wrapped_key_len, - struct ck_attribute * templ, - unsigned long attribute_count, - ck_object_handle_t * key)); - _CK_DECLARE_FUNCTION(C_DeriveKey, - (ck_session_handle_t session, - struct ck_mechanism * mechanism, - ck_object_handle_t base_key, - struct ck_attribute * templ, - unsigned long attribute_count, - ck_object_handle_t * key)); - - _CK_DECLARE_FUNCTION(C_SeedRandom, - (ck_session_handle_t session, unsigned char *seed, - unsigned long seed_len)); - _CK_DECLARE_FUNCTION(C_GenerateRandom, - (ck_session_handle_t session, - unsigned char *random_data, - unsigned long random_len)); - - _CK_DECLARE_FUNCTION(C_GetFunctionStatus, - (ck_session_handle_t session)); - _CK_DECLARE_FUNCTION(C_CancelFunction, (ck_session_handle_t session)); - - struct ck_function_list { - struct ck_version version; - CK_C_Initialize C_Initialize; - CK_C_Finalize C_Finalize; - CK_C_GetInfo C_GetInfo; - CK_C_GetFunctionList C_GetFunctionList; - CK_C_GetSlotList C_GetSlotList; - CK_C_GetSlotInfo C_GetSlotInfo; - CK_C_GetTokenInfo C_GetTokenInfo; - CK_C_GetMechanismList C_GetMechanismList; - CK_C_GetMechanismInfo C_GetMechanismInfo; - CK_C_InitToken C_InitToken; - CK_C_InitPIN C_InitPIN; - CK_C_SetPIN C_SetPIN; - CK_C_OpenSession C_OpenSession; - CK_C_CloseSession C_CloseSession; - CK_C_CloseAllSessions C_CloseAllSessions; - CK_C_GetSessionInfo C_GetSessionInfo; - CK_C_GetOperationState C_GetOperationState; - CK_C_SetOperationState C_SetOperationState; - CK_C_Login C_Login; - CK_C_Logout C_Logout; - CK_C_CreateObject C_CreateObject; - CK_C_CopyObject C_CopyObject; - CK_C_DestroyObject C_DestroyObject; - CK_C_GetObjectSize C_GetObjectSize; - CK_C_GetAttributeValue C_GetAttributeValue; - CK_C_SetAttributeValue C_SetAttributeValue; - CK_C_FindObjectsInit C_FindObjectsInit; - CK_C_FindObjects C_FindObjects; - CK_C_FindObjectsFinal C_FindObjectsFinal; - CK_C_EncryptInit C_EncryptInit; - CK_C_Encrypt C_Encrypt; - CK_C_EncryptUpdate C_EncryptUpdate; - CK_C_EncryptFinal C_EncryptFinal; - CK_C_DecryptInit C_DecryptInit; - CK_C_Decrypt C_Decrypt; - CK_C_DecryptUpdate C_DecryptUpdate; - CK_C_DecryptFinal C_DecryptFinal; - CK_C_DigestInit C_DigestInit; - CK_C_Digest C_Digest; - CK_C_DigestUpdate C_DigestUpdate; - CK_C_DigestKey C_DigestKey; - CK_C_DigestFinal C_DigestFinal; - CK_C_SignInit C_SignInit; - CK_C_Sign C_Sign; - CK_C_SignUpdate C_SignUpdate; - CK_C_SignFinal C_SignFinal; - CK_C_SignRecoverInit C_SignRecoverInit; - CK_C_SignRecover C_SignRecover; - CK_C_VerifyInit C_VerifyInit; - CK_C_Verify C_Verify; - CK_C_VerifyUpdate C_VerifyUpdate; - CK_C_VerifyFinal C_VerifyFinal; - CK_C_VerifyRecoverInit C_VerifyRecoverInit; - CK_C_VerifyRecover C_VerifyRecover; - CK_C_DigestEncryptUpdate C_DigestEncryptUpdate; - CK_C_DecryptDigestUpdate C_DecryptDigestUpdate; - CK_C_SignEncryptUpdate C_SignEncryptUpdate; - CK_C_DecryptVerifyUpdate C_DecryptVerifyUpdate; - CK_C_GenerateKey C_GenerateKey; - CK_C_GenerateKeyPair C_GenerateKeyPair; - CK_C_WrapKey C_WrapKey; - CK_C_UnwrapKey C_UnwrapKey; - CK_C_DeriveKey C_DeriveKey; - CK_C_SeedRandom C_SeedRandom; - CK_C_GenerateRandom C_GenerateRandom; - CK_C_GetFunctionStatus C_GetFunctionStatus; - CK_C_CancelFunction C_CancelFunction; - CK_C_WaitForSlotEvent C_WaitForSlotEvent; - }; - - typedef ck_rv_t(*ck_createmutex_t) (void **mutex); - typedef ck_rv_t(*ck_destroymutex_t) (void *mutex); - typedef ck_rv_t(*ck_lockmutex_t) (void *mutex); - typedef ck_rv_t(*ck_unlockmutex_t) (void *mutex); - - struct ck_c_initialize_args { - ck_createmutex_t create_mutex; - ck_destroymutex_t destroy_mutex; - ck_lockmutex_t lock_mutex; - ck_unlockmutex_t unlock_mutex; - ck_flags_t flags; - void *reserved; - }; - -#define CKF_LIBRARY_CANT_CREATE_OS_THREADS (1UL << 0) -#define CKF_OS_LOCKING_OK (1UL << 1) - -#define CKR_OK (0UL) -#define CKR_CANCEL (1UL) -#define CKR_HOST_MEMORY (2UL) -#define CKR_SLOT_ID_INVALID (3UL) -#define CKR_GENERAL_ERROR (5UL) -#define CKR_FUNCTION_FAILED (6UL) -#define CKR_ARGUMENTS_BAD (7UL) -#define CKR_NO_EVENT (8UL) -#define CKR_NEED_TO_CREATE_THREADS (9UL) -#define CKR_CANT_LOCK (0xaUL) -#define CKR_ATTRIBUTE_READ_ONLY (0x10UL) -#define CKR_ATTRIBUTE_SENSITIVE (0x11UL) -#define CKR_ATTRIBUTE_TYPE_INVALID (0x12UL) -#define CKR_ATTRIBUTE_VALUE_INVALID (0x13UL) -#define CKR_DATA_INVALID (0x20UL) -#define CKR_DATA_LEN_RANGE (0x21UL) -#define CKR_DEVICE_ERROR (0x30UL) -#define CKR_DEVICE_MEMORY (0x31UL) -#define CKR_DEVICE_REMOVED (0x32UL) -#define CKR_ENCRYPTED_DATA_INVALID (0x40UL) -#define CKR_ENCRYPTED_DATA_LEN_RANGE (0x41UL) -#define CKR_FUNCTION_CANCELED (0x50UL) -#define CKR_FUNCTION_NOT_PARALLEL (0x51UL) -#define CKR_FUNCTION_NOT_SUPPORTED (0x54UL) -#define CKR_KEY_HANDLE_INVALID (0x60UL) -#define CKR_KEY_SIZE_RANGE (0x62UL) -#define CKR_KEY_TYPE_INCONSISTENT (0x63UL) -#define CKR_KEY_NOT_NEEDED (0x64UL) -#define CKR_KEY_CHANGED (0x65UL) -#define CKR_KEY_NEEDED (0x66UL) -#define CKR_KEY_INDIGESTIBLE (0x67UL) -#define CKR_KEY_FUNCTION_NOT_PERMITTED (0x68UL) -#define CKR_KEY_NOT_WRAPPABLE (0x69UL) -#define CKR_KEY_UNEXTRACTABLE (0x6aUL) -#define CKR_MECHANISM_INVALID (0x70UL) -#define CKR_MECHANISM_PARAM_INVALID (0x71UL) -#define CKR_OBJECT_HANDLE_INVALID (0x82UL) -#define CKR_OPERATION_ACTIVE (0x90UL) -#define CKR_OPERATION_NOT_INITIALIZED (0x91UL) -#define CKR_PIN_INCORRECT (0xa0UL) -#define CKR_PIN_INVALID (0xa1UL) -#define CKR_PIN_LEN_RANGE (0xa2UL) -#define CKR_PIN_EXPIRED (0xa3UL) -#define CKR_PIN_LOCKED (0xa4UL) -#define CKR_SESSION_CLOSED (0xb0UL) -#define CKR_SESSION_COUNT (0xb1UL) -#define CKR_SESSION_HANDLE_INVALID (0xb3UL) -#define CKR_SESSION_PARALLEL_NOT_SUPPORTED (0xb4UL) -#define CKR_SESSION_READ_ONLY (0xb5UL) -#define CKR_SESSION_EXISTS (0xb6UL) -#define CKR_SESSION_READ_ONLY_EXISTS (0xb7UL) -#define CKR_SESSION_READ_WRITE_SO_EXISTS (0xb8UL) -#define CKR_SIGNATURE_INVALID (0xc0UL) -#define CKR_SIGNATURE_LEN_RANGE (0xc1UL) -#define CKR_TEMPLATE_INCOMPLETE (0xd0UL) -#define CKR_TEMPLATE_INCONSISTENT (0xd1UL) -#define CKR_TOKEN_NOT_PRESENT (0xe0UL) -#define CKR_TOKEN_NOT_RECOGNIZED (0xe1UL) -#define CKR_TOKEN_WRITE_PROTECTED (0xe2UL) -#define CKR_UNWRAPPING_KEY_HANDLE_INVALID (0xf0UL) -#define CKR_UNWRAPPING_KEY_SIZE_RANGE (0xf1UL) -#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT (0xf2UL) -#define CKR_USER_ALREADY_LOGGED_IN (0x100UL) -#define CKR_USER_NOT_LOGGED_IN (0x101UL) -#define CKR_USER_PIN_NOT_INITIALIZED (0x102UL) -#define CKR_USER_TYPE_INVALID (0x103UL) -#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN (0x104UL) -#define CKR_USER_TOO_MANY_TYPES (0x105UL) -#define CKR_WRAPPED_KEY_INVALID (0x110UL) -#define CKR_WRAPPED_KEY_LEN_RANGE (0x112UL) -#define CKR_WRAPPING_KEY_HANDLE_INVALID (0x113UL) -#define CKR_WRAPPING_KEY_SIZE_RANGE (0x114UL) -#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT (0x115UL) -#define CKR_RANDOM_SEED_NOT_SUPPORTED (0x120UL) -#define CKR_RANDOM_NO_RNG (0x121UL) -#define CKR_DOMAIN_PARAMS_INVALID (0x130UL) -#define CKR_BUFFER_TOO_SMALL (0x150UL) -#define CKR_SAVED_STATE_INVALID (0x160UL) -#define CKR_INFORMATION_SENSITIVE (0x170UL) -#define CKR_STATE_UNSAVEABLE (0x180UL) -#define CKR_CRYPTOKI_NOT_INITIALIZED (0x190UL) -#define CKR_CRYPTOKI_ALREADY_INITIALIZED (0x191UL) -#define CKR_MUTEX_BAD (0x1a0UL) -#define CKR_MUTEX_NOT_LOCKED (0x1a1UL) -#define CKR_FUNCTION_REJECTED (0x200UL) -#define CKR_VENDOR_DEFINED ((unsigned long) (1UL << 31)) - -/* Compatibility layer. */ - -#ifdef CRYPTOKI_COMPAT - -#undef CK_DEFINE_FUNCTION -#define CK_DEFINE_FUNCTION(retval, name) retval CK_SPEC name - -/* For NULL. */ -#include - - typedef unsigned char CK_BYTE; - typedef unsigned char CK_CHAR; - typedef unsigned char CK_UTF8CHAR; - typedef unsigned char CK_BBOOL; - typedef unsigned long int CK_ULONG; - typedef long int CK_LONG; - typedef CK_BYTE *CK_BYTE_PTR; - typedef CK_CHAR *CK_CHAR_PTR; - typedef CK_UTF8CHAR *CK_UTF8CHAR_PTR; - typedef CK_ULONG *CK_ULONG_PTR; - typedef void *CK_VOID_PTR; - typedef void **CK_VOID_PTR_PTR; -#define CK_FALSE 0 -#define CK_TRUE 1 -#ifndef CK_DISABLE_TRUE_FALSE -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE 1 -#endif -#endif - - typedef struct ck_version CK_VERSION; - typedef struct ck_version *CK_VERSION_PTR; - - typedef struct ck_info CK_INFO; - typedef struct ck_info *CK_INFO_PTR; - - typedef ck_slot_id_t *CK_SLOT_ID_PTR; - - typedef struct ck_slot_info CK_SLOT_INFO; - typedef struct ck_slot_info *CK_SLOT_INFO_PTR; - - typedef struct ck_token_info CK_TOKEN_INFO; - typedef struct ck_token_info *CK_TOKEN_INFO_PTR; - - typedef ck_session_handle_t *CK_SESSION_HANDLE_PTR; - - typedef struct ck_session_info CK_SESSION_INFO; - typedef struct ck_session_info *CK_SESSION_INFO_PTR; - - typedef ck_object_handle_t *CK_OBJECT_HANDLE_PTR; - - typedef ck_object_class_t *CK_OBJECT_CLASS_PTR; - - typedef struct ck_attribute CK_ATTRIBUTE; - typedef struct ck_attribute *CK_ATTRIBUTE_PTR; - - typedef struct ck_date CK_DATE; - typedef struct ck_date *CK_DATE_PTR; - - typedef ck_mechanism_type_t *CK_MECHANISM_TYPE_PTR; - - typedef struct ck_mechanism CK_MECHANISM; - typedef struct ck_mechanism *CK_MECHANISM_PTR; - - typedef struct ck_mechanism_info CK_MECHANISM_INFO; - typedef struct ck_mechanism_info *CK_MECHANISM_INFO_PTR; - - typedef struct ck_function_list CK_FUNCTION_LIST; - typedef struct ck_function_list *CK_FUNCTION_LIST_PTR; - typedef struct ck_function_list **CK_FUNCTION_LIST_PTR_PTR; - - typedef struct ck_c_initialize_args CK_C_INITIALIZE_ARGS; - typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR; - -#define NULL_PTR NULL - -/* Delete the helper macros defined at the top of the file. */ -#undef ck_flags_t -#undef ck_version - -#undef ck_info -#undef cryptoki_version -#undef manufacturer_id -#undef library_description -#undef library_version - -#undef ck_notification_t -#undef ck_slot_id_t - -#undef ck_slot_info -#undef slot_description -#undef hardware_version -#undef firmware_version - -#undef ck_token_info -#undef serial_number -#undef max_session_count -#undef session_count -#undef max_rw_session_count -#undef rw_session_count -#undef max_pin_len -#undef min_pin_len -#undef total_public_memory -#undef free_public_memory -#undef total_private_memory -#undef free_private_memory -#undef utc_time - -#undef ck_session_handle_t -#undef ck_user_type_t -#undef ck_state_t - -#undef ck_session_info -#undef slot_id -#undef device_error - -#undef ck_object_handle_t -#undef ck_object_class_t -#undef ck_hw_feature_type_t -#undef ck_key_type_t -#undef ck_certificate_type_t -#undef ck_attribute_type_t - -#undef ck_attribute -#undef value -#undef value_len - -#undef ck_date - -#undef ck_mechanism_type_t - -#undef ck_mechanism -#undef parameter -#undef parameter_len - -#undef ck_mechanism_info -#undef min_key_size -#undef max_key_size - -#undef ck_rv_t -#undef ck_notify_t - -#undef ck_function_list - -#undef ck_createmutex_t -#undef ck_destroymutex_t -#undef ck_lockmutex_t -#undef ck_unlockmutex_t - -#undef ck_c_initialize_args -#undef create_mutex -#undef destroy_mutex -#undef lock_mutex -#undef unlock_mutex -#undef reserved - -#endif /* CRYPTOKI_COMPAT */ - -/* System dependencies. */ -#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32) -#pragma pack(pop, cryptoki) -#endif - -#if defined(__cplusplus) -} -#endif -#endif /* PKCS11_H */ diff --git a/ext/pkcs11-proxy/pkcs11/pkcs11g.h b/ext/pkcs11-proxy/pkcs11/pkcs11g.h deleted file mode 100644 index 1252182c0..000000000 --- a/ext/pkcs11-proxy/pkcs11/pkcs11g.h +++ /dev/null @@ -1,100 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* pkcs11g.h - GNOME extensions to PKCS#11 - - Copyright (C) 2008, Stef Walter - - The Gnome Keyring Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The Gnome Keyring 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the Gnome Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Stef Walter -*/ - -#ifndef PKCS11G_H -#define PKCS11G_H - -#include "pkcs11.h" - -#define CKA_GNOME (CKA_VENDOR_DEFINED | 0x474E4D45 /* GNME */ ) -#define CKO_GNOME (CKO_VENDOR_DEFINED | 0x474E4D45 /* GNME */ ) - -/* ------------------------------------------------------------------- - * OBJECT AUTHENTICATION - */ - -#define CKA_GNOME_AUTH_CACHE (CKA_GNOME + 300) -#define CKV_GNOME_AUTH_CACHE_NEVER ((CK_ULONG)-1) -#define CKV_GNOME_AUTH_CACHE_SESSION 0x40000000 -#define CKV_GNOME_AUTH_CACHE_UNLIMITED 0x80000000 - -#define CKA_GNOME_AUTH_CACHED (CKA_GNOME + 301) - -/* ------------------------------------------------------------------- - * OBJECT UNIQUE IDENTIFIER - */ - -/* A string unique among all objects on a given machine */ -#define CKA_GNOME_UNIQUE (CKA_GNOME + 350) - -/* ------------------------------------------------------------------- - * PURPOSES - */ - -/* - * Whether the key or certificate is restricted to a set of - * purposes (ie: enhanced usages). - * - * CK_BBOOL - * - * - When CK_TRUE see CKA_PURPOSE_OIDS for the set of purposes. - * - When CK_FALSE then is not restricted to any specific purpose. - */ -#define CKA_GNOME_PURPOSE_RESTRICTED (CKA_GNOME + 12) - -/* - * The available purposes that a certificate or key can be - * used for. - * - * CK_STRING - * - * - This is only relevant if CKA_PURPOSE_RESTRICTED is CK_TRUE. - * - Use CKA_TRUSTED and CKA_CERTIFICATE_CATEGORY to validate whether - * usage of the certificate for these purposes is directly or - * indirectly trusted by the user. - * - The returned string is a space delemited set of OIDs. - * - When an empty string is returned then no purposes are valid. - */ -#define CKA_GNOME_PURPOSE_OIDS (CKA_GNOME + 11) - -/* - * The key or certificate can be used for the purpose - * indicated - * - * CK_BBOOL - * - * - These are shortcuts to using CKA_PURPOSE_OIDS - * - Use CKA_TRUSTED and CKA_CERTIFICATE_CATEGORY to validate whether - * the certificate is directly or indirectly trusted by the user. - */ -#define CKA_GNOME_PURPOSE_SSH_AUTH (CKA_GNOME + 101) -#define CKA_GNOME_PURPOSE_SERVER_AUTH (CKA_GNOME + 102) -#define CKA_GNOME_PURPOSE_CLIENT_AUTH (CKA_GNOME + 103) -#define CKA_GNOME_PURPOSE_CODE_SIGNING (CKA_GNOME + 104) -#define CKA_GNOME_PURPOSE_EMAIL_PROTECTION (CKA_GNOME + 105) -#define CKA_GNOME_PURPOSE_IPSEC_END_SYSTEM (CKA_GNOME + 106) -#define CKA_GNOME_PURPOSE_IPSEC_TUNNEL (CKA_GNOME + 107) -#define CKA_GNOME_PURPOSE_IPSEC_USER (CKA_GNOME + 108) -#define CKA_GNOME_PURPOSE_TIME_STAMPING (CKA_GNOME + 109) - -#endif /* PKCS11G_H */ diff --git a/ext/pkcs11-proxy/pkcs11/pkcs11i.h b/ext/pkcs11-proxy/pkcs11/pkcs11i.h deleted file mode 100644 index ce15393f3..000000000 --- a/ext/pkcs11-proxy/pkcs11/pkcs11i.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* pkcs11g.h - GNOME internal definitions to PKCS#11 - - Copyright (C) 2008, Stef Walter - - The Gnome Keyring Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The Gnome Keyring 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the Gnome Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - Author: Stef Walter -*/ - -#ifndef PKCS11I_H -#define PKCS11I_H - -#include "pkcs11.h" -#include "pkcs11g.h" - -/* Signifies that nobody is logged in */ -#define CKU_NONE G_MAXULONG - -/* ---------------------------------------------------------------------- - * APARTMENT SLOTS - * - * The lower 10 bits of the CK_SLOT_ID are used as the actual slot identifier, - * and the remainder are used as application identifiers. - * - * This enables a single loaded module to serve multiple applications - * concurrently. The caller of a module should check the - * CKF_GNOME_VIRTUAL_SLOTS flag before using this functionality. - */ - -/* Flag for CK_INFO when virtual slots are supported */ -#define CKF_GNOME_APPARTMENTS 0x40000000 - -/* Get an actual slot id from a virtual slot */ -#define CK_GNOME_APPARTMENT_SLOT(virt) ((virt) & 0x000003FF) - -/* Get an app id from a virtual slot */ -#define CK_GNOME_APPARTMENT_APP(virt) ((virt) >> 10) - -/* Is the app id valid for use in a virtual slot? */ -#define CK_GNOME_APPARTMENT_IS_APP(app) ((app) < (((CK_ULONG)-1) >> 10)) - -/* Build a virtual slot from an actual slot id, and an app id */ -#define CK_GNOME_MAKE_APPARTMENT(slot, app) (((slot) & 0x000003FF) | ((app) << 10)) - -/* ------------------------------------------------------------------- - * LIMITED HANDLES - * - * The upper 10 bits of a CK_SESSION_HANDLE and CK_OBJECT_HANDLE are - * never used by Gnome Keyring PKCS#11 modules. These bits are used - * for tracking purposes when combining modules into a single module. - */ - -#define CK_GNOME_MAX_SLOT (0x000003FF) -#define CK_GNOME_MAX_APP (((CK_ULONG)-1) >> 10) -#define CK_GNOME_MAX_HANDLE (((CK_ULONG)-1) >> 10) - -/* ------------------------------------------------------------------- - * OBJECT HASH - */ - -#define CKA_GNOME_INTERNAL_SHA1 (CKA_GNOME + 1000) - -#endif /* PKCS11I_H */ diff --git a/ext/pkcs11-proxy/pkcs11/pkcs11n.h b/ext/pkcs11-proxy/pkcs11/pkcs11n.h deleted file mode 100644 index 39bb59f4f..000000000 --- a/ext/pkcs11-proxy/pkcs11/pkcs11n.h +++ /dev/null @@ -1,221 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Dr Stephen Henson - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef _PKCS11N_H_ -#define _PKCS11N_H_ - -#ifdef DEBUG -static const char CKT_CVS_ID[] = - "@(#) $RCSfile: pkcs11n.h,v $ $Revision: 1.15 $ $Date: 2005/09/28 17:12:17 $"; - -#endif /* DEBUG */ - -/* - * pkcs11n.h - * - * This file contains the NSS-specific type definitions for Cryptoki - * (PKCS#11). - */ - -/* - * NSSCK_VENDOR_NETSCAPE - * - * Cryptoki reserves the high half of all the number spaces for - * vendor-defined use. I'd like to keep all of our Netscape- - * specific values together, but not in the oh-so-obvious - * 0x80000001, 0x80000002, etc. area. So I've picked an offset, - * and constructed values for the beginnings of our spaces. - * - * Note that some "historical" Netscape values don't fall within - * this range. - */ -#define NSSCK_VENDOR_NETSCAPE 0x4E534350 /* NSCP */ - -/* - * Netscape-defined object classes - * - */ -#define CKO_NETSCAPE (CKO_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) - -#define CKO_NETSCAPE_CRL (CKO_NETSCAPE + 1) -#define CKO_NETSCAPE_SMIME (CKO_NETSCAPE + 2) -#define CKO_NETSCAPE_TRUST (CKO_NETSCAPE + 3) -#define CKO_NETSCAPE_BUILTIN_ROOT_LIST (CKO_NETSCAPE + 4) -#define CKO_NETSCAPE_NEWSLOT (CKO_NETSCAPE + 5) -#define CKO_NETSCAPE_DELSLOT (CKO_NETSCAPE + 6) - -/* - * Netscape-defined key types - * - */ -#define CKK_NETSCAPE (CKK_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) - -#define CKK_NETSCAPE_PKCS8 (CKK_NETSCAPE + 1) -/* - * Netscape-defined certificate types - * - */ -#define CKC_NETSCAPE (CKC_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) - -/* - * Netscape-defined object attributes - * - */ -#define CKA_NETSCAPE (CKA_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) - -#define CKA_NETSCAPE_URL (CKA_NETSCAPE + 1) -#define CKA_NETSCAPE_EMAIL (CKA_NETSCAPE + 2) -#define CKA_NETSCAPE_SMIME_INFO (CKA_NETSCAPE + 3) -#define CKA_NETSCAPE_SMIME_TIMESTAMP (CKA_NETSCAPE + 4) -#define CKA_NETSCAPE_PKCS8_SALT (CKA_NETSCAPE + 5) -#define CKA_NETSCAPE_PASSWORD_CHECK (CKA_NETSCAPE + 6) -#define CKA_NETSCAPE_EXPIRES (CKA_NETSCAPE + 7) -#define CKA_NETSCAPE_KRL (CKA_NETSCAPE + 8) - -#define CKA_NETSCAPE_PQG_COUNTER (CKA_NETSCAPE + 20) -#define CKA_NETSCAPE_PQG_SEED (CKA_NETSCAPE + 21) -#define CKA_NETSCAPE_PQG_H (CKA_NETSCAPE + 22) -#define CKA_NETSCAPE_PQG_SEED_BITS (CKA_NETSCAPE + 23) -#define CKA_NETSCAPE_MODULE_SPEC (CKA_NETSCAPE + 24) - -/* - * Trust attributes: - * - * If trust goes standard, these probably will too. So I'll - * put them all in one place. - */ - -#define CKA_TRUST (CKA_NETSCAPE + 0x2000) - -/* "Usage" key information */ -#define CKA_TRUST_DIGITAL_SIGNATURE (CKA_TRUST + 1) -#define CKA_TRUST_NON_REPUDIATION (CKA_TRUST + 2) -#define CKA_TRUST_KEY_ENCIPHERMENT (CKA_TRUST + 3) -#define CKA_TRUST_DATA_ENCIPHERMENT (CKA_TRUST + 4) -#define CKA_TRUST_KEY_AGREEMENT (CKA_TRUST + 5) -#define CKA_TRUST_KEY_CERT_SIGN (CKA_TRUST + 6) -#define CKA_TRUST_CRL_SIGN (CKA_TRUST + 7) - -/* "Purpose" trust information */ -#define CKA_TRUST_SERVER_AUTH (CKA_TRUST + 8) -#define CKA_TRUST_CLIENT_AUTH (CKA_TRUST + 9) -#define CKA_TRUST_CODE_SIGNING (CKA_TRUST + 10) -#define CKA_TRUST_EMAIL_PROTECTION (CKA_TRUST + 11) -#define CKA_TRUST_IPSEC_END_SYSTEM (CKA_TRUST + 12) -#define CKA_TRUST_IPSEC_TUNNEL (CKA_TRUST + 13) -#define CKA_TRUST_IPSEC_USER (CKA_TRUST + 14) -#define CKA_TRUST_TIME_STAMPING (CKA_TRUST + 15) -#define CKA_TRUST_STEP_UP_APPROVED (CKA_TRUST + 16) - -#define CKA_CERT_SHA1_HASH (CKA_TRUST + 100) -#define CKA_CERT_MD5_HASH (CKA_TRUST + 101) - -/* Netscape trust stuff */ -/* XXX fgmr new ones here-- step-up, etc. */ - -/* HISTORICAL: define used to pass in the database key for DSA private keys */ -#define CKA_NETSCAPE_DB 0xD5A0DB00L -#define CKA_NETSCAPE_TRUST 0x80000001L - -/* - * Netscape-defined crypto mechanisms - * - */ -#define CKM_NETSCAPE (CKM_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) - -#define CKM_NETSCAPE_AES_KEY_WRAP (CKM_NETSCAPE + 1) -#define CKM_NETSCAPE_AES_KEY_WRAP_PAD (CKM_NETSCAPE + 2) - -/* - * HISTORICAL: - * Do not attempt to use these. They are only used by NETSCAPE's internal - * PKCS #11 interface. Most of these are place holders for other mechanism - * and will change in the future. - */ -#define CKM_NETSCAPE_PBE_SHA1_DES_CBC 0x80000002L -#define CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC 0x80000003L -#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC 0x80000004L -#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC 0x80000005L -#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4 0x80000006L -#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4 0x80000007L -#define CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC 0x80000008L -#define CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN 0x80000009L -#define CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN 0x8000000aL -#define CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN 0x8000000bL - -#define CKM_TLS_PRF_GENERAL 0x80000373L - -/* - * Netscape-defined return values - * - */ -#define CKR_NETSCAPE (CKM_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) - -#define CKR_NETSCAPE_CERTDB_FAILED (CKR_NETSCAPE + 1) -#define CKR_NETSCAPE_KEYDB_FAILED (CKR_NETSCAPE + 2) - -/* - * Trust info - * - * This isn't part of the Cryptoki standard (yet), so I'm putting - * all the definitions here. Some of this would move to nssckt.h - * if trust info were made part of the standard. In view of this - * possibility, I'm putting my (Netscape) values in the netscape - * vendor space, like everything else. - */ - typedef CK_ULONG CK_TRUST; - -/* The following trust types are defined: */ -#define CKT_VENDOR_DEFINED 0x80000000 - -#define CKT_NETSCAPE (CKT_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) - -/* If trust goes standard, these'll probably drop out of vendor space. */ -#define CKT_NETSCAPE_TRUSTED (CKT_NETSCAPE + 1) -#define CKT_NETSCAPE_TRUSTED_DELEGATOR (CKT_NETSCAPE + 2) -#define CKT_NETSCAPE_UNTRUSTED (CKT_NETSCAPE + 3) -#define CKT_NETSCAPE_MUST_VERIFY (CKT_NETSCAPE + 4) -#define CKT_NETSCAPE_TRUST_UNKNOWN (CKT_NETSCAPE + 5) /* default */ - -/* - * These may well remain Netscape-specific; I'm only using them - * to cache resolution data. - */ -#define CKT_NETSCAPE_VALID (CKT_NETSCAPE + 10) -#define CKT_NETSCAPE_VALID_DELEGATOR (CKT_NETSCAPE + 11) - -#endif /* _PKCS11N_H_ */ diff --git a/ext/pkcs11-proxy/seccomp-bpf.h b/ext/pkcs11-proxy/seccomp-bpf.h deleted file mode 100644 index 32e113764..000000000 --- a/ext/pkcs11-proxy/seccomp-bpf.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * seccomp example for x86 (32-bit and 64-bit) with BPF macros - * - * Copyright (c) 2012 The Chromium OS Authors - * Authors: - * Will Drewry - * Kees Cook - * - * The code may be used by anyone for any purpose, and can serve as a - * starting point for developing applications using mode 2 seccomp. - */ -#ifndef _SECCOMP_BPF_H_ -#define _SECCOMP_BPF_H_ - -#define _GNU_SOURCE 1 -#include -#include -#include -#include -#include -#include -#include - -#include -#ifndef PR_SET_NO_NEW_PRIVS -# define PR_SET_NO_NEW_PRIVS 38 -#endif - -#include -#include -#include -#ifdef HAVE_LINUX_SECCOMP_H -# include -#endif -#ifndef SECCOMP_MODE_FILTER -# define SECCOMP_MODE_FILTER 2 /* uses user-supplied filter. */ -# define SECCOMP_RET_KILL 0x00000000U /* kill the task immediately */ -# define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */ -# define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */ -struct seccomp_data { - int nr; - __u32 arch; - __u64 instruction_pointer; - __u64 args[6]; -}; -#endif -#ifndef SYS_SECCOMP -# define SYS_SECCOMP 1 -#endif - -#define syscall_nr (offsetof(struct seccomp_data, nr)) -#define arch_nr (offsetof(struct seccomp_data, arch)) - -#ifdef SECCOMP -#if defined(__i386__) -# define REG_SYSCALL REG_EAX -# define ARCH_NR AUDIT_ARCH_I386 -#elif defined(__x86_64__) -# define REG_SYSCALL REG_RAX -# define ARCH_NR AUDIT_ARCH_X86_64 -#else -# warning "Platform does not support seccomp filter yet" -# define REG_SYSCALL 0 -# define ARCH_NR 0 -#endif -#endif /* SECCOMP */ - -#define VALIDATE_ARCHITECTURE \ - BPF_STMT(BPF_LD+BPF_W+BPF_ABS, arch_nr), \ - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, 1, 0), \ - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL) - -#define EXAMINE_SYSCALL \ - BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_nr) - -#define ALLOW_SYSCALL(name) \ - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_##name, 0, 1), \ - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) - -#define KILL_PROCESS \ - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL) - -#endif /* _SECCOMP_BPF_H_ */ diff --git a/ext/pkcs11-proxy/syscall-reporter.c b/ext/pkcs11-proxy/syscall-reporter.c deleted file mode 100644 index b7750a2ff..000000000 --- a/ext/pkcs11-proxy/syscall-reporter.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * syscall reporting example for seccomp - * - * Copyright (c) 2012 The Chromium OS Authors - * Authors: - * Will Drewry - * Kees Cook - * - * The code may be used by anyone for any purpose, and can serve as a - * starting point for developing applications using mode 2 seccomp. - */ -#include "syscall-reporter.h" -#include "syscall-names.h" - -const char * const msg_needed = "Looks like you also need syscall: "; - -/* Since "sprintf" is technically not signal-safe, reimplement %d here. */ -static void write_uint(char *buf, unsigned int val) -{ - int width = 0; - unsigned int tens; - - if (val == 0) { - strcpy(buf, "0"); - return; - } - for (tens = val; tens; tens /= 10) - ++ width; - buf[width] = '\0'; - for (tens = val; tens; tens /= 10) - buf[--width] = '0' + (tens % 10); -} - -static void reporter(int nr, siginfo_t *info, void *void_context) -{ -#ifdef SECCOMP - char buf[128]; - ucontext_t *ctx = (ucontext_t *)(void_context); - unsigned int syscall; - if (info->si_code != SYS_SECCOMP) - return; - if (!ctx) - return; - syscall = ctx->uc_mcontext.gregs[REG_SYSCALL]; - strcpy(buf, msg_needed); - if (syscall < sizeof(syscall_names)) { - strcat(buf, syscall_names[syscall]); - strcat(buf, "("); - } - write_uint(buf + strlen(buf), syscall); - if (syscall < sizeof(syscall_names)) - strcat(buf, ")"); - strcat(buf, "\n"); - write(STDERR_FILENO, buf, strlen(buf)); - _exit(1); -#endif -} - -int install_syscall_reporter(void) -{ -#ifdef SECCOMP - struct sigaction act; - sigset_t mask; - memset(&act, 0, sizeof(act)); - sigemptyset(&mask); - sigaddset(&mask, SIGSYS); - - act.sa_sigaction = &reporter; - act.sa_flags = SA_SIGINFO; - if (sigaction(SIGSYS, &act, NULL) < 0) { - perror("sigaction"); - return -1; - } - if (sigprocmask(SIG_UNBLOCK, &mask, NULL)) { - perror("sigprocmask"); - return -1; - } -#endif - return 0; -} diff --git a/ext/pkcs11-proxy/syscall-reporter.h b/ext/pkcs11-proxy/syscall-reporter.h deleted file mode 100644 index ea4847e45..000000000 --- a/ext/pkcs11-proxy/syscall-reporter.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * syscall reporting example for seccomp - * - * Copyright (c) 2012 The Chromium OS Authors - * Authors: - * Kees Cook - * Will Drewry - * - * The code may be used by anyone for any purpose, and can serve as a - * starting point for developing applications using mode 2 seccomp. - */ -#ifndef _BPF_REPORTER_H_ -#define _BPF_REPORTER_H_ - -#include "seccomp-bpf.h" - -/* Since this redfines "KILL_PROCESS" into a TRAP for the reporter hook, - * we want to make sure it stands out in the build as it should not be - * used in the final program. - */ -#warning "You've included the syscall reporter. Do not use in production!" -#undef KILL_PROCESS -#define KILL_PROCESS \ - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRAP) - -extern int install_syscall_reporter(void); - -#endif diff --git a/scripts/deployment_dependencies.sh b/scripts/deployment_dependencies.sh new file mode 100755 index 000000000..5281eb727 --- /dev/null +++ b/scripts/deployment_dependencies.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +# exit on errors +set -e + +# add the STOL APT repository +echo "deb [trusted=yes] http://s3.amazonaws.com/stol-apt-repository develop main" > /etc/apt/sources.list.d/stol-apt-repository.list + +apt-get update + +# NOTE: libwebsockets-dev from Ubuntu 20 on is sufficient +DEPENDENCIES="build-essential \ + cmake \ + libboost-all-dev \ + libgps-dev \ + libjsoncpp-dev \ + libmysqlclient-dev \ + libmysqlcppconn-dev \ + librdkafka-dev \ + libsnmp-dev \ + libssl-dev \ + libwebsockets-dev \ + libxerces-c-dev \ + qtbase5-dev \ + uuid-dev \ + zip \ + zlib1g \ + curl" + +# STOL library dependencies +LIBRARY_DEPENDENCIES=" \ + carma-clock-1 \ +" + +# install all things needed for deployment, always done +apt-get install -y $DEPENDENCIES ${LIBRARY_DEPENDENCIES} diff --git a/src/tmx/Security/softhsm/CMakeLists.txt b/src/tmx/Security/softhsm/CMakeLists.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/tmx/Security/softhsm/softhsm.cc b/src/tmx/Security/softhsm/softhsm.cc deleted file mode 100644 index ed5f40201..000000000 --- a/src/tmx/Security/softhsm/softhsm.cc +++ /dev/null @@ -1,23 +0,0 @@ -/* implementation code that allows softhsm access through the pkcs11 proxy API */ - - - - -#include "softhsm.h" - - - - -namespace tmx { - - - - - - - - - - - -} \ No newline at end of file diff --git a/src/tmx/Security/softhsm/softhsm.h b/src/tmx/Security/softhsm/softhsm.h deleted file mode 100644 index 3682c2cfe..000000000 --- a/src/tmx/Security/softhsm/softhsm.h +++ /dev/null @@ -1,77 +0,0 @@ -/***** Implimentation of pkcs11 proxy class for integrating softhsm module with V2X hub */ -/* Author: Anjan Rayamajhi, leidos Inc */ - - -#include "config.h" - -#include - - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - - - -#define SOCKET_PATH "tcp://127.0.0.1" - -#ifdef SECCOMP -#include -//#include "seccomp-bpf.h" -#ifdef DEBUG_SECCOMP -# include "syscall-reporter.h" -#endif /* DEBUG_SECCOMP */ -#include /* for seccomp init */ -#endif /* SECCOMP */ - - - - -struct hsmtoken -{ - int slotID; - char* slotLabel; - char* userID; - char* userpin; -}; - - - -namespace tmx { - - class softhsmHelper - { - public: - - char *path, *tsk_file_path, *socket_url; - - int socket; - fd_set filedesc; - - hsmtoken tk; - - - - protected: - - int get_slot_info(char *path, int slotID, char* label, char* userPIN, char* username); // returns the success/failure of slot access and info - hsmtoken create_token(char *path, int slotID, char* label, char* userPIN, char* username); - char* psk_keygen_helper(char* passcode, char* encryption); - int encrypt(char* input, char* output); - int decrypt(char* input, char* output); - int get_slot0_token(); // this might be necessary if the install process sets up a slot 0 token for general use - - int sign_messages(char* input, char* output); - - } - -}; - diff --git a/src/tmx/Security/softhsm/token.h b/src/tmx/Security/softhsm/token.h deleted file mode 100644 index 6fd63dfe7..000000000 --- a/src/tmx/Security/softhsm/token.h +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - -namespace tmx { - - class hsmtoken - { - public: - int slotID; - char* slotLable; - char* userID; - char* userpin; - } - - - -} \ No newline at end of file diff --git a/src/v2i-hub/SpatPlugin/src/SpatPlugin.cpp b/src/v2i-hub/SpatPlugin/src/SpatPlugin.cpp index ecdad2fb0..c47a4863f 100644 --- a/src/v2i-hub/SpatPlugin/src/SpatPlugin.cpp +++ b/src/v2i-hub/SpatPlugin/src/SpatPlugin.cpp @@ -21,19 +21,13 @@ SpatPlugin::~SpatPlugin() { void SpatPlugin::UpdateConfigSettings() { GetConfigValue("SignalGroupMapping", signalGroupMappingJson, &data_lock); - GetConfigValue("Local_IP", localIp, &data_lock); - GetConfigValue("Local_UDP_Port", localUdpPort, &data_lock); - GetConfigValue("TSC_IP", tscIp, &data_lock); - GetConfigValue("TSC_Remote_SNMP_Port", tscRemoteSnmpPort, &data_lock); - GetConfigValue("Intersection_Name", intersectionName, &data_lock); - GetConfigValue("Intersection_Id", intersectionId, &data_lock); isConfigurationLoaded = true; From 31773e9dedfd15726e4dacff336047fec90ae227 Mon Sep 17 00:00:00 2001 From: dan-du-car <62157949+dan-du-car@users.noreply.github.com> Date: Tue, 18 Apr 2023 16:26:54 -0400 Subject: [PATCH 02/14] Update TIM Plugin to accept standard XML format (#508) # PR Details ## Description Currently, the TIM plugin only encodes Curve Speed Warning information in a non-standard XML into a TIM message. I would like to have all ITIS codes and text inputs accepted in a standard XML format and encoded into a TIM message. The below XML is a sample standard XML accepted by the TIM plugin ``` 1 115549 000000000023667BAC 0 389549775 -771491835 390 1111111111111111 115549 1 7 0 389549775 -771491835 390 1111111111111111

389549775 -771491835 390
74 0 0 7186 9476 13569 987654321 ``` ## Related Issue https://github.com/usdot-fhwa-OPS/V2X-Hub/issues/502 ## Motivation and Context ## How Has This Been Tested? ## Types of changes - [ ] Defect fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [x] Breaking change (fix or feature that cause existing functionality to change) ## Checklist: - [ ] I have added any new packages to the sonar-scanner.properties file - [ ] My change requires a change to the documentation. - [ ] I have updated the documentation accordingly. - [x] I have read the **CONTRIBUTING** document. [V2XHUB Contributing Guide](https://github.com/usdot-fhwa-OPS/V2X-Hub/blob/develop/Contributing.md) - [ ] I have added tests to cover my changes. - [ ] All new and existing tests passed. --- docs/V2X-Hub_Plugins.pdf | Bin 0 -> 595429 bytes src/tmx/TmxUtils/test/J2735MessageTest.cpp | 17 ++ src/v2i-hub/TimPlugin/manifest.json | 25 +- src/v2i-hub/TimPlugin/src/TimPlugin.cpp | 288 ++++++++++----------- src/v2i-hub/TimPlugin/src/TimPlugin.h | 20 +- 5 files changed, 168 insertions(+), 182 deletions(-) create mode 100755 docs/V2X-Hub_Plugins.pdf diff --git a/docs/V2X-Hub_Plugins.pdf b/docs/V2X-Hub_Plugins.pdf new file mode 100755 index 0000000000000000000000000000000000000000..67455b1e76f595dec7cd6a32c2e4778dd62547db GIT binary patch literal 595429 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

j1e}&n`RHiP~K0xP3wEp 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%0DUpW7Ab+|b2F`SwT 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

@bKwY$7~j{=&Xxo%up&&pU4 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 QkDhhk4F~RTJ=ypF1?+C@(EtDd literal 0 HcmV?d00001 diff --git a/src/tmx/TmxUtils/test/J2735MessageTest.cpp b/src/tmx/TmxUtils/test/J2735MessageTest.cpp index b70aa513e..ab6fb9a0e 100644 --- a/src/tmx/TmxUtils/test/J2735MessageTest.cpp +++ b/src/tmx/TmxUtils/test/J2735MessageTest.cpp @@ -643,4 +643,21 @@ TEST_F(J2735MessageTest, EncodeTrafficControlMessage){ ASSERT_EQ(245, tsm5Enc.get_msgId()); } + +TEST_F(J2735MessageTest, EncodeTravelerInformation){ + //Advisory + string timStr="1115549000000000023667BAC0389549775-7714918353901111111111111111115549170389549775-7714918353901111111111111111

389549775-771491835390
74007186curve13569987654321"; + std::stringstream ss; + TimMessage timMsg; + TimEncodedMessage timEnc; + tmx::message_container_type container; + ss<(ss); + timMsg.set_contents(container.get_storage().get_tree()); + timEnc.encode_j2735_message(timMsg); + ASSERT_EQ(31, timEnc.get_msgId()); + string expectedHex = "001f526011c35d000000000023667bac0407299b9ef9e7a9b9408230dfffe4386ba00078005a53373df3cf5372810461b90ffff53373df3cf53728104618129800010704a04c7d7976ca3501872e1bb66ad19b2620"; + ASSERT_EQ(expectedHex, timEnc.get_payload_str()); +} + } diff --git a/src/v2i-hub/TimPlugin/manifest.json b/src/v2i-hub/TimPlugin/manifest.json index 74a910212..293c504bf 100644 --- a/src/v2i-hub/TimPlugin/manifest.json +++ b/src/v2i-hub/TimPlugin/manifest.json @@ -23,26 +23,6 @@ "default":"/var/www/plugins/MAP/IVP_GF_TIM.xml", "description":"" }, - { - "key":"Start_Broadcast_Date", - "default":"01-01-2019", - "description":"The Start Broadcast Date for the TIM message in the (mm-dd-YYYY) format." - }, - { - "key":"Stop_Broadcast_Date", - "default":"12-31-2020", - "description":"The Stop Broadcast Date for the TIM message in the (mm-dd-YYYY) format." - }, - { - "key":"Start_Broadcast_Time", - "default":"06:00:00", - "description":"The Start Broadcast Time for the TIM message in the (HH:MM:SS) format." - }, - { - "key":"Stop_Broadcast_Time", - "default":"21:00:00", - "description":"The Start Broadcast Time for the TIM message in the (HH:MM:SS) format." - }, { "key":"WebServiceIP", "default":"127.0.0.1", @@ -52,6 +32,11 @@ "key":"WebServicePort", "default":"10000", "description":"Port at which Web service exists" + }, + { + "key":"LogLevel", + "default":"DEBUG", + "description": "TIM Plugin Log Level controls which log statements are printed to the terminal." } ] diff --git a/src/v2i-hub/TimPlugin/src/TimPlugin.cpp b/src/v2i-hub/TimPlugin/src/TimPlugin.cpp index 6002d8873..6aa2d8c8f 100644 --- a/src/v2i-hub/TimPlugin/src/TimPlugin.cpp +++ b/src/v2i-hub/TimPlugin/src/TimPlugin.cpp @@ -3,7 +3,6 @@ #include "Clock.h" #include "XmlCurveParser.h" #include -#include using namespace std; using namespace tmx::messages; @@ -12,9 +11,6 @@ using namespace xercesc; using namespace boost::property_tree; namespace TimPlugin { - - - /** * Construct a new TimPlugin with the given name. * @@ -31,9 +27,13 @@ TimPlugin::~TimPlugin() { void TimPlugin::TimRequestHandler(QHttpEngine::Socket *socket) { - + if(socket->bytesAvailable() == 0) + { + PLOG(logERROR) << "TimPlugin does not receive web service request content!" <::create(); QString st; while(socket->bytesAvailable()>0) { @@ -43,54 +43,23 @@ void TimPlugin::TimRequestHandler(QHttpEngine::Socket *socket) char* _cloudUpdate = array.data(); // would be the cloud update packet, needs parsing - std::stringstream ss; ss << _cloudUpdate; - - ptree ptr; - - // Catch XML parse exceptions + PLOG(logDEBUG) << "Received from webservice: " << ss.str() << std::endl; try { - // Using open command with std::ofstream::out mode overwrites existing files - tmpTIM.open("/tmp/tmpTIM.xml", std::ofstream::out); - read_xml(ss,ptr); - lock_guard lock(_cfgLock); - BOOST_FOREACH(auto &n, ptr.get_child("timdata")) - { - std::string labeltext = n.first; - - if(labeltext == "starttime") - _startTime = n.second.get_value(); - - if(labeltext == "stoptime") - _stopTime = n.second.get_value(); - - if(labeltext == "startdate") - _startDate = n.second.get_value(); - - if(labeltext == "stopdate") - _stopDate = n.second.get_value(); - - if(labeltext == "timupdate"){ - tmpTIM<(); - - _mapFile = "/tmp/tmpTIM.xml"; - _isMapFileNew = true; - } - - } - // Close file each time to avoid appending to open file - tmpTIM.close(); + tmx::message_container_type container; + container.load(ss); + _timMsgPtr = std::make_shared(); + _timMsgPtr->set_contents(container.get_storage().get_tree()); + _isTimUpdated = true; writeResponse(QHttpEngine::Socket::Created, socket); } - catch( const ptree_error &e ) { - PLOG(logERROR) << "Error parsing file: " << e.what() << std::endl; + catch (TmxException &ex) { + PLOG(logERROR) << "Failed to encode message : " << ex.what(); writeResponse(QHttpEngine::Socket::BadRequest, socket); } - - } /** * Write HTTP response. @@ -104,8 +73,6 @@ void TimPlugin::writeResponse(int responseCode , QHttpEngine::Socket *socket) { } - - int TimPlugin::StartWebService() { //Web services @@ -114,31 +81,36 @@ int TimPlugin::StartWebService() QCoreApplication a(placeholderC,placeholderX); QHostAddress address = QHostAddress(QString::fromStdString (webip)); - quint16 port = static_cast(webport); + quint16 port = static_cast(webport); QSharedPointer handler(new OpenAPI::OAIApiRequestHandler()); handler = QSharedPointer (new OpenAPI::OAIApiRequestHandler()); + auto router = QSharedPointer::create(); + router->setUpRoutes(); + QObject::connect(handler.data(), &OpenAPI::OAIApiRequestHandler::requestReceived, [&](QHttpEngine::Socket *socket) { - this->TimRequestHandler(socket); + TimRequestHandler(socket); + }); + + QObject::connect(handler.data(), &OpenAPI::OAIApiRequestHandler::requestReceived, [&](QHttpEngine::Socket *socket) { + router->processRequest(socket); }); QHttpEngine::Server server(handler.data()); if (!server.listen(address, port)) { - qCritical("TimPlugin:: Unable to listen on the specified port."); + qCritical("TimPlugin::Unable to listen on the specified port."); return 1; } - PLOG(logDEBUG4)<<"TimPlugin:: Started web service"; + PLOG(logINFO)<<"TimPlugin:: Started web service"; return a.exec(); } - void TimPlugin::UpdateConfigSettings() { - lock_guard lock(_cfgLock); GetConfigValue("Frequency", _frequency); @@ -154,12 +126,8 @@ void TimPlugin::UpdateConfigSettings() { } - GetConfigValue("Start_Broadcast_Date", _startDate); - GetConfigValue("Stop_Broadcast_Date", _stopDate); - GetConfigValue("Start_Broadcast_Time", _startTime); - GetConfigValue("Stop_Broadcast_Time", _stopTime); - GetConfigValue("WebServiceIP",webip); - GetConfigValue("WebServicePort",webport); + GetConfigValue("WebServiceIP", webip); + GetConfigValue("WebServicePort", webport); } @@ -183,56 +151,53 @@ void TimPlugin::OnStateChange(IvpPluginState state) { } } - - -bool TimPlugin::TimDuration() +bool TimPlugin::TimDuration(std::shared_ptr TimMsg) { - PLOG(logDEBUG)<<"TimPlugin:: Reached in TimDuration"; - - ostringstream firstTimTime_; - firstTimTime_ << _startDate << " " << _startTime; - auto firstTime = firstTimTime_.str(); - - ostringstream lastTimTime_; - lastTimTime_ << _stopDate << " " << _stopTime; - auto lastTime = lastTimTime_.str(); + PLOG(logINFO)<<"TimPlugin:: Reached in TimDuration upcon receiving TIM message."; + lock_guard lock(_cfgLock); + auto timPtr = TimMsg->get_j2735_data(); + //startTime unit of minute + auto startTime = timPtr->dataFrames.list.array[0]->startTime; + if(startTime >= 527040) + { + PLOG(logERROR) << "Invalid startTime." << std::endl; + return false; + } + //Duration is unit of minute + auto duration = timPtr->dataFrames.list.array[0]->duratonTime; + bool isPersist = false; + if(duration >= 32000) + { + PLOG(logERROR) << "Duration = 32000, ignore stop time." << std::endl; + isPersist = true; + } - istringstream stopTimTime(lastTime); - istringstream startTimTime(firstTime); - - // start time in seconds - struct tm date_start; - startTimTime >> get_time( &date_start, "%m-%d-%Y %H:%M:%S" ); - time_t secondsStart = mktime( & date_start ); - PLOG(logDEBUG) << "START : " << date_start.tm_mon << "-" << date_start.tm_mday << "-" - << date_start.tm_year << " " << date_start.tm_hour << ":" << date_start.tm_min << ":" - << date_start.tm_sec << std::endl; - // stop time in seconds - struct tm date_stop; - stopTimTime >> get_time( &date_stop, "%m-%d-%Y %H:%M:%S" ); - PLOG(logDEBUG) << "STOP : " << date_stop.tm_mon << "-" << date_stop.tm_mday << "-" - << date_stop.tm_year << " " << date_stop.tm_hour << ":" << date_stop.tm_min << ":" - << date_stop.tm_sec << std::endl; - time_t secondsStop = mktime( & date_stop ); - - // Current Time in seconds + //Get year start UTC in seconds auto t = time(nullptr); - struct tm tm; - localtime_r(&t, &tm); - ostringstream oss1; - oss1 << put_time(&tm, "%m-%d-%Y %H:%M:%S"); - auto _currentTimTime = oss1.str(); - istringstream currentTimTime(_currentTimTime); - struct tm date_current; - currentTimTime >> get_time( &date_current, "%m-%d-%Y %H:%M:%S" ); - PLOG(logDEBUG) << "CURRENT : " << date_current.tm_mon << "-" << date_current.tm_mday << "-" - << date_current.tm_year << " " << date_current.tm_hour << ":" << date_current.tm_min << ":" - << date_current.tm_sec << std::endl; - time_t secondsCurrent = mktime( & date_current ); - - PLOG(logDEBUG) << "Start : " << secondsStart << " Stop : " << secondsStop << - " Current : " << secondsCurrent << std::endl; - if ( secondsStart <= secondsCurrent && secondsCurrent <= secondsStop) { + struct tm* timeInfo = gmtime(&t); + ostringstream currentYearStartOS; + currentYearStartOS << (timeInfo->tm_year+1900) <<"-01-01T00:00:00.000Z"; + struct tm currentYearStartTimeInfo; + istringstream currentYearStartIS(currentYearStartOS.str()); + currentYearStartIS >> get_time( ¤tYearStartTimeInfo, "%Y-%m-%dT%H:%M:%S%Z" ); + currentYearStartTimeInfo.tm_isdst = 0; //Day light saving flag + PLOG(logINFO) << "Year Start : " << (currentYearStartTimeInfo.tm_mon + 1) << "-" << currentYearStartTimeInfo.tm_mday << "-" + << (currentYearStartTimeInfo.tm_year + 1900) << " " << currentYearStartTimeInfo.tm_hour << ":" << currentYearStartTimeInfo.tm_min << ":" + << currentYearStartTimeInfo.tm_sec << " DST:" << currentYearStartTimeInfo.tm_isdst << std::endl; + time_t secondsYearStart = mktime( ¤tYearStartTimeInfo ); + + //Start Time in seconds + time_t secondsStart = secondsYearStart + startTime * 60; + //Stop Time in seconds + time_t secondsStop = secondsStart + duration * 60; + + // Current UTC Time in seconds; + auto secondsCurrent = time(nullptr); + + //Comparing current time with start and end time + PLOG(logINFO) << "Year Start(s): " << secondsYearStart << " Broadcast Start(s):" << secondsStart << " Broadcast Stop(s): " << secondsStop << + " Current(s):" << secondsCurrent << " Elpased minutes since year start(min):" << ((secondsCurrent-secondsYearStart)/60.0)<< std::endl; + if ( secondsStart <= secondsCurrent && (secondsCurrent <= secondsStop || isPersist)) { return true; } else { return false; @@ -241,25 +206,18 @@ bool TimPlugin::TimDuration() bool TimPlugin::LoadTim(TravelerInformation *tim, const char *mapFile) { - memset(tim, 0, sizeof(TravelerInformation)); - // J2735 packet header. - //tim->msgID = DSRCmsgID_travelerInformation; DsrcBuilder::SetPacketId(tim); - // Data Frame (1 of 1). - XmlCurveParser curveParser; - // Read the curve file, which creates and populates the data frame of the TIM. if (!curveParser.ReadCurveFile(mapFile, tim)) return false; - _speedLimit = curveParser.SpeedLimit; PluginUtil::SetStatus(_plugin, "Speed Limit", _speedLimit); @@ -267,64 +225,82 @@ bool TimPlugin::LoadTim(TravelerInformation *tim, const char *mapFile) return true; } +bool TimPlugin::LoadTim(std::shared_ptr TimMsg, const char *mapFile) +{ + std::ifstream in = std::ifstream(mapFile, ios_base::in); + if(in && in.is_open()) + { + try + { + std::stringstream ss; + ss << in.rdbuf(); + in.close(); + + tmx::message_container_type container; + container.load(ss); + TimMsg->set_contents(container.get_storage().get_tree()); + PLOG(logINFO) << "Loaded MapFile and updated TIM." << std::endl; + return true; + } + catch(const std::exception& e) + { + PLOG(logERROR)<<"Cannot read file " << mapFile<state != IvpPluginState_error) { + if (IsPluginState(IvpPluginState_registered)) + { - while (TimDuration()) { - - if (IsPluginState(IvpPluginState_registered)) - { - uint64_t sendFrequency = _frequency; - - // Load the TIM from the map file if it is new. - //cout<<"TimPlugin:: isMAPfileNEW "<<_isMapFileNew< lock(_cfgLock); + PLOG(logINFO)<<"TimPlugin:: isMAPfileNEW "<<_isMapFileNew<(); + _isTimLoaded = LoadTim(_timMsgPtr, _mapFile.c_str()); + if(!_isTimLoaded) { - { - //lock_guard lock(_cfgLock); - //mapFileCopy = _mapFile; - _isMapFileNew = false; - } - _isTimLoaded = LoadTim(&_tim, _mapFile.c_str()); + _timMsgPtr = nullptr; } - - uint64_t time = Clock::GetMillisecondsSinceEpoch(); - - if (_isTimLoaded && (time - lastUpdateTime) > updateFrequency) - { - lastUpdateTime = time; - if (_isTimLoaded) - { - DsrcBuilder::SetPacketId(&_tim); - DsrcBuilder::SetStartTimeToYesterday(_tim.dataFrames.list.array[0]); - } + } + while (_timMsgPtr && TimDuration(_timMsgPtr)) + { + lock_guard lock(_cfgLock); + uint64_t sendFrequency = _frequency; + + if(_isTimUpdated){ + PLOG(logINFO) <<"TimPlugin:: _isTimUpdated via Post request: "<< _isTimUpdated< 0 && (time - lastSendTime) > sendFrequency) + if (_timMsgPtr) { - - lastSendTime = time; - TimMessage timMsg(_tim); - //PLOG(logERROR) <<"timMsg XML to send....."<< timMsg<(&timEncMsg); - if (rMsg) BroadcastMessage(*rMsg); + if (rMsg) BroadcastMessage(*rMsg); } + + //Make sure send frequency configuration is positive, otherwise set to default 1000 milliseconds + sendFrequency = sendFrequency > 0 ? sendFrequency: 1000; + //Sleep sendFrequency for every attempt to broadcast TIM + this_thread::sleep_for(chrono::milliseconds(sendFrequency)); } } this_thread::sleep_for(chrono::milliseconds(500)); diff --git a/src/v2i-hub/TimPlugin/src/TimPlugin.h b/src/v2i-hub/TimPlugin/src/TimPlugin.h index 7409b933b..82d7420e0 100644 --- a/src/v2i-hub/TimPlugin/src/TimPlugin.h +++ b/src/v2i-hub/TimPlugin/src/TimPlugin.h @@ -64,6 +64,7 @@ #include #include #include +#include @@ -103,8 +104,17 @@ class TimPlugin: public PluginClient { //void OnMessageReceived(IvpMessage *msg); void OnStateChange(IvpPluginState state); - bool TimDuration(); + /** + * @brief Calculate tim duration based on the J2735 TIM message startTime and Duration + */ + bool TimDuration(std::shared_ptr TimMsg); bool LoadTim(TravelerInformation *tim, const char *mapFile); + /** + * @brief Read map file and populate TIM message + * @param TimMsg A shared pointer to the TIM object to be updated + * @param mapFile File path that has the standard J2735 TIM message in XML format + */ + bool LoadTim(std::shared_ptr TimMsg, const char *mapFile); int StartWebService(); void TimRequestHandler(QHttpEngine::Socket *socket); void writeResponse(int responseCode , QHttpEngine::Socket *socket); @@ -118,21 +128,19 @@ class TimPlugin: public PluginClient { uint64_t _frequency = 0; - std::string _startDate; - std::string _stopDate; - std::string _startTime; - std::string _stopTime; std::string _timupdate; uint16_t webport; std::string webip; - TravelerInformation _tim; + std::shared_ptr _timMsgPtr; mutex _mapFileLock; string _mapFile; std::ofstream tmpTIM; atomic _isMapFileNew{false}; atomic _isTimFileNew{false}; + //Post request to update TIM + atomic _isTimUpdated{false}; bool _isTimLoaded = false; unsigned int _speedLimit = 0; int _lastMsgIdSent = -1; From ab90a16f58402774afa76243e61f1f1c24a813fe Mon Sep 17 00:00:00 2001 From: dan-du-car <62157949+dan-du-car@users.noreply.github.com> Date: Tue, 18 Apr 2023 19:21:37 -0400 Subject: [PATCH 03/14] V2XHub / CARMA Streets to process SRM for MRP consumption (#518) # PR Details ## Description For the POC TIM/TSP use case, priority-eligible vehicles will broadcast J2375 Signal Request Message (SRM) to the MMITSS Roadside Processor (MRP). Since MRP is being integrated with CARMA Streets, CARMA Streets / V2XHub (more specifically the V2XHub CARMA-Streets-plugin) needs to process the [ASN.1 SRM](https://leidoscorpus.sharepoint.us/:f:/s/STR/EpU-cLOWhUtGvsddHUSf8I4Bf7-Ot8oMIY4yf2m7x2-Uag?e=0Rvpug) and convert to the json format that MMITSS MRP uses internally (see [here](https://github.com/mmitss/mmitss-az/blob/master/src/mrp/priority-request-server/Readme.md)), and publish the json SRM on the CARMA Streets Kafak broker. ## Related Issue NA ## Motivation and Context NA ## How Has This Been Tested? Local integration testing ## Types of changes - [ ] Defect fix (non-breaking change that fixes an issue) - [x] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that cause existing functionality to change) ## Checklist: - [ ] I have added any new packages to the sonar-scanner.properties file - [ ] My change requires a change to the documentation. - [ ] I have updated the documentation accordingly. - [x] I have read the **CONTRIBUTING** document. [V2XHUB Contributing Guide](https://github.com/usdot-fhwa-OPS/V2X-Hub/blob/develop/Contributing.md) - [ ] I have added tests to cover my changes. - [ ] All new and existing tests passed. --- src/tmx/TmxUtils/test/J2735MessageTest.cpp | 90 +++++++++++- src/v2i-hub/CARMAStreetsPlugin/CMakeLists.txt | 2 +- src/v2i-hub/CARMAStreetsPlugin/manifest.json | 10 ++ .../src/CARMAStreetsPlugin.cpp | 31 ++++ .../src/CARMAStreetsPlugin.h | 14 ++ .../src/J2735ToSRMJsonConverter.cpp | 135 +++++++++++++++++ .../src/J2735ToSRMJsonConverter.h | 27 ++++ .../test/test_J2735ToSRMJsonConverter.cpp | 137 ++++++++++++++++++ 8 files changed, 444 insertions(+), 2 deletions(-) mode change 100644 => 100755 src/v2i-hub/CARMAStreetsPlugin/src/CARMAStreetsPlugin.cpp mode change 100644 => 100755 src/v2i-hub/CARMAStreetsPlugin/src/CARMAStreetsPlugin.h create mode 100755 src/v2i-hub/CARMAStreetsPlugin/src/J2735ToSRMJsonConverter.cpp create mode 100755 src/v2i-hub/CARMAStreetsPlugin/src/J2735ToSRMJsonConverter.h create mode 100644 src/v2i-hub/CARMAStreetsPlugin/test/test_J2735ToSRMJsonConverter.cpp diff --git a/src/tmx/TmxUtils/test/J2735MessageTest.cpp b/src/tmx/TmxUtils/test/J2735MessageTest.cpp index ab6fb9a0e..5a72f9458 100644 --- a/src/tmx/TmxUtils/test/J2735MessageTest.cpp +++ b/src/tmx/TmxUtils/test/J2735MessageTest.cpp @@ -643,6 +643,95 @@ TEST_F(J2735MessageTest, EncodeTrafficControlMessage){ ASSERT_EQ(245, tsm5Enc.get_msgId()); } +TEST_F (J2735MessageTest, EncodeSrm) +{ + SignalRequestMessage_t *message = (SignalRequestMessage_t *)calloc(1, sizeof(SignalRequestMessage_t)); + message->second = 12; + RequestorDescription_t *requestor = (RequestorDescription_t *)calloc(1, sizeof(RequestorDescription_t)); + VehicleID_t *veh_id = (VehicleID_t *)calloc(1, sizeof(VehicleID_t)); + veh_id->present = VehicleID_PR_entityID; + TemporaryID_t *entity_id = (TemporaryID_t *)calloc(1, sizeof(TemporaryID_t)); + uint8_t my_bytes_id[4] = {(uint8_t)1, (uint8_t)12, (uint8_t)12, (uint8_t)10}; + entity_id->buf = my_bytes_id; + entity_id->size = sizeof(my_bytes_id); + veh_id->choice.entityID = *entity_id; + requestor->id = *veh_id; + RequestorType_t *requestType = (RequestorType_t *)calloc(1, sizeof(RequestorType_t)); + requestType->role = 0; + requestor->type = requestType; + RequestorPositionVector_t *position = (RequestorPositionVector_t *)calloc(1, sizeof(RequestorPositionVector_t)); + DSRC_Angle_t *heading_angle = (DSRC_Angle_t *)calloc(1, sizeof(DSRC_Angle_t)); + *heading_angle = 123; + position->heading = heading_angle; + Position3D_t *position_point = (Position3D_t *)calloc(1, sizeof(Position3D_t)); + DSRC_Elevation_t *elev = (DSRC_Elevation_t *)calloc(1, sizeof(DSRC_Elevation_t)); + *elev = 12; + position_point->elevation = elev; + position_point->lat = 3712333; + position_point->Long = 8012333; + position->position = *position_point; + TransmissionAndSpeed_t *speed = (TransmissionAndSpeed_t *)calloc(1, sizeof(TransmissionAndSpeed_t)); + speed->speed = 10; + TransmissionState_t *transmission_state = (TransmissionState_t *)calloc(1, sizeof(TransmissionState_t)); + *transmission_state = 1111; + speed->transmisson = 7; + position->speed = speed; + requestor->position = position; + message->requestor = *requestor; + + SignalRequestList_t *requests = (SignalRequestList_t *)calloc(1, sizeof(SignalRequestList_t)); + //First: Request Package + SignalRequestPackage_t *request_package = (SignalRequestPackage_t *)calloc(1, sizeof(SignalRequestPackage_t)); + MinuteOfTheYear_t *min = (MinuteOfTheYear_t *)calloc(1, sizeof(MinuteOfTheYear_t)); + *min = 123; + request_package->minute = min; + DSecond_t *duration = (DSecond_t *)calloc(1, sizeof(DSecond_t)); + *duration = 122; + request_package->duration = duration; + DSecond_t *second = (DSecond_t *)calloc(1, sizeof(DSecond_t)); + *second = 1212; + request_package->second = second; + SignalRequest_t *request = (SignalRequest_t *)calloc(1, sizeof(SignalRequest_t)); + IntersectionReferenceID_t *refer_id = (IntersectionReferenceID_t *)calloc(1, sizeof(IntersectionReferenceID_t)); + refer_id->id = 1222; + request->id = *refer_id; + request->requestID = 1; + request->requestType = 0; + IntersectionAccessPoint_t *inBoundLane = (IntersectionAccessPoint_t *)calloc(1, sizeof(IntersectionAccessPoint_t)); + inBoundLane->present = IntersectionAccessPoint_PR_lane; + inBoundLane->choice.lane = 1; + request->inBoundLane = *inBoundLane; + request_package->request = *request; + asn_sequence_add(&requests->list.array, request_package); + + //Second: Request Package + SignalRequestPackage_t *request_package_2 = (SignalRequestPackage_t *)calloc(1, sizeof(SignalRequestPackage_t)); + request_package_2->minute = min; + request_package_2->duration = duration; + request_package_2->second = second; + SignalRequest_t *request_2 = (SignalRequest_t *)calloc(1, sizeof(SignalRequest_t)); + IntersectionReferenceID_t *referId2 = (IntersectionReferenceID_t *)calloc(1, sizeof(IntersectionReferenceID_t)); + referId2->id = 2333; + request_2->id = *referId2; + request_2->requestID = 2; + request_2->requestType = 1; + IntersectionAccessPoint_t *inBoundLane2 = (IntersectionAccessPoint_t *)calloc(1, sizeof(IntersectionAccessPoint_t)); + inBoundLane2->present = IntersectionAccessPoint_PR_approach; + inBoundLane2->choice.approach = 1; + request_2->inBoundLane = *inBoundLane2; + request_package_2->request = *request_2; + asn_sequence_add(&requests->list.array, request_package_2); + message->requests = requests; + tmx::messages::SrmEncodedMessage srmEncodeMessage; + auto _srmMessage = new tmx::messages::SrmMessage(message); + tmx::messages::MessageFrameMessage frame_msg(_srmMessage->get_j2735_data()); + srmEncodeMessage.set_data(TmxJ2735EncodedMessage::encode_j2735_message>(frame_msg)); + free(message); + free(frame_msg.get_j2735_data().get()); + ASSERT_EQ(29, srmEncodeMessage.get_msgId()); + std::string expectedSRMEncHex = "001d311000605c0098c020008003d825e003d380247408910007b04bc007a60004303028001a6bbb1c9ad7882858201801ef8028"; + ASSERT_EQ(expectedSRMEncHex, srmEncodeMessage.get_payload_str()); +} TEST_F(J2735MessageTest, EncodeTravelerInformation){ //Advisory @@ -659,5 +748,4 @@ TEST_F(J2735MessageTest, EncodeTravelerInformation){ string expectedHex = "001f526011c35d000000000023667bac0407299b9ef9e7a9b9408230dfffe4386ba00078005a53373df3cf5372810461b90ffff53373df3cf53728104618129800010704a04c7d7976ca3501872e1bb66ad19b2620"; ASSERT_EQ(expectedHex, timEnc.get_payload_str()); } - } diff --git a/src/v2i-hub/CARMAStreetsPlugin/CMakeLists.txt b/src/v2i-hub/CARMAStreetsPlugin/CMakeLists.txt index c9a2a11ee..58b6dc136 100644 --- a/src/v2i-hub/CARMAStreetsPlugin/CMakeLists.txt +++ b/src/v2i-hub/CARMAStreetsPlugin/CMakeLists.txt @@ -9,7 +9,7 @@ TARGET_LINK_LIBRARIES (${PROJECT_NAME} tmxutils rdkafka++ jsoncpp) ############# enable_testing() include_directories(${PROJECT_SOURCE_DIR}/src) -add_library(${PROJECT_NAME}_lib src/J2735MapToJsonConverter.cpp src/JsonToJ2735SpatConverter.cpp) +add_library(${PROJECT_NAME}_lib src/J2735MapToJsonConverter.cpp src/JsonToJ2735SpatConverter.cpp src/J2735ToSRMJsonConverter.cpp) target_link_libraries(${PROJECT_NAME}_lib PUBLIC ${TMXAPI_LIBRARIES} ${ASN_J2735_LIBRARIES} ${MYSQL_LIBRARIES} diff --git a/src/v2i-hub/CARMAStreetsPlugin/manifest.json b/src/v2i-hub/CARMAStreetsPlugin/manifest.json index 634421f62..c4fb269cd 100644 --- a/src/v2i-hub/CARMAStreetsPlugin/manifest.json +++ b/src/v2i-hub/CARMAStreetsPlugin/manifest.json @@ -25,6 +25,11 @@ "subtype":"MAP-P", "description":"Full geometric layout of the intersection." }, + { + "type":"J2735", + "subtype":"SRM", + "description": "Signal request message for intersection" + }, { "type":"J2735", "subtype":"SPAT-P", @@ -62,6 +67,11 @@ "default": "v2xhub_mobility_operation_in", "description": "Apache Kafka topic plugin will transmit message to." }, + { + "key":"SRMTopic", + "default": "v2xhub_srm_in", + "description": "Apache Kafka topic plugin will transmit message to." + }, { "key": "MobilityPathTopic", "default": "v2xhub_mobility_path_in", diff --git a/src/v2i-hub/CARMAStreetsPlugin/src/CARMAStreetsPlugin.cpp b/src/v2i-hub/CARMAStreetsPlugin/src/CARMAStreetsPlugin.cpp old mode 100644 new mode 100755 index 6b3c1ba82..2e2fdf499 --- a/src/v2i-hub/CARMAStreetsPlugin/src/CARMAStreetsPlugin.cpp +++ b/src/v2i-hub/CARMAStreetsPlugin/src/CARMAStreetsPlugin.cpp @@ -25,6 +25,7 @@ CARMAStreetsPlugin::CARMAStreetsPlugin(string name) : AddMessageFilter < tsm3Message > (this, &CARMAStreetsPlugin::HandleMobilityOperationMessage); AddMessageFilter < tsm2Message > (this, &CARMAStreetsPlugin::HandleMobilityPathMessage); AddMessageFilter < MapDataMessage > (this, &CARMAStreetsPlugin::HandleMapMessage); + AddMessageFilter < SrmMessage > (this, &CARMAStreetsPlugin::HandleSRMMessage); SubscribeToMessages(); @@ -50,6 +51,7 @@ void CARMAStreetsPlugin::UpdateConfigSettings() { GetConfigValue("MobilityOperationTopic", _transmitMobilityOperationTopic); GetConfigValue("MobilityPathTopic", _transmitMobilityPathTopic); GetConfigValue("MapTopic", _transmitMAPTopic); + GetConfigValue("SRMTopic", _transmitSRMTopic); // Populate strategies config string config; GetConfigValue("MobilityOperationStrategies", config); @@ -286,6 +288,35 @@ void CARMAStreetsPlugin::HandleMobilityPathMessage(tsm2Message &msg, routeable_m } } +void CARMAStreetsPlugin::HandleSRMMessage(SrmMessage &msg, routeable_message &routeableMsg) +{ + J2735ToSRMJsonConverter srmJsonConverter; + std::vector srmJsonV; + try{ + srmJsonConverter.toSRMJsonV(srmJsonV , &msg); + }catch(std::exception& ex) + { + PLOG(logERROR) << "Fatal error with SRM To JSON converter. " << ex.what() << std::endl; + SetStatus(Key_SRMMessageSkipped, ++_srmMessageSkipped); + return; + } + + if(srmJsonV.empty()) + { + PLOG(logERROR) << "SRM message content is empty." << std::endl; + SetStatus(Key_SRMMessageSkipped, ++_srmMessageSkipped); + + }else{ + for (auto srmJson : srmJsonV) + { + Json::StreamWriterBuilder builder; + const std::string srmJsonStr = Json::writeString(builder, srmJson); + PLOG(logINFO) << "SRM Json message: " << srmJsonStr << std::endl; + produce_kafka_msg(srmJsonStr, _transmitSRMTopic); + } + } +} + void CARMAStreetsPlugin::HandleBasicSafetyMessage(BsmMessage &msg, routeable_message &routeableMsg) { try diff --git a/src/v2i-hub/CARMAStreetsPlugin/src/CARMAStreetsPlugin.h b/src/v2i-hub/CARMAStreetsPlugin/src/CARMAStreetsPlugin.h old mode 100644 new mode 100755 index 01856cbf4..a9111e945 --- a/src/v2i-hub/CARMAStreetsPlugin/src/CARMAStreetsPlugin.h +++ b/src/v2i-hub/CARMAStreetsPlugin/src/CARMAStreetsPlugin.h @@ -16,6 +16,7 @@ #include #include "J2735MapToJsonConverter.h" #include "JsonToJ2735SpatConverter.h" +#include "J2735ToSRMJsonConverter.h" @@ -49,6 +50,10 @@ class CARMAStreetsPlugin: public PluginClient { * @param routeableMsg */ void HandleMapMessage(MapDataMessage &msg, routeable_message &routeableMsg); + /** + * @brief Subscribe to SRM message received from RSU and publish the message to a Kafka topic + */ + void HandleSRMMessage (SrmMessage &msg, routeable_message &routeableMsg); /** * @brief Subcribe to scheduling plan Kafka topic created by carma-streets */ @@ -78,6 +83,7 @@ class CARMAStreetsPlugin: public PluginClient { std::string _transmitMobilityPathTopic; std::string _transmitBSMTopic; std::string _transmitMAPTopic; + std::string _transmitSRMTopic; std::string _kafkaBrokerIp; std::string _kafkaBrokerPort; RdKafka::Conf *kafka_conf; @@ -155,6 +161,14 @@ class CARMAStreetsPlugin: public PluginClient { * @brief Intersection Id for intersection */ std::string _intersectionId = "UNSET"; + /** + * @brief Status label for SRM messages skipped due to errors. + */ + const char* Key_SRMMessageSkipped = "SRM messages skipped due to errors."; + /** + * @brief Count for SRM messages skipped due to errors. + */ + uint _srmMessageSkipped = 0; }; std::mutex _cfgLock; diff --git a/src/v2i-hub/CARMAStreetsPlugin/src/J2735ToSRMJsonConverter.cpp b/src/v2i-hub/CARMAStreetsPlugin/src/J2735ToSRMJsonConverter.cpp new file mode 100755 index 000000000..0ddde3d4a --- /dev/null +++ b/src/v2i-hub/CARMAStreetsPlugin/src/J2735ToSRMJsonConverter.cpp @@ -0,0 +1,135 @@ +#include "J2735ToSRMJsonConverter.h" + +namespace CARMAStreetsPlugin +{ + J2735ToSRMJsonConverter::J2735ToSRMJsonConverter() + { + } + + J2735ToSRMJsonConverter::~J2735ToSRMJsonConverter() + { + } + + void J2735ToSRMJsonConverter::toSRMJsonV(std::vector &jsonV, tmx::messages::SrmMessage *srm) + { + if(!srm) + { + return; + } + auto srm_ptr = srm->get_j2735_data(); + if(!srm_ptr || !srm_ptr->requests || srm_ptr->requests->list.count <= 0) + { + return; + } + + for(auto i = 0; i < srm_ptr->requests->list.count; i++) + { + Json::Value srmJson; + srmJson["MsgType"] = MsgType; + /*** + * Request data for one or more signalized intersections that support SRM dialogs. + */ + Json::Value request; + if(srm_ptr->sequenceNumber) + { + request["msgCount"] = srm_ptr->sequenceNumber; + } + if(srm_ptr->timeStamp){ + request["minuteOfYear"] = srm_ptr->timeStamp; + } + request["msOfMinute"] = srm_ptr->second; + if(srm_ptr->requests->list.array[i]->minute) + { + request["minuteOfYear"] = *srm_ptr->requests->list.array[i]->minute; + } + if(srm_ptr->requests->list.array[i]->second) + { + request["msOfMinute"] = *srm_ptr->requests->list.array[i]->second; + } + request["intersectionID"] = srm_ptr->requests->list.array[i]->request.id.id; + request["priorityRequestType"] = srm_ptr->requests->list.array[i]->request.requestType; + request["basicVehicleRole"] = srm_ptr->requestor.type->role; + + Json::Value inBoundLane; + switch(srm_ptr->requests->list.array[i]->request.inBoundLane.present) + { + case IntersectionAccessPoint_PR_NOTHING: + break; + case IntersectionAccessPoint_PR_lane: + inBoundLane["LaneID"] = srm_ptr->requests->list.array[i]->request.inBoundLane.choice.lane; + break; + case IntersectionAccessPoint_PR_approach: + inBoundLane["ApproachID"] = srm_ptr->requests->list.array[i]->request.inBoundLane.choice.approach; + break; + case IntersectionAccessPoint_PR_connection: + inBoundLane["ConnectionID"] = srm_ptr->requests->list.array[i]->request.inBoundLane.choice.connection; + break; + } + request["inBoundLane"] = inBoundLane; + + Json::Value expectedTimeOfArrival; + // Minute of the year + if(srm_ptr->requests->list.array[i]->minute) + { + expectedTimeOfArrival["ETA_Minute"] = *srm_ptr->requests->list.array[i]->minute; + } + if(srm_ptr->requests->list.array[i]->second) + { + expectedTimeOfArrival["ETA_Second"] = *srm_ptr->requests->list.array[i]->second; + } + /** + * The duration value is used to provide a short interval that extends + * the ETA so that the requesting vehicle can arrive at the point of service with + * uncertainty or with some desired duration of service. This concept can be used + * to avoid needing to frequently update the request. The requester must update + * the ETA and duration values if the period if services extends beyond the duration + * time. It should be assumed that if the vehicle does not clear the intersection + * when the duration is reached, the request will be cancelled and the intersection will + * revert to normal operation. + */ + if(srm_ptr->requests->list.array[i]->duration) + { + expectedTimeOfArrival["ETA_Duration"] = *srm_ptr->requests->list.array[i]->duration; + } + request["expectedTimeOfArrival"] = expectedTimeOfArrival; + + /** + * The requestor identifies itself using its current speed, heading and location. + */ + std::stringstream ss; + ss << srm_ptr->requestor.id.choice.entityID.buf; + auto id_len = srm_ptr->requestor.id.choice.entityID.size; + unsigned long id_num = 0; + for(auto i = 0; i < id_len; i++) + { + id_num = (id_num << 8) | srm_ptr->requestor.id.choice.entityID.buf[i]; + } + std::stringstream id_fill_ss; + id_fill_ss << std::hex << id_num; + request["vehicleID"] = id_fill_ss.str(); + if( srm_ptr->requestor.position) + { + if(srm_ptr->requestor.position->heading) + { + request["heading_Degree"] = *srm_ptr->requestor.position->heading; + } + if(srm_ptr->requestor.position->speed) + { + request["speed_MeterPerSecond"] = srm_ptr->requestor.position->speed->speed / FIFTY_TH; + } + } + + Json::Value position; + position["latitude_DecimalDegree"] = srm_ptr->requestor.position->position.lat / DEGREE_TO_TENTH_MICRODEGREE; + position["longitude_DecimalDegree"] = srm_ptr->requestor.position->position.Long / DEGREE_TO_TENTH_MICRODEGREE; + if(srm_ptr->requestor.position->position.elevation) + { + position["elevation_Meter"] = *srm_ptr->requestor.position->position.elevation * 10; + } + request["position"] = position; + srmJson["SignalRequest"] = request; + jsonV.push_back(srmJson); + } + + } +} diff --git a/src/v2i-hub/CARMAStreetsPlugin/src/J2735ToSRMJsonConverter.h b/src/v2i-hub/CARMAStreetsPlugin/src/J2735ToSRMJsonConverter.h new file mode 100755 index 000000000..aed9077db --- /dev/null +++ b/src/v2i-hub/CARMAStreetsPlugin/src/J2735ToSRMJsonConverter.h @@ -0,0 +1,27 @@ +#include "jsoncpp/json/json.h" +#include + +namespace CARMAStreetsPlugin +{ + class J2735ToSRMJsonConverter + { + private: + const std::string MsgType = "SRM"; + const float FIFTY_TH = 0.02; + const float DEGREE_TO_TENTH_MICRODEGREE = 10000000.0; + const int TEN_CM_TO_METER = 10; + + public: + /*** + *@brief Constructor to initialize the SRM to JSON converter + */ + J2735ToSRMJsonConverter(); + /*** + * @brief Convert J2735 SRM message into SignalRequests in JSON format + * @param Vector of JSON to be populated with SignalRequests from J2735 + * @param SrmMessage that has the J2735 SRM information + */ + void toSRMJsonV(std::vector &jsonV, tmx::messages::SrmMessage *srm); + ~J2735ToSRMJsonConverter(); + }; +} \ No newline at end of file diff --git a/src/v2i-hub/CARMAStreetsPlugin/test/test_J2735ToSRMJsonConverter.cpp b/src/v2i-hub/CARMAStreetsPlugin/test/test_J2735ToSRMJsonConverter.cpp new file mode 100644 index 000000000..aacbcaddf --- /dev/null +++ b/src/v2i-hub/CARMAStreetsPlugin/test/test_J2735ToSRMJsonConverter.cpp @@ -0,0 +1,137 @@ +#include +#include +#include + +class test_J2735ToSRMJsonConverter : public ::testing::Test +{ + +public: + test_J2735ToSRMJsonConverter() = default; + ~test_J2735ToSRMJsonConverter() = default; + +protected: + tmx::messages::SrmMessage *_srmMessage; + SignalRequestMessage_t *_message; + void SetUp() override + { + _message = (SignalRequestMessage_t *)calloc(1, sizeof(SignalRequestMessage_t)); + _message->second = 12; + RequestorDescription_t *requestor = (RequestorDescription_t *)calloc(1, sizeof(RequestorDescription_t)); + VehicleID_t *veh_id = (VehicleID_t *)calloc(1, sizeof(VehicleID_t)); + veh_id->present = VehicleID_PR_entityID; + TemporaryID_t *entity_id = (TemporaryID_t *)calloc(1, sizeof(TemporaryID_t)); + uint8_t my_bytes_id[4] = {(uint8_t)1, (uint8_t)12, (uint8_t)12, (uint8_t)10}; + entity_id->buf = my_bytes_id; + entity_id->size = sizeof(my_bytes_id); + veh_id->choice.entityID = *entity_id; + requestor->id = *veh_id; + RequestorType_t *requestType = (RequestorType_t *)calloc(1, sizeof(RequestorType_t)); + requestType->role = 0; + requestor->type = requestType; + RequestorPositionVector_t *position = (RequestorPositionVector_t *)calloc(1, sizeof(RequestorPositionVector_t)); + DSRC_Angle_t *heading_angle = (DSRC_Angle_t *)calloc(1, sizeof(DSRC_Angle_t)); + *heading_angle = 123; + position->heading = heading_angle; + Position3D_t *position_point = (Position3D_t *)calloc(1, sizeof(Position3D_t)); + DSRC_Elevation_t *elev = (DSRC_Elevation_t *)calloc(1, sizeof(DSRC_Elevation_t)); + *elev = 12; + position_point->elevation = elev; + position_point->lat = 3712333; + position_point->Long = 8012333; + position->position = *position_point; + TransmissionAndSpeed_t *speed = (TransmissionAndSpeed_t *)calloc(1, sizeof(TransmissionAndSpeed_t)); + speed->speed = 10; + TransmissionState_t *transmission_state = (TransmissionState_t *)calloc(1, sizeof(TransmissionState_t)); + *transmission_state = 1111; + speed->transmisson = 7; + position->speed = speed; + requestor->position = position; + _message->requestor = *requestor; + + SignalRequestList_t *requests = (SignalRequestList_t *)calloc(1, sizeof(SignalRequestList_t)); + //First: Request Package + SignalRequestPackage_t *request_package = (SignalRequestPackage_t *)calloc(1, sizeof(SignalRequestPackage_t)); + MinuteOfTheYear_t *min = (MinuteOfTheYear_t *)calloc(1, sizeof(MinuteOfTheYear_t)); + *min = 123; + request_package->minute = min; + DSecond_t *duration = (DSecond_t *)calloc(1, sizeof(DSecond_t)); + *duration = 122; + request_package->duration = duration; + DSecond_t *second = (DSecond_t *)calloc(1, sizeof(DSecond_t)); + *second = 1212; + request_package->second = second; + SignalRequest_t *request = (SignalRequest_t *)calloc(1, sizeof(SignalRequest_t)); + IntersectionReferenceID_t *refer_id = (IntersectionReferenceID_t *)calloc(1, sizeof(IntersectionReferenceID_t)); + refer_id->id = 1222; + request->id = *refer_id; + request->requestID = 1; + request->requestType = 0; + IntersectionAccessPoint_t *inBoundLane = (IntersectionAccessPoint_t *)calloc(1, sizeof(IntersectionAccessPoint_t)); + inBoundLane->present = IntersectionAccessPoint_PR_lane; + inBoundLane->choice.lane = 1; + request->inBoundLane = *inBoundLane; + request_package->request = *request; + asn_sequence_add(&requests->list.array, request_package); + + //Second: Request Package + SignalRequestPackage_t *request_package_2 = (SignalRequestPackage_t *)calloc(1, sizeof(SignalRequestPackage_t)); + request_package_2->minute = min; + request_package_2->duration = duration; + request_package_2->second = second; + SignalRequest_t *request_2 = (SignalRequest_t *)calloc(1, sizeof(SignalRequest_t)); + IntersectionReferenceID_t *referId2 = (IntersectionReferenceID_t *)calloc(1, sizeof(IntersectionReferenceID_t)); + referId2->id = 2333; + request_2->id = *referId2; + request_2->requestID = 2; + request_2->requestType = 1; + IntersectionAccessPoint_t *inBoundLane2 = (IntersectionAccessPoint_t *)calloc(1, sizeof(IntersectionAccessPoint_t)); + inBoundLane2->present = IntersectionAccessPoint_PR_approach; + inBoundLane2->choice.approach = 1; + request_2->inBoundLane = *inBoundLane2; + request_package_2->request = *request_2; + asn_sequence_add(&requests->list.array, request_package_2); + _message->requests = requests; + tmx::messages::SrmEncodedMessage srmEncodeMessage; + _srmMessage = new tmx::messages::SrmMessage(_message); + } +}; + +namespace unit_test +{ + TEST_F(test_J2735ToSRMJsonConverter, toSRMJson) + { + CARMAStreetsPlugin::J2735ToSRMJsonConverter srmConverter; + std::vector srmJsonV; + srmConverter.toSRMJsonV(srmJsonV, _srmMessage); + int expectedSrmSize = 2; + ASSERT_EQ(expectedSrmSize, srmJsonV.size()); + int i = 0; + for (auto srmJson : srmJsonV) + { + Json::FastWriter fastWriter; + std::string message = fastWriter.write(srmJson); + std::string expectedSrmStr = ""; + if (i == 0) + { + expectedSrmStr = "{\"MsgType\":\"SRM\",\"SignalRequest\":{\"basicVehicleRole\":0,\"expectedTimeOfArrival\":{\"ETA_Duration\":122,\"ETA_Minute\":123,\"ETA_Second\":1212},\"heading_Degree\":123,\"inBoundLane\":{\"LaneID\":1},\"intersectionID\":1222,\"minuteOfYear\":123,\"msOfMinute\":1212,\"position\":{\"elevation_Meter\":120,\"latitude_DecimalDegree\":0.37123331427574158,\"longitude_DecimalDegree\":0.80123329162597656},\"priorityRequestType\":0,\"speed_MeterPerSecond\":500.0,\"vehicleID\":\"10c0c0a\"}}\n"; + } + else if (i == 1) + { + expectedSrmStr = "{\"MsgType\":\"SRM\",\"SignalRequest\":{\"basicVehicleRole\":0,\"expectedTimeOfArrival\":{\"ETA_Duration\":122,\"ETA_Minute\":123,\"ETA_Second\":1212},\"heading_Degree\":123,\"inBoundLane\":{\"ApproachID\":1},\"intersectionID\":2333,\"minuteOfYear\":123,\"msOfMinute\":1212,\"position\":{\"elevation_Meter\":120,\"latitude_DecimalDegree\":0.37123331427574158,\"longitude_DecimalDegree\":0.80123329162597656},\"priorityRequestType\":1,\"speed_MeterPerSecond\":500.0,\"vehicleID\":\"10c0c0a\"}}\n"; + } + ASSERT_EQ(expectedSrmStr, message); + i++; + } + } + + TEST_F(test_J2735ToSRMJsonConverter, toSRMJsonNULLObj) + { + CARMAStreetsPlugin::J2735ToSRMJsonConverter srmConverter; + std::vector invalidSRMJson; + SignalRequestMessage_t *message = (SignalRequestMessage_t *)calloc(1, sizeof(SignalRequestMessage_t)); + auto invalidSRMmMessage = new tmx::messages::SrmMessage(message); + srmConverter.toSRMJsonV(invalidSRMJson, invalidSRMmMessage); + int expectedSrmSize = 0; + ASSERT_EQ(expectedSrmSize, invalidSRMJson.size()); + } +} From 1e65ccfda0816bf9fb46d5fd589a656239b1f1ae Mon Sep 17 00:00:00 2001 From: paulbourelly999 <77466294+paulbourelly999@users.noreply.github.com> Date: Fri, 5 May 2023 10:24:32 -0400 Subject: [PATCH 04/14] Fix for development image throwing exception unknown source stoul (#526) + Added /usr/lib and /usr/bin to deployed image + Adding log statement for handshake + Removing cpprest library dependency which is unused # PR Details ## Description ## Related Issue #525 ## Motivation and Context Fix CDASimAdapterPlugin functionality in development image ## How Has This Been Tested? Locally integration tested using steps in the related issue. ## Types of changes - [x] Defect fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that cause existing functionality to change) ## Checklist: - [ ] I have added any new packages to the sonar-scanner.properties file - [ ] My change requires a change to the documentation. - [ ] I have updated the documentation accordingly. - [x ] I have read the **CONTRIBUTING** document. [V2XHUB Contributing Guide](https://github.com/usdot-fhwa-OPS/V2X-Hub/blob/develop/Contributing.md) - [ ] I have added tests to cover my changes. - [ ] All new and existing tests passed. --- .dockerignore | 2 ++ Dockerfile | 2 ++ scripts/install_dependencies.sh | 1 - src/v2i-hub/CARMACloudPlugin/CMakeLists.txt | 2 +- src/v2i-hub/CDASimAdapter/src/CDASimConnection.cpp | 8 ++++++++ .../test/TestCARMASimulationConnection.cpp | 12 ++++++++++++ 6 files changed, 25 insertions(+), 2 deletions(-) diff --git a/.dockerignore b/.dockerignore index 4f9521841..b4fc88967 100644 --- a/.dockerignore +++ b/.dockerignore @@ -14,3 +14,5 @@ Dockerfile docker-compose.yml *.md +**/build + diff --git a/Dockerfile b/Dockerfile index 9bf05373d..0ba4b10e4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -42,6 +42,8 @@ RUN ldconfig COPY --from=dependencies /usr/local/plugins/ /usr/local/plugins/ COPY --from=dependencies /usr/local/lib/ /usr/local/lib/ COPY --from=dependencies /usr/local/bin/ /usr/local/bin/ +COPY --from=dependencies /usr/lib/ /usr/lib/ +COPY --from=dependencies /usr/bin/ /usr/bin/ COPY --from=dependencies /usr/local/share/ /usr/local/share/ COPY --from=dependencies /var/www/plugins/ /var/www/plugins/ COPY --from=dependencies /var/log/tmx/ /var/log/tmx/ diff --git a/scripts/install_dependencies.sh b/scripts/install_dependencies.sh index efd5f5010..9ddc86c72 100755 --- a/scripts/install_dependencies.sh +++ b/scripts/install_dependencies.sh @@ -13,7 +13,6 @@ DEPENDENCIES="build-essential \ cmake \ git \ libboost-all-dev \ - libcpprest-dev \ libcurl4-openssl-dev \ libev-dev \ libgps-dev \ diff --git a/src/v2i-hub/CARMACloudPlugin/CMakeLists.txt b/src/v2i-hub/CARMACloudPlugin/CMakeLists.txt index 767f81dc7..84ca7becd 100644 --- a/src/v2i-hub/CARMACloudPlugin/CMakeLists.txt +++ b/src/v2i-hub/CARMACloudPlugin/CMakeLists.txt @@ -30,7 +30,7 @@ BuildTmxPlugin () TARGET_INCLUDE_DIRECTORIES ( ${PROJECT_NAME} PUBLIC ${XercesC_INCLUDE_DIRS} ${NETSNMP_INCLUDE_DIRS} ${Qt5Core_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS}) -TARGET_LINK_LIBRARIES ( ${PROJECT_NAME} PUBLIC tmxutils ${XercesC_LIBRARY} ${NETSNMP_LIBRARIES} ${QHttpEngine_LIBRARY} ${Boost_SYSTEM_LIBRARY} ZLIB::ZLIB curl cpprest Qt5Widgets Qt5Core Qt5Network ssl crypto qhttpengine v2xhubWebAPI) +TARGET_LINK_LIBRARIES ( ${PROJECT_NAME} PUBLIC tmxutils ${XercesC_LIBRARY} ${NETSNMP_LIBRARIES} ${QHttpEngine_LIBRARY} ${Boost_SYSTEM_LIBRARY} ZLIB::ZLIB curl Qt5Widgets Qt5Core Qt5Network ssl crypto qhttpengine v2xhubWebAPI) link_directories(${CMAKE_PREFIX_PATH}/lib) \ No newline at end of file diff --git a/src/v2i-hub/CDASimAdapter/src/CDASimConnection.cpp b/src/v2i-hub/CDASimAdapter/src/CDASimConnection.cpp index b43e8c441..7349bda38 100644 --- a/src/v2i-hub/CDASimAdapter/src/CDASimConnection.cpp +++ b/src/v2i-hub/CDASimAdapter/src/CDASimConnection.cpp @@ -193,12 +193,20 @@ namespace CDASimAdapter{ void CDASimConnection::forward_message( const std::string &msg, const std::shared_ptr _client ) const { if ( !msg.empty() && _client) { + PLOG(logDEBUG) << "Sending UDP msg " << msg << " to host " << _client->GetAddress() + << ":" << _client->GetPort() << "." << std::endl; int ret =_client->Send(msg); if ( ret < 0) { throw UdpClientRuntimeError(("Failed to send message " + msg + " to " + _client->GetAddress() + ":" + std::to_string(_client->GetPort()) + " with error code : " + std::to_string(errno)).c_str()); } } + else if ( msg.empty() ) { + PLOG(logWARNING) << "Unable to send empty message to " << _client->GetAddress() << ":" << _client->GetPort() << "." << std::endl; + } + else { + PLOG(logWARNING) << "Unable to send message from uninitialized client." << std::endl; + } } void CDASimConnection::forward_v2x_message_to_simulation(const std::string &msg) const { diff --git a/src/v2i-hub/CDASimAdapter/test/TestCARMASimulationConnection.cpp b/src/v2i-hub/CDASimAdapter/test/TestCARMASimulationConnection.cpp index fa00203ce..442c83142 100644 --- a/src/v2i-hub/CDASimAdapter/test/TestCARMASimulationConnection.cpp +++ b/src/v2i-hub/CDASimAdapter/test/TestCARMASimulationConnection.cpp @@ -47,6 +47,18 @@ namespace CDASimAdapter { connection->forward_message(test_message, client); } + TEST_F( TestCARMASimulationConnection, forward_message_invalid ) { + std::shared_ptr client = std::make_shared(); + std::string test_message = ""; + // ASSERT that we never call Send message. + EXPECT_CALL( *client, Send(test_message) ).Times(0); + // sent empty message + connection->forward_message(test_message,client); + test_message = "message"; + client = nullptr; + connection->forward_message(test_message, client); + } + TEST_F( TestCARMASimulationConnection, consume_msg){ std::shared_ptr server = std::make_shared(); From 0ebfac5bedc0a5f00b4ec72c194158d075cda342 Mon Sep 17 00:00:00 2001 From: Saikrishna Bairamoni <84093461+SaikrishnaBairamoni@users.noreply.github.com> Date: Mon, 8 May 2023 14:54:10 -0400 Subject: [PATCH 05/14] Update Release_notes.md with 7.5.0 version --- docs/Release_notes.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/Release_notes.md b/docs/Release_notes.md index c03fe51c1..3ab4842c9 100644 --- a/docs/Release_notes.md +++ b/docs/Release_notes.md @@ -1,5 +1,31 @@ V2X-Hub Release Notes --------------------------------- + +Version 7.5.0, released May 5th, 2023 +-------------------------------------------------------- + +**Summary:** +V2X Hub release 7.5.0 is comprised of the following new features: a new ERVCloudForwardingPlugin to enable BSMs from active Emergency Response Vehicles (ERVs) to be forwarded to CARMA Cloud in support of message forwarding to V2X Hub instances along an ERV’s future route when deployed along with other CARMA tools to demonstrate move-over law when an ERV is approaching a CDA vehicle from behind; new features to support CARMA Simulation integration such as simulation clock functionality; and a newly developed CARMA Simulation adaptor shell and handshake functionality to allow multiple V2X Hub instances to connect with a single CARMA Simulation platform. Along with the above enhancements, several enhancements and bug fixes are included in this release. + +**Freight Emergency Response Functionalities** + +Enhancements in this release related to Freight Emergency Response: + +- PR 460: The creation of a new ERVCloudForwardingPlugin that enables V2X Hub to register a connected RSU, along with its location information, with CARMA Cloud. Additionally, this plugin is responsible for sending received BSMs from active Emergency Response Vehicles (ERVs) to CARMA Cloud in support of message forwarding to V2X Hub instances located along the ERV’s future route. + +**Other** + +Enhancements in this release: + +- Issue 262: Updated CARMA Streets plugin to receive and decode Mobility Path messages into JSON through Kafka. +- PR 486: Updated the V2X Hub docker images to Ubuntu 22 (Jammy) which has LTS support through April 2027. This will also support new libraries created using the Carma-builds project. +- PR 487: Added some changes to allow for Docker to be installed on different Linux distros for arm64. + +Fixes in this release: + +- Issue 484: Fixed PedestrianPlugin does not update when any configuration changes are made with in Plugin, either when plugin is off or on. +- PR 494: Sets some error message in the Command Plugin for file upload operations to ERROR instead of DEBUG so they can be seen on the command line by default. + Version 7.4.0, released Feb 10th, 2023 -------------------------------------------------------- From f7d694f383c2ca289ea03beb938e74edde52251a Mon Sep 17 00:00:00 2001 From: Saikrishna Bairamoni <84093461+SaikrishnaBairamoni@users.noreply.github.com> Date: Mon, 8 May 2023 15:01:48 -0400 Subject: [PATCH 06/14] update docker compose to point latest from release images --- configuration/amd64/docker-compose.yml | 6 +++--- configuration/arm64/docker-compose.yml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/configuration/amd64/docker-compose.yml b/configuration/amd64/docker-compose.yml index ffafacc38..6b5188297 100755 --- a/configuration/amd64/docker-compose.yml +++ b/configuration/amd64/docker-compose.yml @@ -20,7 +20,7 @@ services: - mysql-datavolume:/var/lib/mysql php: - image: usdotfhwaops/php:k900 + image: usdotfhwaops/php:latest container_name: php network_mode: host depends_on: @@ -30,7 +30,7 @@ services: tty: true v2xhub: - image: usdotfhwaops/v2xhubamd:k900 + image: usdotfhwaops/v2xhubamd:latest container_name: v2xhub network_mode: host restart: always @@ -44,7 +44,7 @@ services: - ./logs:/var/log/tmx - ./MAP:/var/www/plugins/MAP port_drayage_webservice: - image: usdotfhwaops/port-drayage-webservice:k900 + image: usdotfhwaops/port-drayage-webservice:latest container_name: port_drayage_webservice network_mode: host secrets: diff --git a/configuration/arm64/docker-compose.yml b/configuration/arm64/docker-compose.yml index 38c3359c6..a32c31fab 100644 --- a/configuration/arm64/docker-compose.yml +++ b/configuration/arm64/docker-compose.yml @@ -20,7 +20,7 @@ services: - mysql-datavolume:/var/lib/mysql php: - image: usdotfhwaops/php_arm:k900 + image: usdotfhwaops/php_arm:latest container_name: php network_mode: host depends_on: @@ -30,7 +30,7 @@ services: tty: true v2xhub: - image: usdotfhwaops/v2xhubarm:k900 + image: usdotfhwaops/v2xhubarm:latest container_name: v2xhub network_mode: host restart: always @@ -44,7 +44,7 @@ services: - ./logs:/var/log/tmx - ./MAP:/var/www/plugins/MAP port_drayage_webservice: - image: usdotfhwaops/port-drayage-webservice_arm:k900 + image: usdotfhwaops/port-drayage-webservice_arm:latest container_name: port_drayage_webservice network_mode: host secrets: From 71a6fe3b484febdbc3d41f8ef60451ddba0d1b91 Mon Sep 17 00:00:00 2001 From: paulbourelly999 <77466294+paulbourelly999@users.noreply.github.com> Date: Thu, 18 May 2023 16:32:23 -0400 Subject: [PATCH 07/14] Fix infrastructure sim message string (#532) # PR Details ## Description V2X-Hub CDASimAdapter would throw stoul invalid argument exceptions when attempting to set a string for the INFRASTRUCTURE_ID. This id needs to support string since NS-3/Mosiac rsu registration needs the rsu registration id to match the following format `rsu_`. This fixed the internal infrastructure id field to be string as well as removing the stoul casting of a string to a long to remove this exception. ## Related Issue #525 ## Motivation and Context See description ## How Has This Been Tested? Tested in AWS XIL Cloud deployment and on ubuntu v2xhub deployment. ## Types of changes - x] Defect fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that cause existing functionality to change) ## Checklist: - [ ] I have added any new packages to the sonar-scanner.properties file - [ ] My change requires a change to the documentation. - [ ] I have updated the documentation accordingly. - [x] I have read the **CONTRIBUTING** document. [V2XHUB Contributing Guide](https://github.com/usdot-fhwa-OPS/V2X-Hub/blob/develop/Contributing.md) - [ ] I have added tests to cover my changes. - [ ] All new and existing tests passed. --- src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp | 8 +++++++- src/v2i-hub/CDASimAdapter/src/CDASimConnection.cpp | 6 +++--- .../CDASimAdapter/src/include/CDASimConnection.hpp | 8 ++++---- .../CDASimAdapter/test/TestCARMASimulationConnection.cpp | 9 ++++----- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp b/src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp index a036ff6f2..b0883891d 100644 --- a/src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp +++ b/src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp @@ -86,7 +86,7 @@ namespace CDASimAdapter{ uint time_sync_port = std::stoul(sim::get_sim_config(sim::TIME_SYNC_PORT)); uint v2x_port = std::stoul(sim::get_sim_config(sim::V2X_PORT)); uint sim_v2x_port = std::stoul(sim::get_sim_config(sim::SIM_V2X_PORT)); - uint infrastructure_id = std::stoul(sim::get_sim_config(sim::INFRASTRUCTURE_ID));; + std::string infrastructure_id = sim::get_sim_config(sim::INFRASTRUCTURE_ID); PLOG(logINFO) << "CDASim connecting " << simulation_ip << "\nUsing Registration Port : " << std::to_string( simulation_registration_port) << @@ -106,6 +106,12 @@ namespace CDASimAdapter{ catch (const TmxException &e) { PLOG(logERROR) << "Exception occured attempting to initialize CDASim Connection : " << e.what() << std::endl; return false; + } + catch (const std::invalid_argument &e ) { + // std::stoul throws invalid arguement exception when provided with a string that contains characters that are not numbers. + PLOG(logERROR) << "Exception occured attempting to initialize CDASim Connection : " << e.what() << + ". Check environment variables are set to the correct type!"; + return false; } return connection->connect(); } diff --git a/src/v2i-hub/CDASimAdapter/src/CDASimConnection.cpp b/src/v2i-hub/CDASimAdapter/src/CDASimConnection.cpp index 7349bda38..54ac69758 100644 --- a/src/v2i-hub/CDASimAdapter/src/CDASimConnection.cpp +++ b/src/v2i-hub/CDASimAdapter/src/CDASimConnection.cpp @@ -4,7 +4,7 @@ using namespace tmx::utils; namespace CDASimAdapter{ - CDASimConnection::CDASimConnection(const std::string &simulation_ip, const uint infrastructure_id, const uint simulation_registration_port, const uint sim_v2x_port, + CDASimConnection::CDASimConnection(const std::string &simulation_ip, const std::string infrastructure_id, const uint simulation_registration_port, const uint sim_v2x_port, const std::string &local_ip, const uint time_sync_port, const uint v2x_port, const WGS84Point &location) : _simulation_ip(simulation_ip), _infrastructure_id(infrastructure_id), _simulation_registration_port(simulation_registration_port), @@ -33,7 +33,7 @@ namespace CDASimAdapter{ return _connected; } - std::string CDASimConnection::get_handshake_json(const uint infrastructure_id, const std::string &local_ip, const uint time_sync_port, const uint v2x_port, + std::string CDASimConnection::get_handshake_json(const std::string infrastructure_id, const std::string &local_ip, const uint time_sync_port, const uint v2x_port, const WGS84Point &location) const { @@ -52,7 +52,7 @@ namespace CDASimAdapter{ return message_str; } - bool CDASimConnection::carma_simulation_handshake(const std::string &simulation_ip, const uint infrastructure_id, const uint simulation_registration_port, + bool CDASimConnection::carma_simulation_handshake(const std::string &simulation_ip, const std::string infrastructure_id, const uint simulation_registration_port, const std::string &local_ip, const uint time_sync_port, const uint v2x_port, const WGS84Point &location) { diff --git a/src/v2i-hub/CDASimAdapter/src/include/CDASimConnection.hpp b/src/v2i-hub/CDASimAdapter/src/include/CDASimConnection.hpp index ab6771609..4ee21d643 100644 --- a/src/v2i-hub/CDASimAdapter/src/include/CDASimConnection.hpp +++ b/src/v2i-hub/CDASimAdapter/src/include/CDASimConnection.hpp @@ -32,7 +32,7 @@ namespace CDASimAdapter { * @param location Simulationed location of infrastructure. * @param producer Kafka Producer for forwarding time synchronization messages. */ - explicit CDASimConnection( const std::string &simulation_ip, const uint infrastructure_id, const uint simulation_registration_port, + explicit CDASimConnection( const std::string &simulation_ip, const std::string infrastructure_id, const uint simulation_registration_port, const uint sim_v2x_port, const std::string &local_ip, const uint time_sync_port, const uint v2x_port, const tmx::utils::WGS84Point &location); @@ -95,7 +95,7 @@ namespace CDASimAdapter { * @param location simulated location of infrastructure hardware. * @return true if handshake successful and false if handshake unsuccessful. */ - bool carma_simulation_handshake(const std::string &simulation_ip, const uint infrastructure_id, const uint simulation_registration_port, + bool carma_simulation_handshake(const std::string &simulation_ip, const std::string infrastructure_id, const uint simulation_registration_port, const std::string &local_ip, const uint time_sync_port, const uint v2x_port, const tmx::utils::WGS84Point &location); @@ -131,12 +131,12 @@ namespace CDASimAdapter { * @param location simulated location of infrastructure hardware. * @return true if handshake successful and false if handshake unsuccessful. */ - std::string get_handshake_json(const uint infrastructure_id, const std::string &local_ip, const uint time_sync_port, + std::string get_handshake_json(const std::string infrastructure_id, const std::string &local_ip, const uint time_sync_port, const uint v2x_port, const tmx::utils::WGS84Point &location) const; std::string _simulation_ip; uint _simulation_registration_port; - uint _infrastructure_id; + std::string _infrastructure_id; uint _simulation_v2x_port; std::string _local_ip; uint _time_sync_port; diff --git a/src/v2i-hub/CDASimAdapter/test/TestCARMASimulationConnection.cpp b/src/v2i-hub/CDASimAdapter/test/TestCARMASimulationConnection.cpp index 442c83142..32882a18d 100644 --- a/src/v2i-hub/CDASimAdapter/test/TestCARMASimulationConnection.cpp +++ b/src/v2i-hub/CDASimAdapter/test/TestCARMASimulationConnection.cpp @@ -24,7 +24,7 @@ namespace CDASimAdapter { void SetUp() override { // Initialize CARMA Simulation connection with (0,0,0) location and mock kafka producer. WGS84Point location; - connection = std::make_shared("127.0.0.1", 1212, 4567, 4678, "127.0.0.1", 1213, 1214, location); + connection = std::make_shared("127.0.0.1", "1212", 4567, 4678, "127.0.0.1", 1213, 1214, location); } void TearDown() override { @@ -87,15 +87,14 @@ namespace CDASimAdapter { location.Elevation = 1000; location.Latitude = 38.955; location.Longitude = -77.149; - - ASSERT_EQ(connection->get_handshake_json(4566, "127.0.0.1", 4567, 4568, location), - "{\n \"infrastructureId\" : 4566,\n \"location\" : {\n \"elevation\" : 1000.0,\n \"latitude\" : 38.954999999999998,\n \"longitude\" : -77.149000000000001\n },\n \"rxMessageIpAddress\" : \"127.0.0.1\",\n \"rxMessagePort\" : 4568,\n \"timeSyncPort\" : 4567\n}\n"); + ASSERT_EQ(connection->get_handshake_json("4566", "127.0.0.1", 4567, 4568, location), + "{\n \"infrastructureId\" : \"4566\",\n \"location\" : {\n \"elevation\" : 1000.0,\n \"latitude\" : 38.954999999999998,\n \"longitude\" : -77.149000000000001\n },\n \"rxMessageIpAddress\" : \"127.0.0.1\",\n \"rxMessagePort\" : 4568,\n \"timeSyncPort\" : 4567\n}\n"); } TEST_F( TestCARMASimulationConnection, carma_simulation_handshake) { WGS84Point location; // UDP creation error - ASSERT_FALSE(connection->carma_simulation_handshake("", 45, NULL, + ASSERT_FALSE(connection->carma_simulation_handshake("", "45", NULL, "", 45, 45, location)); } From 53f34f0e380879b3d0461adc171600cac53574a4 Mon Sep 17 00:00:00 2001 From: paulbourelly999 <77466294+paulbourelly999@users.noreply.github.com> Date: Mon, 22 May 2023 18:08:15 -0400 Subject: [PATCH 08/14] Added Point class and used as cartesian point for (#535) CDASim Infrastructure registration # PR Details ## Description Updated infrastructure registration to use a cartesian point as location over a geodetic point to allow for easier configuration of simulated location of rsu ## Related Issue ## Motivation and Context ## How Has This Been Tested? Tested using dev-container 1) Started up dev container with SIMULATION_MODE true 2) Saw log message for sending Infrastructure Registration Message ## Types of changes - [x] Defect fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that cause existing functionality to change) ## Checklist: - [ ] I have added any new packages to the sonar-scanner.properties file - [x] My change requires a change to the documentation. - [x] I have updated the documentation accordingly. - [x] I have read the **CONTRIBUTING** document. [V2XHUB Contributing Guide](https://github.com/usdot-fhwa-OPS/V2X-Hub/blob/develop/Contributing.md) - [ ] I have added tests to cover my changes. - [x] All new and existing tests passed. --- src/tmx/TmxUtils/src/Point.h | 19 +++++++++++++++++++ src/v2i-hub/CDASimAdapter/manifest.json | 12 ++++++------ .../CDASimAdapter/src/CDASimAdapter.cpp | 10 +++++----- .../CDASimAdapter/src/CDASimConnection.cpp | 14 +++++++------- .../src/include/CDASimAdapter.hpp | 2 +- .../src/include/CDASimConnection.hpp | 12 ++++++------ .../test/TestCARMASimulationConnection.cpp | 17 +++++++++-------- 7 files changed, 53 insertions(+), 33 deletions(-) create mode 100644 src/tmx/TmxUtils/src/Point.h diff --git a/src/tmx/TmxUtils/src/Point.h b/src/tmx/TmxUtils/src/Point.h new file mode 100644 index 000000000..b075d4430 --- /dev/null +++ b/src/tmx/TmxUtils/src/Point.h @@ -0,0 +1,19 @@ +#pragma once + +namespace tmx::utils { + + + /// Cartesian Coordinates on a . + typedef struct Point + { + Point() : X(0), Y(0), Z(0) {} + + Point(double x, double y, double z = 0.0): + X(x), Y(y), Z(z) { } + + double X; + double Y; + double Z; + } Point; + +} // namespace tmx::utils diff --git a/src/v2i-hub/CDASimAdapter/manifest.json b/src/v2i-hub/CDASimAdapter/manifest.json index e01753f7a..00859a144 100755 --- a/src/v2i-hub/CDASimAdapter/manifest.json +++ b/src/v2i-hub/CDASimAdapter/manifest.json @@ -14,19 +14,19 @@ "description":"The log level for this plugin" }, { - "key":"Longitude", + "key":"X", "default":"0.0", - "description":"Longitude (in degrees) of the location of the simulated infrastructure." + "description":"Cartesian X coordinate in simulated map (in meters)." }, { - "key":"Latitude", + "key":"Y", "default":"0.0", - "description":"Latitude (in degrees) of the location of the simulated infrastructure." + "description":"Cartesian Y coordinate in simulated map (in meters)." }, { - "key":"Elevation", + "key":"Z", "default":"0.0", - "description":"Elevation (in degrees) of the location of the simulated infrastructure." + "description":"Cartesian Z coordinate in simulated map (in meters)." } ] diff --git a/src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp b/src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp index b0883891d..4820a413b 100644 --- a/src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp +++ b/src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp @@ -13,11 +13,11 @@ namespace CDASimAdapter{ } void CDASimAdapter::UpdateConfigSettings() { - GetConfigValue("Longitude", location.Longitude); - GetConfigValue("Latitude", location.Latitude); - GetConfigValue("Elevation", location.Elevation); - PLOG(logINFO) << "Location of Simulated V2X-Hub updated to : {" << location.Longitude << ", " - << location.Latitude << ", " << location.Elevation << "}." << std::endl; + GetConfigValue("X", location.Z); + GetConfigValue("Y", location.Y); + GetConfigValue("Z", location.X); + PLOG(logINFO) << "Location of Simulated V2X-Hub updated to : {" << location.X << ", " + << location.Y << ", " << location.Z << "}." << std::endl; } void CDASimAdapter::OnConfigChanged(const char *key, const char *value) { diff --git a/src/v2i-hub/CDASimAdapter/src/CDASimConnection.cpp b/src/v2i-hub/CDASimAdapter/src/CDASimConnection.cpp index 54ac69758..e5e3a4a66 100644 --- a/src/v2i-hub/CDASimAdapter/src/CDASimConnection.cpp +++ b/src/v2i-hub/CDASimAdapter/src/CDASimConnection.cpp @@ -6,7 +6,7 @@ using namespace tmx::utils; namespace CDASimAdapter{ CDASimConnection::CDASimConnection(const std::string &simulation_ip, const std::string infrastructure_id, const uint simulation_registration_port, const uint sim_v2x_port, const std::string &local_ip, const uint time_sync_port, const uint v2x_port, - const WGS84Point &location) : + const Point &location) : _simulation_ip(simulation_ip), _infrastructure_id(infrastructure_id), _simulation_registration_port(simulation_registration_port), _simulation_v2x_port(sim_v2x_port), _local_ip(local_ip), _time_sync_port(time_sync_port), _v2x_port(v2x_port), _location(location) { @@ -33,8 +33,8 @@ namespace CDASimAdapter{ return _connected; } - std::string CDASimConnection::get_handshake_json(const std::string infrastructure_id, const std::string &local_ip, const uint time_sync_port, const uint v2x_port, - const WGS84Point &location) const + std::string CDASimConnection::get_handshake_json(const std::string &infrastructure_id, const std::string &local_ip, const uint time_sync_port, const uint v2x_port, + const Point &location) const { Json::Value message; @@ -44,9 +44,9 @@ namespace CDASimAdapter{ message["infrastructureId"] = infrastructure_id; message["rxMessagePort"] = v2x_port; message["timeSyncPort"] = time_sync_port; - message["location"]["latitude"] = location.Latitude; - message["location"]["longitude"] = location.Longitude; - message["location"]["elevation"] = location.Elevation; + message["location"]["x"] = location.X; + message["location"]["y"] = location.Y; + message["location"]["z"] = location.Z; Json::StyledWriter writer; message_str = writer.write(message); return message_str; @@ -54,7 +54,7 @@ namespace CDASimAdapter{ bool CDASimConnection::carma_simulation_handshake(const std::string &simulation_ip, const std::string infrastructure_id, const uint simulation_registration_port, const std::string &local_ip, const uint time_sync_port, const uint v2x_port, - const WGS84Point &location) + const Point &location) { // Create JSON message with the content std::string payload = ""; diff --git a/src/v2i-hub/CDASimAdapter/src/include/CDASimAdapter.hpp b/src/v2i-hub/CDASimAdapter/src/include/CDASimAdapter.hpp index 6de71bcd6..69cbbf135 100644 --- a/src/v2i-hub/CDASimAdapter/src/include/CDASimAdapter.hpp +++ b/src/v2i-hub/CDASimAdapter/src/include/CDASimAdapter.hpp @@ -110,7 +110,7 @@ namespace CDASimAdapter { private: - tmx::utils::WGS84Point location; + tmx::utils::Point location; std::shared_ptr time_producer; std::unique_ptr connection; std::mutex _lock; diff --git a/src/v2i-hub/CDASimAdapter/src/include/CDASimConnection.hpp b/src/v2i-hub/CDASimAdapter/src/include/CDASimConnection.hpp index 4ee21d643..8612c72f6 100644 --- a/src/v2i-hub/CDASimAdapter/src/include/CDASimConnection.hpp +++ b/src/v2i-hub/CDASimAdapter/src/include/CDASimConnection.hpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include #include @@ -34,7 +34,7 @@ namespace CDASimAdapter { */ explicit CDASimConnection( const std::string &simulation_ip, const std::string infrastructure_id, const uint simulation_registration_port, const uint sim_v2x_port, const std::string &local_ip, const uint time_sync_port, const uint v2x_port, - const tmx::utils::WGS84Point &location); + const tmx::utils::Point &location); /** * @brief Method to forward v2x message to CARMA Simulation @@ -97,7 +97,7 @@ namespace CDASimAdapter { */ bool carma_simulation_handshake(const std::string &simulation_ip, const std::string infrastructure_id, const uint simulation_registration_port, const std::string &local_ip, const uint time_sync_port, const uint v2x_port, - const tmx::utils::WGS84Point &location); + const tmx::utils::Point &location); /** * @brief Method to setup UDP Servers and Clients after handshake to facilate message forwarding. @@ -131,8 +131,8 @@ namespace CDASimAdapter { * @param location simulated location of infrastructure hardware. * @return true if handshake successful and false if handshake unsuccessful. */ - std::string get_handshake_json(const std::string infrastructure_id, const std::string &local_ip, const uint time_sync_port, - const uint v2x_port, const tmx::utils::WGS84Point &location) const; + std::string get_handshake_json(const std::string &infrastructure_id, const std::string &local_ip, const uint time_sync_port, + const uint v2x_port, const tmx::utils::Point &location) const; std::string _simulation_ip; uint _simulation_registration_port; @@ -141,7 +141,7 @@ namespace CDASimAdapter { std::string _local_ip; uint _time_sync_port; uint _v2x_port; - tmx::utils::WGS84Point _location; + tmx::utils::Point _location; bool _connected = false; std::shared_ptr carma_simulation_listener; diff --git a/src/v2i-hub/CDASimAdapter/test/TestCARMASimulationConnection.cpp b/src/v2i-hub/CDASimAdapter/test/TestCARMASimulationConnection.cpp index 32882a18d..28b7376ab 100644 --- a/src/v2i-hub/CDASimAdapter/test/TestCARMASimulationConnection.cpp +++ b/src/v2i-hub/CDASimAdapter/test/TestCARMASimulationConnection.cpp @@ -23,9 +23,8 @@ namespace CDASimAdapter { protected: void SetUp() override { // Initialize CARMA Simulation connection with (0,0,0) location and mock kafka producer. - WGS84Point location; + Point location; connection = std::make_shared("127.0.0.1", "1212", 4567, 4678, "127.0.0.1", 1213, 1214, location); - } void TearDown() override { @@ -83,16 +82,18 @@ namespace CDASimAdapter { } TEST_F( TestCARMASimulationConnection, get_handshake_json) { - WGS84Point location; - location.Elevation = 1000; - location.Latitude = 38.955; - location.Longitude = -77.149; + Point location; + location.X = 1000; + location.Y = 38.955; + location.Z = -77.149; + ASSERT_EQ(connection->get_handshake_json("4566", "127.0.0.1", 4567, 4568, location), - "{\n \"infrastructureId\" : \"4566\",\n \"location\" : {\n \"elevation\" : 1000.0,\n \"latitude\" : 38.954999999999998,\n \"longitude\" : -77.149000000000001\n },\n \"rxMessageIpAddress\" : \"127.0.0.1\",\n \"rxMessagePort\" : 4568,\n \"timeSyncPort\" : 4567\n}\n"); + "{\n \"infrastructureId\" : \"4566\",\n \"location\" : {\n \"x\" : 1000.0,\n \"y\" : 38.954999999999998,\n \"z\" : -77.149000000000001\n },\n \"rxMessageIpAddress\" : \"127.0.0.1\",\n \"rxMessagePort\" : 4568,\n \"timeSyncPort\" : 4567\n}\n"); + } TEST_F( TestCARMASimulationConnection, carma_simulation_handshake) { - WGS84Point location; + Point location; // UDP creation error ASSERT_FALSE(connection->carma_simulation_handshake("", "45", NULL, "", 45, 45, location)); From e2d8c6e36a142cbfcb6544727a15566a780ea12d Mon Sep 17 00:00:00 2001 From: paulbourelly999 <77466294+paulbourelly999@users.noreply.github.com> Date: Wed, 24 May 2023 13:47:30 -0400 Subject: [PATCH 09/14] Fixed X and Z coordinate configuration loading (#537) # PR Details ## Description Fix configuration parameters to correctly map x,y,z coordinates to Point for Infrastructure registration. ## Related Issue ## Motivation and Context Fix configuration parameters to correctly map x,y,z coordinates to Point for Infrastructure registration. ## How Has This Been Tested? ## Types of changes - [ x] Defect fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that cause existing functionality to change) ## Checklist: - [ ] I have added any new packages to the sonar-scanner.properties file - [ ] My change requires a change to the documentation. - [ ] I have updated the documentation accordingly. - [x ] I have read the **CONTRIBUTING** document. [V2XHUB Contributing Guide](https://github.com/usdot-fhwa-OPS/V2X-Hub/blob/develop/Contributing.md) - [ ] I have added tests to cover my changes. - [ ] All new and existing tests passed. --- src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp b/src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp index 4820a413b..95754fa9f 100644 --- a/src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp +++ b/src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp @@ -13,9 +13,9 @@ namespace CDASimAdapter{ } void CDASimAdapter::UpdateConfigSettings() { - GetConfigValue("X", location.Z); + GetConfigValue("X", location.X); GetConfigValue("Y", location.Y); - GetConfigValue("Z", location.X); + GetConfigValue("Z", location.Z); PLOG(logINFO) << "Location of Simulated V2X-Hub updated to : {" << location.X << ", " << location.Y << ", " << location.Z << "}." << std::endl; } From 9169f459a613d686834b369e2e010795e91fe3b7 Mon Sep 17 00:00:00 2001 From: paulbourelly999 <77466294+paulbourelly999@users.noreply.github.com> Date: Fri, 2 Jun 2023 12:23:10 -0400 Subject: [PATCH 10/14] =?UTF-8?q?Fix:=20Added=20sleep=20between=20connecti?= =?UTF-8?q?on=20attempts=20to=20avoid=20excessive=20failu=E2=80=A6=20(#536?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …res and logs # PR Details ## Description Fix for CDASimAdapter Plugin which was excessively logging connection failures and CDASim crashes. Added a sleep period inbetween connection attempts ## Related Issue ## Motivation and Context Avoid excessive failed connection attempts and resulting excessive failed connection logs. ## How Has This Been Tested? In progress ## Types of changes - [ x] Defect fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that cause existing functionality to change) ## Checklist: - [ ] I have added any new packages to the sonar-scanner.properties file - [ ] My change requires a change to the documentation. - [ ] I have updated the documentation accordingly. - [x] I have read the **CONTRIBUTING** document. [V2XHUB Contributing Guide](https://github.com/usdot-fhwa-OPS/V2X-Hub/blob/develop/Contributing.md) - [ ] I have added tests to cover my changes. - [ ] All new and existing tests passed. --- src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp b/src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp index 95754fa9f..05378d199 100644 --- a/src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp +++ b/src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp @@ -33,7 +33,11 @@ namespace CDASimAdapter{ // While CARMA Simulation connection is down, attempt to reconnect while ( !connection || !connection->is_connected() ) { - connect(); + bool success = connect(); + // Sleep for 2 seconds in between connection attempts + if ( !connection->is_connected() ) { + sleep(2); + } } if ( connection->is_connected() ) { From 281ad943fed3588320424ec4529f6ae50005c0e3 Mon Sep 17 00:00:00 2001 From: paulbourelly999 <77466294+paulbourelly999@users.noreply.github.com> Date: Tue, 6 Jun 2023 10:25:41 -0400 Subject: [PATCH 11/14] Added configuration parameters to CDASimAdapter (#539) # PR Details ## Description + Added MaxConnectionAttempts to limit connection attempts + Added configurable sleep time between attempts + Added comments and renamed some internal variable to improve readability ## Related Issue ## Motivation and Context More robust CDASim connection logic ## How Has This Been Tested? Integration tested with dev container setup ## Types of changes - [ ] Defect fix (non-breaking change that fixes an issue) - [x] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that cause existing functionality to change) ## Checklist: - [ ] I have added any new packages to the sonar-scanner.properties file - [x] My change requires a change to the documentation. - [x] I have updated the documentation accordingly. - [x] I have read the **CONTRIBUTING** document. [V2XHUB Contributing Guide](https://github.com/usdot-fhwa-OPS/V2X-Hub/blob/develop/Contributing.md) - [ ] I have added tests to cover my changes. - [x] All new and existing tests passed. --- src/v2i-hub/CDASimAdapter/manifest.json | 11 ++++ .../CDASimAdapter/src/CDASimAdapter.cpp | 66 ++++++++++++------- .../CDASimAdapter/src/CDASimConnection.cpp | 4 +- .../src/include/CDASimAdapter.hpp | 55 ++++++++++------ .../src/include/CDASimConnection.hpp | 4 +- 5 files changed, 92 insertions(+), 48 deletions(-) diff --git a/src/v2i-hub/CDASimAdapter/manifest.json b/src/v2i-hub/CDASimAdapter/manifest.json index 00859a144..aabe404be 100755 --- a/src/v2i-hub/CDASimAdapter/manifest.json +++ b/src/v2i-hub/CDASimAdapter/manifest.json @@ -27,7 +27,18 @@ "key":"Z", "default":"0.0", "description":"Cartesian Z coordinate in simulated map (in meters)." + }, + { + "key":"MaxConnectionAttempts", + "default":"10", + "description":"Number of connection attempts CDASimAdapter plugin will execute before failing. Valid values are any integers greater than or equal to 1. Any value less than 1 will result in unlimited connection attemtps." + }, + { + "key":"ConnectionSleepTime", + "default":"4", + "description":"Number of seconds to wait after a failed CDASim connection attempt, before retrying to establish connection. Valid values are equal or greater than 1. Any value less than 1 will be treated as 1." } + ] } diff --git a/src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp b/src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp index 05378d199..01cec61ef 100644 --- a/src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp +++ b/src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp @@ -13,11 +13,22 @@ namespace CDASimAdapter{ } void CDASimAdapter::UpdateConfigSettings() { - GetConfigValue("X", location.X); - GetConfigValue("Y", location.Y); - GetConfigValue("Z", location.Z); + std::scoped_lock lock(_lock); + bool success = false; + success = GetConfigValue("X", location.X); + success = success && GetConfigValue("Y", location.Y); + success = success && GetConfigValue("Z", location.Z); PLOG(logINFO) << "Location of Simulated V2X-Hub updated to : {" << location.X << ", " << location.Y << ", " << location.Z << "}." << std::endl; + success = success && GetConfigValue("MaxConnectionAttempts", max_connection_attempts); + success = success && GetConfigValue("ConnectionSleepTime", connection_sleep_time); + if (connection_sleep_time < 1 ) { + PLOG(logWARNING) << "ConnectionSleepTime of " << connection_sleep_time << " is invalid. Valid values are <= 1." << std::endl; + connection_sleep_time = 1; + } + if (!success) { + PLOG(logWARNING) << "Some configuration parameters were not successfully loaded! Please ensure configuration parameter keys are correct!" << std::endl; + } } void CDASimAdapter::OnConfigChanged(const char *key, const char *value) { @@ -32,18 +43,27 @@ namespace CDASimAdapter{ UpdateConfigSettings(); // While CARMA Simulation connection is down, attempt to reconnect - while ( !connection || !connection->is_connected() ) { + int connection_attempts = 0; + while ( (!connection || !connection->is_connected()) && (connection_attempts < max_connection_attempts || max_connection_attempts < 1 ) ) { + PLOG(logINFO) << "Attempting CDASim connection " << connection_attempts << "/" << max_connection_attempts << " ..." << std::endl; bool success = connect(); - // Sleep for 2 seconds in between connection attempts - if ( !connection->is_connected() ) { - sleep(2); + if (success) { + PLOG(logINFO) << "Connection to CDASim established!" << std::endl; + } + connection_attempts++; + // Sleep for configurable seconds in between connection attempts. No sleep is required on final failing attempt + if ( !connection->is_connected() && (connection_attempts < max_connection_attempts || max_connection_attempts < 1 ) ) { + PLOG(logDEBUG) << "Sleeping for " << connection_sleep_time << " seconds before next connection attempt ..." << std::endl; + std::this_thread::sleep_for(std::chrono::seconds(connection_sleep_time)); } } if ( connection->is_connected() ) { start_time_sync_thread_timer(); - start_amf_msg_thread(); - start_binary_msg_thread(); + start_immediate_forward_thread(); + start_message_receiver_thread(); + }else { + PLOG(logERROR) << "CDASim connection failed!" << std::endl; } } @@ -122,30 +142,30 @@ namespace CDASimAdapter{ - void CDASimAdapter::start_amf_msg_thread() { - if ( !amf_thread_timer ) { - amf_thread_timer = std::make_unique(); + void CDASimAdapter::start_immediate_forward_thread() { + if ( !immediate_forward_timer ) { + immediate_forward_timer = std::make_unique(); } - amf_msg_tick_id = amf_thread_timer->AddPeriodicTick([this]() { + immediate_forward_tick_id = immediate_forward_timer->AddPeriodicTick([this]() { this->attempt_message_from_v2xhub(); } // end of lambda expression , std::chrono::milliseconds(100) ); - amf_thread_timer->Start(); + immediate_forward_timer->Start(); } - void CDASimAdapter::start_binary_msg_thread() { - if ( !binary_thread_timer ) { - binary_thread_timer = std::make_unique(); + void CDASimAdapter::start_message_receiver_thread() { + if ( !message_receiver_timer ) { + message_receiver_timer = std::make_unique(); } - binary_msg_tick_id = binary_thread_timer->AddPeriodicTick([this]() { + message_receiver_tick_id = message_receiver_timer->AddPeriodicTick([this]() { this->attempt_message_from_simulation(); } // end of lambda expression , std::chrono::milliseconds(100) ); - binary_thread_timer->Start(); + message_receiver_timer->Start(); } @@ -185,15 +205,15 @@ namespace CDASimAdapter{ void CDASimAdapter::start_time_sync_thread_timer() { PLOG(logDEBUG) << "Creating Thread Timer for time sync" << std::endl; - if ( !thread_timer ) { - thread_timer = std::make_unique(); + if ( !time_sync_timer ) { + time_sync_timer = std::make_unique(); } - time_sync_tick_id = thread_timer->AddPeriodicTick([this]() { + time_sync_tick_id = time_sync_timer->AddPeriodicTick([this]() { PLOG(logDEBUG1) << "Listening for time sync messages from CDASim." << std::endl; this->attempt_time_sync(); } // end of lambda expression , std::chrono::milliseconds(100)); - thread_timer->Start(); + time_sync_timer->Start(); } void CDASimAdapter::attempt_time_sync() { diff --git a/src/v2i-hub/CDASimAdapter/src/CDASimConnection.cpp b/src/v2i-hub/CDASimAdapter/src/CDASimConnection.cpp index e5e3a4a66..51f55eaf2 100644 --- a/src/v2i-hub/CDASimAdapter/src/CDASimConnection.cpp +++ b/src/v2i-hub/CDASimAdapter/src/CDASimConnection.cpp @@ -4,7 +4,7 @@ using namespace tmx::utils; namespace CDASimAdapter{ - CDASimConnection::CDASimConnection(const std::string &simulation_ip, const std::string infrastructure_id, const uint simulation_registration_port, const uint sim_v2x_port, + CDASimConnection::CDASimConnection(const std::string &simulation_ip, const std::string &infrastructure_id, const uint simulation_registration_port, const uint sim_v2x_port, const std::string &local_ip, const uint time_sync_port, const uint v2x_port, const Point &location) : _simulation_ip(simulation_ip), _infrastructure_id(infrastructure_id), _simulation_registration_port(simulation_registration_port), @@ -52,7 +52,7 @@ namespace CDASimAdapter{ return message_str; } - bool CDASimConnection::carma_simulation_handshake(const std::string &simulation_ip, const std::string infrastructure_id, const uint simulation_registration_port, + bool CDASimConnection::carma_simulation_handshake(const std::string &simulation_ip, const std::string &infrastructure_id, const uint simulation_registration_port, const std::string &local_ip, const uint time_sync_port, const uint v2x_port, const Point &location) { diff --git a/src/v2i-hub/CDASimAdapter/src/include/CDASimAdapter.hpp b/src/v2i-hub/CDASimAdapter/src/include/CDASimAdapter.hpp index 69cbbf135..fd586fafc 100644 --- a/src/v2i-hub/CDASimAdapter/src/include/CDASimAdapter.hpp +++ b/src/v2i-hub/CDASimAdapter/src/include/CDASimAdapter.hpp @@ -1,7 +1,7 @@ //============================================================================ -// Name : EpcwPlugin.cpp -// Author : -// Version : +// Name : CDASimAdapter.cpp +// Author : Paul Bourelly +// Version : 7.5.1 // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //============================================================================ @@ -23,24 +23,24 @@ #include #include "ThreadWorker.h" - - - -namespace CDASimAdapter { +namespace CDASimAdapter +{ /** - * @brief V2X-Hub Plugin that acts as a adapter for integration with CARMA-Simulation. Plugin used + * @brief V2X-Hub Plugin that acts as a adapter for integration with CARMA-Simulation. Plugin used * environment variable to be installed and enabled by default. */ - class CDASimAdapter: public tmx::utils::PluginClient{ + class CDASimAdapter : public tmx::utils::PluginClient + { public: /** * @brief CARMA-Simulation Infrastructure Adapter constructor. * @param name name of plugin. */ explicit CDASimAdapter(const std::string &name); - - int Main() override ; + + int Main() override; + protected: /** * @brief Called everytime a configuration value is changed for the plugin. @@ -60,7 +60,7 @@ namespace CDASimAdapter { */ void OnStateChange(IvpPluginState state) override; // Virtual method overrides END. - + /** * @brief Get Kafka Connection string from environment variable KAFKA_BROKER_ADDRESS and time sync topic name from * CARMA_INFRASTRUCTURE_TIME_SYNC_TOPIC and initialize a Kafka producer to forward time synchronization messages to @@ -77,12 +77,12 @@ namespace CDASimAdapter { /** * @brief Method to start thread timer for processing msg from v2xhub */ - void start_amf_msg_thread(); + void start_immediate_forward_thread(); /** * @brief Method to start thread timer for processing msg from CDASimConnection */ - void start_binary_msg_thread(); + void start_message_receiver_thread(); /** * @brief Method to consume msg in amf fromat from V2Xhub and forward to CDASimConnection @@ -107,18 +107,31 @@ namespace CDASimAdapter { * @brief Method to consume time sychrononization from CDASimConnection and forward to tmx core and CARMA Streets */ void attempt_time_sync(); - - private: + private: + // Simulated location of RSU tmx::utils::Point location; + // Stores configurable MaxConnectionAttempts. Any value > 1 will result in infinite connection attempts. + int max_connection_attempts; + // Time in seconds between connection attempts. Most be greater than zero! + uint connection_sleep_time; + // Kafka producer for sending time_sync messages to carma-streets std::shared_ptr time_producer; + // CDASim connection std::unique_ptr connection; + // Mutex for configuration parameter thread safety std::mutex _lock; - std::unique_ptr thread_timer; + // Time sync thread to forward time sync messages to PluginClientClockAware V2X-Hub plugins. + std::unique_ptr time_sync_timer; + // Time sync thread id int time_sync_tick_id; - std::unique_ptr amf_thread_timer; - std::unique_ptr binary_thread_timer; - int amf_msg_tick_id; - int binary_msg_tick_id; + // Immediate forward thread to consume messages from the immediate forward plugin and send to CDASim + std::unique_ptr immediate_forward_timer; + // Immediate forward thread id + int immediate_forward_tick_id; + // Message receiver thread to consume messages from CDASim and forward them to the message receiver. + std::unique_ptr message_receiver_timer; + // Message receiver thread id + int message_receiver_tick_id; }; } \ No newline at end of file diff --git a/src/v2i-hub/CDASimAdapter/src/include/CDASimConnection.hpp b/src/v2i-hub/CDASimAdapter/src/include/CDASimConnection.hpp index 8612c72f6..86bd0ff95 100644 --- a/src/v2i-hub/CDASimAdapter/src/include/CDASimConnection.hpp +++ b/src/v2i-hub/CDASimAdapter/src/include/CDASimConnection.hpp @@ -32,7 +32,7 @@ namespace CDASimAdapter { * @param location Simulationed location of infrastructure. * @param producer Kafka Producer for forwarding time synchronization messages. */ - explicit CDASimConnection( const std::string &simulation_ip, const std::string infrastructure_id, const uint simulation_registration_port, + explicit CDASimConnection( const std::string &simulation_ip, const std::string &infrastructure_id, const uint simulation_registration_port, const uint sim_v2x_port, const std::string &local_ip, const uint time_sync_port, const uint v2x_port, const tmx::utils::Point &location); @@ -95,7 +95,7 @@ namespace CDASimAdapter { * @param location simulated location of infrastructure hardware. * @return true if handshake successful and false if handshake unsuccessful. */ - bool carma_simulation_handshake(const std::string &simulation_ip, const std::string infrastructure_id, const uint simulation_registration_port, + bool carma_simulation_handshake(const std::string &simulation_ip, const std::string &infrastructure_id, const uint simulation_registration_port, const std::string &local_ip, const uint time_sync_port, const uint v2x_port, const tmx::utils::Point &location); From d89ef32cc77d7c678847857483d84836b249dde6 Mon Sep 17 00:00:00 2001 From: Saikrishna Bairamoni <84093461+SaikrishnaBairamoni@users.noreply.github.com> Date: Tue, 6 Jun 2023 11:40:17 -0400 Subject: [PATCH 12/14] Update dockercompose files to point release images --- configuration/amd64/docker-compose.yml | 6 +++--- configuration/arm64/docker-compose.yml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/configuration/amd64/docker-compose.yml b/configuration/amd64/docker-compose.yml index 6b5188297..21b5a8368 100755 --- a/configuration/amd64/docker-compose.yml +++ b/configuration/amd64/docker-compose.yml @@ -20,7 +20,7 @@ services: - mysql-datavolume:/var/lib/mysql php: - image: usdotfhwaops/php:latest + image: usdotfhwaops/php:k900-xil container_name: php network_mode: host depends_on: @@ -30,7 +30,7 @@ services: tty: true v2xhub: - image: usdotfhwaops/v2xhubamd:latest + image: usdotfhwaops/v2xhubamd:k900-xil container_name: v2xhub network_mode: host restart: always @@ -44,7 +44,7 @@ services: - ./logs:/var/log/tmx - ./MAP:/var/www/plugins/MAP port_drayage_webservice: - image: usdotfhwaops/port-drayage-webservice:latest + image: usdotfhwaops/port-drayage-webservice:k900-xil container_name: port_drayage_webservice network_mode: host secrets: diff --git a/configuration/arm64/docker-compose.yml b/configuration/arm64/docker-compose.yml index a32c31fab..5537b1216 100644 --- a/configuration/arm64/docker-compose.yml +++ b/configuration/arm64/docker-compose.yml @@ -20,7 +20,7 @@ services: - mysql-datavolume:/var/lib/mysql php: - image: usdotfhwaops/php_arm:latest + image: usdotfhwaops/php_arm:k900-xil container_name: php network_mode: host depends_on: @@ -30,7 +30,7 @@ services: tty: true v2xhub: - image: usdotfhwaops/v2xhubarm:latest + image: usdotfhwaops/v2xhubarm:k900-xil container_name: v2xhub network_mode: host restart: always @@ -44,7 +44,7 @@ services: - ./logs:/var/log/tmx - ./MAP:/var/www/plugins/MAP port_drayage_webservice: - image: usdotfhwaops/port-drayage-webservice_arm:latest + image: usdotfhwaops/port-drayage-webservice_arm:k900-xil container_name: port_drayage_webservice network_mode: host secrets: From 25dc8bb3805f772e5fb8b25e8b6177a044ec204d Mon Sep 17 00:00:00 2001 From: Saikrishna Bairamoni <84093461+SaikrishnaBairamoni@users.noreply.github.com> Date: Fri, 16 Jun 2023 14:35:00 -0400 Subject: [PATCH 13/14] update docker files to point 7.5.1 --- configuration/amd64/docker-compose.yml | 6 +++--- configuration/arm64/docker-compose.yml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/configuration/amd64/docker-compose.yml b/configuration/amd64/docker-compose.yml index 21b5a8368..201463578 100755 --- a/configuration/amd64/docker-compose.yml +++ b/configuration/amd64/docker-compose.yml @@ -20,7 +20,7 @@ services: - mysql-datavolume:/var/lib/mysql php: - image: usdotfhwaops/php:k900-xil + image: usdotfhwaops/php:7.5.1 container_name: php network_mode: host depends_on: @@ -30,7 +30,7 @@ services: tty: true v2xhub: - image: usdotfhwaops/v2xhubamd:k900-xil + image: usdotfhwaops/v2xhubamd:7.5.1 container_name: v2xhub network_mode: host restart: always @@ -44,7 +44,7 @@ services: - ./logs:/var/log/tmx - ./MAP:/var/www/plugins/MAP port_drayage_webservice: - image: usdotfhwaops/port-drayage-webservice:k900-xil + image: usdotfhwaops/port-drayage-webservice:7.5.1 container_name: port_drayage_webservice network_mode: host secrets: diff --git a/configuration/arm64/docker-compose.yml b/configuration/arm64/docker-compose.yml index 5537b1216..4974d26ee 100644 --- a/configuration/arm64/docker-compose.yml +++ b/configuration/arm64/docker-compose.yml @@ -20,7 +20,7 @@ services: - mysql-datavolume:/var/lib/mysql php: - image: usdotfhwaops/php_arm:k900-xil + image: usdotfhwaops/php_arm:7.5.1 container_name: php network_mode: host depends_on: @@ -30,7 +30,7 @@ services: tty: true v2xhub: - image: usdotfhwaops/v2xhubarm:k900-xil + image: usdotfhwaops/v2xhubarm:7.5.1 container_name: v2xhub network_mode: host restart: always @@ -44,7 +44,7 @@ services: - ./logs:/var/log/tmx - ./MAP:/var/www/plugins/MAP port_drayage_webservice: - image: usdotfhwaops/port-drayage-webservice_arm:k900-xil + image: usdotfhwaops/port-drayage-webservice_arm:7.5.1 container_name: port_drayage_webservice network_mode: host secrets: From ae58c2eb8cc06469845072aa02533a27dc4d4b35 Mon Sep 17 00:00:00 2001 From: Cody Garver Date: Mon, 19 Jun 2023 11:57:03 -0400 Subject: [PATCH 14/14] Bump version 7.5.0 to 7.5.1 --- src/v2i-hub/CARMACloudPlugin/CMakeLists.txt | 2 +- src/v2i-hub/CARMAStreetsPlugin/CMakeLists.txt | 2 +- src/v2i-hub/CDASimAdapter/CMakeLists.txt | 2 +- src/v2i-hub/CommandPlugin/CMakeLists.txt | 2 +- src/v2i-hub/CswPlugin/CMakeLists.txt | 2 +- src/v2i-hub/DmsPlugin/CMakeLists.txt | 2 +- src/v2i-hub/ERVCloudForwardingPlugin/CMakeLists.txt | 2 +- src/v2i-hub/ImmediateForwardPlugin/CMakeLists.txt | 2 +- src/v2i-hub/LocationPlugin/CMakeLists.txt | 2 +- src/v2i-hub/MapPlugin/CMakeLists.txt | 2 +- src/v2i-hub/MessageLoggerPlugin/CMakeLists.txt | 2 +- src/v2i-hub/MessageReceiverPlugin/CMakeLists.txt | 2 +- src/v2i-hub/ODEForwardPlugin/CMakeLists.txt | 2 +- src/v2i-hub/PedestrianPlugin/CMakeLists.txt | 2 +- src/v2i-hub/PortDrayagePlugin/CMakeLists.txt | 2 +- src/v2i-hub/PreemptionPlugin/CMakeLists.txt | 2 +- src/v2i-hub/RtcmPlugin/CMakeLists.txt | 2 +- src/v2i-hub/SpatPlugin/CMakeLists.txt | 2 +- src/v2i-hub/TimPlugin/CMakeLists.txt | 2 +- 19 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/v2i-hub/CARMACloudPlugin/CMakeLists.txt b/src/v2i-hub/CARMACloudPlugin/CMakeLists.txt index ad036336b..6c913e69d 100644 --- a/src/v2i-hub/CARMACloudPlugin/CMakeLists.txt +++ b/src/v2i-hub/CARMACloudPlugin/CMakeLists.txt @@ -1,4 +1,4 @@ -PROJECT ( CARMACloudPlugin VERSION 7.5.0 LANGUAGES CXX ) +PROJECT ( CARMACloudPlugin VERSION 7.5.1 LANGUAGES CXX ) SET (TMX_PLUGIN_NAME "CARMACloud") add_compile_options(-fPIC) diff --git a/src/v2i-hub/CARMAStreetsPlugin/CMakeLists.txt b/src/v2i-hub/CARMAStreetsPlugin/CMakeLists.txt index f904ecac6..7e4e9b6c9 100644 --- a/src/v2i-hub/CARMAStreetsPlugin/CMakeLists.txt +++ b/src/v2i-hub/CARMAStreetsPlugin/CMakeLists.txt @@ -1,4 +1,4 @@ -PROJECT ( CARMAStreetsPlugin VERSION 7.5.0 LANGUAGES CXX ) +PROJECT ( CARMAStreetsPlugin VERSION 7.5.1 LANGUAGES CXX ) BuildTmxPlugin ( ) diff --git a/src/v2i-hub/CDASimAdapter/CMakeLists.txt b/src/v2i-hub/CDASimAdapter/CMakeLists.txt index e8e8cd794..97468a2cf 100755 --- a/src/v2i-hub/CDASimAdapter/CMakeLists.txt +++ b/src/v2i-hub/CDASimAdapter/CMakeLists.txt @@ -1,4 +1,4 @@ -PROJECT ( CDASimAdapter VERSION 7.5.0 LANGUAGES CXX ) +PROJECT ( CDASimAdapter VERSION 7.5.1 LANGUAGES CXX ) set(CMAKE_CXX_STANDARD 17) FIND_PACKAGE( carma-clock ) diff --git a/src/v2i-hub/CommandPlugin/CMakeLists.txt b/src/v2i-hub/CommandPlugin/CMakeLists.txt index 651e1af0a..a1543ab51 100644 --- a/src/v2i-hub/CommandPlugin/CMakeLists.txt +++ b/src/v2i-hub/CommandPlugin/CMakeLists.txt @@ -1,4 +1,4 @@ -PROJECT ( CommandPlugin VERSION 7.5.0 LANGUAGES CXX ) +PROJECT ( CommandPlugin VERSION 7.5.1 LANGUAGES CXX ) FIND_PACKAGE (OpenSSL REQUIRED) diff --git a/src/v2i-hub/CswPlugin/CMakeLists.txt b/src/v2i-hub/CswPlugin/CMakeLists.txt index 66d0d9545..5e154a2c7 100644 --- a/src/v2i-hub/CswPlugin/CMakeLists.txt +++ b/src/v2i-hub/CswPlugin/CMakeLists.txt @@ -1,4 +1,4 @@ -PROJECT ( CswPlugin VERSION 7.5.0 LANGUAGES CXX ) +PROJECT ( CswPlugin VERSION 7.5.1 LANGUAGES CXX ) SET (TMX_PLUGIN_NAME "CSW") diff --git a/src/v2i-hub/DmsPlugin/CMakeLists.txt b/src/v2i-hub/DmsPlugin/CMakeLists.txt index 4508c8084..08cf09b17 100644 --- a/src/v2i-hub/DmsPlugin/CMakeLists.txt +++ b/src/v2i-hub/DmsPlugin/CMakeLists.txt @@ -1,4 +1,4 @@ -PROJECT ( DmsPlugin VERSION 7.5.0 LANGUAGES CXX ) +PROJECT ( DmsPlugin VERSION 7.5.1 LANGUAGES CXX ) SET (TMX_PLUGIN_NAME "Dynamic Message Sign") diff --git a/src/v2i-hub/ERVCloudForwardingPlugin/CMakeLists.txt b/src/v2i-hub/ERVCloudForwardingPlugin/CMakeLists.txt index 56f71f571..cc456077a 100644 --- a/src/v2i-hub/ERVCloudForwardingPlugin/CMakeLists.txt +++ b/src/v2i-hub/ERVCloudForwardingPlugin/CMakeLists.txt @@ -1,4 +1,4 @@ -PROJECT(ERVCloudForwardingPlugin VERSION 7.5.0 LANGUAGES CXX) +PROJECT(ERVCloudForwardingPlugin VERSION 7.5.1 LANGUAGES CXX) SET(TMX_PLUGIN_NAME "ERVCloudForwarding") add_compile_options(-fPIC) diff --git a/src/v2i-hub/ImmediateForwardPlugin/CMakeLists.txt b/src/v2i-hub/ImmediateForwardPlugin/CMakeLists.txt index e3d2365a2..31e28d6ae 100644 --- a/src/v2i-hub/ImmediateForwardPlugin/CMakeLists.txt +++ b/src/v2i-hub/ImmediateForwardPlugin/CMakeLists.txt @@ -1,4 +1,4 @@ -PROJECT ( ImmediateForwardPlugin VERSION 7.5.0 LANGUAGES CXX ) +PROJECT ( ImmediateForwardPlugin VERSION 7.5.1 LANGUAGES CXX ) SET (TMX_PLUGIN_NAME "Immediate Forward") diff --git a/src/v2i-hub/LocationPlugin/CMakeLists.txt b/src/v2i-hub/LocationPlugin/CMakeLists.txt index eb929373b..5926227c4 100644 --- a/src/v2i-hub/LocationPlugin/CMakeLists.txt +++ b/src/v2i-hub/LocationPlugin/CMakeLists.txt @@ -1,4 +1,4 @@ -project( LocationPlugin VERSION 7.5.0 LANGUAGES CXX ) +project( LocationPlugin VERSION 7.5.1 LANGUAGES CXX ) SET (TMX_PLUGIN_NAME Location) diff --git a/src/v2i-hub/MapPlugin/CMakeLists.txt b/src/v2i-hub/MapPlugin/CMakeLists.txt index 7cf372de0..553f1e58a 100644 --- a/src/v2i-hub/MapPlugin/CMakeLists.txt +++ b/src/v2i-hub/MapPlugin/CMakeLists.txt @@ -1,4 +1,4 @@ -PROJECT ( MapPlugin VERSION 7.5.0 LANGUAGES CXX ) +PROJECT ( MapPlugin VERSION 7.5.1 LANGUAGES CXX ) SET (TMX_PLUGIN_NAME "MAP") diff --git a/src/v2i-hub/MessageLoggerPlugin/CMakeLists.txt b/src/v2i-hub/MessageLoggerPlugin/CMakeLists.txt index b63b6d6df..514b31984 100644 --- a/src/v2i-hub/MessageLoggerPlugin/CMakeLists.txt +++ b/src/v2i-hub/MessageLoggerPlugin/CMakeLists.txt @@ -1,4 +1,4 @@ -PROJECT ( MessageLoggerPlugin VERSION 7.5.0 LANGUAGES CXX ) +PROJECT ( MessageLoggerPlugin VERSION 7.5.1 LANGUAGES CXX ) SET (TMX_PLUGIN_NAME "MessageLoggerPlugin") diff --git a/src/v2i-hub/MessageReceiverPlugin/CMakeLists.txt b/src/v2i-hub/MessageReceiverPlugin/CMakeLists.txt index f77e4c1a3..908bc1e90 100644 --- a/src/v2i-hub/MessageReceiverPlugin/CMakeLists.txt +++ b/src/v2i-hub/MessageReceiverPlugin/CMakeLists.txt @@ -1,4 +1,4 @@ -PROJECT ( MessageReceiverPlugin VERSION 7.5.0 LANGUAGES CXX ) +PROJECT ( MessageReceiverPlugin VERSION 7.5.1 LANGUAGES CXX ) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/src/v2i-hub/ODEForwardPlugin/CMakeLists.txt b/src/v2i-hub/ODEForwardPlugin/CMakeLists.txt index 815527534..8c594fdbe 100644 --- a/src/v2i-hub/ODEForwardPlugin/CMakeLists.txt +++ b/src/v2i-hub/ODEForwardPlugin/CMakeLists.txt @@ -1,4 +1,4 @@ -PROJECT ( ODEForwardPlugin VERSION 7.5.0 LANGUAGES CXX ) +PROJECT ( ODEForwardPlugin VERSION 7.5.1 LANGUAGES CXX ) SET (TMX_PLUGIN_NAME "ODEForwardPlugin") diff --git a/src/v2i-hub/PedestrianPlugin/CMakeLists.txt b/src/v2i-hub/PedestrianPlugin/CMakeLists.txt index 8b0ba693f..ecb8c8cec 100755 --- a/src/v2i-hub/PedestrianPlugin/CMakeLists.txt +++ b/src/v2i-hub/PedestrianPlugin/CMakeLists.txt @@ -1,4 +1,4 @@ -PROJECT ( PedestrianPlugin VERSION 7.5.0 LANGUAGES CXX ) +PROJECT ( PedestrianPlugin VERSION 7.5.1 LANGUAGES CXX ) SET (TMX_PLUGIN_NAME "Pedestrian") add_compile_options(-fPIC) diff --git a/src/v2i-hub/PortDrayagePlugin/CMakeLists.txt b/src/v2i-hub/PortDrayagePlugin/CMakeLists.txt index eb069bfd7..199be4090 100644 --- a/src/v2i-hub/PortDrayagePlugin/CMakeLists.txt +++ b/src/v2i-hub/PortDrayagePlugin/CMakeLists.txt @@ -1,4 +1,4 @@ -PROJECT ( PortDrayagePlugin VERSION 7.5.0 LANGUAGES CXX ) +PROJECT ( PortDrayagePlugin VERSION 7.5.1 LANGUAGES CXX ) SET (TMX_PLUGIN_NAME "PortDrayage") set(CMAKE_AUTOMOC ON) diff --git a/src/v2i-hub/PreemptionPlugin/CMakeLists.txt b/src/v2i-hub/PreemptionPlugin/CMakeLists.txt index eed709d13..1613c3b46 100644 --- a/src/v2i-hub/PreemptionPlugin/CMakeLists.txt +++ b/src/v2i-hub/PreemptionPlugin/CMakeLists.txt @@ -1,4 +1,4 @@ -PROJECT ( PreemptionPlugin VERSION 7.5.0 LANGUAGES CXX ) +PROJECT ( PreemptionPlugin VERSION 7.5.1 LANGUAGES CXX ) SET (TMX_PLUGIN_NAME "Preemption") diff --git a/src/v2i-hub/RtcmPlugin/CMakeLists.txt b/src/v2i-hub/RtcmPlugin/CMakeLists.txt index f10a35a31..694b04ef2 100644 --- a/src/v2i-hub/RtcmPlugin/CMakeLists.txt +++ b/src/v2i-hub/RtcmPlugin/CMakeLists.txt @@ -1,4 +1,4 @@ -PROJECT ( RtcmPlugin VERSION 7.5.0 LANGUAGES CXX ) +PROJECT ( RtcmPlugin VERSION 7.5.1 LANGUAGES CXX ) SET (TMX_PLUGIN_NAME "RTCM") diff --git a/src/v2i-hub/SpatPlugin/CMakeLists.txt b/src/v2i-hub/SpatPlugin/CMakeLists.txt index ec48c6f14..fb28fcada 100644 --- a/src/v2i-hub/SpatPlugin/CMakeLists.txt +++ b/src/v2i-hub/SpatPlugin/CMakeLists.txt @@ -1,4 +1,4 @@ -PROJECT ( SpatPlugin VERSION 7.5.0 LANGUAGES CXX ) +PROJECT ( SpatPlugin VERSION 7.5.1 LANGUAGES CXX ) SET (TMX_PLUGIN_NAME "SPAT") diff --git a/src/v2i-hub/TimPlugin/CMakeLists.txt b/src/v2i-hub/TimPlugin/CMakeLists.txt index 79a3ac8ca..3f8c9779e 100644 --- a/src/v2i-hub/TimPlugin/CMakeLists.txt +++ b/src/v2i-hub/TimPlugin/CMakeLists.txt @@ -1,4 +1,4 @@ -PROJECT ( TimPlugin VERSION 7.5.0 LANGUAGES CXX ) +PROJECT ( TimPlugin VERSION 7.5.1 LANGUAGES CXX ) SET (TMX_PLUGIN_NAME "TIM") add_compile_options(-fPIC)