├── .gitignore ├── CMakeLists.txt ├── Dockerfile.jenkins ├── README.rst ├── THANKS ├── UPSTREAM_REV ├── USAGE ├── config.h ├── debian ├── .gitignore ├── changelog ├── compat ├── control ├── copyright ├── pkcs11-daemon.install ├── pkcs11-proxy1.install ├── rules └── source │ └── format ├── egg-buffer.c ├── egg-buffer.h ├── ext ├── include │ └── dlfcn.h └── lib │ └── libdl.a ├── gck-rpc-daemon-standalone.c ├── gck-rpc-dispatch.c ├── gck-rpc-layer.h ├── gck-rpc-message.c ├── gck-rpc-module.c ├── gck-rpc-private.h ├── gck-rpc-tls-psk.c ├── gck-rpc-tls-psk.h ├── gck-rpc-util.c ├── mksyscalls.sh ├── p11proxy-mitm ├── pkcs11 ├── pkcs11.h ├── pkcs11g.h ├── pkcs11i.h └── pkcs11n.h ├── seccomp-bpf.h ├── syscall-reporter.c └── syscall-reporter.h /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | *.o 3 | moc_*.cpp 4 | ui_*.h 5 | *~ 6 | vb-agent 7 | res/.directory 8 | .\#* 9 | \#*# 10 | Makefile 11 | Trolltech.conf 12 | obj-i686-linux-gnu 13 | syscall-names.h 14 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.4) 2 | 3 | if(COMMAND cmake_policy) 4 | cmake_policy(SET CMP0003 NEW) 5 | endif(COMMAND cmake_policy) 6 | 7 | project (pkcs11 C) 8 | 9 | set(PKCS11_PROXY_SRCS gck-rpc-module.c gck-rpc-message.c gck-rpc-util.c egg-buffer.c gck-rpc-tls-psk.c) 10 | 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) 11 | 12 | add_definitions(-Wall) 13 | add_library(pkcs11-proxy SHARED ${PKCS11_PROXY_SRCS}) 14 | 15 | # Disable console when building Win32 binary in release mode 16 | if (WIN32) 17 | if("${CMAKE_BUILD_TYPE}" MATCHES "^Rel.*") 18 | set(GUI_TYPE WIN32) 19 | endif() 20 | endif() 21 | 22 | add_executable (pkcs11-daemon ${GUI_TYPE} ${PKCS11_DAEMON_SRCS}) 23 | 24 | set_target_properties(pkcs11-proxy PROPERTIES VERSION 0.1 SOVERSION 0) 25 | 26 | if (WIN32) 27 | include_directories("ext/include") 28 | 29 | add_library(dl STATIC IMPORTED) 30 | set_property(TARGET dl PROPERTY 31 | IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/ext/lib/libdl.a) 32 | target_link_libraries (pkcs11-daemon ws2_32) 33 | target_link_libraries (pkcs11-proxy ws2_32) 34 | endif (WIN32) 35 | 36 | target_link_libraries (pkcs11-proxy pthread ssl crypto) 37 | target_link_libraries (pkcs11-daemon dl pthread ssl crypto seccomp) 38 | 39 | install_targets (/lib pkcs11-proxy) 40 | install_targets (/bin pkcs11-daemon) 41 | 42 | add_custom_command( 43 | OUTPUT syscall-names.h 44 | COMMAND ${CMAKE_SOURCE_DIR}/mksyscalls.sh 45 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) 46 | -------------------------------------------------------------------------------- /Dockerfile.jenkins: -------------------------------------------------------------------------------- 1 | FROM docker.sunet.se/jenkins-job 2 | RUN apt-get install -y libssl-dev libseccomp-dev 3 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | 2 | PKCS11 Proxy 3 | ============ 4 | 5 | This fork has the following additional features: 6 | 7 | - support for running in "inetd mode", useful for calling directly from stunnel 8 | - seccomp syscall filtering (only tested in inetd-mode) 9 | - getaddrinfo support for IPv6, fallback and DNS resolution 10 | - TLS-PSK support to optionally encrypt communication 11 | 12 | Plus a number of important bug fixes. This version passes the SoftHSM test 13 | suite. 14 | 15 | An ubuntu PPA that tracks this version is ppa:leifj 16 | -------------------------------------------------------------------------------- /THANKS: -------------------------------------------------------------------------------- 1 | Gnome Project - gnome keyring http://live.gnome.org/GnomeKeyring 2 | Casper Gielen - documentation -------------------------------------------------------------------------------- /UPSTREAM_REV: -------------------------------------------------------------------------------- 1 | r1724 -------------------------------------------------------------------------------- /USAGE: -------------------------------------------------------------------------------- 1 | PKCS11-Proxy is a proxy for the PKCS11-library. 2 | 3 | This project is based on a stripped down Gnome Keyring without all gnome 4 | dependencies and other features. 5 | 6 | The proxy tunnels PKCS11-requests over the network. One possible use 7 | is to store cryptograhic information on a seperate server. This way 8 | the crypto can be isolated from the rest of the system. 9 | 10 | Example 11 | ======= 12 | 13 | Here is an example of using pkcs11-proxy together with SoftHSM (from the 14 | OpenDNSSEC project). The benefit of this setup is that no extra hardware 15 | is needed at all. This could also be considered the greatest weakeness. 16 | For demonstration purposes, however, security is not a consideration. 17 | 18 | $ sudo adduser cgielen pkcs11 19 | $ sudo adduser cgielen softhsm 20 | 21 | $ softhsm --init-token --slot 0 --label test 22 | The SO PIN must have a length between 4 and 255 characters. 23 | Enter SO PIN: 24 | The user PIN must have a length between 4 and 255 characters. 25 | Enter user PIN: 26 | The token has been initialized. 27 | 28 | $ PKCS11_DAEMON_SOCKET="tcp://127.0.0.1:2345" pkcs11-daemon /usr/lib/libsofthsm.so 29 | $ PKCS11_PROXY_SOCKET="tcp://127.0.0.1:2345" pkcs11-tool --module=/usr/lib/libpkcs11-proxy.so -L Available 30 | slots: Slot 0 SoftHSM 31 | token label: test token manuf: SoftHSM token model: SoftHSM 32 | token flags: rng, login required, PIN initialized, token initialized, 33 | other flags=0x40 serial num : 1 34 | 35 | 36 | IPv6 and DNS 37 | ============ 38 | 39 | The PKCS11_DAEMON_SOCKET and PKCS11_PROXY_SOCKET environment variables can 40 | have both hostnames and IPv6 addresses in them. getaddrinfo(3) is used to 41 | resolve any DNS name. 42 | 43 | $ PKCS11_DAEMON_SOCKET="tcp://server.example.com:2345" ... 44 | 45 | If `server.example.com' resolves to more than one IP address (such as one 46 | IPv4 and one IPv6 address), these will be tried sequentially. Currently, 47 | no attempt is made to speed up connection establishment using Happy Eyeballs 48 | (RFC 6555) or similar, so timeouts in case of unreachable addresses could 49 | be expected to be quite problematic. 50 | 51 | IPv6 addresses should be enclosed by square brackets. 52 | 53 | $ PKCS11_DAEMON_SOCKET="tcp://[::1]:2345" ... 54 | 55 | 56 | Encryption 57 | ========== 58 | 59 | This version supports encrypting the communication between the client and 60 | proxy using OpenSSL TLS-PSK (pre-shared key). The PSK is read from a file 61 | that usees the GnuTLS psktool format. This format includes PSK identity 62 | as well as key. 63 | 64 | Currently, there is no way to specify the identity to use on the client 65 | side (client tells server what identity should be used), and the first 66 | identity found in the PSK file is used. The server side will correctly 67 | look up the identity requested by the client in it's PSK file, so it is 68 | possible to have one unique PSK identity and key per PKCS11 client, and 69 | have all the identitys and keys in the PSK file for the PKCS11 daemon. 70 | 71 | $ cat test.psk 72 | test:e9622c85018998993fcc16f5ce9c15e9 73 | $ PKCS11_PROXY_TLS_PSK_FILE="test.psk" \ 74 | PKCS11_DAEMON_SOCKET="tls://server.example.com:2345" \ 75 | pkcs11-daemon /usr/lib/libsofthsm.so 76 | $ PKCS11_PROXY_TLS_PSK_FILE="test.psk" \ 77 | PKCS11_PROXY_SOCKET="tls://server.example.com:2345" \ 78 | pkcs11-tool --module=/usr/lib/libpkcs11-proxy.so -L Available 79 | slots: Slot 0 SoftHSM 80 | token label: test token manuf: SoftHSM token model: SoftHSM 81 | token flags: rng, login required, PIN initialized, token initialized, 82 | other flags=0x40 serial num : 1 83 | -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_H 2 | # define CONFIG_H 3 | 4 | # define DEBUG_OUTPUT 0 // change to 1 to enable debugging 5 | 6 | # define PKCS11PROXY_LISTEN_BACKLOG 128 7 | # define PKCS11PROXY_MAX_SESSION_COUNT 256 8 | 9 | # define PKCS11PROXY_TLS_PSK_CIPHERS "PSK-AES128-CBC-SHA:PSK-AES256-CBC-SHA"; 10 | 11 | //# define DEBUG_SECCOMP 12 | //# define SECCOMP 13 | 14 | #ifdef __MINGW32__ 15 | 16 | # include 17 | # include 18 | # include 19 | # include 20 | 21 | typedef uint32_t __uid32_t; 22 | typedef uint32_t __gid32_t; 23 | typedef uint32_t uid_t; 24 | typedef int socklen_t; 25 | 26 | struct sockaddr_un { 27 | uint16_t sun_family; 28 | char sun_path[PATH_MAX]; 29 | }; 30 | 31 | enum { 32 | SHUT_RD = 0, /* No more receptions. */ 33 | SHUT_WR, /* No more transmissions. */ 34 | SHUT_RDWR /* No more receptions or transmissions. */ 35 | }; 36 | 37 | #ifdef __MINGW32__ 38 | static inline int inet_aton(const char * cp, struct in_addr *pin) 39 | { 40 | int rc = inet_addr(cp); 41 | if (rc == -1 && strcmp(cp, "255.255.255.255")) 42 | return 0; 43 | 44 | pin->s_addr = rc; 45 | return 1; 46 | } 47 | #endif 48 | 49 | #endif 50 | 51 | #endif /* CONFIG_H */ 52 | -------------------------------------------------------------------------------- /debian/.gitignore: -------------------------------------------------------------------------------- 1 | files 2 | pkcs11-daemon.debhelper.log 3 | pkcs11-daemon.substvars 4 | pkcs11-proxy1.debhelper.log 5 | pkcs11-proxy1.postinst.debhelper 6 | pkcs11-proxy1.postrm.debhelper 7 | pkcs11-proxy1.substvars 8 | stamp-makefile-build 9 | stamp-makefile-install 10 | tmp 11 | pkcs11-daemon 12 | pkcs11-proxy1 13 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | pkcs11-proxy (0.4-1ubuntu4) trusty; urgency=medium 2 | 3 | * debian updates 4 | 5 | -- Leif Johansson Fri, 17 Jul 2015 11:02:03 +0200 6 | 7 | pkcs11-proxy (0.4-1ubuntu3) trusty; urgency=medium 8 | 9 | [ Klaus Darilion ] 10 | * Update seccomp usage to match Ubuntu 14.04. 11 | 12 | -- Fredrik Thulin Tue, 17 Feb 2015 19:20:13 +0100 13 | 14 | pkcs11-proxy (0.4-1ubuntu2) precise; urgency=low 15 | 16 | * Support IPv6 and connect-fallback through getaddrinfo() 17 | * Implement TLS-PSK using OpenSSL 18 | * Use libseccomp and reduce number of syscalls allowed in dispatchers 19 | * Several important bug fixes (now passes SoftHSM test suite) 20 | 21 | -- Fredrik Thulin Wed, 30 Jan 2013 09:56:34 +0100 22 | 23 | pkcs11-proxy (0.4-1ubuntu1) precise; urgency=low 24 | 25 | * disable debugging by default 26 | * use syslog instead of stderr unless DEBUG_OUTPUT is 1 27 | 28 | -- Leif Johansson Tue, 04 Sep 2012 15:58:45 +0200 29 | 30 | pkcs11-proxy (0.3-1ubuntu~seccomp1) precise; urgency=low 31 | 32 | [ Corentin Chary ] 33 | * debian: remove commonit specific stuff 34 | 35 | [ Andre Grueneberg ] 36 | * Compile in normal debian environment 37 | * Error in SetPIN 38 | 39 | [ Leif Johansson ] 40 | * basic seccmp filter 41 | 42 | -- Leif Johansson Tue, 04 Sep 2012 13:37:56 +0200 43 | 44 | pkcs11-proxy (0.2-1ubuntu1) precise; urgency=low 45 | 46 | [ Corentin Chary ] 47 | * Initial release. 48 | 49 | [ Leif Johansson ] 50 | * Make it build without the opt prefix 51 | * support for calling pkcs11-daemon from inetd/stunnel directly 52 | 53 | -- Leif Johansson Tue, 04 Sep 2012 09:02:52 +0200 54 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 7 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: pkcs11-proxy 2 | Priority: extra 3 | Maintainer: Corentin Chary 4 | Uploaders: Leif Johansson 5 | Build-Depends: cdbs, debhelper (>= 6), cmake, libssl-dev (>= 1.0.0), libseccomp-dev (>= 1.0.0) 6 | Standards-Version: 3.8.0 7 | Section: libs 8 | 9 | Package: pkcs11-proxy1 10 | Architecture: any 11 | Depends: ${shlibs:Depends}, ${misc:Depends} 12 | Recommends: 13 | Description: pkcs11-proxy 14 | A pkcs11 proxy to use pkcs11 over the network 15 | 16 | Package: pkcs11-daemon 17 | Architecture: any 18 | Depends: ${shlibs:Depends}, ${misc:Depends} 19 | Recommends: 20 | Description: pkcs11-proxy 21 | A pkcs11 daemon to talk with pkcs11-proxy 22 | 23 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | License: 2 | This program is free software; you can redistribute it and/or modify 3 | it under the terms of the GNU General Public License version 2 as 4 | published by the Free Software Foundation. 5 | 6 | This program is distributed in the hope that it will be useful, 7 | but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 | GNU General Public License for more details. 10 | 11 | You should have received a copy of the GNU General Public License 12 | along with this program; if not, write to the Free Software 13 | Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, 14 | MA 02110-1301, USA. 15 | 16 | 17 | On Debian systems, the complete text of the GNU General 18 | Public License can be found in `/usr/share/common-licenses/GPL-2'. 19 | -------------------------------------------------------------------------------- /debian/pkcs11-daemon.install: -------------------------------------------------------------------------------- 1 | debian/tmp/usr/bin/pkcs11-daemon /usr/bin 2 | -------------------------------------------------------------------------------- /debian/pkcs11-proxy1.install: -------------------------------------------------------------------------------- 1 | debian/tmp/usr/lib/libpkcs11-proxy*.so* /usr/lib 2 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | %: 4 | dh $@ --buildsystem=cmake --builddirectory=build --sourcedirectory=. 5 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (native) 2 | -------------------------------------------------------------------------------- /egg-buffer.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ 2 | /* egg-buffer.c - Generic data buffer, used by openssh, gnome-keyring 3 | 4 | Copyright (C) 2007 Stefan Walter 5 | 6 | The Gnome Keyring Library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Library General Public License as 8 | published by the Free Software Foundation; either version 2 of the 9 | License, or (at your option) any later version. 10 | 11 | The Gnome Keyring Library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Library General Public License for more details. 15 | 16 | You should have received a copy of the GNU Library General Public 17 | License along with the Gnome Library; see the file COPYING.LIB. If not, 18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 | Boston, MA 02111-1307, USA. 20 | 21 | Author: Stef Walter 22 | */ 23 | #include "config.h" 24 | 25 | #include 26 | #include 27 | 28 | #include "egg-buffer.h" 29 | 30 | #define DEFAULT_ALLOCATOR ((EggBufferAllocator)realloc) 31 | 32 | int egg_buffer_init(EggBuffer * buffer, size_t reserve) 33 | { 34 | return egg_buffer_init_full(buffer, reserve, NULL); 35 | } 36 | 37 | int 38 | egg_buffer_init_full(EggBuffer * buffer, size_t reserve, 39 | EggBufferAllocator allocator) 40 | { 41 | memset(buffer, 0, sizeof(*buffer)); 42 | 43 | if (!allocator) 44 | allocator = DEFAULT_ALLOCATOR; 45 | if (reserve == 0) 46 | reserve = 64; 47 | 48 | buffer->buf = (allocator) (NULL, reserve); 49 | if (!buffer->buf) { 50 | buffer->failures++; 51 | return 0; 52 | } 53 | 54 | buffer->len = 0; 55 | buffer->allocated_len = reserve; 56 | buffer->failures = 0; 57 | buffer->allocator = allocator; 58 | 59 | return 1; 60 | } 61 | 62 | void egg_buffer_init_static(EggBuffer * buffer, unsigned char *buf, size_t len) 63 | { 64 | memset(buffer, 0, sizeof(*buffer)); 65 | 66 | buffer->buf = buf; 67 | buffer->len = len; 68 | buffer->allocated_len = len; 69 | buffer->failures = 0; 70 | 71 | /* A null allocator, and the buffer can't change in size */ 72 | buffer->allocator = NULL; 73 | } 74 | 75 | void 76 | egg_buffer_init_allocated(EggBuffer * buffer, unsigned char *buf, size_t len, 77 | EggBufferAllocator allocator) 78 | { 79 | memset(buffer, 0, sizeof(*buffer)); 80 | 81 | if (!allocator) 82 | allocator = DEFAULT_ALLOCATOR; 83 | 84 | buffer->buf = buf; 85 | buffer->len = len; 86 | buffer->allocated_len = len; 87 | buffer->failures = 0; 88 | buffer->allocator = allocator; 89 | } 90 | 91 | void egg_buffer_reset(EggBuffer * buffer) 92 | { 93 | memset(buffer->buf, 0, buffer->allocated_len); 94 | buffer->len = 0; 95 | buffer->failures = 0; 96 | } 97 | 98 | void egg_buffer_uninit(EggBuffer * buffer) 99 | { 100 | if (!buffer) 101 | return; 102 | 103 | /* 104 | * Free the memory block using allocator. If no allocator, 105 | * then this memory is ownerd elsewhere and not to be freed. 106 | */ 107 | if (buffer->buf && buffer->allocator) 108 | (buffer->allocator) (buffer->buf, 0); 109 | 110 | memset(buffer, 0, sizeof(*buffer)); 111 | } 112 | 113 | int egg_buffer_set_allocator(EggBuffer * buffer, EggBufferAllocator allocator) 114 | { 115 | unsigned char *buf = NULL; 116 | 117 | if (!allocator) 118 | allocator = DEFAULT_ALLOCATOR; 119 | if (buffer->allocator == allocator) 120 | return 1; 121 | 122 | if (buffer->allocated_len) { 123 | /* Reallocate memory block using new allocator */ 124 | buf = (allocator) (NULL, buffer->allocated_len); 125 | if (buf == NULL) 126 | return 0; 127 | 128 | /* Copy stuff into new memory */ 129 | memcpy(buf, buffer->buf, buffer->allocated_len); 130 | } 131 | 132 | /* If old wasn't static, then free it */ 133 | if (buffer->allocator && buffer->buf) 134 | (buffer->allocator) (buffer->buf, 0); 135 | 136 | buffer->buf = buf; 137 | buffer->allocator = allocator; 138 | 139 | return 1; 140 | } 141 | 142 | int egg_buffer_equal(EggBuffer * b1, EggBuffer * b2) 143 | { 144 | if (b1->len != b2->len) 145 | return 0; 146 | return memcmp(b1->buf, b2->buf, b1->len) == 0; 147 | } 148 | 149 | int egg_buffer_reserve(EggBuffer * buffer, size_t len) 150 | { 151 | unsigned char *newbuf; 152 | size_t newlen; 153 | 154 | if (len < buffer->allocated_len) 155 | return 1; 156 | 157 | /* Calculate a new length, minimize number of buffer allocations */ 158 | newlen = buffer->allocated_len * 2; 159 | if (len > newlen) 160 | newlen += len; 161 | 162 | /* Memory owned elsewhere can't be reallocated */ 163 | if (!buffer->allocator) { 164 | buffer->failures++; 165 | return 0; 166 | } 167 | 168 | /* Reallocate built in buffer using allocator */ 169 | newbuf = (buffer->allocator) (buffer->buf, newlen); 170 | if (!newbuf) { 171 | buffer->failures++; 172 | return 0; 173 | } 174 | 175 | buffer->buf = newbuf; 176 | buffer->allocated_len = newlen; 177 | 178 | return 1; 179 | } 180 | 181 | int egg_buffer_resize(EggBuffer * buffer, size_t len) 182 | { 183 | if (!egg_buffer_reserve(buffer, len)) 184 | return 0; 185 | 186 | buffer->len = len; 187 | return 1; 188 | } 189 | 190 | unsigned char *egg_buffer_add_empty(EggBuffer * buffer, size_t len) 191 | { 192 | size_t pos = buffer->len; 193 | if (!egg_buffer_reserve(buffer, buffer->len + len)) 194 | return NULL; 195 | buffer->len += len; 196 | return buffer->buf + pos; 197 | } 198 | 199 | int egg_buffer_append(EggBuffer * buffer, const unsigned char *val, size_t len) 200 | { 201 | if (!egg_buffer_reserve(buffer, buffer->len + len)) 202 | return 0; /* failures already incremented */ 203 | memcpy(buffer->buf + buffer->len, val, len); 204 | buffer->len += len; 205 | return 1; 206 | } 207 | 208 | int egg_buffer_add_byte(EggBuffer * buffer, unsigned char val) 209 | { 210 | if (!egg_buffer_reserve(buffer, buffer->len + 1)) 211 | return 0; /* failures already incremented */ 212 | buffer->buf[buffer->len] = val; 213 | buffer->len++; 214 | return 1; 215 | } 216 | 217 | int 218 | egg_buffer_get_byte(EggBuffer * buffer, size_t offset, 219 | size_t * next_offset, unsigned char *val) 220 | { 221 | unsigned char *ptr; 222 | if (buffer->len < 1 || offset > buffer->len - 1) { 223 | buffer->failures++; 224 | return 0; 225 | } 226 | ptr = (unsigned char *)buffer->buf + offset; 227 | if (val != NULL) 228 | *val = *ptr; 229 | if (next_offset != NULL) 230 | *next_offset = offset + 1; 231 | return 1; 232 | } 233 | 234 | void egg_buffer_encode_uint16(unsigned char *buf, uint16_t val) 235 | { 236 | buf[0] = (val >> 8) & 0xff; 237 | buf[1] = (val >> 0) & 0xff; 238 | } 239 | 240 | uint16_t egg_buffer_decode_uint16(unsigned char *buf) 241 | { 242 | uint16_t val = buf[0] << 8 | buf[1]; 243 | return val; 244 | } 245 | 246 | int egg_buffer_add_uint16(EggBuffer * buffer, uint16_t val) 247 | { 248 | if (!egg_buffer_reserve(buffer, buffer->len + 2)) 249 | return 0; /* failures already incremented */ 250 | buffer->len += 2; 251 | egg_buffer_set_uint16(buffer, buffer->len - 2, val); 252 | return 1; 253 | } 254 | 255 | int egg_buffer_set_uint16(EggBuffer * buffer, size_t offset, uint16_t val) 256 | { 257 | unsigned char *ptr; 258 | if (buffer->len < 2 || offset > buffer->len - 2) { 259 | buffer->failures++; 260 | return 0; 261 | } 262 | ptr = (unsigned char *)buffer->buf + offset; 263 | egg_buffer_encode_uint16(ptr, val); 264 | return 1; 265 | } 266 | 267 | int 268 | egg_buffer_get_uint16(EggBuffer * buffer, size_t offset, 269 | size_t * next_offset, uint16_t * val) 270 | { 271 | unsigned char *ptr; 272 | if (buffer->len < 2 || offset > buffer->len - 2) { 273 | buffer->failures++; 274 | return 0; 275 | } 276 | ptr = (unsigned char *)buffer->buf + offset; 277 | if (val != NULL) 278 | *val = egg_buffer_decode_uint16(ptr); 279 | if (next_offset != NULL) 280 | *next_offset = offset + 2; 281 | return 1; 282 | } 283 | 284 | void egg_buffer_encode_uint32(unsigned char *buf, uint32_t val) 285 | { 286 | buf[0] = (val >> 24) & 0xff; 287 | buf[1] = (val >> 16) & 0xff; 288 | buf[2] = (val >> 8) & 0xff; 289 | buf[3] = (val >> 0) & 0xff; 290 | } 291 | 292 | uint32_t egg_buffer_decode_uint32(unsigned char *ptr) 293 | { 294 | uint32_t val = ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3]; 295 | return val; 296 | } 297 | 298 | int egg_buffer_add_uint32(EggBuffer * buffer, uint32_t val) 299 | { 300 | if (!egg_buffer_reserve(buffer, buffer->len + 4)) 301 | return 0; /* failures already incremented */ 302 | buffer->len += 4; 303 | egg_buffer_set_uint32(buffer, buffer->len - 4, val); 304 | return 1; 305 | } 306 | 307 | int egg_buffer_set_uint32(EggBuffer * buffer, size_t offset, uint32_t val) 308 | { 309 | unsigned char *ptr; 310 | if (buffer->len < 4 || offset > buffer->len - 4) { 311 | buffer->failures++; 312 | return 0; 313 | } 314 | ptr = (unsigned char *)buffer->buf + offset; 315 | egg_buffer_encode_uint32(ptr, val); 316 | return 1; 317 | } 318 | 319 | int 320 | egg_buffer_get_uint32(EggBuffer * buffer, size_t offset, size_t * next_offset, 321 | uint32_t * val) 322 | { 323 | unsigned char *ptr; 324 | if (buffer->len < 4 || offset > buffer->len - 4) { 325 | buffer->failures++; 326 | return 0; 327 | } 328 | ptr = (unsigned char *)buffer->buf + offset; 329 | if (val != NULL) 330 | *val = egg_buffer_decode_uint32(ptr); 331 | if (next_offset != NULL) 332 | *next_offset = offset + 4; 333 | return 1; 334 | } 335 | 336 | int egg_buffer_add_uint64(EggBuffer * buffer, uint64_t val) 337 | { 338 | if (!egg_buffer_add_uint32(buffer, ((val >> 32) & 0xffffffff))) 339 | return 0; 340 | return egg_buffer_add_uint32(buffer, (val & 0xffffffff)); 341 | } 342 | 343 | int 344 | egg_buffer_get_uint64(EggBuffer * buffer, size_t offset, 345 | size_t * next_offset, uint64_t * val) 346 | { 347 | uint32_t a, b; 348 | if (!egg_buffer_get_uint32(buffer, offset, &offset, &a)) 349 | return 0; 350 | if (!egg_buffer_get_uint32(buffer, offset, &offset, &b)) 351 | return 0; 352 | if (val != NULL) 353 | *val = ((uint64_t) a) << 32 | b; 354 | if (next_offset != NULL) 355 | *next_offset = offset; 356 | return 1; 357 | } 358 | 359 | int 360 | egg_buffer_add_byte_array(EggBuffer * buffer, const unsigned char *val, 361 | size_t len) 362 | { 363 | if (val == NULL) 364 | return egg_buffer_add_uint32(buffer, 0xffffffff); 365 | if (len >= 0x7fffffff) { 366 | buffer->failures++; 367 | return 0; 368 | } 369 | if (!egg_buffer_add_uint32(buffer, len)) 370 | return 0; 371 | return egg_buffer_append(buffer, val, len); 372 | } 373 | 374 | unsigned char *egg_buffer_add_byte_array_empty(EggBuffer * buffer, size_t vlen) 375 | { 376 | if (vlen >= 0x7fffffff) { 377 | buffer->failures++; 378 | return NULL; 379 | } 380 | if (!egg_buffer_add_uint32(buffer, vlen)) 381 | return NULL; 382 | return egg_buffer_add_empty(buffer, vlen); 383 | } 384 | 385 | int 386 | egg_buffer_get_byte_array(EggBuffer * buffer, size_t offset, 387 | size_t * next_offset, const unsigned char **val, 388 | size_t * vlen) 389 | { 390 | uint32_t len; 391 | if (!egg_buffer_get_uint32(buffer, offset, &offset, &len)) 392 | return 0; 393 | if (len == 0xffffffff) { 394 | if (next_offset) 395 | *next_offset = offset; 396 | if (val) 397 | *val = NULL; 398 | if (vlen) 399 | *vlen = 0; 400 | return 1; 401 | } else if (len >= 0x7fffffff) { 402 | buffer->failures++; 403 | return 0; 404 | } 405 | 406 | if (buffer->len < len || offset > buffer->len - len) { 407 | buffer->failures++; 408 | return 0; 409 | } 410 | 411 | if (val) 412 | *val = buffer->buf + offset; 413 | if (vlen) 414 | *vlen = len; 415 | if (next_offset) 416 | *next_offset = offset + len; 417 | 418 | return 1; 419 | } 420 | 421 | int egg_buffer_add_string(EggBuffer * buffer, const char *str) 422 | { 423 | if (str == NULL) { 424 | return egg_buffer_add_uint32(buffer, 0xffffffff); 425 | } else { 426 | size_t len = strlen(str); 427 | if (len >= 0x7fffffff) 428 | return 0; 429 | if (!egg_buffer_add_uint32(buffer, len)) 430 | return 0; 431 | return egg_buffer_append(buffer, (unsigned char *)str, len); 432 | } 433 | } 434 | 435 | int 436 | egg_buffer_get_string(EggBuffer * buffer, size_t offset, size_t * next_offset, 437 | char **str_ret, EggBufferAllocator allocator) 438 | { 439 | uint32_t len; 440 | 441 | if (!allocator) 442 | allocator = buffer->allocator; 443 | if (!allocator) 444 | allocator = DEFAULT_ALLOCATOR; 445 | 446 | if (!egg_buffer_get_uint32(buffer, offset, &offset, &len)) { 447 | return 0; 448 | } 449 | if (len == 0xffffffff) { 450 | *next_offset = offset; 451 | *str_ret = NULL; 452 | return 1; 453 | } else if (len >= 0x7fffffff) { 454 | return 0; 455 | } 456 | 457 | if (buffer->len < len || offset > buffer->len - len) { 458 | return 0; 459 | } 460 | 461 | /* Make sure no null characters in string */ 462 | if (memchr(buffer->buf + offset, 0, len) != NULL) 463 | return 0; 464 | 465 | /* The passed allocator may be for non-pageable memory */ 466 | *str_ret = (allocator) (NULL, len + 1); 467 | if (!*str_ret) 468 | return 0; 469 | memcpy(*str_ret, buffer->buf + offset, len); 470 | 471 | /* Always zero terminate */ 472 | (*str_ret)[len] = 0; 473 | *next_offset = offset + len; 474 | 475 | return 1; 476 | } 477 | 478 | int egg_buffer_add_stringv(EggBuffer * buffer, const char **strv) 479 | { 480 | const char **v; 481 | uint32_t n = 0; 482 | 483 | if (!strv) 484 | return 0; 485 | 486 | /* Add the number of strings coming */ 487 | for (v = strv; *v; ++v) 488 | ++n; 489 | if (!egg_buffer_add_uint32(buffer, n)) 490 | return 0; 491 | 492 | /* Add the individual strings */ 493 | for (v = strv; *v; ++v) { 494 | if (!egg_buffer_add_string(buffer, *v)) 495 | return 0; 496 | } 497 | 498 | return 1; 499 | } 500 | 501 | int 502 | egg_buffer_get_stringv(EggBuffer * buffer, size_t offset, size_t * next_offset, 503 | char ***strv_ret, EggBufferAllocator allocator) 504 | { 505 | uint32_t n, i, j; 506 | size_t len; 507 | 508 | if (!allocator) 509 | allocator = buffer->allocator; 510 | if (!allocator) 511 | allocator = DEFAULT_ALLOCATOR; 512 | 513 | /* First the number of environment variable lines */ 514 | if (!egg_buffer_get_uint32(buffer, offset, &offset, &n)) 515 | return 0; 516 | 517 | /* Then that number of strings */ 518 | len = (n + 1) * sizeof(char *); 519 | *strv_ret = (char **)(allocator) (NULL, len); 520 | if (!*strv_ret) 521 | return 0; 522 | 523 | /* All null strings */ 524 | memset(*strv_ret, 0, len); 525 | 526 | for (i = 0; i < n; ++i) { 527 | if (!egg_buffer_get_string(buffer, offset, &offset, 528 | &((*strv_ret)[i]), allocator)) { 529 | 530 | /* Free all the strings on failure */ 531 | for (j = 0; j < i; ++j) { 532 | if ((*strv_ret)[j]) 533 | (allocator) ((*strv_ret)[j], 0); 534 | } 535 | 536 | return 0; 537 | } 538 | } 539 | 540 | if (next_offset != NULL) 541 | *next_offset = offset; 542 | 543 | return 1; 544 | } 545 | -------------------------------------------------------------------------------- /egg-buffer.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ 2 | /* egg-buffer.h - Generic data buffer, used by openssh, gnome-keyring 3 | 4 | Copyright (C) 2007, Stefan Walter 5 | 6 | The Gnome Keyring Library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Library General Public License as 8 | published by the Free Software Foundation; either version 2 of the 9 | License, or (at your option) any later version. 10 | 11 | The Gnome Keyring Library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Library General Public License for more details. 15 | 16 | You should have received a copy of the GNU Library General Public 17 | License along with the Gnome Library; see the file COPYING.LIB. If not, 18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 | Boston, MA 02111-1307, USA. 20 | 21 | Author: Stef Walter 22 | */ 23 | 24 | #ifndef EGG_BUFFER_H 25 | #define EGG_BUFFER_H 26 | 27 | #include 28 | #include 29 | 30 | /* ------------------------------------------------------------------- 31 | * EggBuffer 32 | * 33 | * IMPORTANT: This is pure vanila standard C, no glib. We need this 34 | * because certain consumers of this protocol need to be built 35 | * without linking in any special libraries. ie: the PKCS#11 module. 36 | * 37 | * Memory Allocation 38 | * 39 | * Callers can set their own allocator. If NULL is used then standard 40 | * C library heap memory is used and failures will not be fatal. Memory 41 | * failures will instead result in a zero return value or 42 | * egg_buffer_has_error() returning one. 43 | * 44 | * If you use something like g_realloc as the allocator, then memory 45 | * failures become fatal just like in a standard GTK program. 46 | * 47 | * Don't change the allocator manually in the EggBuffer structure. The 48 | * egg_buffer_set_allocator() func will reallocate and handle things 49 | * properly. 50 | * 51 | * Pointers into the Buffer 52 | * 53 | * Any write operation has the posibility of reallocating memory 54 | * and invalidating any direct pointers into the buffer. 55 | */ 56 | 57 | /* The allocator for the EggBuffer. This follows the realloc() syntax and logic */ 58 | typedef void* (*EggBufferAllocator) (void* p, size_t len); 59 | 60 | typedef struct _EggBuffer { 61 | unsigned char *buf; 62 | size_t len; 63 | size_t allocated_len; 64 | int failures; 65 | EggBufferAllocator allocator; 66 | } EggBuffer; 67 | 68 | #define EGG_BUFFER_EMPTY { NULL, 0, 0, 0, NULL } 69 | 70 | int egg_buffer_init (EggBuffer *buffer, size_t reserve); 71 | 72 | int egg_buffer_init_full (EggBuffer *buffer, 73 | size_t reserve, 74 | EggBufferAllocator allocator); 75 | 76 | void egg_buffer_init_static (EggBuffer *buffer, 77 | unsigned char *buf, 78 | size_t len); 79 | 80 | void egg_buffer_init_allocated (EggBuffer *buffer, 81 | unsigned char *buf, 82 | size_t len, 83 | EggBufferAllocator allocator); 84 | 85 | void egg_buffer_uninit (EggBuffer *buffer); 86 | 87 | int egg_buffer_set_allocator (EggBuffer *buffer, 88 | EggBufferAllocator allocator); 89 | 90 | void egg_buffer_reset (EggBuffer *buffer); 91 | 92 | int egg_buffer_equal (EggBuffer *b1, 93 | EggBuffer *b2); 94 | 95 | int egg_buffer_reserve (EggBuffer *buffer, 96 | size_t len); 97 | 98 | int egg_buffer_resize (EggBuffer *buffer, 99 | size_t len); 100 | 101 | int egg_buffer_append (EggBuffer *buffer, 102 | const unsigned char *val, 103 | size_t len); 104 | 105 | unsigned char* egg_buffer_add_empty (EggBuffer *buffer, 106 | size_t len); 107 | 108 | int egg_buffer_add_byte (EggBuffer *buffer, 109 | unsigned char val); 110 | 111 | int egg_buffer_get_byte (EggBuffer *buffer, 112 | size_t offset, 113 | size_t *next_offset, 114 | unsigned char *val); 115 | 116 | void egg_buffer_encode_uint32 (unsigned char* buf, 117 | uint32_t val); 118 | 119 | uint32_t egg_buffer_decode_uint32 (unsigned char* buf); 120 | 121 | int egg_buffer_add_uint32 (EggBuffer *buffer, 122 | uint32_t val); 123 | 124 | int egg_buffer_set_uint32 (EggBuffer *buffer, 125 | size_t offset, 126 | uint32_t val); 127 | 128 | int egg_buffer_get_uint32 (EggBuffer *buffer, 129 | size_t offset, 130 | size_t *next_offset, 131 | uint32_t *val); 132 | 133 | void egg_buffer_encode_uint16 (unsigned char* buf, 134 | uint16_t val); 135 | 136 | uint16_t egg_buffer_decode_uint16 (unsigned char* buf); 137 | 138 | int egg_buffer_add_uint16 (EggBuffer *buffer, 139 | uint16_t val); 140 | 141 | int egg_buffer_set_uint16 (EggBuffer *buffer, 142 | size_t offset, 143 | uint16_t val); 144 | 145 | int egg_buffer_get_uint16 (EggBuffer *buffer, 146 | size_t offset, 147 | size_t *next_offset, 148 | uint16_t *val); 149 | 150 | int egg_buffer_add_byte_array (EggBuffer *buffer, 151 | const unsigned char *val, 152 | size_t len); 153 | 154 | int egg_buffer_get_byte_array (EggBuffer *buffer, 155 | size_t offset, 156 | size_t *next_offset, 157 | const unsigned char **val, 158 | size_t *vlen); 159 | 160 | unsigned char* egg_buffer_add_byte_array_empty (EggBuffer *buffer, 161 | size_t vlen); 162 | 163 | int egg_buffer_add_string (EggBuffer *buffer, 164 | const char *str); 165 | 166 | int egg_buffer_get_string (EggBuffer *buffer, 167 | size_t offset, 168 | size_t *next_offset, 169 | char **str_ret, 170 | EggBufferAllocator allocator); 171 | 172 | int egg_buffer_add_stringv (EggBuffer *buffer, 173 | const char** strv); 174 | 175 | int egg_buffer_get_stringv (EggBuffer *buffer, 176 | size_t offset, 177 | size_t *next_offset, 178 | char ***strv_ret, 179 | EggBufferAllocator allocator); 180 | 181 | int egg_buffer_add_uint64 (EggBuffer *buffer, 182 | uint64_t val); 183 | 184 | int egg_buffer_get_uint64 (EggBuffer *buffer, 185 | size_t offset, 186 | size_t *next_offset, 187 | uint64_t *val); 188 | 189 | #define egg_buffer_length(b) ((b)->len) 190 | 191 | #define egg_buffer_has_error(b) ((b)->failures > 0) 192 | 193 | #endif /* EGG_BUFFER_H */ 194 | 195 | -------------------------------------------------------------------------------- /ext/include/dlfcn.h: -------------------------------------------------------------------------------- 1 | /* 2 | * dlfcn-win32 3 | * Copyright (c) 2007 Ramiro Polla 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef DLFCN_H 21 | #define DLFCN_H 22 | 23 | /* POSIX says these are implementation-defined. 24 | * To simplify use with Windows API, we treat them the same way. 25 | */ 26 | 27 | #define RTLD_LAZY 0 28 | #define RTLD_NOW 0 29 | 30 | #define RTLD_GLOBAL (1 << 1) 31 | #define RTLD_LOCAL (1 << 2) 32 | 33 | /* These two were added in The Open Group Base Specifications Issue 6. 34 | * Note: All other RTLD_* flags in any dlfcn.h are not standard compliant. 35 | */ 36 | 37 | #define RTLD_DEFAULT 0 38 | #define RTLD_NEXT 0 39 | 40 | void *dlopen ( const char *file, int mode ); 41 | int dlclose( void *handle ); 42 | void *dlsym ( void *handle, const char *name ); 43 | char *dlerror( void ); 44 | 45 | #endif /* DLFCN_H */ 46 | -------------------------------------------------------------------------------- /ext/lib/libdl.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SUNET/pkcs11-proxy/2032875c95563c15cf77395f924191fdd6a1b33f/ext/lib/libdl.a -------------------------------------------------------------------------------- /gck-rpc-daemon-standalone.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ 2 | /* gck-rpc-daemon-standalone.c - A sample daemon. 3 | 4 | Copyright (C) 2008, Stef Walter 5 | 6 | The Gnome Keyring Library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Library General Public License as 8 | published by the Free Software Foundation; either version 2 of the 9 | License, or (at your option) any later version. 10 | 11 | The Gnome Keyring Library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Library General Public License for more details. 15 | 16 | You should have received a copy of the GNU Library General Public 17 | License along with the Gnome Library; see the file COPYING.LIB. If not, 18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 | Boston, MA 02111-1307, USA. 20 | 21 | Author: Stef Walter 22 | */ 23 | 24 | #include "config.h" 25 | 26 | #include "pkcs11/pkcs11.h" 27 | 28 | #include "gck-rpc-layer.h" 29 | #include "gck-rpc-tls-psk.h" 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #include 39 | #include 40 | 41 | #include 42 | 43 | #ifdef __MINGW32__ 44 | # include 45 | #endif 46 | 47 | #define SOCKET_PATH "tcp://127.0.0.1" 48 | 49 | #ifdef SECCOMP 50 | #include 51 | //#include "seccomp-bpf.h" 52 | #ifdef DEBUG_SECCOMP 53 | # include "syscall-reporter.h" 54 | #endif /* DEBUG_SECCOMP */ 55 | #include /* for seccomp init */ 56 | #endif /* SECCOMP */ 57 | 58 | 59 | static int install_syscall_filter(const int sock, const char *tls_psk_keyfile, const char *path) 60 | { 61 | #ifdef SECCOMP 62 | int rc = -1; 63 | scmp_filter_ctx ctx; 64 | 65 | #ifdef DEBUG_SECCOMP 66 | ctx = seccomp_init(SCMP_ACT_TRAP); 67 | #else 68 | ctx = seccomp_init(SCMP_ACT_KILL); 69 | #endif /* DEBUG_SECCOMP */ 70 | if (ctx == NULL) 71 | goto failure_scmp; 72 | /* 73 | * These are the basic syscalls needed to be able to use 74 | * the syscall-reporter to figure out the rest 75 | */ 76 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(write), 0); 77 | #ifdef DEBUG_SECCOMP 78 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0); 79 | # ifdef __NR_sigreturn 80 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(sigreturn), 0); 81 | # endif 82 | #endif /* DEBUG_SECCOMP */ 83 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(exit), 0); 84 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0); 85 | 86 | /* 87 | * Network related syscalls. 88 | */ 89 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(read), 0); 90 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(select), 0); 91 | if (sock) 92 | /* Allow accept() only for the listening socket */ 93 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(accept), 1, 94 | SCMP_A0(SCMP_CMP_EQ, sock)); 95 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(sendto), 0); 96 | if (path[0] && 97 | strncmp(path, "tcp://", strlen("tcp://")) == 0) { 98 | /* TCP socket - not needed for TLS */ 99 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(recvfrom), 0); 100 | } 101 | 102 | /* 103 | * These are probably pthreads-related. 104 | */ 105 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0); 106 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(munmap), 0); 107 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 0); 108 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(clone), 0); 109 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(set_robust_list), 0); 110 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(madvise), 0); 111 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(munlock), 0); 112 | 113 | /* 114 | * Both pthreads (? file is "/sys/devices/system/cpu/online") and TLS-PSK open files. 115 | */ 116 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(open), 1, 117 | SCMP_A1(SCMP_CMP_EQ, O_RDONLY | O_CLOEXEC)); 118 | 119 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(close), 0); 120 | 121 | /* 122 | * UNIX domain socket 123 | */ 124 | if (path[0] && 125 | strncmp(path, "tcp://", strlen("tcp://")) != 0 && 126 | strncmp(path, "tls://", strlen("tls://")) != 0) { 127 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(unlink), 0); 128 | } 129 | 130 | /* 131 | * Allow spawned threads to initialize a new seccomp policy (subset of this). 132 | */ 133 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(prctl), 0); 134 | 135 | /* 136 | * SoftHSM 1.3.0 required syscalls 137 | */ 138 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(getcwd), 0); 139 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(stat), 0); 140 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(open), 0); 141 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 0); 142 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0); 143 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(lseek), 0); 144 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(access), 0); 145 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(fsync), 0); 146 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(unlink), 0); 147 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(ftruncate), 0); 148 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(select), 0); 149 | seccomp_rule_add(ctx,SCMP_ACT_ALLOW, SCMP_SYS(futex), 0); 150 | 151 | #ifdef DEBUG_SECCOMP 152 | /* Dumps the generated BPF rules in sort-of human readable syntax. */ 153 | seccomp_export_pfc(ctx,STDERR_FILENO); 154 | 155 | /* Print the name of syscalls stopped by seccomp. Should not be used in production. */ 156 | if (install_syscall_reporter()) 157 | return 1; 158 | #endif /* DEBUG_SECCOMP */ 159 | 160 | rc = seccomp_load(ctx); 161 | if (rc < 0) 162 | goto failure_scmp; 163 | seccomp_release(ctx); 164 | 165 | return 0; 166 | 167 | failure_scmp: 168 | errno = -rc; 169 | fprintf(stderr, "Seccomp filter initialization failed, errno = %u\n", errno); 170 | return errno; 171 | #else /* SECCOMP */ 172 | return 0; 173 | #endif /* SECCOMP */ 174 | } 175 | 176 | 177 | #if 0 178 | /* Sample configuration for loading NSS remotely */ 179 | static CK_C_INITIALIZE_ARGS p11_init_args = { 180 | NULL, 181 | NULL, 182 | NULL, 183 | NULL, 184 | CKF_OS_LOCKING_OK, 185 | "init-string = configdir='/tmp' certPrefix='' keyPrefix='' secmod='/tmp/secmod.db' flags=" 186 | }; 187 | #endif 188 | 189 | static int is_running = 1; 190 | 191 | static int usage(void) 192 | { 193 | fprintf(stderr, "usage: pkcs11-daemon pkcs11-module [|\"-\"]\n\tUsing \"-\" results in a single-thread inetd-type daemon\n"); 194 | exit(2); 195 | } 196 | 197 | void termination_handler (int signum) 198 | { 199 | is_running = 0; 200 | } 201 | 202 | enum { 203 | /* Used to un-confuse clang checker */ 204 | GCP_RPC_DAEMON_MODE_INETD = 0, 205 | GCP_RPC_DAEMON_MODE_SOCKET 206 | }; 207 | 208 | int main(int argc, char *argv[]) 209 | { 210 | CK_C_GetFunctionList func_get_list; 211 | CK_FUNCTION_LIST_PTR funcs; 212 | void *module; 213 | const char *path, *tls_psk_keyfile; 214 | fd_set read_fds; 215 | int sock, ret, mode; 216 | CK_RV rv; 217 | CK_C_INITIALIZE_ARGS init_args; 218 | GckRpcTlsPskState *tls; 219 | 220 | /* The module to load is the argument */ 221 | if (argc != 2 && argc != 3) 222 | usage(); 223 | 224 | openlog("pkcs11-proxy",LOG_CONS|LOG_PID,LOG_DAEMON); 225 | 226 | /* Load the library */ 227 | module = dlopen(argv[1], RTLD_NOW); 228 | if (!module) { 229 | fprintf(stderr, "couldn't open library: %s: %s\n", argv[1], 230 | dlerror()); 231 | exit(1); 232 | } 233 | 234 | /* Lookup the appropriate function in library */ 235 | func_get_list = 236 | (CK_C_GetFunctionList) dlsym(module, "C_GetFunctionList"); 237 | if (!func_get_list) { 238 | fprintf(stderr, 239 | "couldn't find C_GetFunctionList in library: %s: %s\n", 240 | argv[1], dlerror()); 241 | exit(1); 242 | } 243 | 244 | /* Get the function list */ 245 | rv = (func_get_list) (&funcs); 246 | if (rv != CKR_OK || !funcs) { 247 | fprintf(stderr, 248 | "couldn't get function list from C_GetFunctionList" 249 | "in libary: %s: 0x%08x\n", 250 | argv[1], (int)rv); 251 | exit(1); 252 | } 253 | 254 | /* RPC layer expects initialized module */ 255 | memset(&init_args, 0, sizeof(init_args)); 256 | init_args.flags = CKF_OS_LOCKING_OK; 257 | 258 | rv = (funcs->C_Initialize) (&init_args); 259 | if (rv != CKR_OK) { 260 | fprintf(stderr, "couldn't initialize module: %s: 0x%08x\n", 261 | argv[1], (int)rv); 262 | exit(1); 263 | } 264 | 265 | path = getenv("PKCS11_DAEMON_SOCKET"); 266 | if (!path && argc == 3) 267 | path = argv[2]; 268 | if (!path) 269 | path = SOCKET_PATH; 270 | 271 | /* Initialize TLS, if appropriate */ 272 | tls = NULL; 273 | tls_psk_keyfile = NULL; 274 | if (! strncmp("tls://", path, 6)) { 275 | tls_psk_keyfile = getenv("PKCS11_PROXY_TLS_PSK_FILE"); 276 | if (! tls_psk_keyfile || ! tls_psk_keyfile[0]) { 277 | fprintf(stderr, "key file must be specified for tls:// socket.\n"); 278 | exit(1); 279 | } 280 | 281 | tls = calloc(1, sizeof(GckRpcTlsPskState)); 282 | if (tls == NULL) { 283 | fprintf(stderr, "can't allocate memory for TLS-PSK"); 284 | exit(1); 285 | } 286 | 287 | if (! gck_rpc_init_tls_psk(tls, tls_psk_keyfile, NULL, GCK_RPC_TLS_PSK_SERVER)) { 288 | fprintf(stderr, "TLS-PSK initialization failed"); 289 | exit(1); 290 | } 291 | } 292 | 293 | if (strcmp(path,"-") == 0) { 294 | /* inetd mode */ 295 | sock = 0; 296 | mode = GCP_RPC_DAEMON_MODE_INETD; 297 | } else { 298 | /* Do some initialization before enabling seccomp. */ 299 | sock = gck_rpc_layer_initialize(path, funcs); 300 | if (sock == -1) 301 | exit(1); 302 | 303 | /* Shut down gracefully on SIGTERM. */ 304 | if (signal (SIGTERM, termination_handler) == SIG_IGN) 305 | signal (SIGTERM, SIG_IGN); 306 | 307 | mode = GCP_RPC_DAEMON_MODE_SOCKET; 308 | } 309 | 310 | /* 311 | * Enable seccomp. This is essentially a whitelist containing all the syscalls 312 | * we expect to call from here on. Anything not whitelisted will cause the 313 | * process to terminate. 314 | */ 315 | if (install_syscall_filter(sock, tls_psk_keyfile, path)) 316 | return 1; 317 | 318 | if (mode == GCP_RPC_DAEMON_MODE_INETD) { 319 | gck_rpc_layer_inetd(funcs); 320 | } else if (mode == GCP_RPC_DAEMON_MODE_SOCKET) { 321 | is_running = 1; 322 | while (is_running) { 323 | FD_ZERO(&read_fds); 324 | FD_SET(sock, &read_fds); 325 | ret = select(sock + 1, &read_fds, NULL, NULL, NULL); 326 | if (ret < 0) { 327 | if (errno == EINTR) 328 | continue; 329 | fprintf(stderr, "error watching socket: %s\n", 330 | strerror(errno)); 331 | exit(1); 332 | } 333 | 334 | if (FD_ISSET(sock, &read_fds)) 335 | gck_rpc_layer_accept(tls); 336 | } 337 | 338 | gck_rpc_layer_uninitialize(); 339 | } else { 340 | /* Not reached */ 341 | exit(-1); 342 | } 343 | 344 | rv = (funcs->C_Finalize) (NULL); 345 | if (rv != CKR_OK) 346 | fprintf(stderr, "couldn't finalize module: %s: 0x%08x\n", 347 | argv[1], (int)rv); 348 | 349 | dlclose(module); 350 | 351 | if (tls) { 352 | gck_rpc_close_tls(tls); 353 | free(tls); 354 | tls = NULL; 355 | } 356 | 357 | return 0; 358 | } 359 | -------------------------------------------------------------------------------- /gck-rpc-layer.h: -------------------------------------------------------------------------------- 1 | #ifndef GCKRPC_LAYER_H_ 2 | #define GCKRPC_LAYER_H_ 3 | 4 | #include "pkcs11/pkcs11.h" 5 | 6 | #include "gck-rpc-tls-psk.h" 7 | 8 | /* ------------------------------------------------------------------ 9 | * DISPATCHER 10 | */ 11 | 12 | /* Call to initialize the module and start listening, returns socket or -1 */ 13 | int gck_rpc_layer_initialize(const char *prefix, CK_FUNCTION_LIST_PTR funcs); 14 | 15 | /* Should be called to cleanup dispatcher */ 16 | void gck_rpc_layer_uninitialize(void); 17 | 18 | /* Accept a new connection. Should be called when above fd has read */ 19 | void gck_rpc_layer_accept(GckRpcTlsPskState *tls); 20 | 21 | /* Run a single connection off of STDIN - call from inetd or stunnel */ 22 | void gck_rpc_layer_inetd(CK_FUNCTION_LIST_PTR funcs); 23 | 24 | #endif /* GCKRPC_LAYER_H_ */ 25 | -------------------------------------------------------------------------------- /gck-rpc-message.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ 2 | /* p11-rpc-message.c - our marshalled PKCS#11 protocol. 3 | 4 | Copyright (C) 2008, Stef Walter 5 | 6 | The Gnome Keyring Library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Library General Public License as 8 | published by the Free Software Foundation; either version 2 of the 9 | License, or (at your option) any later version. 10 | 11 | The Gnome Keyring Library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Library General Public License for more details. 15 | 16 | You should have received a copy of the GNU Library General Public 17 | License along with the Gnome Library; see the file COPYING.LIB. If not, 18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 | Boston, MA 02111-1307, USA. 20 | 21 | Author: Stef Walter 22 | */ 23 | 24 | #include "config.h" 25 | 26 | #include "gck-rpc-layer.h" 27 | #include "gck-rpc-private.h" 28 | 29 | #include 30 | 31 | #ifdef G_DISABLE_ASSERT 32 | #define assert(x) 33 | #else 34 | #include 35 | #endif 36 | 37 | GckRpcMessage *gck_rpc_message_new(EggBufferAllocator allocator) 38 | { 39 | GckRpcMessage *msg; 40 | 41 | assert(allocator); 42 | 43 | msg = (GckRpcMessage *) (allocator) (NULL, sizeof(GckRpcMessage)); 44 | if (!msg) 45 | return NULL; 46 | memset(msg, 0, sizeof(*msg)); 47 | 48 | if (!egg_buffer_init_full(&msg->buffer, 64, allocator)) { 49 | (allocator) (msg, 0); /* Frees allocation */ 50 | return NULL; 51 | } 52 | 53 | gck_rpc_message_reset(msg); 54 | 55 | return msg; 56 | } 57 | 58 | void gck_rpc_message_free(GckRpcMessage * msg) 59 | { 60 | EggBufferAllocator allocator; 61 | 62 | if (msg) { 63 | assert(msg->buffer.allocator); 64 | allocator = msg->buffer.allocator; 65 | egg_buffer_uninit(&msg->buffer); 66 | 67 | /* frees data buffer */ 68 | (allocator) (msg, 0); 69 | } 70 | } 71 | 72 | void gck_rpc_message_reset(GckRpcMessage * msg) 73 | { 74 | assert(msg); 75 | 76 | msg->call_id = 0; 77 | msg->call_type = 0; 78 | msg->signature = NULL; 79 | msg->sigverify = NULL; 80 | msg->parsed = 0; 81 | 82 | egg_buffer_reset(&msg->buffer); 83 | } 84 | 85 | int 86 | gck_rpc_message_prep(GckRpcMessage * msg, int call_id, GckRpcMessageType type) 87 | { 88 | int len; 89 | 90 | assert(type); 91 | assert(call_id >= GCK_RPC_CALL_ERROR); 92 | assert(call_id < GCK_RPC_CALL_MAX); 93 | 94 | gck_rpc_message_reset(msg); 95 | 96 | if (call_id != GCK_RPC_CALL_ERROR) { 97 | 98 | /* The call id and signature */ 99 | if (type == GCK_RPC_REQUEST) 100 | msg->signature = gck_rpc_calls[call_id].request; 101 | else if (type == GCK_RPC_RESPONSE) 102 | msg->signature = gck_rpc_calls[call_id].response; 103 | else 104 | assert(0 && "invalid message type"); 105 | assert(msg->signature); 106 | msg->sigverify = msg->signature; 107 | } 108 | 109 | msg->call_id = call_id; 110 | msg->call_type = type; 111 | 112 | /* Encode the two of them */ 113 | egg_buffer_add_uint32(&msg->buffer, call_id); 114 | if (msg->signature) { 115 | len = strlen(msg->signature); 116 | egg_buffer_add_byte_array(&msg->buffer, 117 | (unsigned char *)msg->signature, len); 118 | } 119 | 120 | msg->parsed = 0; 121 | return !egg_buffer_has_error(&msg->buffer); 122 | } 123 | 124 | int gck_rpc_message_parse(GckRpcMessage * msg, GckRpcMessageType type) 125 | { 126 | const unsigned char *val; 127 | size_t len; 128 | uint32_t call_id; 129 | 130 | msg->parsed = 0; 131 | 132 | /* Pull out the call identifier */ 133 | if (!egg_buffer_get_uint32 134 | (&msg->buffer, msg->parsed, &(msg->parsed), &call_id)) { 135 | gck_rpc_warn("invalid message: couldn't read call identifier"); 136 | return 0; 137 | } 138 | 139 | msg->signature = msg->sigverify = NULL; 140 | 141 | /* If it's an error code then no more processing */ 142 | if (call_id == GCK_RPC_CALL_ERROR) { 143 | if (type == GCK_RPC_REQUEST) { 144 | gck_rpc_warn("invalid message: error code in request"); 145 | return 0; 146 | } 147 | 148 | return 1; 149 | } 150 | 151 | /* The call id and signature */ 152 | if (call_id <= 0 || call_id >= GCK_RPC_CALL_MAX) { 153 | gck_rpc_warn("invalid message: bad call id: %d", call_id); 154 | return 0; 155 | } 156 | if (type == GCK_RPC_REQUEST) 157 | msg->signature = gck_rpc_calls[call_id].request; 158 | else if (type == GCK_RPC_RESPONSE) 159 | msg->signature = gck_rpc_calls[call_id].response; 160 | else 161 | assert(0 && "invalid message type"); 162 | msg->call_id = call_id; 163 | msg->call_type = type; 164 | msg->sigverify = msg->signature; 165 | 166 | /* Verify the incoming signature */ 167 | if (!egg_buffer_get_byte_array 168 | (&msg->buffer, msg->parsed, &(msg->parsed), &val, &len)) { 169 | gck_rpc_warn("invalid message: couldn't read signature"); 170 | return 0; 171 | } 172 | 173 | if ((strlen(msg->signature) != len) 174 | || (memcmp(val, msg->signature, len) != 0)) { 175 | gck_rpc_warn("invalid message: signature doesn't match"); 176 | return 0; 177 | } 178 | 179 | return 1; 180 | } 181 | 182 | int gck_rpc_message_equals(GckRpcMessage * m1, GckRpcMessage * m2) 183 | { 184 | assert(m1 && m2); 185 | 186 | /* Any errors and messages are never equal */ 187 | if (egg_buffer_has_error(&m1->buffer) || 188 | egg_buffer_has_error(&m2->buffer)) 189 | return 0; 190 | 191 | /* Calls and signatures must be identical */ 192 | if (m1->call_id != m2->call_id) 193 | return 0; 194 | if (m1->call_type != m2->call_type) 195 | return 0; 196 | if (m1->signature && m2->signature) { 197 | if (strcmp(m1->signature, m2->signature) != 0) 198 | return 0; 199 | } else if (m1->signature != m2->signature) { 200 | return 0; 201 | } 202 | 203 | /* Data in buffer must be identical */ 204 | return egg_buffer_equal(&m1->buffer, &m2->buffer); 205 | } 206 | 207 | int gck_rpc_message_verify_part(GckRpcMessage * msg, const char *part) 208 | { 209 | int len, ok; 210 | 211 | if (!msg->sigverify) 212 | return 1; 213 | 214 | len = strlen(part); 215 | ok = (strncmp(msg->sigverify, part, len) == 0); 216 | if (ok) 217 | msg->sigverify += len; 218 | return ok; 219 | } 220 | 221 | int 222 | gck_rpc_message_write_attribute_buffer(GckRpcMessage * msg, 223 | CK_ATTRIBUTE_PTR arr, CK_ULONG num) 224 | { 225 | CK_ATTRIBUTE_PTR attr; 226 | CK_ULONG i; 227 | 228 | assert(!num || arr); 229 | assert(msg); 230 | 231 | /* Make sure this is in the rigth order */ 232 | assert(!msg->signature || gck_rpc_message_verify_part(msg, "fA")); 233 | 234 | /* Write the number of items */ 235 | egg_buffer_add_uint32(&msg->buffer, num); 236 | 237 | for (i = 0; i < num; ++i) { 238 | attr = &(arr[i]); 239 | 240 | /* The attribute type */ 241 | egg_buffer_add_uint32(&msg->buffer, attr->type); 242 | 243 | /* And the attribute buffer length */ 244 | egg_buffer_add_uint32(&msg->buffer, 245 | attr->pValue ? attr->ulValueLen : 0); 246 | } 247 | 248 | return !egg_buffer_has_error(&msg->buffer); 249 | } 250 | 251 | int 252 | gck_rpc_message_write_attribute_array(GckRpcMessage * msg, 253 | CK_ATTRIBUTE_PTR arr, CK_ULONG num) 254 | { 255 | CK_ULONG i; 256 | CK_ATTRIBUTE_PTR attr; 257 | unsigned char validity; 258 | 259 | assert(!num || arr); 260 | assert(msg); 261 | 262 | /* Make sure this is in the rigth order */ 263 | assert(!msg->signature || gck_rpc_message_verify_part(msg, "aA")); 264 | 265 | /* Write the number of items */ 266 | egg_buffer_add_uint32(&msg->buffer, num); 267 | 268 | for (i = 0; i < num; ++i) { 269 | attr = &(arr[i]); 270 | 271 | /* The attribute type */ 272 | egg_buffer_add_uint32(&msg->buffer, attr->type); 273 | 274 | /* Write out the attribute validity */ 275 | validity = (((CK_LONG) attr->ulValueLen) == -1) ? 0 : 1; 276 | egg_buffer_add_byte(&msg->buffer, validity); 277 | 278 | /* The attribute length and value */ 279 | if (validity) { 280 | egg_buffer_add_uint32(&msg->buffer, attr->ulValueLen); 281 | if (gck_rpc_has_bad_sized_ulong_parameter(attr)) { 282 | uint64_t val = *(CK_ULONG *)attr->pValue; 283 | 284 | egg_buffer_add_byte_array (&msg->buffer, (unsigned char *)&val, sizeof (val)); 285 | } else 286 | egg_buffer_add_byte_array(&msg->buffer, attr->pValue, 287 | attr->ulValueLen); 288 | } 289 | } 290 | 291 | return !egg_buffer_has_error(&msg->buffer); 292 | } 293 | 294 | int gck_rpc_message_read_byte(GckRpcMessage * msg, CK_BYTE * val) 295 | { 296 | assert(msg); 297 | 298 | /* Make sure this is in the right order */ 299 | assert(!msg->signature || gck_rpc_message_verify_part(msg, "y")); 300 | return egg_buffer_get_byte(&msg->buffer, msg->parsed, &msg->parsed, 301 | val); 302 | } 303 | 304 | int gck_rpc_message_write_byte(GckRpcMessage * msg, CK_BYTE val) 305 | { 306 | assert(msg); 307 | 308 | /* Make sure this is in the right order */ 309 | assert(!msg->signature || gck_rpc_message_verify_part(msg, "y")); 310 | return egg_buffer_add_byte(&msg->buffer, val); 311 | } 312 | 313 | int gck_rpc_message_read_ulong(GckRpcMessage * msg, CK_ULONG * val) 314 | { 315 | uint64_t v; 316 | assert(msg); 317 | 318 | /* Make sure this is in the right order */ 319 | assert(!msg->signature || gck_rpc_message_verify_part(msg, "u")); 320 | 321 | if (!egg_buffer_get_uint64(&msg->buffer, msg->parsed, &msg->parsed, &v)) 322 | return 0; 323 | if (val) 324 | *val = (CK_ULONG) v; 325 | return 1; 326 | } 327 | 328 | int gck_rpc_message_write_ulong(GckRpcMessage * msg, CK_ULONG val) 329 | { 330 | assert(msg); 331 | 332 | /* Make sure this is in the rigth order */ 333 | assert(!msg->signature || gck_rpc_message_verify_part(msg, "u")); 334 | return egg_buffer_add_uint64(&msg->buffer, val); 335 | } 336 | 337 | int gck_rpc_message_write_byte_buffer(GckRpcMessage * msg, CK_BYTE_PTR arr, CK_ULONG *count_ptr) 338 | { 339 | uint8_t flags; 340 | assert(msg); 341 | 342 | /* Make sure this is in the right order */ 343 | assert(!msg->signature || gck_rpc_message_verify_part(msg, "fy")); 344 | 345 | flags = 0; 346 | if (! arr) 347 | flags |= GCK_RPC_BYTE_BUFFER_NULL_DATA; 348 | if (! count_ptr) 349 | flags |= GCK_RPC_BYTE_BUFFER_NULL_COUNT; 350 | 351 | egg_buffer_add_byte(&msg->buffer, flags); 352 | 353 | egg_buffer_add_uint32(&msg->buffer, count_ptr ? *count_ptr : 0x0); 354 | 355 | return !egg_buffer_has_error(&msg->buffer); 356 | } 357 | 358 | int 359 | gck_rpc_message_write_byte_array(GckRpcMessage * msg, CK_BYTE_PTR arr, 360 | CK_ULONG num) 361 | { 362 | assert(msg); 363 | 364 | /* Make sure this is in the right order */ 365 | assert(!msg->signature || gck_rpc_message_verify_part(msg, "ay")); 366 | 367 | /* No array, no data, just length */ 368 | if (!arr) { 369 | egg_buffer_add_byte(&msg->buffer, 0); 370 | egg_buffer_add_uint32(&msg->buffer, num); 371 | } else { 372 | egg_buffer_add_byte(&msg->buffer, 1); 373 | egg_buffer_add_byte_array(&msg->buffer, arr, num); 374 | } 375 | 376 | return !egg_buffer_has_error(&msg->buffer); 377 | } 378 | 379 | int gck_rpc_message_write_ulong_buffer(GckRpcMessage * msg, CK_ULONG count) 380 | { 381 | assert(msg); 382 | 383 | /* Make sure this is in the right order */ 384 | assert(!msg->signature || gck_rpc_message_verify_part(msg, "fu")); 385 | return egg_buffer_add_uint32(&msg->buffer, count); 386 | } 387 | 388 | int 389 | gck_rpc_message_write_ulong_array(GckRpcMessage * msg, CK_ULONG_PTR array, 390 | CK_ULONG n_array) 391 | { 392 | CK_ULONG i; 393 | 394 | assert(msg); 395 | 396 | /* Check that we're supposed to have this at this point */ 397 | assert(!msg->signature || gck_rpc_message_verify_part(msg, "au")); 398 | 399 | /* We send a byte which determines whether there's actual data present or not */ 400 | egg_buffer_add_byte(&msg->buffer, array ? 1 : 0); 401 | egg_buffer_add_uint32(&msg->buffer, n_array); 402 | 403 | /* Now send the data if valid */ 404 | if (array) { 405 | for (i = 0; i < n_array; ++i) 406 | egg_buffer_add_uint64(&msg->buffer, array[i]); 407 | } 408 | 409 | return !egg_buffer_has_error(&msg->buffer); 410 | } 411 | 412 | int gck_rpc_message_read_version(GckRpcMessage * msg, CK_VERSION * version) 413 | { 414 | assert(msg); 415 | assert(version); 416 | 417 | /* Check that we're supposed to have this at this point */ 418 | assert(!msg->signature || gck_rpc_message_verify_part(msg, "v")); 419 | 420 | return egg_buffer_get_byte(&msg->buffer, msg->parsed, &msg->parsed, 421 | &version->major) 422 | && egg_buffer_get_byte(&msg->buffer, msg->parsed, &msg->parsed, 423 | &version->minor); 424 | } 425 | 426 | int gck_rpc_message_write_version(GckRpcMessage * msg, CK_VERSION * version) 427 | { 428 | assert(msg); 429 | assert(version); 430 | 431 | /* Check that we're supposed to have this at this point */ 432 | assert(!msg->signature || gck_rpc_message_verify_part(msg, "v")); 433 | 434 | egg_buffer_add_byte(&msg->buffer, version->major); 435 | egg_buffer_add_byte(&msg->buffer, version->minor); 436 | 437 | return !egg_buffer_has_error(&msg->buffer); 438 | } 439 | 440 | int 441 | gck_rpc_message_read_space_string(GckRpcMessage * msg, CK_UTF8CHAR * buffer, 442 | CK_ULONG length) 443 | { 444 | const unsigned char *data; 445 | size_t n_data; 446 | 447 | assert(msg); 448 | assert(buffer); 449 | assert(length); 450 | 451 | assert(!msg->signature || gck_rpc_message_verify_part(msg, "s")); 452 | 453 | if (!egg_buffer_get_byte_array 454 | (&msg->buffer, msg->parsed, &msg->parsed, &data, &n_data)) 455 | return 0; 456 | 457 | if (n_data != length) { 458 | gck_rpc_warn 459 | ("invalid length space padded string received: %d != %d", 460 | length, n_data); 461 | return 0; 462 | } 463 | 464 | memcpy(buffer, data, length); 465 | return 1; 466 | } 467 | 468 | int 469 | gck_rpc_message_write_space_string(GckRpcMessage * msg, CK_UTF8CHAR * buffer, 470 | CK_ULONG length) 471 | { 472 | assert(msg); 473 | assert(buffer); 474 | assert(length); 475 | 476 | assert(!msg->signature || gck_rpc_message_verify_part(msg, "s")); 477 | 478 | /* XXX it's not really right to treat UTF-8 input as a byte buffer, 479 | * although CK_UTF8CHAR is currently typedef'd to unsigned char in pkcs11.h. 480 | */ 481 | return egg_buffer_add_byte_array(&msg->buffer, buffer, length); 482 | } 483 | -------------------------------------------------------------------------------- /gck-rpc-private.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ 2 | /* p11-rpc-private.h - various ids and signatures for our protocol 3 | 4 | Copyright (C) 2008, Stef Walter 5 | 6 | The Gnome Keyring Library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Library General Public License as 8 | published by the Free Software Foundation; either version 2 of the 9 | License, or (at your option) any later version. 10 | 11 | The Gnome Keyring Library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Library General Public License for more details. 15 | 16 | You should have received a copy of the GNU Library General Public 17 | License along with the Gnome Library; see the file COPYING.LIB. If not, 18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 | Boston, MA 02111-1307, USA. 20 | 21 | Author: Stef Walter 22 | */ 23 | 24 | #ifndef GCK_RPC_CALLS_H 25 | #define GCK_RPC_CALLS_H 26 | 27 | #include "config.h" 28 | 29 | #include 30 | #include 31 | 32 | #include "egg-buffer.h" 33 | 34 | #include "pkcs11/pkcs11.h" 35 | 36 | /* The calls, must be in sync with array below */ 37 | enum { 38 | GCK_RPC_CALL_ERROR = 0, 39 | 40 | GCK_RPC_CALL_C_Initialize, 41 | GCK_RPC_CALL_C_Finalize, 42 | GCK_RPC_CALL_C_GetInfo, 43 | GCK_RPC_CALL_C_GetSlotList, 44 | GCK_RPC_CALL_C_GetSlotInfo, 45 | GCK_RPC_CALL_C_GetTokenInfo, 46 | GCK_RPC_CALL_C_GetMechanismList, 47 | GCK_RPC_CALL_C_GetMechanismInfo, 48 | GCK_RPC_CALL_C_InitToken, 49 | GCK_RPC_CALL_C_WaitForSlotEvent, 50 | 51 | GCK_RPC_CALL_C_OpenSession, 52 | 53 | GCK_RPC_CALL_C_CloseSession, 54 | GCK_RPC_CALL_C_CloseAllSessions, 55 | GCK_RPC_CALL_C_GetFunctionStatus, 56 | GCK_RPC_CALL_C_CancelFunction, 57 | 58 | GCK_RPC_CALL_C_GetSessionInfo, 59 | GCK_RPC_CALL_C_InitPIN, 60 | GCK_RPC_CALL_C_SetPIN, 61 | GCK_RPC_CALL_C_GetOperationState, 62 | GCK_RPC_CALL_C_SetOperationState, 63 | GCK_RPC_CALL_C_Login, 64 | GCK_RPC_CALL_C_Logout, 65 | GCK_RPC_CALL_C_CreateObject, 66 | GCK_RPC_CALL_C_CopyObject, 67 | GCK_RPC_CALL_C_DestroyObject, 68 | GCK_RPC_CALL_C_GetObjectSize, 69 | GCK_RPC_CALL_C_GetAttributeValue, 70 | GCK_RPC_CALL_C_SetAttributeValue, 71 | GCK_RPC_CALL_C_FindObjectsInit, 72 | GCK_RPC_CALL_C_FindObjects, 73 | GCK_RPC_CALL_C_FindObjectsFinal, 74 | GCK_RPC_CALL_C_EncryptInit, 75 | GCK_RPC_CALL_C_Encrypt, 76 | GCK_RPC_CALL_C_EncryptUpdate, 77 | GCK_RPC_CALL_C_EncryptFinal, 78 | GCK_RPC_CALL_C_DecryptInit, 79 | GCK_RPC_CALL_C_Decrypt, 80 | GCK_RPC_CALL_C_DecryptUpdate, 81 | GCK_RPC_CALL_C_DecryptFinal, 82 | GCK_RPC_CALL_C_DigestInit, 83 | GCK_RPC_CALL_C_Digest, 84 | GCK_RPC_CALL_C_DigestUpdate, 85 | GCK_RPC_CALL_C_DigestKey, 86 | GCK_RPC_CALL_C_DigestFinal, 87 | GCK_RPC_CALL_C_SignInit, 88 | GCK_RPC_CALL_C_Sign, 89 | GCK_RPC_CALL_C_SignUpdate, 90 | GCK_RPC_CALL_C_SignFinal, 91 | GCK_RPC_CALL_C_SignRecoverInit, 92 | GCK_RPC_CALL_C_SignRecover, 93 | GCK_RPC_CALL_C_VerifyInit, 94 | GCK_RPC_CALL_C_Verify, 95 | GCK_RPC_CALL_C_VerifyUpdate, 96 | GCK_RPC_CALL_C_VerifyFinal, 97 | GCK_RPC_CALL_C_VerifyRecoverInit, 98 | GCK_RPC_CALL_C_VerifyRecover, 99 | GCK_RPC_CALL_C_DigestEncryptUpdate, 100 | GCK_RPC_CALL_C_DecryptDigestUpdate, 101 | GCK_RPC_CALL_C_SignEncryptUpdate, 102 | GCK_RPC_CALL_C_DecryptVerifyUpdate, 103 | GCK_RPC_CALL_C_GenerateKey, 104 | GCK_RPC_CALL_C_GenerateKeyPair, 105 | GCK_RPC_CALL_C_WrapKey, 106 | GCK_RPC_CALL_C_UnwrapKey, 107 | GCK_RPC_CALL_C_DeriveKey, 108 | GCK_RPC_CALL_C_SeedRandom, 109 | GCK_RPC_CALL_C_GenerateRandom, 110 | 111 | GCK_RPC_CALL_MAX 112 | }; 113 | 114 | typedef struct _GckRpcCall { 115 | int call_id; 116 | const char *name; 117 | const char *request; 118 | const char *response; 119 | } GckRpcCall; 120 | 121 | /* 122 | * a_ = prefix denotes array of _ 123 | * A = CK_ATTRIBUTE 124 | * f_ = prefix denotes buffer for _ 125 | * M = CK_MECHANISM 126 | * u = CK_ULONG 127 | * s = space padded string 128 | * v = CK_VERSION 129 | * y = CK_BYTE 130 | */ 131 | 132 | static const GckRpcCall gck_rpc_calls[] = { 133 | {GCK_RPC_CALL_ERROR, "ERROR", NULL, NULL}, 134 | {GCK_RPC_CALL_C_Initialize, "C_Initialize", "ay", ""}, 135 | {GCK_RPC_CALL_C_Finalize, "C_Finalize", "", ""}, 136 | {GCK_RPC_CALL_C_GetInfo, "C_GetInfo", "", "vsusv"}, 137 | {GCK_RPC_CALL_C_GetSlotList, "C_GetSlotList", "yfu", "au"}, 138 | {GCK_RPC_CALL_C_GetSlotInfo, "C_GetSlotInfo", "u", "ssuvv"}, 139 | {GCK_RPC_CALL_C_GetTokenInfo, "C_GetTokenInfo", "u", 140 | "ssssuuuuuuuuuuuvvs"}, 141 | {GCK_RPC_CALL_C_GetMechanismList, "C_GetMechanismList", "ufu", "au"}, 142 | {GCK_RPC_CALL_C_GetMechanismInfo, "C_GetMechanismInfo", "uu", "uuu"}, 143 | {GCK_RPC_CALL_C_InitToken, "C_InitToken", "uays", ""}, 144 | {GCK_RPC_CALL_C_WaitForSlotEvent, "C_WaitForSlotEvent", "u", "u"}, 145 | {GCK_RPC_CALL_C_OpenSession, "C_OpenSession", "uu", "u"}, 146 | {GCK_RPC_CALL_C_CloseSession, "C_CloseSession", "u", ""}, 147 | {GCK_RPC_CALL_C_CloseAllSessions, "C_CloseAllSessions", "u", ""}, 148 | {GCK_RPC_CALL_C_GetFunctionStatus, "C_GetFunctionStatus", "u", ""}, 149 | {GCK_RPC_CALL_C_CancelFunction, "C_CancelFunction", "u", ""}, 150 | {GCK_RPC_CALL_C_GetSessionInfo, "C_GetSessionInfo", "u", "uuuu"}, 151 | {GCK_RPC_CALL_C_InitPIN, "C_InitPIN", "uay", ""}, 152 | {GCK_RPC_CALL_C_SetPIN, "C_SetPIN", "uayay", ""}, 153 | {GCK_RPC_CALL_C_GetOperationState, "C_GetOperationState", "ufy", "ay"}, 154 | {GCK_RPC_CALL_C_SetOperationState, "C_SetOperationState", "uayuu", ""}, 155 | {GCK_RPC_CALL_C_Login, "C_Login", "uuay", ""}, 156 | {GCK_RPC_CALL_C_Logout, "C_Logout", "u", ""}, 157 | {GCK_RPC_CALL_C_CreateObject, "C_CreateObject", "uaA", "u"}, 158 | {GCK_RPC_CALL_C_CopyObject, "C_CopyObject", "uuaA", "u"}, 159 | {GCK_RPC_CALL_C_DestroyObject, "C_DestroyObject", "uu", ""}, 160 | {GCK_RPC_CALL_C_GetObjectSize, "C_GetObjectSize", "uu", "u"}, 161 | {GCK_RPC_CALL_C_GetAttributeValue, "C_GetAttributeValue", "uufA", 162 | "aAu"}, 163 | {GCK_RPC_CALL_C_SetAttributeValue, "C_SetAttributeValue", "uuaA", ""}, 164 | {GCK_RPC_CALL_C_FindObjectsInit, "C_FindObjectsInit", "uaA", ""}, 165 | {GCK_RPC_CALL_C_FindObjects, "C_FindObjects", "ufu", "au"}, 166 | {GCK_RPC_CALL_C_FindObjectsFinal, "C_FindObjectsFinal", "u", ""}, 167 | {GCK_RPC_CALL_C_EncryptInit, "C_EncryptInit", "uMu", ""}, 168 | {GCK_RPC_CALL_C_Encrypt, "C_Encrypt", "uayfy", "ay"}, 169 | {GCK_RPC_CALL_C_EncryptUpdate, "C_EncryptUpdate", "uayfy", "ay"}, 170 | {GCK_RPC_CALL_C_EncryptFinal, "C_EncryptFinal", "ufy", "ay"}, 171 | {GCK_RPC_CALL_C_DecryptInit, "C_DecryptInit", "uMu", ""}, 172 | {GCK_RPC_CALL_C_Decrypt, "C_Decrypt", "uayfy", "ay"}, 173 | {GCK_RPC_CALL_C_DecryptUpdate, "C_DecryptUpdate", "uayfy", "ay"}, 174 | {GCK_RPC_CALL_C_DecryptFinal, "C_DecryptFinal", "ufy", "ay"}, 175 | {GCK_RPC_CALL_C_DigestInit, "C_DigestInit", "uM", ""}, 176 | {GCK_RPC_CALL_C_Digest, "C_Digest", "uayfy", "ay"}, 177 | {GCK_RPC_CALL_C_DigestUpdate, "C_DigestUpdate", "uay", ""}, 178 | {GCK_RPC_CALL_C_DigestKey, "C_DigestKey", "uu", ""}, 179 | {GCK_RPC_CALL_C_DigestFinal, "C_DigestFinal", "ufy", "ay"}, 180 | {GCK_RPC_CALL_C_SignInit, "C_SignInit", "uMu", ""}, 181 | {GCK_RPC_CALL_C_Sign, "C_Sign", "uayfy", "ay"}, 182 | {GCK_RPC_CALL_C_SignUpdate, "C_SignUpdate", "uay", ""}, 183 | {GCK_RPC_CALL_C_SignFinal, "C_SignFinal", "ufy", "ay"}, 184 | {GCK_RPC_CALL_C_SignRecoverInit, "C_SignRecoverInit", "uMu", ""}, 185 | {GCK_RPC_CALL_C_SignRecover, "C_SignRecover", "uayfy", "ay"}, 186 | {GCK_RPC_CALL_C_VerifyInit, "C_VerifyInit", "uMu", ""}, 187 | {GCK_RPC_CALL_C_Verify, "C_Verify", "uayay", ""}, 188 | {GCK_RPC_CALL_C_VerifyUpdate, "C_VerifyUpdate", "uay", ""}, 189 | {GCK_RPC_CALL_C_VerifyFinal, "C_VerifyFinal", "uay", ""}, 190 | {GCK_RPC_CALL_C_VerifyRecoverInit, "C_VerifyRecoverInit", "uMu", ""}, 191 | {GCK_RPC_CALL_C_VerifyRecover, "C_VerifyRecover", "uayfy", "ay"}, 192 | {GCK_RPC_CALL_C_DigestEncryptUpdate, "C_DigestEncryptUpdate", "uayfy", 193 | "ay"}, 194 | {GCK_RPC_CALL_C_DecryptDigestUpdate, "C_DecryptDigestUpdate", "uayfy", 195 | "ay"}, 196 | {GCK_RPC_CALL_C_SignEncryptUpdate, "C_SignEncryptUpdate", "uayfy", 197 | "ay"}, 198 | {GCK_RPC_CALL_C_DecryptVerifyUpdate, "C_DecryptVerifyUpdate", "uayfy", 199 | "ay"}, 200 | {GCK_RPC_CALL_C_GenerateKey, "C_GenerateKey", "uMaA", "u"}, 201 | {GCK_RPC_CALL_C_GenerateKeyPair, "C_GenerateKeyPair", "uMaAaA", "uu"}, 202 | {GCK_RPC_CALL_C_WrapKey, "C_WrapKey", "uMuufy", "ay"}, 203 | {GCK_RPC_CALL_C_UnwrapKey, "C_UnwrapKey", "uMuayaA", "u"}, 204 | {GCK_RPC_CALL_C_DeriveKey, "C_DeriveKey", "uMuaA", "u"}, 205 | {GCK_RPC_CALL_C_SeedRandom, "C_SeedRandom", "uay", ""}, 206 | {GCK_RPC_CALL_C_GenerateRandom, "C_GenerateRandom", "ufy", "ay"}, 207 | }; 208 | 209 | #ifdef _DEBUG 210 | #define GCK_RPC_CHECK_CALLS() \ 211 | { int i; for (i = 0; i < GCK_RPC_CALL_MAX; ++i) assert (gck_rpc_calls[i].call_id == i); } 212 | #endif 213 | 214 | #define GCK_RPC_HANDSHAKE \ 215 | "PRIVATE-GNOME-KEYRING-PKCS11-PROTOCOL-V-3" 216 | #define GCK_RPC_HANDSHAKE_LEN \ 217 | (sizeof (GCK_RPC_HANDSHAKE) - 1) 218 | 219 | #define GCK_RPC_SOCKET_EXT "pkcs11" 220 | 221 | typedef enum _GckRpcMessageType { 222 | GCK_RPC_REQUEST = 1, 223 | GCK_RPC_RESPONSE 224 | } GckRpcMessageType; 225 | 226 | typedef struct _GckRpcMessage { 227 | int call_id; 228 | GckRpcMessageType call_type; 229 | const char *signature; 230 | EggBuffer buffer; 231 | 232 | size_t parsed; 233 | const char *sigverify; 234 | } GckRpcMessage; 235 | 236 | #define GCK_RPC_BYTE_BUFFER_NULL_DATA 1 237 | #define GCK_RPC_BYTE_BUFFER_NULL_COUNT 2 238 | 239 | GckRpcMessage *gck_rpc_message_new(EggBufferAllocator allocator); 240 | 241 | void gck_rpc_message_free(GckRpcMessage * msg); 242 | 243 | void gck_rpc_message_reset(GckRpcMessage * msg); 244 | 245 | int gck_rpc_message_equals(GckRpcMessage * m1, GckRpcMessage * m2); 246 | 247 | #define gck_rpc_message_is_verified(msg) (!(msg)->sigverify || (msg)->sigverify[0] == 0) 248 | 249 | #define gck_rpc_message_buffer_error(msg) (egg_buffer_has_error(&(msg)->buffer)) 250 | 251 | int gck_rpc_message_prep(GckRpcMessage * msg, 252 | int call_id, GckRpcMessageType type); 253 | 254 | int gck_rpc_message_parse(GckRpcMessage * msg, GckRpcMessageType type); 255 | 256 | int gck_rpc_message_verify_part(GckRpcMessage * msg, const char *part); 257 | 258 | int gck_rpc_message_write_byte(GckRpcMessage * msg, CK_BYTE val); 259 | 260 | int gck_rpc_message_write_ulong(GckRpcMessage * msg, CK_ULONG val); 261 | 262 | int gck_rpc_message_write_space_string(GckRpcMessage * msg, 263 | CK_UTF8CHAR * buffer, CK_ULONG length); 264 | 265 | int gck_rpc_message_write_byte_buffer(GckRpcMessage * msg, CK_BYTE_PTR arr, CK_ULONG *count_ptr); 266 | 267 | int gck_rpc_message_write_byte_array(GckRpcMessage * msg, 268 | CK_BYTE_PTR arr, CK_ULONG num); 269 | 270 | int gck_rpc_message_write_ulong_buffer(GckRpcMessage * msg, CK_ULONG count); 271 | 272 | int gck_rpc_message_write_ulong_array(GckRpcMessage * msg, 273 | CK_ULONG_PTR arr, CK_ULONG num); 274 | 275 | int gck_rpc_message_write_attribute_buffer(GckRpcMessage * msg, 276 | CK_ATTRIBUTE_PTR arr, CK_ULONG num); 277 | 278 | int gck_rpc_message_write_attribute_array(GckRpcMessage * msg, 279 | CK_ATTRIBUTE_PTR arr, CK_ULONG num); 280 | 281 | int gck_rpc_message_write_version(GckRpcMessage * msg, CK_VERSION * version); 282 | 283 | int gck_rpc_message_read_byte(GckRpcMessage * msg, CK_BYTE * val); 284 | 285 | int gck_rpc_message_read_ulong(GckRpcMessage * msg, CK_ULONG * val); 286 | 287 | int gck_rpc_message_read_space_string(GckRpcMessage * msg, 288 | CK_UTF8CHAR * buffer, CK_ULONG length); 289 | 290 | int gck_rpc_message_read_version(GckRpcMessage * msg, CK_VERSION * version); 291 | 292 | void gck_rpc_log(const char *msg, ...); 293 | 294 | void gck_rpc_warn(const char *msg, ...); 295 | 296 | void gck_rpc_debug(const char *msg, ...); 297 | 298 | #ifdef G_DISABLE_ASSERT 299 | #define assert(x) 300 | #else 301 | #include 302 | #endif 303 | 304 | /* 305 | * PKCS#11 mechanism parameters are not easy to serialize. They're 306 | * completely different for so many mechanisms, they contain 307 | * pointers to arbitrary memory, and many callers don't initialize 308 | * them completely or properly. 309 | * 310 | * We only support certain mechanisms. 311 | * 312 | * Also callers do yucky things like leaving parts of the structure 313 | * pointing to garbage if they don't think it's going to be used. 314 | */ 315 | 316 | int gck_rpc_mechanism_is_supported(CK_MECHANISM_TYPE mech); 317 | void gck_rpc_mechanism_list_purge(CK_MECHANISM_TYPE_PTR mechs, 318 | CK_ULONG_PTR n_mechs); 319 | int gck_rpc_mechanism_has_sane_parameters(CK_MECHANISM_TYPE type); 320 | int gck_rpc_mechanism_has_no_parameters(CK_MECHANISM_TYPE mech); 321 | int gck_rpc_has_bad_sized_ulong_parameter(CK_ATTRIBUTE_PTR attr); 322 | int gck_rpc_has_ulong_parameter(CK_ATTRIBUTE_TYPE type); 323 | 324 | /* Parses strings (prefix) to host and port components. */ 325 | int gck_rpc_parse_host_port(const char *prefix, char **host, char **port); 326 | 327 | #endif /* GCK_RPC_CALLS_H */ 328 | -------------------------------------------------------------------------------- /gck-rpc-tls-psk.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ 2 | /* gck-rpc-tls-psk.c - TLS-PSK functionality to protect communication 3 | 4 | Copyright (C) 2013, NORDUnet A/S 5 | 6 | pkcs11-proxy is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Library General Public License as 8 | published by the Free Software Foundation; either version 2 of the 9 | License, or (at your option) any later version. 10 | 11 | pkcs11-proxy is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Library General Public License for more details. 15 | 16 | You should have received a copy of the GNU Library General Public 17 | License along with the Gnome Library; see the file COPYING.LIB. If not, 18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 | Boston, MA 02111-1307, USA. 20 | 21 | Author: Fredrik Thulin 22 | */ 23 | 24 | #include "config.h" 25 | 26 | #include "gck-rpc-private.h" 27 | #include "gck-rpc-tls-psk.h" 28 | 29 | #include 30 | #include 31 | 32 | /* for file I/O */ 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | /* TLS pre-shared key */ 39 | static char tls_psk_identity[128] = { 0, }; 40 | static char tls_psk_key_filename[MAXPATHLEN] = { 0, }; 41 | 42 | /* ----------------------------------------------------------------------------- 43 | * LOGGING and DEBUGGING 44 | */ 45 | #ifndef DEBUG_OUTPUT 46 | #define DEBUG_OUTPUT 0 47 | #endif 48 | #if DEBUG_OUTPUT 49 | #define debug(x) gck_rpc_debug x 50 | #else 51 | #define debug(x) 52 | #endif 53 | #define warning(x) gck_rpc_warn x 54 | 55 | 56 | /* ----------------------------------------------------------------------------- 57 | * TLS-PSK (pre-shared key) functionality 58 | */ 59 | 60 | /* Utility function to decode a single hex char. 61 | * 62 | * Returns value as integer, or -1 on invalid hex char (not 0-9, a-f or A-F). 63 | */ 64 | static int 65 | _tls_psk_to_hex(char val) 66 | { 67 | if (val >= '0' && val <= '9') 68 | return val - '0'; 69 | if (val >= 'a' && val <= 'f') 70 | return val - 'a' + 10; 71 | if (val >= 'A' && val <= 'F') 72 | return val - 'A' + 10; 73 | return -1; 74 | } 75 | 76 | /* Hex decode the key from an entry in the TLS-PSK key file. Entrys are of the form 77 | * 78 | * identity:hex-key\n 79 | * 80 | * Logging debug/error messages here is a bit problematic since the key is sensitive 81 | * and should not be logged to syslog for example. This code avoids logging the key 82 | * part and only logs identity. 83 | * 84 | * Returns 0 on failure, number of bytes in hex-decoded key on success. 85 | */ 86 | static int 87 | _tls_psk_decode_key(const char *identity, const char *hexkey, unsigned char *psk, unsigned int max_psk_len) 88 | { 89 | int psk_len, i; 90 | 91 | /* check that length of the key is even */ 92 | if ((strlen(hexkey) % 2) != 0) { 93 | warning(("un-even length TLS-PSK key")); 94 | return 0; 95 | } 96 | 97 | memset(psk, 0, max_psk_len); 98 | psk_len = 0; 99 | 100 | while (*hexkey && (psk_len < max_psk_len)) { 101 | /* decode first half of byte, check for errors */ 102 | if ((i = _tls_psk_to_hex(*hexkey)) < 0) { 103 | warning(("bad TLS-PSK '%.100s' hex char at position %i (%c)", 104 | identity, psk_len + 1, *hexkey)); 105 | return 0; 106 | } 107 | *psk = i << 4; 108 | hexkey++; 109 | 110 | /* decode second half of byte, check for errors */ 111 | if ((i = _tls_psk_to_hex(*hexkey)) < 0) { 112 | warning(("bad TLS-PSK '%.100s' hex char at position %i (%c)", 113 | identity, psk_len + 1, *hexkey)); 114 | return 0; 115 | } 116 | *psk |= i; 117 | hexkey++; 118 | 119 | psk_len++; 120 | psk++; 121 | } 122 | if (*hexkey) { 123 | warning(("too long TLS-PSK '%.100s' key (max %i)", identity, max_psk_len)); 124 | return 0; 125 | } 126 | 127 | return psk_len; 128 | } 129 | 130 | /* 131 | * Read from a file descriptor until a newline is spotted. 132 | * 133 | * Using open() and _fgets() instead of fopen() and fgets() avoids having to 134 | * seccomp-allow the mmap() syscall. 135 | * 136 | * Reading one byte at a time is perhaps not optimal from a performance 137 | * standpoint, but the kernel will surely have pre-buffered the data anyways. 138 | */ 139 | int _fgets(char *buf, unsigned int len, const int fd) 140 | { 141 | int bytes; 142 | 143 | bytes = 0; 144 | 145 | while (len) { 146 | if (read(fd, buf, 1) != 1) 147 | break; 148 | bytes++; 149 | if (*buf == '\n') { 150 | buf++; 151 | len--; 152 | break; 153 | } 154 | buf++; 155 | len--; 156 | } 157 | 158 | if (! len) 159 | /* ran out of space */ 160 | return -1; 161 | *buf = '\0'; 162 | return bytes; 163 | } 164 | 165 | /* 166 | * Callbacks invoked by OpenSSL PSK initialization. 167 | */ 168 | 169 | 170 | /* Server side TLS-PSK initialization callback. Given an identity (chosen by the client), 171 | * locate a pre-shared key and put it in psk. 172 | * 173 | * Returns the number of bytes put in psk, or 0 on failure. 174 | */ 175 | static unsigned int 176 | _tls_psk_server_cb(SSL *ssl, const char *identity, 177 | unsigned char *psk, unsigned int max_psk_len) 178 | { 179 | char line[1024], *hexkey; 180 | unsigned int psk_len; 181 | int i, fd; 182 | 183 | debug(("Initializing TLS-PSK with keyfile '%.100s', identity '%.100s'", 184 | tls_psk_key_filename, identity)); 185 | 186 | if ((fd = open(tls_psk_key_filename, O_RDONLY | O_CLOEXEC)) < 0) { 187 | gck_rpc_warn("can't open TLS-PSK keyfile '%.100s' for reading : %s", 188 | tls_psk_key_filename, strerror(errno)); 189 | return 0; 190 | } 191 | 192 | /* Format of PSK file is that of GnuTLS psktool. 193 | * 194 | * identity:hex-key 195 | * other:another-hex-key 196 | */ 197 | psk_len = 0; 198 | 199 | while (_fgets(line, sizeof(line) - 1, fd) > 0) { 200 | /* Find first colon and replace it with NULL */ 201 | hexkey = strchr(line, ':'); 202 | if (! hexkey) 203 | continue; 204 | *hexkey = 0; 205 | hexkey++; 206 | 207 | /* Remove newline(s) at the end */ 208 | for (i = strlen(hexkey) - 1; i && (hexkey[i] == '\n' || hexkey[i] == '\r'); i--) 209 | hexkey[i] = 0; 210 | 211 | if (identity == NULL || ! identity[0] || ! strcmp(line, identity)) { 212 | /* If the line starts with identity: or identity is not provided, parse this line. */ 213 | psk_len = _tls_psk_decode_key(line, hexkey, psk, max_psk_len); 214 | if (psk_len) 215 | debug(("Loaded TLS-PSK '%.100s' from keyfile '%.100s'", 216 | line, tls_psk_key_filename)); 217 | else 218 | warning(("Failed loading TLS-PSK '%.100s' from keyfile '%.100s'", 219 | line, tls_psk_key_filename)); 220 | break; 221 | } 222 | } 223 | close(fd); 224 | 225 | return psk_len; 226 | } 227 | 228 | /* Client side TLS-PSK initialization callback. Indicate to OpenSSL what identity to 229 | * use, and the pre-shared key for that identity. 230 | * 231 | * Returns the number of bytes put in psk, or 0 on failure. 232 | */ 233 | static unsigned int 234 | _tls_psk_client_cb(SSL *ssl, const char *hint, 235 | char *identity, unsigned int max_identity_len, 236 | unsigned char *psk, unsigned int max_psk_len) 237 | { 238 | /* Client tells server which identity it wants to use in ClientKeyExchange */ 239 | snprintf(identity, max_identity_len, "%s", tls_psk_identity); 240 | 241 | /* We currently just discard the hint sent to us by the server */ 242 | return _tls_psk_server_cb(ssl, identity, psk, max_psk_len); 243 | } 244 | 245 | 246 | /* Initialize OpenSSL and create an SSL CTX. Should be called just once. 247 | * 248 | * Returns 0 on failure and 1 on success. 249 | */ 250 | int 251 | gck_rpc_init_tls_psk(GckRpcTlsPskState *state, const char *key_filename, 252 | const char *identity, enum gck_rpc_tls_psk_caller caller) 253 | { 254 | char *tls_psk_ciphers = PKCS11PROXY_TLS_PSK_CIPHERS; 255 | 256 | if (state->initialized == 1) { 257 | warning(("TLS state already initialized")); 258 | return 0; 259 | } 260 | 261 | /* Global OpenSSL initialization */ 262 | SSL_load_error_strings(); 263 | SSL_library_init(); 264 | OpenSSL_add_ssl_algorithms(); 265 | 266 | assert(caller == GCK_RPC_TLS_PSK_CLIENT || caller == GCK_RPC_TLS_PSK_SERVER); 267 | 268 | state->ssl_ctx = SSL_CTX_new(TLSv1_2_method()); 269 | 270 | if (state->ssl_ctx == NULL) { 271 | gck_rpc_warn("can't initialize SSL_CTX"); 272 | return 0; 273 | } 274 | 275 | /* Set up callback for TLS-PSK initialization */ 276 | if (caller == GCK_RPC_TLS_PSK_CLIENT) 277 | SSL_CTX_set_psk_client_callback(state->ssl_ctx, _tls_psk_client_cb); 278 | else 279 | SSL_CTX_set_psk_server_callback(state->ssl_ctx, _tls_psk_server_cb); 280 | 281 | /* Disable compression, for security (CRIME Attack). */ 282 | SSL_CTX_set_options(state->ssl_ctx, SSL_OP_NO_COMPRESSION); 283 | 284 | /* Specify ciphers to use */ 285 | SSL_CTX_set_cipher_list(state->ssl_ctx, tls_psk_ciphers); 286 | 287 | snprintf(tls_psk_key_filename, sizeof(tls_psk_key_filename), "%s", key_filename); 288 | snprintf(tls_psk_identity, sizeof(tls_psk_identity), "%s", identity ? identity : ""); 289 | 290 | state->type = caller; 291 | state->initialized = 1; 292 | 293 | debug(("Initialized TLS-PSK %s", caller == GCK_RPC_TLS_PSK_CLIENT ? "client" : "server")); 294 | 295 | return 1; 296 | } 297 | 298 | /* Set up SSL for a new socket. Call this after accept() or connect(). 299 | * 300 | * When a socket has been created, call gck_rpc_start_tls() with the TLS state 301 | * initialized using gck_rpc_init_tls_psk() and the new socket. 302 | * 303 | * Returns 1 on success and 0 on failure. 304 | */ 305 | int 306 | gck_rpc_start_tls(GckRpcTlsPskState *state, int sock) 307 | { 308 | int res; 309 | char buf[256]; 310 | 311 | state->ssl = SSL_new(state->ssl_ctx); 312 | if (! state->ssl) { 313 | warning(("can't initialize SSL")); 314 | return 0; 315 | } 316 | 317 | state->bio = BIO_new_socket(sock, BIO_NOCLOSE); 318 | if (! state->bio) { 319 | warning(("can't initialize SSL BIO")); 320 | return 0; 321 | } 322 | 323 | SSL_set_bio(state->ssl, state->bio, state->bio); 324 | 325 | /* Set up callback for TLS-PSK initialization */ 326 | if (state->type == GCK_RPC_TLS_PSK_CLIENT) 327 | res = SSL_connect(state->ssl); 328 | else 329 | res = SSL_accept(state->ssl); 330 | 331 | if (res != 1) { 332 | ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); 333 | warning(("can't start TLS : %i/%i (%s perhaps)", 334 | res, SSL_get_error(state->ssl, res), strerror(errno))); 335 | warning(("SSL ERR: %s", buf)); 336 | return 0; 337 | } 338 | 339 | return 1; 340 | } 341 | 342 | /* Un-initialize everything SSL related. Call this on application shut down. 343 | */ 344 | void 345 | gck_rpc_close_tls(GckRpcTlsPskState *state) 346 | { 347 | if (state->ssl_ctx) { 348 | SSL_CTX_free(state->ssl_ctx); 349 | state->ssl_ctx = NULL; 350 | } 351 | 352 | if (state->ssl) { 353 | SSL_free(state->ssl); 354 | state->ssl = NULL; 355 | } 356 | } 357 | 358 | /* Send data using SSL. 359 | * 360 | * Returns the number of bytes written. 361 | */ 362 | int 363 | gck_rpc_tls_write_all(GckRpcTlsPskState *state, void *data, unsigned int len) 364 | { 365 | int bytes, error; 366 | char buf[256]; 367 | 368 | assert(state); 369 | assert(data); 370 | assert(len > 0); 371 | 372 | bytes = SSL_write(state->ssl, data, len); 373 | 374 | if (bytes <= 0) { 375 | while ((error = ERR_get_error())) { 376 | ERR_error_string_n(error, buf, sizeof(buf)); 377 | warning(("SSL_write error: %s", buf)); 378 | } 379 | return 0; 380 | } 381 | 382 | return bytes; 383 | } 384 | 385 | /* Read data using SSL. 386 | * 387 | * Returns the number of bytes read. 388 | */ 389 | int 390 | gck_rpc_tls_read_all(GckRpcTlsPskState *state, void *data, unsigned int len) 391 | { 392 | int bytes, error; 393 | char buf[256]; 394 | 395 | assert(state); 396 | assert(data); 397 | assert(len > 0); 398 | 399 | bytes = SSL_read(state->ssl, data, len); 400 | 401 | if (bytes <= 0) { 402 | while ((error = ERR_get_error())) { 403 | ERR_error_string_n(error, buf, sizeof(buf)); 404 | warning(("SSL_read error: %s", buf)); 405 | } 406 | return 0; 407 | } 408 | 409 | return bytes; 410 | } 411 | -------------------------------------------------------------------------------- /gck-rpc-tls-psk.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ 2 | #ifndef GCKRPC_TLS_PSK_H_ 3 | #define GCKRPC_TLS_PSK_H_ 4 | 5 | #include "openssl/bio.h" 6 | #include "openssl/ssl.h" 7 | #include "openssl/err.h" 8 | 9 | #if OPENSSL_VERSION_NUMBER < 0x10000000 10 | # error "OpenSSL version >= 1.0.0 required" 11 | #endif 12 | 13 | enum gck_rpc_tls_psk_caller { 14 | GCK_RPC_TLS_PSK_CLIENT, 15 | GCK_RPC_TLS_PSK_SERVER 16 | }; 17 | 18 | typedef struct { 19 | int initialized; 20 | SSL_CTX *ssl_ctx; 21 | BIO *bio; 22 | SSL *ssl; 23 | enum gck_rpc_tls_psk_caller type; 24 | } GckRpcTlsPskState; 25 | 26 | 27 | int gck_rpc_init_tls_psk(GckRpcTlsPskState *state, const char *key_filename, 28 | const char *identity, enum gck_rpc_tls_psk_caller caller); 29 | int gck_rpc_start_tls(GckRpcTlsPskState *state, int sock); 30 | 31 | int gck_rpc_tls_write_all(GckRpcTlsPskState *state, void *data, unsigned int len); 32 | int gck_rpc_tls_read_all(GckRpcTlsPskState *state, void *data, unsigned int len); 33 | 34 | void gck_rpc_close_tls(GckRpcTlsPskState *state); 35 | 36 | #endif /* GCKRPC_TLS_PSK_H_ */ 37 | -------------------------------------------------------------------------------- /gck-rpc-util.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ 2 | /* p11-rpc-util.c - utilities for module and dispatcher 3 | 4 | Copyright (C) 2008, Stef Walter 5 | 6 | The Gnome Keyring Library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Library General Public License as 8 | published by the Free Software Foundation; either version 2 of the 9 | License, or (at your option) any later version. 10 | 11 | The Gnome Keyring Library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Library General Public License for more details. 15 | 16 | You should have received a copy of the GNU Library General Public 17 | License along with the Gnome Library; see the file COPYING.LIB. If not, 18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 | Boston, MA 02111-1307, USA. 20 | 21 | Author: Stef Walter 22 | */ 23 | 24 | #include "config.h" 25 | 26 | #include "gck-rpc-layer.h" 27 | #include "gck-rpc-private.h" 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | static void do_log(const char *pref, const char *msg, va_list va) 34 | { 35 | char buffer[1024]; 36 | size_t len = 0; 37 | 38 | if (pref) { 39 | snprintf(buffer, sizeof(buffer), "%s: ", pref); 40 | len = strlen(buffer); 41 | } 42 | 43 | vsnprintf(buffer + len, sizeof(buffer) - len, msg, va); 44 | gck_rpc_log(buffer); 45 | } 46 | 47 | void gck_rpc_warn(const char *msg, ...) 48 | { 49 | va_list va; 50 | va_start(va, msg); 51 | do_log("WARNING", msg, va); 52 | va_end(va); 53 | } 54 | 55 | void gck_rpc_debug(const char *msg, ...) 56 | { 57 | va_list va; 58 | va_start(va, msg); 59 | do_log("DEBUG", msg, va); 60 | va_end(va); 61 | } 62 | 63 | int gck_rpc_mechanism_is_supported(CK_MECHANISM_TYPE mech) 64 | { 65 | if (gck_rpc_mechanism_has_no_parameters(mech) || 66 | gck_rpc_mechanism_has_sane_parameters(mech)) 67 | return 1; 68 | return 0; 69 | } 70 | 71 | void 72 | gck_rpc_mechanism_list_purge(CK_MECHANISM_TYPE_PTR mechs, CK_ULONG * n_mechs) 73 | { 74 | int i; 75 | 76 | assert(mechs); 77 | assert(n_mechs); 78 | 79 | for (i = 0; i < (int)(*n_mechs); ++i) { 80 | if (!gck_rpc_mechanism_has_no_parameters(mechs[i]) && 81 | !gck_rpc_mechanism_has_sane_parameters(mechs[i])) { 82 | 83 | /* Remove the mechanism from the list */ 84 | memmove(&mechs[i], &mechs[i + 1], 85 | (*n_mechs - i) * sizeof(CK_MECHANISM_TYPE)); 86 | 87 | --(*n_mechs); 88 | --i; 89 | } 90 | } 91 | } 92 | 93 | int gck_rpc_mechanism_has_sane_parameters(CK_MECHANISM_TYPE type) 94 | { 95 | /* This list is incomplete */ 96 | switch (type) { 97 | case CKM_RSA_PKCS_OAEP: 98 | case CKM_RSA_PKCS_PSS: 99 | return 1; 100 | default: 101 | return 0; 102 | } 103 | } 104 | 105 | int gck_rpc_mechanism_has_no_parameters(CK_MECHANISM_TYPE mech) 106 | { 107 | /* This list is incomplete */ 108 | 109 | switch (mech) { 110 | case CKM_RSA_PKCS_KEY_PAIR_GEN: 111 | case CKM_RSA_X9_31_KEY_PAIR_GEN: 112 | case CKM_RSA_PKCS: 113 | case CKM_RSA_9796: 114 | case CKM_RSA_X_509: 115 | case CKM_RSA_X9_31: 116 | case CKM_MD2_RSA_PKCS: 117 | case CKM_MD5_RSA_PKCS: 118 | case CKM_SHA1_RSA_PKCS: 119 | case CKM_SHA256_RSA_PKCS: 120 | case CKM_SHA384_RSA_PKCS: 121 | case CKM_SHA512_RSA_PKCS: 122 | case CKM_RIPEMD128_RSA_PKCS: 123 | case CKM_RIPEMD160_RSA_PKCS: 124 | case CKM_SHA1_RSA_X9_31: 125 | case CKM_DSA_KEY_PAIR_GEN: 126 | case CKM_DSA_PARAMETER_GEN: 127 | case CKM_DSA: 128 | case CKM_DSA_SHA1: 129 | case CKM_FORTEZZA_TIMESTAMP: 130 | case CKM_EC_KEY_PAIR_GEN: 131 | case CKM_ECDSA: 132 | case CKM_ECDSA_SHA1: 133 | case CKM_DH_PKCS_KEY_PAIR_GEN: 134 | case CKM_DH_PKCS_PARAMETER_GEN: 135 | case CKM_X9_42_DH_KEY_PAIR_GEN: 136 | case CKM_X9_42_DH_PARAMETER_GEN: 137 | case CKM_KEA_KEY_PAIR_GEN: 138 | case CKM_GENERIC_SECRET_KEY_GEN: 139 | case CKM_RC2_KEY_GEN: 140 | case CKM_RC4_KEY_GEN: 141 | case CKM_RC4: 142 | case CKM_RC5_KEY_GEN: 143 | case CKM_AES_KEY_GEN: 144 | case CKM_AES_ECB: 145 | case CKM_AES_MAC: 146 | case CKM_DES_KEY_GEN: 147 | case CKM_DES2_KEY_GEN: 148 | case CKM_DES3_KEY_GEN: 149 | case CKM_CDMF_KEY_GEN: 150 | case CKM_CAST_KEY_GEN: 151 | case CKM_CAST3_KEY_GEN: 152 | case CKM_CAST128_KEY_GEN: 153 | case CKM_IDEA_KEY_GEN: 154 | case CKM_SSL3_PRE_MASTER_KEY_GEN: 155 | case CKM_TLS_PRE_MASTER_KEY_GEN: 156 | case CKM_SKIPJACK_KEY_GEN: 157 | case CKM_BATON_KEY_GEN: 158 | case CKM_JUNIPER_KEY_GEN: 159 | case CKM_RC2_ECB: 160 | case CKM_DES_ECB: 161 | case CKM_DES3_ECB: 162 | case CKM_CDMF_ECB: 163 | case CKM_CAST_ECB: 164 | case CKM_CAST3_ECB: 165 | case CKM_CAST128_ECB: 166 | case CKM_RC5_ECB: 167 | case CKM_IDEA_ECB: 168 | case CKM_RC2_MAC: 169 | case CKM_DES_MAC: 170 | case CKM_DES3_MAC: 171 | case CKM_CDMF_MAC: 172 | case CKM_CAST_MAC: 173 | case CKM_CAST3_MAC: 174 | case CKM_RC5_MAC: 175 | case CKM_IDEA_MAC: 176 | case CKM_SSL3_MD5_MAC: 177 | case CKM_SSL3_SHA1_MAC: 178 | case CKM_SKIPJACK_WRAP: 179 | case CKM_BATON_WRAP: 180 | case CKM_JUNIPER_WRAP: 181 | case CKM_MD2: 182 | case CKM_MD2_HMAC: 183 | case CKM_MD5: 184 | case CKM_MD5_HMAC: 185 | case CKM_SHA_1: 186 | case CKM_SHA_1_HMAC: 187 | case CKM_SHA256: 188 | case CKM_SHA256_HMAC: 189 | case CKM_SHA384: 190 | case CKM_SHA384_HMAC: 191 | case CKM_SHA512: 192 | case CKM_SHA512_HMAC: 193 | case CKM_FASTHASH: 194 | case CKM_RIPEMD128: 195 | case CKM_RIPEMD128_HMAC: 196 | case CKM_RIPEMD160: 197 | case CKM_RIPEMD160_HMAC: 198 | case CKM_KEY_WRAP_LYNKS: 199 | return 1; 200 | default: 201 | return 0; 202 | }; 203 | } 204 | 205 | int 206 | gck_rpc_has_ulong_parameter(CK_ATTRIBUTE_TYPE type) 207 | { 208 | switch (type) { 209 | case CKA_CLASS: 210 | case CKA_KEY_TYPE: 211 | case CKA_CERTIFICATE_TYPE: 212 | case CKA_HW_FEATURE_TYPE: 213 | case CKA_MODULUS_BITS: 214 | return 1; 215 | default: 216 | return 0; 217 | } 218 | } 219 | 220 | int 221 | gck_rpc_has_bad_sized_ulong_parameter(CK_ATTRIBUTE_PTR attr) 222 | { 223 | if (!attr->pValue) 224 | return 0; 225 | /* All this parameters are transmited on the network 226 | * as 64bit integers */ 227 | if (sizeof (uint64_t) != attr->ulValueLen) 228 | return 0; 229 | if (sizeof (CK_ULONG) == attr->ulValueLen) 230 | return 0; 231 | return gck_rpc_has_ulong_parameter(attr->type); 232 | } 233 | 234 | /* 235 | * Parses prefix into two strings (host and port). Port may be a NULL pointer 236 | * if none is specified. Since this code does not decode port in any way, a 237 | * service name works too (but requires other code (like 238 | * _get_listening_socket()) able to resolve service names). 239 | * 240 | * This should work for IPv4 and IPv6 inputs : 241 | * 242 | * 0.0.0.0:2345 243 | * 0.0.0.0 244 | * [::]:2345 245 | * [::] 246 | * [::1]:2345 247 | * localhost:2345 248 | * localhost 249 | * localhost:p11proxy (if p11proxy is a known service name) 250 | * 251 | * Returns 0 on failure, and 1 on success. 252 | */ 253 | int gck_rpc_parse_host_port(const char *prefix, char **host, char **port) 254 | { 255 | char *p = NULL; 256 | int is_ipv6; 257 | 258 | is_ipv6 = (prefix[0] == '[') ? 1 : 0; 259 | 260 | *host = strdup(prefix + is_ipv6); 261 | *port = NULL; 262 | 263 | if (*host == NULL) { 264 | gck_rpc_warn("out of memory"); 265 | return 0; 266 | } 267 | 268 | if (is_ipv6 && prefix[0] == '[') 269 | p = strchr(*host, ']'); 270 | else 271 | p = strchr(*host, ':'); 272 | 273 | if (p) { 274 | is_ipv6 = (*p == ']'); /* remember if separator was ']' */ 275 | 276 | *p = '\0'; /* replace separator will NULL to terminate *host */ 277 | *port = p + 1; 278 | 279 | if (is_ipv6 && (**port == ':')) 280 | *port = p + 2; 281 | } 282 | 283 | return 1; 284 | } 285 | -------------------------------------------------------------------------------- /mksyscalls.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | (echo "static const char *syscall_names[] = {" 3 | 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' 4 | echo "};")> syscall-names.h 5 | -------------------------------------------------------------------------------- /p11proxy-mitm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # Copyright (c) 2012, 2013, NORDUnet A/S 4 | # All rights reserved. 5 | # 6 | # Redistribution and use in source and binary forms, with or 7 | # without modification, are permitted provided that the following 8 | # conditions are met: 9 | # 10 | # 1. Redistributions of source code must retain the above copyright 11 | # notice, this list of conditions and the following disclaimer. 12 | # 2. Redistributions in binary form must reproduce the above 13 | # copyright notice, this list of conditions and the following 14 | # disclaimer in the documentation and/or other materials provided 15 | # with the distribution. 16 | # 3. Neither the name of the NORDUnet nor the names of its 17 | # contributors may be used to endorse or promote products derived 18 | # from this software without specific prior written permission. 19 | # 20 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | # POSSIBILITY OF SUCH DAMAGE. 32 | # 33 | # Author : Fredrik Thulin 34 | # 35 | """ 36 | MITM (man in the middle) proxy of pkcs11-proxy. Written while learning 37 | how the (not very documented) wire format worked, as well as to help 38 | diagnose (and fix) a couple of bugs in the C implementation. 39 | 40 | Usage : 41 | 42 | On console 1 : 43 | 44 | $ PKCS11_DAEMON_SOCKET="tcp://127.0.0.1:2345" pkcs11-daemon /usr/lib/libsofthsm.so 45 | 46 | On console 2 : 47 | 48 | $ ./p11proxy-mitm --debug 49 | 50 | On console 3 : 51 | 52 | $ PKCS11_PROXY_SOCKET="tcp://127.0.0.1:2344" pkcs11-tool --show-info --module libpkcs11-proxy.so 53 | 54 | """ 55 | 56 | import sys 57 | import struct 58 | import socket 59 | import logging 60 | import argparse 61 | import SocketServer 62 | import PyKCS11 # used to get all the PKCS#11 defines 63 | 64 | default_host = "localhost" 65 | default_port_in = 2344 66 | default_port_out = 2345 67 | default_timeout = 3 68 | default_debug = False 69 | 70 | args = None 71 | yhsm = None 72 | logger = None 73 | 74 | # Extracted from gck-rpc-private.h. The last two elements of the tuples describe 75 | # the requests/responses. 76 | # 77 | # /* 78 | # * a_ = prefix denotes array of _ 79 | # * A = CK_ATTRIBUTE 80 | # * f_ = prefix denotes buffer for _ 81 | # * M = CK_MECHANISM 82 | # * u = CK_ULONG 83 | # * s = space padded string 84 | # * v = CK_VERSION 85 | # * y = CK_BYTE 86 | # * z = null terminated string 87 | # */ 88 | request_list = [ 89 | (0, "ERROR", None, None), 90 | (1, "C_Initialize", "ay", ""), 91 | (2, "C_Finalize", "", ""), 92 | (3, "C_GetInfo", "", "vsusv"), 93 | (4, "C_GetSlotList", "yfu", "au"), 94 | (5, "C_GetSlotInfo", "u", "ssuvv"), 95 | (6, "C_GetTokenInfo", "u", "ssssuuuuuuuuuuuvvs"), 96 | (7, "C_GetMechanismList", "ufu", "au"), 97 | (8, "C_GetMechanismInfo", "uu", "uuu"), 98 | (9, "C_InitToken", "uays", ""), 99 | (10, "C_WaitForSlotEvent", "u", "u"), 100 | (11, "C_OpenSession", "uu", "u"), 101 | (12, "C_CloseSession", "u", ""), 102 | (13, "C_CloseAllSessions", "u", ""), 103 | (14, "C_GetFunctionStatus", "u", ""), 104 | (15, "C_CancelFunction", "u", ""), 105 | (16, "C_GetSessionInfo", "u", "uuuu"), 106 | (17, "C_InitPIN", "uay", ""), 107 | (18, "C_SetPIN", "uayay", ""), 108 | (19, "C_GetOperationState", "ufy", "ay"), 109 | (20, "C_SetOperationState", "uayuu", ""), 110 | (21, "C_Login", "uuay", ""), 111 | (22, "C_Logout", "u", ""), 112 | (23, "C_CreateObject", "uaA", "u"), 113 | (24, "C_CopyObject", "uuaA", "u"), 114 | (25, "C_DestroyObject", "uu", ""), 115 | (26, "C_GetObjectSize", "uu", "u"), 116 | (27, "C_GetAttributeValue", "uufA", "aAu"), 117 | (28, "C_SetAttributeValue", "uuaA", ""), 118 | (29, "C_FindObjectsInit", "uaA", ""), 119 | (30, "C_FindObjects", "ufu", "au"), 120 | (31, "C_FindObjectsFinal", "u", ""), 121 | (32, "C_EncryptInit", "uMu", ""), 122 | (33, "C_Encrypt", "uayfy", "ay"), 123 | (34, "C_EncryptUpdate", "uayfy", "ay"), 124 | (35, "C_EncryptFinal", "ufy", "ay"), 125 | (36, "C_DecryptInit", "uMu", ""), 126 | (37, "C_Decrypt", "uayfy", "ay"), 127 | (38, "C_DecryptUpdate", "uayfy", "ay"), 128 | (39, "C_DecryptFinal", "ufy", "ay"), 129 | (40, "C_DigestInit", "uM", ""), 130 | (41, "C_Digest", "uayfy", "ay"), 131 | (42, "C_DigestUpdate", "uay", ""), 132 | (43, "C_DigestKey", "uu", ""), 133 | (44, "C_DigestFinal", "ufy", "ay"), 134 | (45, "C_SignInit", "uMu", ""), 135 | (46, "C_Sign", "uayfy", "ay"), 136 | (47, "C_SignUpdate", "uay", ""), 137 | (48, "C_SignFinal", "ufy", "ay"), 138 | (49, "C_SignRecoverInit", "uMu", ""), 139 | (50, "C_SignRecover", "uayfy", "ay"), 140 | (51, "C_VerifyInit", "uMu", ""), 141 | (52, "C_Verify", "uayay", ""), 142 | (53, "C_VerifyUpdate", "uay", ""), 143 | (54, "C_VerifyFinal", "uay", ""), 144 | (55, "C_VerifyRecoverInit", "uMu", ""), 145 | (56, "C_VerifyRecover", "uayfy", "ay"), 146 | (57, "C_DigestEncryptUpdate", "uayfy", "ay"), 147 | (58, "C_DecryptDigestUpdate", "uayfy", "ay"), 148 | (59, "C_SignEncryptUpdate", "uayfy", "ay"), 149 | (60, "C_DecryptVerifyUpdate", "uayfy", "ay"), 150 | (61, "C_GenerateKey", "uMaA", "u"), 151 | (62, "C_GenerateKeyPair", "uMaAaA", "uu"), 152 | (63, "C_WrapKey", "uMuufy", "ay"), 153 | (64, "C_UnwrapKey", "uMuayaA", "u"), 154 | (65, "C_DeriveKey", "uMuaA", "u"), 155 | (66, "C_SeedRandom", "uay", ""), 156 | (67, "C_GenerateRandom", "ufy", "ay"), 157 | ] 158 | 159 | def parse_args(): 160 | """ 161 | Parse the command line arguments. 162 | """ 163 | parser = argparse.ArgumentParser(description = "pkcs11-proxy man-in-the-middle", 164 | add_help = True, 165 | formatter_class = argparse.ArgumentDefaultsHelpFormatter, 166 | ) 167 | 168 | parser.add_argument('-H', '--host', 169 | dest='listen_host', 170 | default=default_host, 171 | help='Host address to listen on', 172 | metavar='HOST', 173 | ) 174 | 175 | parser.add_argument('--host-out', 176 | dest='connect_to_host', 177 | default=default_host, 178 | help='Host address to connect to', 179 | metavar='HOST', 180 | ) 181 | 182 | parser.add_argument('--port-in', 183 | dest='listen_port', 184 | type=int, 185 | default=default_port_in, 186 | help='Port to listen on', 187 | metavar='PORT', 188 | ) 189 | 190 | parser.add_argument('--port-out', 191 | dest='connect_to_port', 192 | type=int, 193 | default=default_port_out, 194 | help='Port to connect to', 195 | metavar='PORT', 196 | ) 197 | 198 | parser.add_argument('--timeout', 199 | dest='timeout', 200 | type=int, default=default_timeout, 201 | required=False, 202 | help='Request timeout in seconds', 203 | metavar='SECONDS', 204 | ) 205 | 206 | parser.add_argument('--debug', 207 | dest='debug', 208 | action='store_true', default=default_debug, 209 | help='Enable debug operation', 210 | ) 211 | 212 | return parser.parse_args() 213 | 214 | class ProxyHandler(SocketServer.StreamRequestHandler): 215 | """ 216 | The RequestHandler class for our server. 217 | 218 | It is instantiated once per connection to the server, and must 219 | override the handle() method to implement communication to the 220 | client. 221 | """ 222 | 223 | def __init__(self, *other_args, **kwargs): 224 | self.timeout = args.timeout 225 | 226 | # Outgoing connection to the real server (pkcs11-daemon) 227 | self.p11proxy = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 228 | self.p11proxy.connect((args.connect_to_host, args.connect_to_port)) 229 | 230 | self.logger = logger 231 | SocketServer.BaseRequestHandler.__init__(self, *other_args, **kwargs) 232 | 233 | def handle(self): 234 | """ 235 | Handle an incoming connection. Read requests/responses and decode them after passing 236 | them on to the real pkcs11-proxy client/server. 237 | """ 238 | # self.request is the TCP socket connected to the client 239 | try: 240 | # 64 bits app id. Randomized on the client, and not really used in the server. 241 | self.appid = self.request.recv(8) 242 | self.p11proxy.send(self.appid) 243 | 244 | while True: 245 | # Read request. First 32 bits are length. 246 | length = self.request.recv(4) 247 | if not length: 248 | break 249 | # Pass length to real server. 250 | self.p11proxy.send(length) 251 | self.logger.debug("\n\nRequest length is {}".format(length.encode('hex'))) 252 | self._handle_request(struct.unpack('>L', length)[0]) 253 | 254 | # Read response. Again, first 32 bits are length. 255 | length = self.p11proxy.recv(4) 256 | # Pass length to client. 257 | self.request.sendall(length) 258 | self.logger.debug("\n\nAnswer length is {}".format(length.encode('hex'))) 259 | self._handle_answer(struct.unpack('>L', length)[0]) 260 | except Exception, e: 261 | self.logger.exception("Got exception handling request from {}".format(self.client_address[0])) 262 | return None 263 | 264 | def _handle_request(self, length): 265 | """ 266 | Given expected length, read the rest of a request, pass it on and decode whatever we can. 267 | """ 268 | self.logger.debug("Request({})".format(length)) 269 | data = self.request.recv(length) 270 | self.logger.debug(" R: {}".format(data.encode('hex'))) 271 | self.p11proxy.send(data) 272 | # parse request 273 | (call_id, rest) = self._get_uint32(data) 274 | if call_id > len(request_list): 275 | return None 276 | self.logger.debug(" R: call_id {}".format(call_id)) 277 | rinfo = request_list[call_id] 278 | self.logger.debug(" R: name {}".format(rinfo[1])) 279 | fmt = rinfo[2] 280 | if fmt: 281 | self.logger.debug(" R: fmt {} ({})".format(fmt, fmt.encode('hex'))) 282 | return self._parse_message('R', fmt, rest) 283 | 284 | def _handle_answer(self, length): 285 | """ 286 | Given expected length, read the rest of a response, pass it on and decode whatever we can. 287 | """ 288 | self.logger.debug("Answer({})".format(length)) 289 | data = self.p11proxy.recv(length) 290 | self.logger.debug(" A: {}".format(data.encode('hex'))) 291 | self.request.sendall(data) 292 | (call_id, rest) = self._get_uint32(data) 293 | if call_id > len(request_list): 294 | return None 295 | # parse answer 296 | (call_id, rest) = self._get_uint32(data) 297 | if call_id > len(request_list): 298 | return None 299 | self.logger.debug(" A: call_id {}".format(call_id)) 300 | rinfo = request_list[call_id] 301 | self.logger.debug(" A: name {}".format(rinfo[1])) 302 | if not call_id: 303 | # This is ERROR 304 | (ckr, _) = self._get_uint32(data[-4:]) 305 | self.logger.debug(" A: {}".format(PyKCS11.CKR[ckr])) 306 | fmt = rinfo[3] 307 | if fmt: 308 | self.logger.debug(" A: fmt {} ({})".format(fmt, fmt.encode('hex'))) 309 | self._parse_message('A', fmt, rest) 310 | 311 | def _parse_message(self, msgtype, fmt, data): 312 | """ 313 | Parse the data in the request/response, which share format. 314 | """ 315 | # Check that the data is of the format we expect it to be. The format of every request/answer 316 | # is redundantly included in the data sent over the network, although we already know what 317 | # it should be. I guess this is a way to reduce the likeliness of undetected stream de-sync, 318 | # because it would be wasteful if it was just used to make developers forget to update the 319 | # handshake string when changing the format for a request/response. 320 | (parsed_fmt, rest) = self._get_byte_array(data) 321 | if parsed_fmt != fmt: 322 | self.logger.error(" {}: Format mismatch, mine is {} and received is {}".format(msgtype, fmt, parsed_fmt)) 323 | return None 324 | self.logger.debug(" {}: format match".format(msgtype)) 325 | try: 326 | res = self._value_dump(msgtype, parsed_fmt, rest) 327 | return res 328 | except Exception: 329 | self.logger.exception("Got exception trying to dump all data") 330 | return [] 331 | 332 | def _value_dump(self, msgtype, fmt, data, res = []): 333 | """ 334 | Decode the data in a request/answer according to fmt. 335 | 336 | Will output the decoded data using self.logger.debug(). 337 | """ 338 | if not fmt: 339 | if data: 340 | self.logger.warning("{} bytes left after processing : {}".format(len(data), data.encode('hex'))) 341 | return [] 342 | #self.logger.debug("PARSING {} FROM {}".format(fmt[0], data.encode('hex'))) 343 | if fmt[0] == 'u': 344 | (this, rest) = self._get_uint64(data) 345 | res.append(this) 346 | self.logger.debug(" {}: uint64 {}".format(msgtype, hex(this))) 347 | elif fmt[0] == 'a': 348 | #self.logger.debug("PARSING {} FROM {}".format(fmt[0], data.encode('hex'))) 349 | if fmt[1] == 'A': 350 | valid = 1 351 | rest = data 352 | else: 353 | (valid, rest) = self._get_uint8(data) 354 | self.logger.debug(" {}: Byte-Array valid : {}".format(msgtype, valid)) 355 | array_num = 0 356 | (array_num, rest) = self._get_uint32(rest) 357 | self.logger.debug(" {}: Byte-Array length : {}/{}".format(msgtype, array_num, hex(array_num))) 358 | if array_num > 256: 359 | raise Exception("Unreasonable array length : {}".format(hex(array_num))) 360 | if not valid: 361 | # /* If not valid, then just the length is encoded, this can signify CKR_BUFFER_TOO_SMALL */ 362 | self.logger.debug(" {}: Array length {}/{}, not valid - maybe CKR_BUFFER_TOO_SMALL".format(msgtype, array_num, array_num)) 363 | # array is now fully handled, remove next element of fmt 364 | fmt = fmt[1:] 365 | if rest: 366 | self.logger.debug(" {}: CKR_BUFFER_TOO_SMALL leaving data {} ({} bytes) for fmt {}".format(msgtype, rest.encode('hex'), len(rest), fmt[1:])) 367 | else: 368 | if fmt[1] == 'y': 369 | # simple byte array (i.e. string to us) 370 | rest = struct.pack('>L', array_num) + rest # restore length before calling _get_byte_array 371 | (this, rest) = self._get_byte_array(rest) 372 | self.logger.debug(" {}: Byte-Array({}) {}".format(msgtype, len(this), repr(this))) 373 | res.append(this) 374 | fmt = fmt[1:] 375 | else: 376 | if array_num > 0: 377 | # modify fmt to match the array length 378 | placeholder = 'X' 379 | array_elements = fmt[1] * (array_num - 1) 380 | fmt_rest = fmt[1:] 381 | fmt = placeholder + array_elements + fmt_rest 382 | else: 383 | # chomp the next fmt too 384 | fmt = fmt[1:] 385 | self.logger.debug(" {}: Array length {}, new fmt {}".format(msgtype, array_num, fmt)) 386 | elif fmt[0] == 's': 387 | (this, rest) = self._get_byte_array(data) 388 | res.append(this) 389 | self.logger.debug(" {}: string({}/{}) {}".format(msgtype, len(this), hex(len(this)), repr(this))) 390 | elif fmt[0] == 'v': 391 | # version, struct ck_version from pkcs11.h 392 | (major, rest) = self._get_uint8(data) 393 | (minor, rest) = self._get_uint8(rest) 394 | self.logger.debug(" {}: CK_Version {}.{}".format(msgtype, major, minor)) 395 | elif fmt[0] == 'y': 396 | (this, rest) = self._get_uint8(data) 397 | self.logger.debug(" {}: CK_Byte {}".format(msgtype, hex(this))) 398 | elif fmt[0] == 'z': 399 | # NULL-terminated string, len == -1 for empty string 400 | (length, rest) = self._get_uint32(data) 401 | if length == 0xffffffff: 402 | res.append('') 403 | else: 404 | (this, rest) = self._get_byte_array(data) 405 | res.append(this) 406 | self.logger.debug(" {}: NULL-string({}/{}) {}".format(msgtype, len(this), hex(len(this)), repr(this))) 407 | elif fmt[0] == 'M': 408 | # Mechanism 409 | #self.logger.debug("PARSING {} FROM {}".format(fmt[0], data.encode('hex'))) 410 | (mech_type, rest) = self._get_uint32(data) 411 | self.logger.debug(" {}: Mechanism {}/{}".format(msgtype, repr(mech_type), PyKCS11.CKM.get(mech_type))) 412 | (this, rest) = self._get_byte_array(rest) 413 | self.logger.debug(" {}: Mechanism parameter {}".format(msgtype, repr(this))) 414 | res.append((mech_type, this)) 415 | elif fmt[0] == 'A': 416 | # Attribute 417 | (this, rest) = self._get_attribute(data) 418 | res.append(this) 419 | #self.logger.debug(" {}: Attribute {}".format(msgtype, this)) 420 | vl = "None" 421 | if this['uValueLen'] is not None: 422 | vl = hex(this['uValueLen']) 423 | self.logger.debug(" {}: Attribute type {}/{}, valid {}, len {}, data {}".format(\ 424 | msgtype, hex(this['type']), PyKCS11.CKA.get(this['type']), this['valid'], vl, this['data'].encode('hex'))) 425 | elif fmt[0] == 'f': 426 | # array buffer 427 | if fmt[1] == 'y': 428 | (flags, rest) = self._get_uint8(data) 429 | else: 430 | rest = data 431 | (num_items, rest) = self._get_uint32(rest) 432 | if fmt[1] == 'A': 433 | self.logger.debug(" {}: Attribute buffer, {} elements".format(msgtype, hex(num_items))) 434 | while num_items: 435 | (attr_type, rest) = self._get_uint32(rest) 436 | (buffer_len, rest) = self._get_uint32(rest) 437 | self.logger.debug(" {}: type {}/{} len {}".format(msgtype, hex(attr_type), PyKCS11.CKA.get(attr_type), hex(buffer_len))) 438 | res.append(('attribute buffer', attr_type, buffer_len)) 439 | num_items -= 1 440 | elif fmt[1] == 'y': 441 | self.logger.debug(" {}: Byte buffer, length {} (flags {})".format(msgtype, hex(num_items), flags)) 442 | # just a number of bytes to alloc 443 | pass 444 | elif fmt[1] == 'u': 445 | # ulong buffer, just an uint32 (?) 446 | self.logger.debug("PARSING {} FROM {}".format(fmt[0], data.encode('hex'))) 447 | (this, rest) = self._get_uint32(data) 448 | self.logger.debug(" {}: ulong buffer {}".format(msgtype, hex(this))) 449 | else: 450 | raise Exception("Unknown array buffer fmt '{}'".format(fmt[1])) 451 | # need to munch an extra fmt 452 | fmt = fmt[1:] 453 | else: 454 | self.logger.warn(" {}: STOPPING at fmt {}, data {}".format(msgtype, fmt[0], data.encode('hex'))) 455 | return [] 456 | return self._value_dump(msgtype, fmt[1:], rest, res) 457 | 458 | def _get_uint64(self, data): 459 | (a, rest) = self._get_uint32(data) 460 | (b, rest) = self._get_uint32(rest) 461 | return (a << 32 | b, data[8:]) 462 | 463 | def _get_uint32(self, data): 464 | res = struct.unpack('>L', data[:4])[0] 465 | return (res, data[4:]) 466 | 467 | def _get_uint8(self, data): 468 | res = ord(data[0]) 469 | return (res, data[1:]) 470 | 471 | def _get_byte_array(self, data): 472 | (length, rest) = self._get_uint32(data) 473 | if length == 0xffffffff: 474 | return('', rest) 475 | if length > len(rest): 476 | raise Exception('Parse error, not enough bytes left for byte-array') 477 | res = rest[:length] 478 | return (res, rest[length:]) 479 | 480 | def _get_attribute(self, data): 481 | attr = {} 482 | (attr_type, rest) = self._get_uint32(data) 483 | (attr_valid, rest) = self._get_uint8(rest) 484 | attr_vallen = None 485 | data = '' 486 | if attr_valid: 487 | (attr_vallen, rest) = self._get_uint32(rest) 488 | # length doubly included, in byte array again? 489 | (data, rest) = self._get_byte_array(rest) 490 | # read data here! 491 | attr['type'] = attr_type 492 | attr['valid'] = attr_valid 493 | attr['uValueLen'] = attr_vallen 494 | attr['data'] = data 495 | return (attr, rest) 496 | 497 | def main(): 498 | global args 499 | args = parse_args() 500 | 501 | level = logging.INFO 502 | if args.debug: 503 | level = logging.DEBUG 504 | logging.basicConfig(level=level) 505 | global logger 506 | logger = logging.getLogger('p11proxy-mitm') 507 | 508 | # Create the server 509 | server = SocketServer.TCPServer((args.listen_host, args.listen_port), \ 510 | ProxyHandler, \ 511 | bind_and_activate=False, \ 512 | ) 513 | server.allow_reuse_address = True 514 | server.timeout = args.timeout 515 | server.server_bind() # Manually bind, to support allow_reuse_address 516 | server.server_activate() # (see above comment) 517 | 518 | # Activate the server; this will keep running until you 519 | # interrupt the program with Ctrl-C 520 | server.serve_forever() 521 | 522 | if __name__ == '__main__': 523 | try: 524 | if main(): 525 | sys.exit(0) 526 | sys.exit(1) 527 | except KeyboardInterrupt: 528 | pass 529 | -------------------------------------------------------------------------------- /pkcs11/pkcs11.h: -------------------------------------------------------------------------------- 1 | /* pkcs11.h 2 | Copyright 2006, 2007 g10 Code GmbH 3 | Copyright 2006 Andreas Jellinghaus 4 | 5 | This file is free software; as a special exception the author gives 6 | unlimited permission to copy and/or distribute it, with or without 7 | modifications, as long as this notice is preserved. 8 | 9 | This file is distributed in the hope that it will be useful, but 10 | WITHOUT ANY WARRANTY, to the extent permitted by law; without even 11 | the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 12 | PURPOSE. */ 13 | 14 | /* Please submit changes back to the Scute project at 15 | http://www.scute.org/ (or send them to marcus@g10code.com), so that 16 | they can be picked up by other projects from there as well. */ 17 | 18 | /* This file is a modified implementation of the PKCS #11 standard by 19 | RSA Security Inc. It is mostly a drop-in replacement, with the 20 | following change: 21 | 22 | This header file does not require any macro definitions by the user 23 | (like CK_DEFINE_FUNCTION etc). In fact, it defines those macros 24 | for you (if useful, some are missing, let me know if you need 25 | more). 26 | 27 | There is an additional API available that does comply better to the 28 | GNU coding standard. It can be switched on by defining 29 | CRYPTOKI_GNU before including this header file. For this, the 30 | following changes are made to the specification: 31 | 32 | All structure types are changed to a "struct ck_foo" where CK_FOO 33 | is the type name in PKCS #11. 34 | 35 | All non-structure types are changed to ck_foo_t where CK_FOO is the 36 | lowercase version of the type name in PKCS #11. The basic types 37 | (CK_ULONG et al.) are removed without substitute. 38 | 39 | All members of structures are modified in the following way: Type 40 | indication prefixes are removed, and underscore characters are 41 | inserted before words. Then the result is lowercased. 42 | 43 | Note that function names are still in the original case, as they 44 | need for ABI compatibility. 45 | 46 | CK_FALSE, CK_TRUE and NULL_PTR are removed without substitute. Use 47 | . 48 | 49 | If CRYPTOKI_COMPAT is defined before including this header file, 50 | then none of the API changes above take place, and the API is the 51 | one defined by the PKCS #11 standard. */ 52 | 53 | #ifndef PKCS11_H 54 | #define PKCS11_H 1 55 | 56 | #if defined(__cplusplus) 57 | extern "C" { 58 | #endif 59 | 60 | /* The version of cryptoki we implement. The revision is changed with 61 | each modification of this file. If you do not use the "official" 62 | version of this file, please consider deleting the revision macro 63 | (you may use a macro with a different name to keep track of your 64 | versions). */ 65 | #define CRYPTOKI_VERSION_MAJOR 2 66 | #define CRYPTOKI_VERSION_MINOR 20 67 | #define CRYPTOKI_VERSION_REVISION 6 68 | 69 | /* Compatibility interface is default, unless CRYPTOKI_GNU is 70 | given. */ 71 | #ifndef CRYPTOKI_GNU 72 | #ifndef CRYPTOKI_COMPAT 73 | #define CRYPTOKI_COMPAT 1 74 | #endif 75 | #endif 76 | 77 | /* System dependencies. */ 78 | 79 | #if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32) 80 | 81 | /* There is a matching pop below. */ 82 | #pragma pack(push, cryptoki, 1) 83 | 84 | #ifdef CRYPTOKI_EXPORTS 85 | #define CK_SPEC __declspec(dllexport) 86 | #else 87 | #define CK_SPEC __declspec(dllimport) 88 | #endif 89 | 90 | #else 91 | 92 | #define CK_SPEC 93 | 94 | #endif 95 | 96 | #ifdef CRYPTOKI_COMPAT 97 | /* If we are in compatibility mode, switch all exposed names to the 98 | PKCS #11 variant. There are corresponding #undefs below. */ 99 | 100 | #define ck_flags_t CK_FLAGS 101 | #define ck_version _CK_VERSION 102 | 103 | #define ck_info _CK_INFO 104 | #define cryptoki_version cryptokiVersion 105 | #define manufacturer_id manufacturerID 106 | #define library_description libraryDescription 107 | #define library_version libraryVersion 108 | 109 | #define ck_notification_t CK_NOTIFICATION 110 | #define ck_slot_id_t CK_SLOT_ID 111 | 112 | #define ck_slot_info _CK_SLOT_INFO 113 | #define slot_description slotDescription 114 | #define hardware_version hardwareVersion 115 | #define firmware_version firmwareVersion 116 | 117 | #define ck_token_info _CK_TOKEN_INFO 118 | #define serial_number serialNumber 119 | #define max_session_count ulMaxSessionCount 120 | #define session_count ulSessionCount 121 | #define max_rw_session_count ulMaxRwSessionCount 122 | #define rw_session_count ulRwSessionCount 123 | #define max_pin_len ulMaxPinLen 124 | #define min_pin_len ulMinPinLen 125 | #define total_public_memory ulTotalPublicMemory 126 | #define free_public_memory ulFreePublicMemory 127 | #define total_private_memory ulTotalPrivateMemory 128 | #define free_private_memory ulFreePrivateMemory 129 | #define utc_time utcTime 130 | 131 | #define ck_session_handle_t CK_SESSION_HANDLE 132 | #define ck_user_type_t CK_USER_TYPE 133 | #define ck_state_t CK_STATE 134 | 135 | #define ck_session_info _CK_SESSION_INFO 136 | #define slot_id slotID 137 | #define device_error ulDeviceError 138 | 139 | #define ck_object_handle_t CK_OBJECT_HANDLE 140 | #define ck_object_class_t CK_OBJECT_CLASS 141 | #define ck_hw_feature_type_t CK_HW_FEATURE_TYPE 142 | #define ck_key_type_t CK_KEY_TYPE 143 | #define ck_certificate_type_t CK_CERTIFICATE_TYPE 144 | #define ck_attribute_type_t CK_ATTRIBUTE_TYPE 145 | 146 | #define ck_attribute _CK_ATTRIBUTE 147 | #define value pValue 148 | #define value_len ulValueLen 149 | 150 | #define ck_date _CK_DATE 151 | 152 | #define ck_mechanism_type_t CK_MECHANISM_TYPE 153 | 154 | #define ck_mechanism _CK_MECHANISM 155 | #define parameter pParameter 156 | #define parameter_len ulParameterLen 157 | 158 | #define ck_mechanism_info _CK_MECHANISM_INFO 159 | #define min_key_size ulMinKeySize 160 | #define max_key_size ulMaxKeySize 161 | 162 | #define ck_rv_t CK_RV 163 | #define ck_notify_t CK_NOTIFY 164 | 165 | #define ck_function_list _CK_FUNCTION_LIST 166 | 167 | #define ck_createmutex_t CK_CREATEMUTEX 168 | #define ck_destroymutex_t CK_DESTROYMUTEX 169 | #define ck_lockmutex_t CK_LOCKMUTEX 170 | #define ck_unlockmutex_t CK_UNLOCKMUTEX 171 | 172 | #define ck_c_initialize_args _CK_C_INITIALIZE_ARGS 173 | #define create_mutex CreateMutex 174 | #define destroy_mutex DestroyMutex 175 | #define lock_mutex LockMutex 176 | #define unlock_mutex UnlockMutex 177 | #define reserved pReserved 178 | 179 | #endif /* CRYPTOKI_COMPAT */ 180 | 181 | typedef unsigned long ck_flags_t; 182 | 183 | struct ck_version { 184 | unsigned char major; 185 | unsigned char minor; 186 | }; 187 | 188 | struct ck_info { 189 | struct ck_version cryptoki_version; 190 | unsigned char manufacturer_id[32]; 191 | ck_flags_t flags; 192 | unsigned char library_description[32]; 193 | struct ck_version library_version; 194 | }; 195 | 196 | typedef unsigned long ck_notification_t; 197 | 198 | #define CKN_SURRENDER (0UL) 199 | 200 | typedef unsigned long ck_slot_id_t; 201 | 202 | struct ck_slot_info { 203 | unsigned char slot_description[64]; 204 | unsigned char manufacturer_id[32]; 205 | ck_flags_t flags; 206 | struct ck_version hardware_version; 207 | struct ck_version firmware_version; 208 | }; 209 | 210 | #define CKF_TOKEN_PRESENT (1UL << 0) 211 | #define CKF_REMOVABLE_DEVICE (1UL << 1) 212 | #define CKF_HW_SLOT (1UL << 2) 213 | #define CKF_ARRAY_ATTRIBUTE (1UL << 30) 214 | 215 | struct ck_token_info { 216 | unsigned char label[32]; 217 | unsigned char manufacturer_id[32]; 218 | unsigned char model[16]; 219 | unsigned char serial_number[16]; 220 | ck_flags_t flags; 221 | unsigned long max_session_count; 222 | unsigned long session_count; 223 | unsigned long max_rw_session_count; 224 | unsigned long rw_session_count; 225 | unsigned long max_pin_len; 226 | unsigned long min_pin_len; 227 | unsigned long total_public_memory; 228 | unsigned long free_public_memory; 229 | unsigned long total_private_memory; 230 | unsigned long free_private_memory; 231 | struct ck_version hardware_version; 232 | struct ck_version firmware_version; 233 | unsigned char utc_time[16]; 234 | }; 235 | 236 | #define CKF_RNG (1UL << 0) 237 | #define CKF_WRITE_PROTECTED (1UL << 1) 238 | #define CKF_LOGIN_REQUIRED (1UL << 2) 239 | #define CKF_USER_PIN_INITIALIZED (1UL << 3) 240 | #define CKF_RESTORE_KEY_NOT_NEEDED (1UL << 5) 241 | #define CKF_CLOCK_ON_TOKEN (1UL << 6) 242 | #define CKF_PROTECTED_AUTHENTICATION_PATH (1UL << 8) 243 | #define CKF_DUAL_CRYPTO_OPERATIONS (1UL << 9) 244 | #define CKF_TOKEN_INITIALIZED (1UL << 10) 245 | #define CKF_SECONDARY_AUTHENTICATION (1UL << 11) 246 | #define CKF_USER_PIN_COUNT_LOW (1UL << 16) 247 | #define CKF_USER_PIN_FINAL_TRY (1UL << 17) 248 | #define CKF_USER_PIN_LOCKED (1UL << 18) 249 | #define CKF_USER_PIN_TO_BE_CHANGED (1UL << 19) 250 | #define CKF_SO_PIN_COUNT_LOW (1UL << 20) 251 | #define CKF_SO_PIN_FINAL_TRY (1UL << 21) 252 | #define CKF_SO_PIN_LOCKED (1UL << 22) 253 | #define CKF_SO_PIN_TO_BE_CHANGED (1UL << 23) 254 | 255 | #define CK_UNAVAILABLE_INFORMATION ((unsigned long)-1L) 256 | #define CK_EFFECTIVELY_INFINITE (0UL) 257 | 258 | typedef unsigned long ck_session_handle_t; 259 | 260 | #define CK_INVALID_HANDLE (0UL) 261 | 262 | typedef unsigned long ck_user_type_t; 263 | 264 | #define CKU_SO (0UL) 265 | #define CKU_USER (1UL) 266 | #define CKU_CONTEXT_SPECIFIC (2UL) 267 | 268 | typedef unsigned long ck_state_t; 269 | 270 | #define CKS_RO_PUBLIC_SESSION (0UL) 271 | #define CKS_RO_USER_FUNCTIONS (1UL) 272 | #define CKS_RW_PUBLIC_SESSION (2UL) 273 | #define CKS_RW_USER_FUNCTIONS (3UL) 274 | #define CKS_RW_SO_FUNCTIONS (4UL) 275 | 276 | struct ck_session_info { 277 | ck_slot_id_t slot_id; 278 | ck_state_t state; 279 | ck_flags_t flags; 280 | unsigned long device_error; 281 | }; 282 | 283 | #define CKF_RW_SESSION (1UL << 1) 284 | #define CKF_SERIAL_SESSION (1UL << 2) 285 | 286 | typedef unsigned long ck_object_handle_t; 287 | 288 | typedef unsigned long ck_object_class_t; 289 | 290 | #define CKO_DATA (0UL) 291 | #define CKO_CERTIFICATE (1UL) 292 | #define CKO_PUBLIC_KEY (2UL) 293 | #define CKO_PRIVATE_KEY (3UL) 294 | #define CKO_SECRET_KEY (4UL) 295 | #define CKO_HW_FEATURE (5UL) 296 | #define CKO_DOMAIN_PARAMETERS (6UL) 297 | #define CKO_MECHANISM (7UL) 298 | #define CKO_VENDOR_DEFINED ((unsigned long) (1UL << 31)) 299 | 300 | typedef unsigned long ck_hw_feature_type_t; 301 | 302 | #define CKH_MONOTONIC_COUNTER (1UL) 303 | #define CKH_CLOCK (2UL) 304 | #define CKH_USER_INTERFACE (3UL) 305 | #define CKH_VENDOR_DEFINED ((unsigned long) (1UL << 31)) 306 | 307 | typedef unsigned long ck_key_type_t; 308 | 309 | #define CKK_RSA (0UL) 310 | #define CKK_DSA (1UL) 311 | #define CKK_DH (2UL) 312 | #define CKK_ECDSA (3UL) 313 | #define CKK_EC (3UL) 314 | #define CKK_X9_42_DH (4UL) 315 | #define CKK_KEA (5UL) 316 | #define CKK_GENERIC_SECRET (0x10UL) 317 | #define CKK_RC2 (0x11UL) 318 | #define CKK_RC4 (0x12UL) 319 | #define CKK_DES (0x13UL) 320 | #define CKK_DES2 (0x14UL) 321 | #define CKK_DES3 (0x15UL) 322 | #define CKK_CAST (0x16UL) 323 | #define CKK_CAST3 (0x17UL) 324 | #define CKK_CAST128 (0x18UL) 325 | #define CKK_RC5 (0x19UL) 326 | #define CKK_IDEA (0x1aUL) 327 | #define CKK_SKIPJACK (0x1bUL) 328 | #define CKK_BATON (0x1cUL) 329 | #define CKK_JUNIPER (0x1dUL) 330 | #define CKK_CDMF (0x1eUL) 331 | #define CKK_AES (0x1fUL) 332 | #define CKK_BLOWFISH (0x20UL) 333 | #define CKK_TWOFISH (0x21UL) 334 | #define CKK_VENDOR_DEFINED ((unsigned long) (1UL << 31)) 335 | 336 | typedef unsigned long ck_certificate_type_t; 337 | 338 | #define CKC_X_509 (0UL) 339 | #define CKC_X_509_ATTR_CERT (1UL) 340 | #define CKC_WTLS (2UL) 341 | #define CKC_VENDOR_DEFINED ((unsigned long) (1UL << 31)) 342 | 343 | typedef unsigned long ck_attribute_type_t; 344 | 345 | #define CKA_CLASS (0UL) 346 | #define CKA_TOKEN (1UL) 347 | #define CKA_PRIVATE (2UL) 348 | #define CKA_LABEL (3UL) 349 | #define CKA_APPLICATION (0x10UL) 350 | #define CKA_VALUE (0x11UL) 351 | #define CKA_OBJECT_ID (0x12UL) 352 | #define CKA_CERTIFICATE_TYPE (0x80UL) 353 | #define CKA_ISSUER (0x81UL) 354 | #define CKA_SERIAL_NUMBER (0x82UL) 355 | #define CKA_AC_ISSUER (0x83UL) 356 | #define CKA_OWNER (0x84UL) 357 | #define CKA_ATTR_TYPES (0x85UL) 358 | #define CKA_TRUSTED (0x86UL) 359 | #define CKA_CERTIFICATE_CATEGORY (0x87UL) 360 | #define CKA_JAVA_MIDP_SECURITY_DOMAIN (0x88UL) 361 | #define CKA_URL (0x89UL) 362 | #define CKA_HASH_OF_SUBJECT_PUBLIC_KEY (0x8aUL) 363 | #define CKA_HASH_OF_ISSUER_PUBLIC_KEY (0x8bUL) 364 | #define CKA_CHECK_VALUE (0x90UL) 365 | #define CKA_KEY_TYPE (0x100UL) 366 | #define CKA_SUBJECT (0x101UL) 367 | #define CKA_ID (0x102UL) 368 | #define CKA_SENSITIVE (0x103UL) 369 | #define CKA_ENCRYPT (0x104UL) 370 | #define CKA_DECRYPT (0x105UL) 371 | #define CKA_WRAP (0x106UL) 372 | #define CKA_UNWRAP (0x107UL) 373 | #define CKA_SIGN (0x108UL) 374 | #define CKA_SIGN_RECOVER (0x109UL) 375 | #define CKA_VERIFY (0x10aUL) 376 | #define CKA_VERIFY_RECOVER (0x10bUL) 377 | #define CKA_DERIVE (0x10cUL) 378 | #define CKA_START_DATE (0x110UL) 379 | #define CKA_END_DATE (0x111UL) 380 | #define CKA_MODULUS (0x120UL) 381 | #define CKA_MODULUS_BITS (0x121UL) 382 | #define CKA_PUBLIC_EXPONENT (0x122UL) 383 | #define CKA_PRIVATE_EXPONENT (0x123UL) 384 | #define CKA_PRIME_1 (0x124UL) 385 | #define CKA_PRIME_2 (0x125UL) 386 | #define CKA_EXPONENT_1 (0x126UL) 387 | #define CKA_EXPONENT_2 (0x127UL) 388 | #define CKA_COEFFICIENT (0x128UL) 389 | #define CKA_PRIME (0x130UL) 390 | #define CKA_SUBPRIME (0x131UL) 391 | #define CKA_BASE (0x132UL) 392 | #define CKA_PRIME_BITS (0x133UL) 393 | #define CKA_SUB_PRIME_BITS (0x134UL) 394 | #define CKA_VALUE_BITS (0x160UL) 395 | #define CKA_VALUE_LEN (0x161UL) 396 | #define CKA_EXTRACTABLE (0x162UL) 397 | #define CKA_LOCAL (0x163UL) 398 | #define CKA_NEVER_EXTRACTABLE (0x164UL) 399 | #define CKA_ALWAYS_SENSITIVE (0x165UL) 400 | #define CKA_KEY_GEN_MECHANISM (0x166UL) 401 | #define CKA_MODIFIABLE (0x170UL) 402 | #define CKA_ECDSA_PARAMS (0x180UL) 403 | #define CKA_EC_PARAMS (0x180UL) 404 | #define CKA_EC_POINT (0x181UL) 405 | #define CKA_SECONDARY_AUTH (0x200UL) 406 | #define CKA_AUTH_PIN_FLAGS (0x201UL) 407 | #define CKA_ALWAYS_AUTHENTICATE (0x202UL) 408 | #define CKA_WRAP_WITH_TRUSTED (0x210UL) 409 | #define CKA_HW_FEATURE_TYPE (0x300UL) 410 | #define CKA_RESET_ON_INIT (0x301UL) 411 | #define CKA_HAS_RESET (0x302UL) 412 | #define CKA_PIXEL_X (0x400UL) 413 | #define CKA_PIXEL_Y (0x401UL) 414 | #define CKA_RESOLUTION (0x402UL) 415 | #define CKA_CHAR_ROWS (0x403UL) 416 | #define CKA_CHAR_COLUMNS (0x404UL) 417 | #define CKA_COLOR (0x405UL) 418 | #define CKA_BITS_PER_PIXEL (0x406UL) 419 | #define CKA_CHAR_SETS (0x480UL) 420 | #define CKA_ENCODING_METHODS (0x481UL) 421 | #define CKA_MIME_TYPES (0x482UL) 422 | #define CKA_MECHANISM_TYPE (0x500UL) 423 | #define CKA_REQUIRED_CMS_ATTRIBUTES (0x501UL) 424 | #define CKA_DEFAULT_CMS_ATTRIBUTES (0x502UL) 425 | #define CKA_SUPPORTED_CMS_ATTRIBUTES (0x503UL) 426 | #define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x211UL) 427 | #define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x212UL) 428 | #define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE | 0x600UL) 429 | #define CKA_VENDOR_DEFINED ((unsigned long) (1UL << 31)) 430 | 431 | struct ck_attribute { 432 | ck_attribute_type_t type; 433 | void *value; 434 | unsigned long value_len; 435 | }; 436 | 437 | struct ck_date { 438 | unsigned char year[4]; 439 | unsigned char month[2]; 440 | unsigned char day[2]; 441 | }; 442 | 443 | typedef unsigned long ck_mechanism_type_t; 444 | 445 | #define CKM_RSA_PKCS_KEY_PAIR_GEN (0UL) 446 | #define CKM_RSA_PKCS (1UL) 447 | #define CKM_RSA_9796 (2UL) 448 | #define CKM_RSA_X_509 (3UL) 449 | #define CKM_MD2_RSA_PKCS (4UL) 450 | #define CKM_MD5_RSA_PKCS (5UL) 451 | #define CKM_SHA1_RSA_PKCS (6UL) 452 | #define CKM_RIPEMD128_RSA_PKCS (7UL) 453 | #define CKM_RIPEMD160_RSA_PKCS (8UL) 454 | #define CKM_RSA_PKCS_OAEP (9UL) 455 | #define CKM_RSA_X9_31_KEY_PAIR_GEN (0xaUL) 456 | #define CKM_RSA_X9_31 (0xbUL) 457 | #define CKM_SHA1_RSA_X9_31 (0xcUL) 458 | #define CKM_RSA_PKCS_PSS (0xdUL) 459 | #define CKM_SHA1_RSA_PKCS_PSS (0xeUL) 460 | #define CKM_DSA_KEY_PAIR_GEN (0x10UL) 461 | #define CKM_DSA (0x11UL) 462 | #define CKM_DSA_SHA1 (0x12UL) 463 | #define CKM_DH_PKCS_KEY_PAIR_GEN (0x20UL) 464 | #define CKM_DH_PKCS_DERIVE (0x21UL) 465 | #define CKM_X9_42_DH_KEY_PAIR_GEN (0x30UL) 466 | #define CKM_X9_42_DH_DERIVE (0x31UL) 467 | #define CKM_X9_42_DH_HYBRID_DERIVE (0x32UL) 468 | #define CKM_X9_42_MQV_DERIVE (0x33UL) 469 | #define CKM_SHA256_RSA_PKCS (0x40UL) 470 | #define CKM_SHA384_RSA_PKCS (0x41UL) 471 | #define CKM_SHA512_RSA_PKCS (0x42UL) 472 | #define CKM_SHA256_RSA_PKCS_PSS (0x43UL) 473 | #define CKM_SHA384_RSA_PKCS_PSS (0x44UL) 474 | #define CKM_SHA512_RSA_PKCS_PSS (0x45UL) 475 | #define CKM_RC2_KEY_GEN (0x100UL) 476 | #define CKM_RC2_ECB (0x101UL) 477 | #define CKM_RC2_CBC (0x102UL) 478 | #define CKM_RC2_MAC (0x103UL) 479 | #define CKM_RC2_MAC_GENERAL (0x104UL) 480 | #define CKM_RC2_CBC_PAD (0x105UL) 481 | #define CKM_RC4_KEY_GEN (0x110UL) 482 | #define CKM_RC4 (0x111UL) 483 | #define CKM_DES_KEY_GEN (0x120UL) 484 | #define CKM_DES_ECB (0x121UL) 485 | #define CKM_DES_CBC (0x122UL) 486 | #define CKM_DES_MAC (0x123UL) 487 | #define CKM_DES_MAC_GENERAL (0x124UL) 488 | #define CKM_DES_CBC_PAD (0x125UL) 489 | #define CKM_DES2_KEY_GEN (0x130UL) 490 | #define CKM_DES3_KEY_GEN (0x131UL) 491 | #define CKM_DES3_ECB (0x132UL) 492 | #define CKM_DES3_CBC (0x133UL) 493 | #define CKM_DES3_MAC (0x134UL) 494 | #define CKM_DES3_MAC_GENERAL (0x135UL) 495 | #define CKM_DES3_CBC_PAD (0x136UL) 496 | #define CKM_CDMF_KEY_GEN (0x140UL) 497 | #define CKM_CDMF_ECB (0x141UL) 498 | #define CKM_CDMF_CBC (0x142UL) 499 | #define CKM_CDMF_MAC (0x143UL) 500 | #define CKM_CDMF_MAC_GENERAL (0x144UL) 501 | #define CKM_CDMF_CBC_PAD (0x145UL) 502 | #define CKM_MD2 (0x200UL) 503 | #define CKM_MD2_HMAC (0x201UL) 504 | #define CKM_MD2_HMAC_GENERAL (0x202UL) 505 | #define CKM_MD5 (0x210UL) 506 | #define CKM_MD5_HMAC (0x211UL) 507 | #define CKM_MD5_HMAC_GENERAL (0x212UL) 508 | #define CKM_SHA_1 (0x220UL) 509 | #define CKM_SHA_1_HMAC (0x221UL) 510 | #define CKM_SHA_1_HMAC_GENERAL (0x222UL) 511 | #define CKM_RIPEMD128 (0x230UL) 512 | #define CKM_RIPEMD128_HMAC (0x231UL) 513 | #define CKM_RIPEMD128_HMAC_GENERAL (0x232UL) 514 | #define CKM_RIPEMD160 (0x240UL) 515 | #define CKM_RIPEMD160_HMAC (0x241UL) 516 | #define CKM_RIPEMD160_HMAC_GENERAL (0x242UL) 517 | #define CKM_SHA256 (0x250UL) 518 | #define CKM_SHA256_HMAC (0x251UL) 519 | #define CKM_SHA256_HMAC_GENERAL (0x252UL) 520 | #define CKM_SHA384 (0x260UL) 521 | #define CKM_SHA384_HMAC (0x261UL) 522 | #define CKM_SHA384_HMAC_GENERAL (0x262UL) 523 | #define CKM_SHA512 (0x270UL) 524 | #define CKM_SHA512_HMAC (0x271UL) 525 | #define CKM_SHA512_HMAC_GENERAL (0x272UL) 526 | #define CKM_CAST_KEY_GEN (0x300UL) 527 | #define CKM_CAST_ECB (0x301UL) 528 | #define CKM_CAST_CBC (0x302UL) 529 | #define CKM_CAST_MAC (0x303UL) 530 | #define CKM_CAST_MAC_GENERAL (0x304UL) 531 | #define CKM_CAST_CBC_PAD (0x305UL) 532 | #define CKM_CAST3_KEY_GEN (0x310UL) 533 | #define CKM_CAST3_ECB (0x311UL) 534 | #define CKM_CAST3_CBC (0x312UL) 535 | #define CKM_CAST3_MAC (0x313UL) 536 | #define CKM_CAST3_MAC_GENERAL (0x314UL) 537 | #define CKM_CAST3_CBC_PAD (0x315UL) 538 | #define CKM_CAST5_KEY_GEN (0x320UL) 539 | #define CKM_CAST128_KEY_GEN (0x320UL) 540 | #define CKM_CAST5_ECB (0x321UL) 541 | #define CKM_CAST128_ECB (0x321UL) 542 | #define CKM_CAST5_CBC (0x322UL) 543 | #define CKM_CAST128_CBC (0x322UL) 544 | #define CKM_CAST5_MAC (0x323UL) 545 | #define CKM_CAST128_MAC (0x323UL) 546 | #define CKM_CAST5_MAC_GENERAL (0x324UL) 547 | #define CKM_CAST128_MAC_GENERAL (0x324UL) 548 | #define CKM_CAST5_CBC_PAD (0x325UL) 549 | #define CKM_CAST128_CBC_PAD (0x325UL) 550 | #define CKM_RC5_KEY_GEN (0x330UL) 551 | #define CKM_RC5_ECB (0x331UL) 552 | #define CKM_RC5_CBC (0x332UL) 553 | #define CKM_RC5_MAC (0x333UL) 554 | #define CKM_RC5_MAC_GENERAL (0x334UL) 555 | #define CKM_RC5_CBC_PAD (0x335UL) 556 | #define CKM_IDEA_KEY_GEN (0x340UL) 557 | #define CKM_IDEA_ECB (0x341UL) 558 | #define CKM_IDEA_CBC (0x342UL) 559 | #define CKM_IDEA_MAC (0x343UL) 560 | #define CKM_IDEA_MAC_GENERAL (0x344UL) 561 | #define CKM_IDEA_CBC_PAD (0x345UL) 562 | #define CKM_GENERIC_SECRET_KEY_GEN (0x350UL) 563 | #define CKM_CONCATENATE_BASE_AND_KEY (0x360UL) 564 | #define CKM_CONCATENATE_BASE_AND_DATA (0x362UL) 565 | #define CKM_CONCATENATE_DATA_AND_BASE (0x363UL) 566 | #define CKM_XOR_BASE_AND_DATA (0x364UL) 567 | #define CKM_EXTRACT_KEY_FROM_KEY (0x365UL) 568 | #define CKM_SSL3_PRE_MASTER_KEY_GEN (0x370UL) 569 | #define CKM_SSL3_MASTER_KEY_DERIVE (0x371UL) 570 | #define CKM_SSL3_KEY_AND_MAC_DERIVE (0x372UL) 571 | #define CKM_SSL3_MASTER_KEY_DERIVE_DH (0x373UL) 572 | #define CKM_TLS_PRE_MASTER_KEY_GEN (0x374UL) 573 | #define CKM_TLS_MASTER_KEY_DERIVE (0x375UL) 574 | #define CKM_TLS_KEY_AND_MAC_DERIVE (0x376UL) 575 | #define CKM_TLS_MASTER_KEY_DERIVE_DH (0x377UL) 576 | #define CKM_SSL3_MD5_MAC (0x380UL) 577 | #define CKM_SSL3_SHA1_MAC (0x381UL) 578 | #define CKM_MD5_KEY_DERIVATION (0x390UL) 579 | #define CKM_MD2_KEY_DERIVATION (0x391UL) 580 | #define CKM_SHA1_KEY_DERIVATION (0x392UL) 581 | #define CKM_PBE_MD2_DES_CBC (0x3a0UL) 582 | #define CKM_PBE_MD5_DES_CBC (0x3a1UL) 583 | #define CKM_PBE_MD5_CAST_CBC (0x3a2UL) 584 | #define CKM_PBE_MD5_CAST3_CBC (0x3a3UL) 585 | #define CKM_PBE_MD5_CAST5_CBC (0x3a4UL) 586 | #define CKM_PBE_MD5_CAST128_CBC (0x3a4UL) 587 | #define CKM_PBE_SHA1_CAST5_CBC (0x3a5UL) 588 | #define CKM_PBE_SHA1_CAST128_CBC (0x3a5UL) 589 | #define CKM_PBE_SHA1_RC4_128 (0x3a6UL) 590 | #define CKM_PBE_SHA1_RC4_40 (0x3a7UL) 591 | #define CKM_PBE_SHA1_DES3_EDE_CBC (0x3a8UL) 592 | #define CKM_PBE_SHA1_DES2_EDE_CBC (0x3a9UL) 593 | #define CKM_PBE_SHA1_RC2_128_CBC (0x3aaUL) 594 | #define CKM_PBE_SHA1_RC2_40_CBC (0x3abUL) 595 | #define CKM_PKCS5_PBKD2 (0x3b0UL) 596 | #define CKM_PBA_SHA1_WITH_SHA1_HMAC (0x3c0UL) 597 | #define CKM_KEY_WRAP_LYNKS (0x400UL) 598 | #define CKM_KEY_WRAP_SET_OAEP (0x401UL) 599 | #define CKM_SKIPJACK_KEY_GEN (0x1000UL) 600 | #define CKM_SKIPJACK_ECB64 (0x1001UL) 601 | #define CKM_SKIPJACK_CBC64 (0x1002UL) 602 | #define CKM_SKIPJACK_OFB64 (0x1003UL) 603 | #define CKM_SKIPJACK_CFB64 (0x1004UL) 604 | #define CKM_SKIPJACK_CFB32 (0x1005UL) 605 | #define CKM_SKIPJACK_CFB16 (0x1006UL) 606 | #define CKM_SKIPJACK_CFB8 (0x1007UL) 607 | #define CKM_SKIPJACK_WRAP (0x1008UL) 608 | #define CKM_SKIPJACK_PRIVATE_WRAP (0x1009UL) 609 | #define CKM_SKIPJACK_RELAYX (0x100aUL) 610 | #define CKM_KEA_KEY_PAIR_GEN (0x1010UL) 611 | #define CKM_KEA_KEY_DERIVE (0x1011UL) 612 | #define CKM_FORTEZZA_TIMESTAMP (0x1020UL) 613 | #define CKM_BATON_KEY_GEN (0x1030UL) 614 | #define CKM_BATON_ECB128 (0x1031UL) 615 | #define CKM_BATON_ECB96 (0x1032UL) 616 | #define CKM_BATON_CBC128 (0x1033UL) 617 | #define CKM_BATON_COUNTER (0x1034UL) 618 | #define CKM_BATON_SHUFFLE (0x1035UL) 619 | #define CKM_BATON_WRAP (0x1036UL) 620 | #define CKM_ECDSA_KEY_PAIR_GEN (0x1040UL) 621 | #define CKM_EC_KEY_PAIR_GEN (0x1040UL) 622 | #define CKM_ECDSA (0x1041UL) 623 | #define CKM_ECDSA_SHA1 (0x1042UL) 624 | #define CKM_ECDH1_DERIVE (0x1050UL) 625 | #define CKM_ECDH1_COFACTOR_DERIVE (0x1051UL) 626 | #define CKM_ECMQV_DERIVE (0x1052UL) 627 | #define CKM_JUNIPER_KEY_GEN (0x1060UL) 628 | #define CKM_JUNIPER_ECB128 (0x1061UL) 629 | #define CKM_JUNIPER_CBC128 (0x1062UL) 630 | #define CKM_JUNIPER_COUNTER (0x1063UL) 631 | #define CKM_JUNIPER_SHUFFLE (0x1064UL) 632 | #define CKM_JUNIPER_WRAP (0x1065UL) 633 | #define CKM_FASTHASH (0x1070UL) 634 | #define CKM_AES_KEY_GEN (0x1080UL) 635 | #define CKM_AES_ECB (0x1081UL) 636 | #define CKM_AES_CBC (0x1082UL) 637 | #define CKM_AES_MAC (0x1083UL) 638 | #define CKM_AES_MAC_GENERAL (0x1084UL) 639 | #define CKM_AES_CBC_PAD (0x1085UL) 640 | #define CKM_DSA_PARAMETER_GEN (0x2000UL) 641 | #define CKM_DH_PKCS_PARAMETER_GEN (0x2001UL) 642 | #define CKM_X9_42_DH_PARAMETER_GEN (0x2002UL) 643 | #define CKM_VENDOR_DEFINED ((unsigned long) (1UL << 31)) 644 | 645 | struct ck_mechanism { 646 | ck_mechanism_type_t mechanism; 647 | void *parameter; 648 | unsigned long parameter_len; 649 | }; 650 | 651 | struct ck_mechanism_info { 652 | unsigned long min_key_size; 653 | unsigned long max_key_size; 654 | ck_flags_t flags; 655 | }; 656 | 657 | #define CKF_HW (1UL << 0) 658 | #define CKF_ENCRYPT (1UL << 8) 659 | #define CKF_DECRYPT (1UL << 9) 660 | #define CKF_DIGEST (1UL << 10) 661 | #define CKF_SIGN (1UL << 11) 662 | #define CKF_SIGN_RECOVER (1UL << 12) 663 | #define CKF_VERIFY (1UL << 13) 664 | #define CKF_VERIFY_RECOVER (1UL << 14) 665 | #define CKF_GENERATE (1UL << 15) 666 | #define CKF_GENERATE_KEY_PAIR (1UL << 16) 667 | #define CKF_WRAP (1UL << 17) 668 | #define CKF_UNWRAP (1UL << 18) 669 | #define CKF_DERIVE (1UL << 19) 670 | #define CKF_EXTENSION ((unsigned long) (1UL << 31)) 671 | 672 | /* Flags for C_WaitForSlotEvent. */ 673 | #define CKF_DONT_BLOCK (1UL) 674 | 675 | typedef unsigned long ck_rv_t; 676 | 677 | typedef ck_rv_t(*ck_notify_t) (ck_session_handle_t session, 678 | ck_notification_t event, 679 | void *application); 680 | 681 | /* Forward reference. */ 682 | struct ck_function_list; 683 | 684 | #define _CK_DECLARE_FUNCTION(name, args) \ 685 | typedef ck_rv_t (*CK_ ## name) args; \ 686 | ck_rv_t CK_SPEC name args 687 | 688 | _CK_DECLARE_FUNCTION(C_Initialize, (void *init_args)); 689 | _CK_DECLARE_FUNCTION(C_Finalize, (void *reserved)); 690 | _CK_DECLARE_FUNCTION(C_GetInfo, (struct ck_info * info)); 691 | _CK_DECLARE_FUNCTION(C_GetFunctionList, 692 | (struct ck_function_list ** function_list)); 693 | 694 | _CK_DECLARE_FUNCTION(C_GetSlotList, 695 | (unsigned char token_present, 696 | ck_slot_id_t * slot_list, unsigned long *count)); 697 | _CK_DECLARE_FUNCTION(C_GetSlotInfo, 698 | (ck_slot_id_t slot_id, 699 | struct ck_slot_info * info)); 700 | _CK_DECLARE_FUNCTION(C_GetTokenInfo, 701 | (ck_slot_id_t slot_id, 702 | struct ck_token_info * info)); 703 | _CK_DECLARE_FUNCTION(C_WaitForSlotEvent, 704 | (ck_flags_t flags, ck_slot_id_t * slot, 705 | void *reserved)); 706 | _CK_DECLARE_FUNCTION(C_GetMechanismList, 707 | (ck_slot_id_t slot_id, 708 | ck_mechanism_type_t * mechanism_list, 709 | unsigned long *count)); 710 | _CK_DECLARE_FUNCTION(C_GetMechanismInfo, 711 | (ck_slot_id_t slot_id, ck_mechanism_type_t type, 712 | struct ck_mechanism_info * info)); 713 | _CK_DECLARE_FUNCTION(C_InitToken, 714 | (ck_slot_id_t slot_id, unsigned char *pin, 715 | unsigned long pin_len, unsigned char *label)); 716 | _CK_DECLARE_FUNCTION(C_InitPIN, 717 | (ck_session_handle_t session, unsigned char *pin, 718 | unsigned long pin_len)); 719 | _CK_DECLARE_FUNCTION(C_SetPIN, 720 | (ck_session_handle_t session, 721 | unsigned char *old_pin, unsigned long old_len, 722 | unsigned char *new_pin, unsigned long new_len)); 723 | 724 | _CK_DECLARE_FUNCTION(C_OpenSession, 725 | (ck_slot_id_t slot_id, ck_flags_t flags, 726 | void *application, ck_notify_t notify, 727 | ck_session_handle_t * session)); 728 | _CK_DECLARE_FUNCTION(C_CloseSession, (ck_session_handle_t session)); 729 | _CK_DECLARE_FUNCTION(C_CloseAllSessions, (ck_slot_id_t slot_id)); 730 | _CK_DECLARE_FUNCTION(C_GetSessionInfo, 731 | (ck_session_handle_t session, 732 | struct ck_session_info * info)); 733 | _CK_DECLARE_FUNCTION(C_GetOperationState, 734 | (ck_session_handle_t session, 735 | unsigned char *operation_state, 736 | unsigned long *operation_state_len)); 737 | _CK_DECLARE_FUNCTION(C_SetOperationState, 738 | (ck_session_handle_t session, 739 | unsigned char *operation_state, 740 | unsigned long operation_state_len, 741 | ck_object_handle_t encryption_key, 742 | ck_object_handle_t authentiation_key)); 743 | _CK_DECLARE_FUNCTION(C_Login, 744 | (ck_session_handle_t session, 745 | ck_user_type_t user_type, unsigned char *pin, 746 | unsigned long pin_len)); 747 | _CK_DECLARE_FUNCTION(C_Logout, (ck_session_handle_t session)); 748 | 749 | _CK_DECLARE_FUNCTION(C_CreateObject, 750 | (ck_session_handle_t session, 751 | struct ck_attribute * templ, 752 | unsigned long count, 753 | ck_object_handle_t * object)); 754 | _CK_DECLARE_FUNCTION(C_CopyObject, 755 | (ck_session_handle_t session, 756 | ck_object_handle_t object, 757 | struct ck_attribute * templ, unsigned long count, 758 | ck_object_handle_t * new_object)); 759 | _CK_DECLARE_FUNCTION(C_DestroyObject, 760 | (ck_session_handle_t session, 761 | ck_object_handle_t object)); 762 | _CK_DECLARE_FUNCTION(C_GetObjectSize, 763 | (ck_session_handle_t session, 764 | ck_object_handle_t object, unsigned long *size)); 765 | _CK_DECLARE_FUNCTION(C_GetAttributeValue, 766 | (ck_session_handle_t session, 767 | ck_object_handle_t object, 768 | struct ck_attribute * templ, 769 | unsigned long count)); 770 | _CK_DECLARE_FUNCTION(C_SetAttributeValue, 771 | (ck_session_handle_t session, 772 | ck_object_handle_t object, 773 | struct ck_attribute * templ, 774 | unsigned long count)); 775 | _CK_DECLARE_FUNCTION(C_FindObjectsInit, 776 | (ck_session_handle_t session, 777 | struct ck_attribute * templ, 778 | unsigned long count)); 779 | _CK_DECLARE_FUNCTION(C_FindObjects, 780 | (ck_session_handle_t session, 781 | ck_object_handle_t * object, 782 | unsigned long max_object_count, 783 | unsigned long *object_count)); 784 | _CK_DECLARE_FUNCTION(C_FindObjectsFinal, 785 | (ck_session_handle_t session)); 786 | 787 | _CK_DECLARE_FUNCTION(C_EncryptInit, 788 | (ck_session_handle_t session, 789 | struct ck_mechanism * mechanism, 790 | ck_object_handle_t key)); 791 | _CK_DECLARE_FUNCTION(C_Encrypt, 792 | (ck_session_handle_t session, 793 | unsigned char *data, unsigned long data_len, 794 | unsigned char *encrypted_data, 795 | unsigned long *encrypted_data_len)); 796 | _CK_DECLARE_FUNCTION(C_EncryptUpdate, 797 | (ck_session_handle_t session, 798 | unsigned char *part, unsigned long part_len, 799 | unsigned char *encrypted_part, 800 | unsigned long *encrypted_part_len)); 801 | _CK_DECLARE_FUNCTION(C_EncryptFinal, 802 | (ck_session_handle_t session, 803 | unsigned char *last_encrypted_part, 804 | unsigned long *last_encrypted_part_len)); 805 | 806 | _CK_DECLARE_FUNCTION(C_DecryptInit, 807 | (ck_session_handle_t session, 808 | struct ck_mechanism * mechanism, 809 | ck_object_handle_t key)); 810 | _CK_DECLARE_FUNCTION(C_Decrypt, 811 | (ck_session_handle_t session, 812 | unsigned char *encrypted_data, 813 | unsigned long encrypted_data_len, 814 | unsigned char *data, unsigned long *data_len)); 815 | _CK_DECLARE_FUNCTION(C_DecryptUpdate, 816 | (ck_session_handle_t session, 817 | unsigned char *encrypted_part, 818 | unsigned long encrypted_part_len, 819 | unsigned char *part, unsigned long *part_len)); 820 | _CK_DECLARE_FUNCTION(C_DecryptFinal, 821 | (ck_session_handle_t session, 822 | unsigned char *last_part, 823 | unsigned long *last_part_len)); 824 | 825 | _CK_DECLARE_FUNCTION(C_DigestInit, 826 | (ck_session_handle_t session, 827 | struct ck_mechanism * mechanism)); 828 | _CK_DECLARE_FUNCTION(C_Digest, 829 | (ck_session_handle_t session, 830 | unsigned char *data, unsigned long data_len, 831 | unsigned char *digest, 832 | unsigned long *digest_len)); 833 | _CK_DECLARE_FUNCTION(C_DigestUpdate, 834 | (ck_session_handle_t session, 835 | unsigned char *part, unsigned long part_len)); 836 | _CK_DECLARE_FUNCTION(C_DigestKey, 837 | (ck_session_handle_t session, 838 | ck_object_handle_t key)); 839 | _CK_DECLARE_FUNCTION(C_DigestFinal, 840 | (ck_session_handle_t session, 841 | unsigned char *digest, 842 | unsigned long *digest_len)); 843 | 844 | _CK_DECLARE_FUNCTION(C_SignInit, 845 | (ck_session_handle_t session, 846 | struct ck_mechanism * mechanism, 847 | ck_object_handle_t key)); 848 | _CK_DECLARE_FUNCTION(C_Sign, 849 | (ck_session_handle_t session, 850 | unsigned char *data, unsigned long data_len, 851 | unsigned char *signature, 852 | unsigned long *signature_len)); 853 | _CK_DECLARE_FUNCTION(C_SignUpdate, 854 | (ck_session_handle_t session, 855 | unsigned char *part, unsigned long part_len)); 856 | _CK_DECLARE_FUNCTION(C_SignFinal, 857 | (ck_session_handle_t session, 858 | unsigned char *signature, 859 | unsigned long *signature_len)); 860 | _CK_DECLARE_FUNCTION(C_SignRecoverInit, 861 | (ck_session_handle_t session, 862 | struct ck_mechanism * mechanism, 863 | ck_object_handle_t key)); 864 | _CK_DECLARE_FUNCTION(C_SignRecover, 865 | (ck_session_handle_t session, 866 | unsigned char *data, unsigned long data_len, 867 | unsigned char *signature, 868 | unsigned long *signature_len)); 869 | 870 | _CK_DECLARE_FUNCTION(C_VerifyInit, 871 | (ck_session_handle_t session, 872 | struct ck_mechanism * mechanism, 873 | ck_object_handle_t key)); 874 | _CK_DECLARE_FUNCTION(C_Verify, 875 | (ck_session_handle_t session, 876 | unsigned char *data, unsigned long data_len, 877 | unsigned char *signature, 878 | unsigned long signature_len)); 879 | _CK_DECLARE_FUNCTION(C_VerifyUpdate, 880 | (ck_session_handle_t session, 881 | unsigned char *part, unsigned long part_len)); 882 | _CK_DECLARE_FUNCTION(C_VerifyFinal, 883 | (ck_session_handle_t session, 884 | unsigned char *signature, 885 | unsigned long signature_len)); 886 | _CK_DECLARE_FUNCTION(C_VerifyRecoverInit, 887 | (ck_session_handle_t session, 888 | struct ck_mechanism * mechanism, 889 | ck_object_handle_t key)); 890 | _CK_DECLARE_FUNCTION(C_VerifyRecover, 891 | (ck_session_handle_t session, 892 | unsigned char *signature, 893 | unsigned long signature_len, 894 | unsigned char *data, unsigned long *data_len)); 895 | 896 | _CK_DECLARE_FUNCTION(C_DigestEncryptUpdate, 897 | (ck_session_handle_t session, 898 | unsigned char *part, unsigned long part_len, 899 | unsigned char *encrypted_part, 900 | unsigned long *encrypted_part_len)); 901 | _CK_DECLARE_FUNCTION(C_DecryptDigestUpdate, 902 | (ck_session_handle_t session, 903 | unsigned char *encrypted_part, 904 | unsigned long encrypted_part_len, 905 | unsigned char *part, unsigned long *part_len)); 906 | _CK_DECLARE_FUNCTION(C_SignEncryptUpdate, 907 | (ck_session_handle_t session, 908 | unsigned char *part, unsigned long part_len, 909 | unsigned char *encrypted_part, 910 | unsigned long *encrypted_part_len)); 911 | _CK_DECLARE_FUNCTION(C_DecryptVerifyUpdate, 912 | (ck_session_handle_t session, 913 | unsigned char *encrypted_part, 914 | unsigned long encrypted_part_len, 915 | unsigned char *part, unsigned long *part_len)); 916 | 917 | _CK_DECLARE_FUNCTION(C_GenerateKey, 918 | (ck_session_handle_t session, 919 | struct ck_mechanism * mechanism, 920 | struct ck_attribute * templ, 921 | unsigned long count, ck_object_handle_t * key)); 922 | _CK_DECLARE_FUNCTION(C_GenerateKeyPair, 923 | (ck_session_handle_t session, 924 | struct ck_mechanism * mechanism, 925 | struct ck_attribute * public_key_template, 926 | unsigned long public_key_attribute_count, 927 | struct ck_attribute * private_key_template, 928 | unsigned long private_key_attribute_count, 929 | ck_object_handle_t * public_key, 930 | ck_object_handle_t * private_key)); 931 | _CK_DECLARE_FUNCTION(C_WrapKey, 932 | (ck_session_handle_t session, 933 | struct ck_mechanism * mechanism, 934 | ck_object_handle_t wrapping_key, 935 | ck_object_handle_t key, 936 | unsigned char *wrapped_key, 937 | unsigned long *wrapped_key_len)); 938 | _CK_DECLARE_FUNCTION(C_UnwrapKey, 939 | (ck_session_handle_t session, 940 | struct ck_mechanism * mechanism, 941 | ck_object_handle_t unwrapping_key, 942 | unsigned char *wrapped_key, 943 | unsigned long wrapped_key_len, 944 | struct ck_attribute * templ, 945 | unsigned long attribute_count, 946 | ck_object_handle_t * key)); 947 | _CK_DECLARE_FUNCTION(C_DeriveKey, 948 | (ck_session_handle_t session, 949 | struct ck_mechanism * mechanism, 950 | ck_object_handle_t base_key, 951 | struct ck_attribute * templ, 952 | unsigned long attribute_count, 953 | ck_object_handle_t * key)); 954 | 955 | _CK_DECLARE_FUNCTION(C_SeedRandom, 956 | (ck_session_handle_t session, unsigned char *seed, 957 | unsigned long seed_len)); 958 | _CK_DECLARE_FUNCTION(C_GenerateRandom, 959 | (ck_session_handle_t session, 960 | unsigned char *random_data, 961 | unsigned long random_len)); 962 | 963 | _CK_DECLARE_FUNCTION(C_GetFunctionStatus, 964 | (ck_session_handle_t session)); 965 | _CK_DECLARE_FUNCTION(C_CancelFunction, (ck_session_handle_t session)); 966 | 967 | struct ck_function_list { 968 | struct ck_version version; 969 | CK_C_Initialize C_Initialize; 970 | CK_C_Finalize C_Finalize; 971 | CK_C_GetInfo C_GetInfo; 972 | CK_C_GetFunctionList C_GetFunctionList; 973 | CK_C_GetSlotList C_GetSlotList; 974 | CK_C_GetSlotInfo C_GetSlotInfo; 975 | CK_C_GetTokenInfo C_GetTokenInfo; 976 | CK_C_GetMechanismList C_GetMechanismList; 977 | CK_C_GetMechanismInfo C_GetMechanismInfo; 978 | CK_C_InitToken C_InitToken; 979 | CK_C_InitPIN C_InitPIN; 980 | CK_C_SetPIN C_SetPIN; 981 | CK_C_OpenSession C_OpenSession; 982 | CK_C_CloseSession C_CloseSession; 983 | CK_C_CloseAllSessions C_CloseAllSessions; 984 | CK_C_GetSessionInfo C_GetSessionInfo; 985 | CK_C_GetOperationState C_GetOperationState; 986 | CK_C_SetOperationState C_SetOperationState; 987 | CK_C_Login C_Login; 988 | CK_C_Logout C_Logout; 989 | CK_C_CreateObject C_CreateObject; 990 | CK_C_CopyObject C_CopyObject; 991 | CK_C_DestroyObject C_DestroyObject; 992 | CK_C_GetObjectSize C_GetObjectSize; 993 | CK_C_GetAttributeValue C_GetAttributeValue; 994 | CK_C_SetAttributeValue C_SetAttributeValue; 995 | CK_C_FindObjectsInit C_FindObjectsInit; 996 | CK_C_FindObjects C_FindObjects; 997 | CK_C_FindObjectsFinal C_FindObjectsFinal; 998 | CK_C_EncryptInit C_EncryptInit; 999 | CK_C_Encrypt C_Encrypt; 1000 | CK_C_EncryptUpdate C_EncryptUpdate; 1001 | CK_C_EncryptFinal C_EncryptFinal; 1002 | CK_C_DecryptInit C_DecryptInit; 1003 | CK_C_Decrypt C_Decrypt; 1004 | CK_C_DecryptUpdate C_DecryptUpdate; 1005 | CK_C_DecryptFinal C_DecryptFinal; 1006 | CK_C_DigestInit C_DigestInit; 1007 | CK_C_Digest C_Digest; 1008 | CK_C_DigestUpdate C_DigestUpdate; 1009 | CK_C_DigestKey C_DigestKey; 1010 | CK_C_DigestFinal C_DigestFinal; 1011 | CK_C_SignInit C_SignInit; 1012 | CK_C_Sign C_Sign; 1013 | CK_C_SignUpdate C_SignUpdate; 1014 | CK_C_SignFinal C_SignFinal; 1015 | CK_C_SignRecoverInit C_SignRecoverInit; 1016 | CK_C_SignRecover C_SignRecover; 1017 | CK_C_VerifyInit C_VerifyInit; 1018 | CK_C_Verify C_Verify; 1019 | CK_C_VerifyUpdate C_VerifyUpdate; 1020 | CK_C_VerifyFinal C_VerifyFinal; 1021 | CK_C_VerifyRecoverInit C_VerifyRecoverInit; 1022 | CK_C_VerifyRecover C_VerifyRecover; 1023 | CK_C_DigestEncryptUpdate C_DigestEncryptUpdate; 1024 | CK_C_DecryptDigestUpdate C_DecryptDigestUpdate; 1025 | CK_C_SignEncryptUpdate C_SignEncryptUpdate; 1026 | CK_C_DecryptVerifyUpdate C_DecryptVerifyUpdate; 1027 | CK_C_GenerateKey C_GenerateKey; 1028 | CK_C_GenerateKeyPair C_GenerateKeyPair; 1029 | CK_C_WrapKey C_WrapKey; 1030 | CK_C_UnwrapKey C_UnwrapKey; 1031 | CK_C_DeriveKey C_DeriveKey; 1032 | CK_C_SeedRandom C_SeedRandom; 1033 | CK_C_GenerateRandom C_GenerateRandom; 1034 | CK_C_GetFunctionStatus C_GetFunctionStatus; 1035 | CK_C_CancelFunction C_CancelFunction; 1036 | CK_C_WaitForSlotEvent C_WaitForSlotEvent; 1037 | }; 1038 | 1039 | typedef ck_rv_t(*ck_createmutex_t) (void **mutex); 1040 | typedef ck_rv_t(*ck_destroymutex_t) (void *mutex); 1041 | typedef ck_rv_t(*ck_lockmutex_t) (void *mutex); 1042 | typedef ck_rv_t(*ck_unlockmutex_t) (void *mutex); 1043 | 1044 | struct ck_c_initialize_args { 1045 | ck_createmutex_t create_mutex; 1046 | ck_destroymutex_t destroy_mutex; 1047 | ck_lockmutex_t lock_mutex; 1048 | ck_unlockmutex_t unlock_mutex; 1049 | ck_flags_t flags; 1050 | void *reserved; 1051 | }; 1052 | 1053 | #define CKF_LIBRARY_CANT_CREATE_OS_THREADS (1UL << 0) 1054 | #define CKF_OS_LOCKING_OK (1UL << 1) 1055 | 1056 | #define CKR_OK (0UL) 1057 | #define CKR_CANCEL (1UL) 1058 | #define CKR_HOST_MEMORY (2UL) 1059 | #define CKR_SLOT_ID_INVALID (3UL) 1060 | #define CKR_GENERAL_ERROR (5UL) 1061 | #define CKR_FUNCTION_FAILED (6UL) 1062 | #define CKR_ARGUMENTS_BAD (7UL) 1063 | #define CKR_NO_EVENT (8UL) 1064 | #define CKR_NEED_TO_CREATE_THREADS (9UL) 1065 | #define CKR_CANT_LOCK (0xaUL) 1066 | #define CKR_ATTRIBUTE_READ_ONLY (0x10UL) 1067 | #define CKR_ATTRIBUTE_SENSITIVE (0x11UL) 1068 | #define CKR_ATTRIBUTE_TYPE_INVALID (0x12UL) 1069 | #define CKR_ATTRIBUTE_VALUE_INVALID (0x13UL) 1070 | #define CKR_DATA_INVALID (0x20UL) 1071 | #define CKR_DATA_LEN_RANGE (0x21UL) 1072 | #define CKR_DEVICE_ERROR (0x30UL) 1073 | #define CKR_DEVICE_MEMORY (0x31UL) 1074 | #define CKR_DEVICE_REMOVED (0x32UL) 1075 | #define CKR_ENCRYPTED_DATA_INVALID (0x40UL) 1076 | #define CKR_ENCRYPTED_DATA_LEN_RANGE (0x41UL) 1077 | #define CKR_FUNCTION_CANCELED (0x50UL) 1078 | #define CKR_FUNCTION_NOT_PARALLEL (0x51UL) 1079 | #define CKR_FUNCTION_NOT_SUPPORTED (0x54UL) 1080 | #define CKR_KEY_HANDLE_INVALID (0x60UL) 1081 | #define CKR_KEY_SIZE_RANGE (0x62UL) 1082 | #define CKR_KEY_TYPE_INCONSISTENT (0x63UL) 1083 | #define CKR_KEY_NOT_NEEDED (0x64UL) 1084 | #define CKR_KEY_CHANGED (0x65UL) 1085 | #define CKR_KEY_NEEDED (0x66UL) 1086 | #define CKR_KEY_INDIGESTIBLE (0x67UL) 1087 | #define CKR_KEY_FUNCTION_NOT_PERMITTED (0x68UL) 1088 | #define CKR_KEY_NOT_WRAPPABLE (0x69UL) 1089 | #define CKR_KEY_UNEXTRACTABLE (0x6aUL) 1090 | #define CKR_MECHANISM_INVALID (0x70UL) 1091 | #define CKR_MECHANISM_PARAM_INVALID (0x71UL) 1092 | #define CKR_OBJECT_HANDLE_INVALID (0x82UL) 1093 | #define CKR_OPERATION_ACTIVE (0x90UL) 1094 | #define CKR_OPERATION_NOT_INITIALIZED (0x91UL) 1095 | #define CKR_PIN_INCORRECT (0xa0UL) 1096 | #define CKR_PIN_INVALID (0xa1UL) 1097 | #define CKR_PIN_LEN_RANGE (0xa2UL) 1098 | #define CKR_PIN_EXPIRED (0xa3UL) 1099 | #define CKR_PIN_LOCKED (0xa4UL) 1100 | #define CKR_SESSION_CLOSED (0xb0UL) 1101 | #define CKR_SESSION_COUNT (0xb1UL) 1102 | #define CKR_SESSION_HANDLE_INVALID (0xb3UL) 1103 | #define CKR_SESSION_PARALLEL_NOT_SUPPORTED (0xb4UL) 1104 | #define CKR_SESSION_READ_ONLY (0xb5UL) 1105 | #define CKR_SESSION_EXISTS (0xb6UL) 1106 | #define CKR_SESSION_READ_ONLY_EXISTS (0xb7UL) 1107 | #define CKR_SESSION_READ_WRITE_SO_EXISTS (0xb8UL) 1108 | #define CKR_SIGNATURE_INVALID (0xc0UL) 1109 | #define CKR_SIGNATURE_LEN_RANGE (0xc1UL) 1110 | #define CKR_TEMPLATE_INCOMPLETE (0xd0UL) 1111 | #define CKR_TEMPLATE_INCONSISTENT (0xd1UL) 1112 | #define CKR_TOKEN_NOT_PRESENT (0xe0UL) 1113 | #define CKR_TOKEN_NOT_RECOGNIZED (0xe1UL) 1114 | #define CKR_TOKEN_WRITE_PROTECTED (0xe2UL) 1115 | #define CKR_UNWRAPPING_KEY_HANDLE_INVALID (0xf0UL) 1116 | #define CKR_UNWRAPPING_KEY_SIZE_RANGE (0xf1UL) 1117 | #define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT (0xf2UL) 1118 | #define CKR_USER_ALREADY_LOGGED_IN (0x100UL) 1119 | #define CKR_USER_NOT_LOGGED_IN (0x101UL) 1120 | #define CKR_USER_PIN_NOT_INITIALIZED (0x102UL) 1121 | #define CKR_USER_TYPE_INVALID (0x103UL) 1122 | #define CKR_USER_ANOTHER_ALREADY_LOGGED_IN (0x104UL) 1123 | #define CKR_USER_TOO_MANY_TYPES (0x105UL) 1124 | #define CKR_WRAPPED_KEY_INVALID (0x110UL) 1125 | #define CKR_WRAPPED_KEY_LEN_RANGE (0x112UL) 1126 | #define CKR_WRAPPING_KEY_HANDLE_INVALID (0x113UL) 1127 | #define CKR_WRAPPING_KEY_SIZE_RANGE (0x114UL) 1128 | #define CKR_WRAPPING_KEY_TYPE_INCONSISTENT (0x115UL) 1129 | #define CKR_RANDOM_SEED_NOT_SUPPORTED (0x120UL) 1130 | #define CKR_RANDOM_NO_RNG (0x121UL) 1131 | #define CKR_DOMAIN_PARAMS_INVALID (0x130UL) 1132 | #define CKR_BUFFER_TOO_SMALL (0x150UL) 1133 | #define CKR_SAVED_STATE_INVALID (0x160UL) 1134 | #define CKR_INFORMATION_SENSITIVE (0x170UL) 1135 | #define CKR_STATE_UNSAVEABLE (0x180UL) 1136 | #define CKR_CRYPTOKI_NOT_INITIALIZED (0x190UL) 1137 | #define CKR_CRYPTOKI_ALREADY_INITIALIZED (0x191UL) 1138 | #define CKR_MUTEX_BAD (0x1a0UL) 1139 | #define CKR_MUTEX_NOT_LOCKED (0x1a1UL) 1140 | #define CKR_FUNCTION_REJECTED (0x200UL) 1141 | #define CKR_VENDOR_DEFINED ((unsigned long) (1UL << 31)) 1142 | 1143 | /* Compatibility layer. */ 1144 | 1145 | #ifdef CRYPTOKI_COMPAT 1146 | 1147 | #undef CK_DEFINE_FUNCTION 1148 | #define CK_DEFINE_FUNCTION(retval, name) retval CK_SPEC name 1149 | 1150 | /* For NULL. */ 1151 | #include 1152 | 1153 | typedef unsigned char CK_BYTE; 1154 | typedef unsigned char CK_CHAR; 1155 | typedef unsigned char CK_UTF8CHAR; 1156 | typedef unsigned char CK_BBOOL; 1157 | typedef unsigned long int CK_ULONG; 1158 | typedef long int CK_LONG; 1159 | typedef CK_BYTE *CK_BYTE_PTR; 1160 | typedef CK_CHAR *CK_CHAR_PTR; 1161 | typedef CK_UTF8CHAR *CK_UTF8CHAR_PTR; 1162 | typedef CK_ULONG *CK_ULONG_PTR; 1163 | typedef void *CK_VOID_PTR; 1164 | typedef void **CK_VOID_PTR_PTR; 1165 | #define CK_FALSE 0 1166 | #define CK_TRUE 1 1167 | #ifndef CK_DISABLE_TRUE_FALSE 1168 | #ifndef FALSE 1169 | #define FALSE 0 1170 | #endif 1171 | #ifndef TRUE 1172 | #define TRUE 1 1173 | #endif 1174 | #endif 1175 | 1176 | typedef struct ck_version CK_VERSION; 1177 | typedef struct ck_version *CK_VERSION_PTR; 1178 | 1179 | typedef struct ck_info CK_INFO; 1180 | typedef struct ck_info *CK_INFO_PTR; 1181 | 1182 | typedef ck_slot_id_t *CK_SLOT_ID_PTR; 1183 | 1184 | typedef struct ck_slot_info CK_SLOT_INFO; 1185 | typedef struct ck_slot_info *CK_SLOT_INFO_PTR; 1186 | 1187 | typedef struct ck_token_info CK_TOKEN_INFO; 1188 | typedef struct ck_token_info *CK_TOKEN_INFO_PTR; 1189 | 1190 | typedef ck_session_handle_t *CK_SESSION_HANDLE_PTR; 1191 | 1192 | typedef struct ck_session_info CK_SESSION_INFO; 1193 | typedef struct ck_session_info *CK_SESSION_INFO_PTR; 1194 | 1195 | typedef ck_object_handle_t *CK_OBJECT_HANDLE_PTR; 1196 | 1197 | typedef ck_object_class_t *CK_OBJECT_CLASS_PTR; 1198 | 1199 | typedef struct ck_attribute CK_ATTRIBUTE; 1200 | typedef struct ck_attribute *CK_ATTRIBUTE_PTR; 1201 | 1202 | typedef struct ck_date CK_DATE; 1203 | typedef struct ck_date *CK_DATE_PTR; 1204 | 1205 | typedef ck_mechanism_type_t *CK_MECHANISM_TYPE_PTR; 1206 | 1207 | typedef struct ck_mechanism CK_MECHANISM; 1208 | typedef struct ck_mechanism *CK_MECHANISM_PTR; 1209 | 1210 | typedef struct ck_mechanism_info CK_MECHANISM_INFO; 1211 | typedef struct ck_mechanism_info *CK_MECHANISM_INFO_PTR; 1212 | 1213 | typedef struct ck_function_list CK_FUNCTION_LIST; 1214 | typedef struct ck_function_list *CK_FUNCTION_LIST_PTR; 1215 | typedef struct ck_function_list **CK_FUNCTION_LIST_PTR_PTR; 1216 | 1217 | typedef struct ck_c_initialize_args CK_C_INITIALIZE_ARGS; 1218 | typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR; 1219 | 1220 | #define NULL_PTR NULL 1221 | 1222 | /* Delete the helper macros defined at the top of the file. */ 1223 | #undef ck_flags_t 1224 | #undef ck_version 1225 | 1226 | #undef ck_info 1227 | #undef cryptoki_version 1228 | #undef manufacturer_id 1229 | #undef library_description 1230 | #undef library_version 1231 | 1232 | #undef ck_notification_t 1233 | #undef ck_slot_id_t 1234 | 1235 | #undef ck_slot_info 1236 | #undef slot_description 1237 | #undef hardware_version 1238 | #undef firmware_version 1239 | 1240 | #undef ck_token_info 1241 | #undef serial_number 1242 | #undef max_session_count 1243 | #undef session_count 1244 | #undef max_rw_session_count 1245 | #undef rw_session_count 1246 | #undef max_pin_len 1247 | #undef min_pin_len 1248 | #undef total_public_memory 1249 | #undef free_public_memory 1250 | #undef total_private_memory 1251 | #undef free_private_memory 1252 | #undef utc_time 1253 | 1254 | #undef ck_session_handle_t 1255 | #undef ck_user_type_t 1256 | #undef ck_state_t 1257 | 1258 | #undef ck_session_info 1259 | #undef slot_id 1260 | #undef device_error 1261 | 1262 | #undef ck_object_handle_t 1263 | #undef ck_object_class_t 1264 | #undef ck_hw_feature_type_t 1265 | #undef ck_key_type_t 1266 | #undef ck_certificate_type_t 1267 | #undef ck_attribute_type_t 1268 | 1269 | #undef ck_attribute 1270 | #undef value 1271 | #undef value_len 1272 | 1273 | #undef ck_date 1274 | 1275 | #undef ck_mechanism_type_t 1276 | 1277 | #undef ck_mechanism 1278 | #undef parameter 1279 | #undef parameter_len 1280 | 1281 | #undef ck_mechanism_info 1282 | #undef min_key_size 1283 | #undef max_key_size 1284 | 1285 | #undef ck_rv_t 1286 | #undef ck_notify_t 1287 | 1288 | #undef ck_function_list 1289 | 1290 | #undef ck_createmutex_t 1291 | #undef ck_destroymutex_t 1292 | #undef ck_lockmutex_t 1293 | #undef ck_unlockmutex_t 1294 | 1295 | #undef ck_c_initialize_args 1296 | #undef create_mutex 1297 | #undef destroy_mutex 1298 | #undef lock_mutex 1299 | #undef unlock_mutex 1300 | #undef reserved 1301 | 1302 | #endif /* CRYPTOKI_COMPAT */ 1303 | 1304 | /* System dependencies. */ 1305 | #if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32) 1306 | #pragma pack(pop, cryptoki) 1307 | #endif 1308 | 1309 | #if defined(__cplusplus) 1310 | } 1311 | #endif 1312 | #endif /* PKCS11_H */ 1313 | -------------------------------------------------------------------------------- /pkcs11/pkcs11g.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ 2 | /* pkcs11g.h - GNOME extensions to PKCS#11 3 | 4 | Copyright (C) 2008, Stef Walter 5 | 6 | The Gnome Keyring Library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Library General Public License as 8 | published by the Free Software Foundation; either version 2 of the 9 | License, or (at your option) any later version. 10 | 11 | The Gnome Keyring Library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Library General Public License for more details. 15 | 16 | You should have received a copy of the GNU Library General Public 17 | License along with the Gnome Library; see the file COPYING.LIB. If not, 18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 | Boston, MA 02111-1307, USA. 20 | 21 | Author: Stef Walter 22 | */ 23 | 24 | #ifndef PKCS11G_H 25 | #define PKCS11G_H 26 | 27 | #include "pkcs11.h" 28 | 29 | #define CKA_GNOME (CKA_VENDOR_DEFINED | 0x474E4D45 /* GNME */ ) 30 | #define CKO_GNOME (CKO_VENDOR_DEFINED | 0x474E4D45 /* GNME */ ) 31 | 32 | /* ------------------------------------------------------------------- 33 | * OBJECT AUTHENTICATION 34 | */ 35 | 36 | #define CKA_GNOME_AUTH_CACHE (CKA_GNOME + 300) 37 | #define CKV_GNOME_AUTH_CACHE_NEVER ((CK_ULONG)-1) 38 | #define CKV_GNOME_AUTH_CACHE_SESSION 0x40000000 39 | #define CKV_GNOME_AUTH_CACHE_UNLIMITED 0x80000000 40 | 41 | #define CKA_GNOME_AUTH_CACHED (CKA_GNOME + 301) 42 | 43 | /* ------------------------------------------------------------------- 44 | * OBJECT UNIQUE IDENTIFIER 45 | */ 46 | 47 | /* A string unique among all objects on a given machine */ 48 | #define CKA_GNOME_UNIQUE (CKA_GNOME + 350) 49 | 50 | /* ------------------------------------------------------------------- 51 | * PURPOSES 52 | */ 53 | 54 | /* 55 | * Whether the key or certificate is restricted to a set of 56 | * purposes (ie: enhanced usages). 57 | * 58 | * CK_BBOOL 59 | * 60 | * - When CK_TRUE see CKA_PURPOSE_OIDS for the set of purposes. 61 | * - When CK_FALSE then is not restricted to any specific purpose. 62 | */ 63 | #define CKA_GNOME_PURPOSE_RESTRICTED (CKA_GNOME + 12) 64 | 65 | /* 66 | * The available purposes that a certificate or key can be 67 | * used for. 68 | * 69 | * CK_STRING 70 | * 71 | * - This is only relevant if CKA_PURPOSE_RESTRICTED is CK_TRUE. 72 | * - Use CKA_TRUSTED and CKA_CERTIFICATE_CATEGORY to validate whether 73 | * usage of the certificate for these purposes is directly or 74 | * indirectly trusted by the user. 75 | * - The returned string is a space delemited set of OIDs. 76 | * - When an empty string is returned then no purposes are valid. 77 | */ 78 | #define CKA_GNOME_PURPOSE_OIDS (CKA_GNOME + 11) 79 | 80 | /* 81 | * The key or certificate can be used for the purpose 82 | * indicated 83 | * 84 | * CK_BBOOL 85 | * 86 | * - These are shortcuts to using CKA_PURPOSE_OIDS 87 | * - Use CKA_TRUSTED and CKA_CERTIFICATE_CATEGORY to validate whether 88 | * the certificate is directly or indirectly trusted by the user. 89 | */ 90 | #define CKA_GNOME_PURPOSE_SSH_AUTH (CKA_GNOME + 101) 91 | #define CKA_GNOME_PURPOSE_SERVER_AUTH (CKA_GNOME + 102) 92 | #define CKA_GNOME_PURPOSE_CLIENT_AUTH (CKA_GNOME + 103) 93 | #define CKA_GNOME_PURPOSE_CODE_SIGNING (CKA_GNOME + 104) 94 | #define CKA_GNOME_PURPOSE_EMAIL_PROTECTION (CKA_GNOME + 105) 95 | #define CKA_GNOME_PURPOSE_IPSEC_END_SYSTEM (CKA_GNOME + 106) 96 | #define CKA_GNOME_PURPOSE_IPSEC_TUNNEL (CKA_GNOME + 107) 97 | #define CKA_GNOME_PURPOSE_IPSEC_USER (CKA_GNOME + 108) 98 | #define CKA_GNOME_PURPOSE_TIME_STAMPING (CKA_GNOME + 109) 99 | 100 | #endif /* PKCS11G_H */ 101 | -------------------------------------------------------------------------------- /pkcs11/pkcs11i.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ 2 | /* pkcs11g.h - GNOME internal definitions to PKCS#11 3 | 4 | Copyright (C) 2008, Stef Walter 5 | 6 | The Gnome Keyring Library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Library General Public License as 8 | published by the Free Software Foundation; either version 2 of the 9 | License, or (at your option) any later version. 10 | 11 | The Gnome Keyring Library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Library General Public License for more details. 15 | 16 | You should have received a copy of the GNU Library General Public 17 | License along with the Gnome Library; see the file COPYING.LIB. If not, 18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 | Boston, MA 02111-1307, USA. 20 | 21 | Author: Stef Walter 22 | */ 23 | 24 | #ifndef PKCS11I_H 25 | #define PKCS11I_H 26 | 27 | #include "pkcs11.h" 28 | #include "pkcs11g.h" 29 | 30 | /* Signifies that nobody is logged in */ 31 | #define CKU_NONE G_MAXULONG 32 | 33 | /* ---------------------------------------------------------------------- 34 | * APARTMENT SLOTS 35 | * 36 | * The lower 10 bits of the CK_SLOT_ID are used as the actual slot identifier, 37 | * and the remainder are used as application identifiers. 38 | * 39 | * This enables a single loaded module to serve multiple applications 40 | * concurrently. The caller of a module should check the 41 | * CKF_GNOME_VIRTUAL_SLOTS flag before using this functionality. 42 | */ 43 | 44 | /* Flag for CK_INFO when virtual slots are supported */ 45 | #define CKF_GNOME_APPARTMENTS 0x40000000 46 | 47 | /* Get an actual slot id from a virtual slot */ 48 | #define CK_GNOME_APPARTMENT_SLOT(virt) ((virt) & 0x000003FF) 49 | 50 | /* Get an app id from a virtual slot */ 51 | #define CK_GNOME_APPARTMENT_APP(virt) ((virt) >> 10) 52 | 53 | /* Is the app id valid for use in a virtual slot? */ 54 | #define CK_GNOME_APPARTMENT_IS_APP(app) ((app) < (((CK_ULONG)-1) >> 10)) 55 | 56 | /* Build a virtual slot from an actual slot id, and an app id */ 57 | #define CK_GNOME_MAKE_APPARTMENT(slot, app) (((slot) & 0x000003FF) | ((app) << 10)) 58 | 59 | /* ------------------------------------------------------------------- 60 | * LIMITED HANDLES 61 | * 62 | * The upper 10 bits of a CK_SESSION_HANDLE and CK_OBJECT_HANDLE are 63 | * never used by Gnome Keyring PKCS#11 modules. These bits are used 64 | * for tracking purposes when combining modules into a single module. 65 | */ 66 | 67 | #define CK_GNOME_MAX_SLOT (0x000003FF) 68 | #define CK_GNOME_MAX_APP (((CK_ULONG)-1) >> 10) 69 | #define CK_GNOME_MAX_HANDLE (((CK_ULONG)-1) >> 10) 70 | 71 | /* ------------------------------------------------------------------- 72 | * OBJECT HASH 73 | */ 74 | 75 | #define CKA_GNOME_INTERNAL_SHA1 (CKA_GNOME + 1000) 76 | 77 | #endif /* PKCS11I_H */ 78 | -------------------------------------------------------------------------------- /pkcs11/pkcs11n.h: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 | * 4 | * The contents of this file are subject to the Mozilla Public License Version 5 | * 1.1 (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * http://www.mozilla.org/MPL/ 8 | * 9 | * Software distributed under the License is distributed on an "AS IS" basis, 10 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | * for the specific language governing rights and limitations under the 12 | * License. 13 | * 14 | * The Original Code is the Netscape security libraries. 15 | * 16 | * The Initial Developer of the Original Code is 17 | * Netscape Communications Corporation. 18 | * Portions created by the Initial Developer are Copyright (C) 1994-2000 19 | * the Initial Developer. All Rights Reserved. 20 | * 21 | * Contributor(s): 22 | * Dr Stephen Henson 23 | * 24 | * Alternatively, the contents of this file may be used under the terms of 25 | * either the GNU General Public License Version 2 or later (the "GPL"), or 26 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 27 | * in which case the provisions of the GPL or the LGPL are applicable instead 28 | * of those above. If you wish to allow use of your version of this file only 29 | * under the terms of either the GPL or the LGPL, and not to allow others to 30 | * use your version of this file under the terms of the MPL, indicate your 31 | * decision by deleting the provisions above and replace them with the notice 32 | * and other provisions required by the GPL or the LGPL. If you do not delete 33 | * the provisions above, a recipient may use your version of this file under 34 | * the terms of any one of the MPL, the GPL or the LGPL. 35 | * 36 | * ***** END LICENSE BLOCK ***** */ 37 | 38 | #ifndef _PKCS11N_H_ 39 | #define _PKCS11N_H_ 40 | 41 | #ifdef DEBUG 42 | static const char CKT_CVS_ID[] = 43 | "@(#) $RCSfile: pkcs11n.h,v $ $Revision: 1.15 $ $Date: 2005/09/28 17:12:17 $"; 44 | 45 | #endif /* DEBUG */ 46 | 47 | /* 48 | * pkcs11n.h 49 | * 50 | * This file contains the NSS-specific type definitions for Cryptoki 51 | * (PKCS#11). 52 | */ 53 | 54 | /* 55 | * NSSCK_VENDOR_NETSCAPE 56 | * 57 | * Cryptoki reserves the high half of all the number spaces for 58 | * vendor-defined use. I'd like to keep all of our Netscape- 59 | * specific values together, but not in the oh-so-obvious 60 | * 0x80000001, 0x80000002, etc. area. So I've picked an offset, 61 | * and constructed values for the beginnings of our spaces. 62 | * 63 | * Note that some "historical" Netscape values don't fall within 64 | * this range. 65 | */ 66 | #define NSSCK_VENDOR_NETSCAPE 0x4E534350 /* NSCP */ 67 | 68 | /* 69 | * Netscape-defined object classes 70 | * 71 | */ 72 | #define CKO_NETSCAPE (CKO_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) 73 | 74 | #define CKO_NETSCAPE_CRL (CKO_NETSCAPE + 1) 75 | #define CKO_NETSCAPE_SMIME (CKO_NETSCAPE + 2) 76 | #define CKO_NETSCAPE_TRUST (CKO_NETSCAPE + 3) 77 | #define CKO_NETSCAPE_BUILTIN_ROOT_LIST (CKO_NETSCAPE + 4) 78 | #define CKO_NETSCAPE_NEWSLOT (CKO_NETSCAPE + 5) 79 | #define CKO_NETSCAPE_DELSLOT (CKO_NETSCAPE + 6) 80 | 81 | /* 82 | * Netscape-defined key types 83 | * 84 | */ 85 | #define CKK_NETSCAPE (CKK_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) 86 | 87 | #define CKK_NETSCAPE_PKCS8 (CKK_NETSCAPE + 1) 88 | /* 89 | * Netscape-defined certificate types 90 | * 91 | */ 92 | #define CKC_NETSCAPE (CKC_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) 93 | 94 | /* 95 | * Netscape-defined object attributes 96 | * 97 | */ 98 | #define CKA_NETSCAPE (CKA_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) 99 | 100 | #define CKA_NETSCAPE_URL (CKA_NETSCAPE + 1) 101 | #define CKA_NETSCAPE_EMAIL (CKA_NETSCAPE + 2) 102 | #define CKA_NETSCAPE_SMIME_INFO (CKA_NETSCAPE + 3) 103 | #define CKA_NETSCAPE_SMIME_TIMESTAMP (CKA_NETSCAPE + 4) 104 | #define CKA_NETSCAPE_PKCS8_SALT (CKA_NETSCAPE + 5) 105 | #define CKA_NETSCAPE_PASSWORD_CHECK (CKA_NETSCAPE + 6) 106 | #define CKA_NETSCAPE_EXPIRES (CKA_NETSCAPE + 7) 107 | #define CKA_NETSCAPE_KRL (CKA_NETSCAPE + 8) 108 | 109 | #define CKA_NETSCAPE_PQG_COUNTER (CKA_NETSCAPE + 20) 110 | #define CKA_NETSCAPE_PQG_SEED (CKA_NETSCAPE + 21) 111 | #define CKA_NETSCAPE_PQG_H (CKA_NETSCAPE + 22) 112 | #define CKA_NETSCAPE_PQG_SEED_BITS (CKA_NETSCAPE + 23) 113 | #define CKA_NETSCAPE_MODULE_SPEC (CKA_NETSCAPE + 24) 114 | 115 | /* 116 | * Trust attributes: 117 | * 118 | * If trust goes standard, these probably will too. So I'll 119 | * put them all in one place. 120 | */ 121 | 122 | #define CKA_TRUST (CKA_NETSCAPE + 0x2000) 123 | 124 | /* "Usage" key information */ 125 | #define CKA_TRUST_DIGITAL_SIGNATURE (CKA_TRUST + 1) 126 | #define CKA_TRUST_NON_REPUDIATION (CKA_TRUST + 2) 127 | #define CKA_TRUST_KEY_ENCIPHERMENT (CKA_TRUST + 3) 128 | #define CKA_TRUST_DATA_ENCIPHERMENT (CKA_TRUST + 4) 129 | #define CKA_TRUST_KEY_AGREEMENT (CKA_TRUST + 5) 130 | #define CKA_TRUST_KEY_CERT_SIGN (CKA_TRUST + 6) 131 | #define CKA_TRUST_CRL_SIGN (CKA_TRUST + 7) 132 | 133 | /* "Purpose" trust information */ 134 | #define CKA_TRUST_SERVER_AUTH (CKA_TRUST + 8) 135 | #define CKA_TRUST_CLIENT_AUTH (CKA_TRUST + 9) 136 | #define CKA_TRUST_CODE_SIGNING (CKA_TRUST + 10) 137 | #define CKA_TRUST_EMAIL_PROTECTION (CKA_TRUST + 11) 138 | #define CKA_TRUST_IPSEC_END_SYSTEM (CKA_TRUST + 12) 139 | #define CKA_TRUST_IPSEC_TUNNEL (CKA_TRUST + 13) 140 | #define CKA_TRUST_IPSEC_USER (CKA_TRUST + 14) 141 | #define CKA_TRUST_TIME_STAMPING (CKA_TRUST + 15) 142 | #define CKA_TRUST_STEP_UP_APPROVED (CKA_TRUST + 16) 143 | 144 | #define CKA_CERT_SHA1_HASH (CKA_TRUST + 100) 145 | #define CKA_CERT_MD5_HASH (CKA_TRUST + 101) 146 | 147 | /* Netscape trust stuff */ 148 | /* XXX fgmr new ones here-- step-up, etc. */ 149 | 150 | /* HISTORICAL: define used to pass in the database key for DSA private keys */ 151 | #define CKA_NETSCAPE_DB 0xD5A0DB00L 152 | #define CKA_NETSCAPE_TRUST 0x80000001L 153 | 154 | /* 155 | * Netscape-defined crypto mechanisms 156 | * 157 | */ 158 | #define CKM_NETSCAPE (CKM_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) 159 | 160 | #define CKM_NETSCAPE_AES_KEY_WRAP (CKM_NETSCAPE + 1) 161 | #define CKM_NETSCAPE_AES_KEY_WRAP_PAD (CKM_NETSCAPE + 2) 162 | 163 | /* 164 | * HISTORICAL: 165 | * Do not attempt to use these. They are only used by NETSCAPE's internal 166 | * PKCS #11 interface. Most of these are place holders for other mechanism 167 | * and will change in the future. 168 | */ 169 | #define CKM_NETSCAPE_PBE_SHA1_DES_CBC 0x80000002L 170 | #define CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC 0x80000003L 171 | #define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC 0x80000004L 172 | #define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC 0x80000005L 173 | #define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4 0x80000006L 174 | #define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4 0x80000007L 175 | #define CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC 0x80000008L 176 | #define CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN 0x80000009L 177 | #define CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN 0x8000000aL 178 | #define CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN 0x8000000bL 179 | 180 | #define CKM_TLS_PRF_GENERAL 0x80000373L 181 | 182 | /* 183 | * Netscape-defined return values 184 | * 185 | */ 186 | #define CKR_NETSCAPE (CKM_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) 187 | 188 | #define CKR_NETSCAPE_CERTDB_FAILED (CKR_NETSCAPE + 1) 189 | #define CKR_NETSCAPE_KEYDB_FAILED (CKR_NETSCAPE + 2) 190 | 191 | /* 192 | * Trust info 193 | * 194 | * This isn't part of the Cryptoki standard (yet), so I'm putting 195 | * all the definitions here. Some of this would move to nssckt.h 196 | * if trust info were made part of the standard. In view of this 197 | * possibility, I'm putting my (Netscape) values in the netscape 198 | * vendor space, like everything else. 199 | */ 200 | typedef CK_ULONG CK_TRUST; 201 | 202 | /* The following trust types are defined: */ 203 | #define CKT_VENDOR_DEFINED 0x80000000 204 | 205 | #define CKT_NETSCAPE (CKT_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) 206 | 207 | /* If trust goes standard, these'll probably drop out of vendor space. */ 208 | #define CKT_NETSCAPE_TRUSTED (CKT_NETSCAPE + 1) 209 | #define CKT_NETSCAPE_TRUSTED_DELEGATOR (CKT_NETSCAPE + 2) 210 | #define CKT_NETSCAPE_UNTRUSTED (CKT_NETSCAPE + 3) 211 | #define CKT_NETSCAPE_MUST_VERIFY (CKT_NETSCAPE + 4) 212 | #define CKT_NETSCAPE_TRUST_UNKNOWN (CKT_NETSCAPE + 5) /* default */ 213 | 214 | /* 215 | * These may well remain Netscape-specific; I'm only using them 216 | * to cache resolution data. 217 | */ 218 | #define CKT_NETSCAPE_VALID (CKT_NETSCAPE + 10) 219 | #define CKT_NETSCAPE_VALID_DELEGATOR (CKT_NETSCAPE + 11) 220 | 221 | #endif /* _PKCS11N_H_ */ 222 | -------------------------------------------------------------------------------- /seccomp-bpf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * seccomp example for x86 (32-bit and 64-bit) with BPF macros 3 | * 4 | * Copyright (c) 2012 The Chromium OS Authors 5 | * Authors: 6 | * Will Drewry 7 | * Kees Cook 8 | * 9 | * The code may be used by anyone for any purpose, and can serve as a 10 | * starting point for developing applications using mode 2 seccomp. 11 | */ 12 | #ifndef _SECCOMP_BPF_H_ 13 | #define _SECCOMP_BPF_H_ 14 | 15 | #define _GNU_SOURCE 1 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #ifndef PR_SET_NO_NEW_PRIVS 26 | # define PR_SET_NO_NEW_PRIVS 38 27 | #endif 28 | 29 | #include 30 | #include 31 | #include 32 | #ifdef HAVE_LINUX_SECCOMP_H 33 | # include 34 | #endif 35 | #ifndef SECCOMP_MODE_FILTER 36 | # define SECCOMP_MODE_FILTER 2 /* uses user-supplied filter. */ 37 | # define SECCOMP_RET_KILL 0x00000000U /* kill the task immediately */ 38 | # define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */ 39 | # define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */ 40 | struct seccomp_data { 41 | int nr; 42 | __u32 arch; 43 | __u64 instruction_pointer; 44 | __u64 args[6]; 45 | }; 46 | #endif 47 | #ifndef SYS_SECCOMP 48 | # define SYS_SECCOMP 1 49 | #endif 50 | 51 | #define syscall_nr (offsetof(struct seccomp_data, nr)) 52 | #define arch_nr (offsetof(struct seccomp_data, arch)) 53 | 54 | #ifdef SECCOMP 55 | #if defined(__i386__) 56 | # define REG_SYSCALL REG_EAX 57 | # define ARCH_NR AUDIT_ARCH_I386 58 | #elif defined(__x86_64__) 59 | # define REG_SYSCALL REG_RAX 60 | # define ARCH_NR AUDIT_ARCH_X86_64 61 | #else 62 | # warning "Platform does not support seccomp filter yet" 63 | # define REG_SYSCALL 0 64 | # define ARCH_NR 0 65 | #endif 66 | #endif /* SECCOMP */ 67 | 68 | #define VALIDATE_ARCHITECTURE \ 69 | BPF_STMT(BPF_LD+BPF_W+BPF_ABS, arch_nr), \ 70 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, 1, 0), \ 71 | BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL) 72 | 73 | #define EXAMINE_SYSCALL \ 74 | BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_nr) 75 | 76 | #define ALLOW_SYSCALL(name) \ 77 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_##name, 0, 1), \ 78 | BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) 79 | 80 | #define KILL_PROCESS \ 81 | BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL) 82 | 83 | #endif /* _SECCOMP_BPF_H_ */ 84 | -------------------------------------------------------------------------------- /syscall-reporter.c: -------------------------------------------------------------------------------- 1 | /* 2 | * syscall reporting example for seccomp 3 | * 4 | * Copyright (c) 2012 The Chromium OS Authors 5 | * Authors: 6 | * Will Drewry 7 | * Kees Cook 8 | * 9 | * The code may be used by anyone for any purpose, and can serve as a 10 | * starting point for developing applications using mode 2 seccomp. 11 | */ 12 | #include "syscall-reporter.h" 13 | #include "syscall-names.h" 14 | 15 | const char * const msg_needed = "Looks like you also need syscall: "; 16 | 17 | /* Since "sprintf" is technically not signal-safe, reimplement %d here. */ 18 | static void write_uint(char *buf, unsigned int val) 19 | { 20 | int width = 0; 21 | unsigned int tens; 22 | 23 | if (val == 0) { 24 | strcpy(buf, "0"); 25 | return; 26 | } 27 | for (tens = val; tens; tens /= 10) 28 | ++ width; 29 | buf[width] = '\0'; 30 | for (tens = val; tens; tens /= 10) 31 | buf[--width] = '0' + (tens % 10); 32 | } 33 | 34 | static void reporter(int nr, siginfo_t *info, void *void_context) 35 | { 36 | #ifdef SECCOMP 37 | char buf[128]; 38 | ucontext_t *ctx = (ucontext_t *)(void_context); 39 | unsigned int syscall; 40 | if (info->si_code != SYS_SECCOMP) 41 | return; 42 | if (!ctx) 43 | return; 44 | syscall = ctx->uc_mcontext.gregs[REG_SYSCALL]; 45 | strcpy(buf, msg_needed); 46 | if (syscall < sizeof(syscall_names)) { 47 | strcat(buf, syscall_names[syscall]); 48 | strcat(buf, "("); 49 | } 50 | write_uint(buf + strlen(buf), syscall); 51 | if (syscall < sizeof(syscall_names)) 52 | strcat(buf, ")"); 53 | strcat(buf, "\n"); 54 | write(STDERR_FILENO, buf, strlen(buf)); 55 | _exit(1); 56 | #endif 57 | } 58 | 59 | int install_syscall_reporter(void) 60 | { 61 | #ifdef SECCOMP 62 | struct sigaction act; 63 | sigset_t mask; 64 | memset(&act, 0, sizeof(act)); 65 | sigemptyset(&mask); 66 | sigaddset(&mask, SIGSYS); 67 | 68 | act.sa_sigaction = &reporter; 69 | act.sa_flags = SA_SIGINFO; 70 | if (sigaction(SIGSYS, &act, NULL) < 0) { 71 | perror("sigaction"); 72 | return -1; 73 | } 74 | if (sigprocmask(SIG_UNBLOCK, &mask, NULL)) { 75 | perror("sigprocmask"); 76 | return -1; 77 | } 78 | #endif 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /syscall-reporter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * syscall reporting example for seccomp 3 | * 4 | * Copyright (c) 2012 The Chromium OS Authors 5 | * Authors: 6 | * Kees Cook 7 | * Will Drewry 8 | * 9 | * The code may be used by anyone for any purpose, and can serve as a 10 | * starting point for developing applications using mode 2 seccomp. 11 | */ 12 | #ifndef _BPF_REPORTER_H_ 13 | #define _BPF_REPORTER_H_ 14 | 15 | #include "seccomp-bpf.h" 16 | 17 | /* Since this redfines "KILL_PROCESS" into a TRAP for the reporter hook, 18 | * we want to make sure it stands out in the build as it should not be 19 | * used in the final program. 20 | */ 21 | #warning "You've included the syscall reporter. Do not use in production!" 22 | #undef KILL_PROCESS 23 | #define KILL_PROCESS \ 24 | BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRAP) 25 | 26 | extern int install_syscall_reporter(void); 27 | 28 | #endif 29 | --------------------------------------------------------------------------------